2011-08-16 26 views
5

Ho 4 tavoli. Nella prima tabella ha appid come chiave primaria e in altre tre la sua chiave esterna. Voglio cancellare i dati da tutti e tre in una query. Ho fatto del mio meglio ma ho fallito. Qualcuno può aiutare?Elimina record da più tabelle contemporaneamente?

+0

Questo è il problema che l'azione referenziale 'ON DELETE CASCADE' è stata inventata per risolvere. A differenza di @ Tony Andrews, lo raccomando come pratica generale. – onedaywhen

risposta

10

Non è possibile scrivere un'istruzione di eliminazione che faccia riferimento a più di una tabella, è necessario scrivere 4 istruzioni di eliminazione.

Tuttavia, se appropriato, è possibile definire le chiavi esterne sulle 3 tabelle figlio su "ON DELETE CASCADE". Quindi, quando si elimina dalla tabella padre, vengono eliminate anche tutte le righe associate dalle 3 tabelle figlio. Questo può essere utile a volte, ma non lo raccomanderei come pratica generale in quanto può essere pericoloso e confuso per gli sviluppatori.

+0

Puoi per favore approfondire la natura pericolosa e confusa delle chiavi esterne a cascata? Perché sono un po 'sorpreso da questa osservazione. – Rene

+2

@Rene, OK bene come succede Attualmente lavoro su un progetto in cui qualcuno ha impostato molte chiavi esterne come ON DELETE CASCADE. Ad esempio, se un utente fa qualcosa come "DELETE order_status_lookup WHERE status_code = 'SHIPPED'" allora succede e tutti gli ordini con lo stato' SHIPPED 'vengono cancellati. Lo chiamo ma pericoloso! In realtà uso ON DELETE CASCADE, ma solo dove ha davvero senso. –

+0

Quindi quello che stai dicendo è che si tratta di uno strumento che può essere molto utile ma utilizzato in modo sbagliato può causare danni. Un po 'come una motosega non è vero? Ma consiglieresti di abbattere manualmente tutti quegli alberi? – Rene

3

Non esiste alcun modo per eliminare da più tabelle con una singola istruzione, ma la domanda migliore è perché è necessario eliminare contemporaneamente tutte le tabelle? Mi sembra che tu non capisca appieno come funzionano le transazioni in Oracle.

Consente di accedere ed eliminare una riga dalla tabella 1, ma non eseguire il commit. Per quanto riguarda tutte le altre sessioni, quella riga non è stata cancellata. Se apri un'altra connessione e esegui una query per la riga, sarà comunque presente.

Quindi si elimina dalle tabelle 2, 3 e 4 a turno. Non hai ancora eseguito il commit della transazione, quindi tutte le altre sessioni nel database possono ancora vedere le righe eliminate.

Quindi si commette.

Allo stesso tempo, le altre sessioni non vedranno più le righe eliminate dalle 4 tabelle, anche se le eliminazioni sono state effettuate in 4 istruzioni separate.

+4

Penso che tu sia un po 'severo. Riesco a vedere il merito in una sintassi 'DELETE ALL' analoga a' INSERT ALL': sarebbe utile zappare tutti i record correlati in un set di tabelle senza doversi preoccupare delle dipendenze e senza utilizzare i vincoli posticipati. (Anche se ammetto che il mio bisogno è di solito per gestire i dati di test piuttosto che negli ambienti di produzione). – APC

+0

+1 Per una risposta chiara e diretta. – Rene

-2

Se il database è Mysql, è possibile utilizzare join in ELIMINA istruzione. Vedere http://dev.mysql.com/doc/refman/5.0/en/delete.html per maggiori informazioni.

+4

Ma non lo è. È Oracle. –

+0

Oltre a un altro commento (transazione o utilizzando Elimina cascata) è possibile utilizzare il trigger per eliminare dalle tabelle figlio. –

Problemi correlati