View Full Version : [MySQL] Garantire l'integrità referenziale con tabelle MyISAM
uReverendo
22-01-2008, 18:36
Ciao a tutti.
Premesso che sono alle prime armi con i database, ho creato un piccolo sito web con un database MySQL. Purtroppo, viste le limitazioni dell'hosting sul quale lo metterò, sono stato costretto ad utilizzare tabelle di tipo MyISAM, le quali non supportano i vincoli di integrità referenziale.:doh:
Avendo tabelle gerarchiche nel DB la mia domanda è: come faccio a garantite l'integrità dei dati?
In particolare, se cancello un record dalla tabella padre come faccio a cancellare tutti i record della tabella figlio e nipote (con il minor numero di query)?
Infine, a cosa devo stare attento durante l'inserimento di nuovi record, e quali sono gli accorgimenti che devo seguire per evitare problemi?
Prima di tutto devi usare le istruzioni LOCK TABLES all'inizio delle query e UNLOCK TABLES alla fine. Devi bloccare tutte le cartella in scrittura perché devi modificare più o meno tutte le tabelle interessate
Poi chiaramente dipende dalla struttura del database: devi fare le query che ti aspetti che un DB con integrità referenziale ti faccia. Ad esempio: cancelli un ID da una tabella ? Allora vai a cancellare tutti record che fanno riferimento a quell'ID all'interno delle tabelle che secondo te devono mantenere l'integrità referenziale (tutte quelle tabelle che secondo te devono avere l'ID della tabella originale come foreign key).
uReverendo
23-01-2008, 11:54
Prima di tutto devi usare le istruzioni LOCK TABLES all'inizio delle query e UNLOCK TABLES alla fine.
Grazie per il consiglio.
Poi chiaramente dipende dalla struttura del database: devi fare le query che ti aspetti che un DB con integrità referenziale ti faccia. Ad esempio: cancelli un ID da una tabella ? Allora vai a cancellare tutti record che fanno riferimento a quell'ID all'interno delle tabelle che secondo te devono mantenere l'integrità referenziale (tutte quelle tabelle che secondo te devono avere l'ID della tabella originale come foreign key).
Si è proprio quello che voglio fare. Putroppo ho problemi con la query.
In pratica, semplificando, ho lo schema seguente:
Categorie
-----------
IdCateg(*)
...
Discussioni
-----------
IdDisc(*)
IdCateg
...
Messaggi
-----------
IdMsg(*)
IdDisc
...
(*) Chiave
Teoricamente dovrei fare una cosa simile:
1) DELETE FROM categorie WHERE IdCateg = ?IdCateg;
2) DELETE FROM discussioni WHERE IdCateg = ?IdCateg;
3) Per ciascun record cancellato, recupera IdDisc ed esegui
4) DELETE FROM messaggi WHERE IdDisc = ?IdDisc;
In pratica non riesco a fare i passagi 3 e 4.
Leggendo la relativa documentazione ho provato a fare una query DELETE su più tabelle:
DELETE categorie, discussioni, messaggi
FROM categorie, discussioni, messaggi
WHERE
categorie.IdCateg = ?IdCateg AND
discussioni.IdCateg = categorie.IdCateg AND
messaggi.IdDisc = discussioni.IdDisc
Purtroppo non avendo compreso bene il funzionamento di questa query, non riesco a farla funzionare corretamente.
Infatti funziona solo se data una categoria, questa ha discussioni e queste ultime hanno messaggi.
Se ad esempio una categoria non ha dicussioni, questa non viene cancellata. Lo stesso accade se una discussione non ha messaggi.
Come posso risolvere il problema?
D4rkAng3l
23-01-2008, 12:15
Prima di tutto devi usare le istruzioni LOCK TABLES all'inizio delle query e UNLOCK TABLES alla fine. Devi bloccare tutte le cartella in scrittura perché devi modificare più o meno tutte le tabelle interessate
Poi chiaramente dipende dalla struttura del database: devi fare le query che ti aspetti che un DB con integrità referenziale ti faccia. Ad esempio: cancelli un ID da una tabella ? Allora vai a cancellare tutti record che fanno riferimento a quell'ID all'interno delle tabelle che secondo te devono mantenere l'integrità referenziale (tutte quelle tabelle che secondo te devono avere l'ID della tabella originale come foreign key).
interessa anche a me...cioè devi dirgli nella query che se magari cancelli una riga da una certa tabella padre allora che deve cancellare anche le righe nelle tabelle figlie con magari uno stesso identificatore? (tutto fatto a mano invece che gestito dal DBMS come se usassi le tabelle di tipo InnoDB)
Ciao
Andrea
Per queste:
1) DELETE FROM categorie WHERE IdCateg = ?IdCateg;
2) DELETE FROM discussioni WHERE IdCateg = ?IdCateg;
3) Per ciascun record cancellato, recupera IdDisc ed esegui
4) DELETE FROM messaggi WHERE IdDisc = ?IdDisc;
Opera in senso inverso:
DELETE FROM messaggi WHERE IdDisc IN (SELECT IdDisc FROM discussioni WHERE IdCateg = ?IdCateg);
DELETE FROM discussioni WHERE IdCateg = ?IdCateg;
DELETE FROM categorie WHERE IdCateg = ?IdCateg;
uReverendo
23-01-2008, 17:17
Per queste:
DELETE FROM messaggi WHERE IdDisc IN (SELECT IdDisc FROM discussioni WHERE IdCateg = ?IdCateg);
DELETE FROM discussioni WHERE IdCateg = ?IdCateg;
DELETE FROM categorie WHERE IdCateg = ?IdCateg;
Perfetto, sei stato di grande aiuto. Grazie.
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.