Differenza tra On Delete Cascade e On Update Cascade in mysql


45

Ho due tabelle in MySQL database- parent, child. Sto cercando di aggiungere riferimenti a chiave esterna alla mia tabella figlio in base alla tabella padre. C'è qualche differenza significativa tra ON UPDATE CASCADEeON DELETE CASCADE

Tabella dei miei genitori

CREATE TABLE parent (
    id INT NOT NULL,
    PRIMARY KEY (id)
) ENGINE=INNODB;

La mia domanda è: qual è la differenza tra le seguenti query sql.

  1. ON DELETE CASCADE

    CREATE TABLE child (
        id INT, 
        parent_id INT,
        INDEX par_ind (parent_id),
        FOREIGN KEY (parent_id) 
            REFERENCES parent(id)
            ON DELETE CASCADE
    ) ENGINE=INNODB;
    
  2. ON UPDATE CASCADE

    CREATE TABLE child (
        id INT, 
        parent_id INT,
        INDEX par_ind (parent_id),
        FOREIGN KEY (parent_id) 
            REFERENCES parent(id)
            ON UPDATE CASCADE
    ) ENGINE=INNODB;
    
  3. ON UPDATE CASCADE ON DELETE CASCADE

    CREATE TABLE child (
            id INT, 
            parent_id INT,
            INDEX par_ind (parent_id),
            FOREIGN KEY (parent_id) 
                REFERENCES parent(id)
                ON UPDATE CASCADE ON DELETE CASCADE
        ) ENGINE=INNODB;
    

Ci sono errori nelle query? Cosa significano queste query (1,2 e 3) ?? Sono uguali ???


1
ps <nitpick> per completezza, di cosa stai parlando sopra sono le istruzioni DDL (Data Definition Language) e non le query. Una query è generalmente considerata DML (SELEZIONA, INSERIRE, AGGIORNARE, CANCELLARE) Data Manipulation Language </nitpick>
Vérace,

Ancora un altro ps per completezza, mi chiedevo quale fosse il default. Quindi ho creato un bambino senza aggiornamenti o eliminazioni. Quello che succede allora è che non puoi né aggiornare né eliminare un genitore che ha un figlio a carico. Questo ha perfettamente senso, tuttavia MySQL non è sempre un modello di quella particolare caratteristica :-)
Vérace,

Risposte:


64

Un ottimo filo su questo argomento si trova qui e anche qui . La guida definitiva per MySQL è, ovviamente, la documentazione, che si trova qui .

Nello standard SQL 2003 ci sono 5 diverse azioni referenziali:

  1. CASCATA
  2. LIMITARE
  3. NESSUNA AZIONE
  4. SET NULL
  5. IMPOSTA DEFAULT

Per rispondere alla domanda:

  1. CASCATA

    • ON DELETE CASCADEsignifica che se il record padre viene eliminato, anche i record figlio vengono eliminati. Questa non è una buona idea secondo me. Dovresti tenere traccia di tutti i dati che sono mai stati in un database, anche se questo può essere fatto usando TRIGGERs. (Tuttavia, vedere le avvertenze nei commenti seguenti).

    • ON UPDATE CASCADEsignifica che se viene modificata la chiave primaria principale, anche il valore secondario cambierà per riflettere tale. Ancora una volta secondo me, non è una grande idea. Se stai cambiando PRIMARY KEYs con regolarità (o addirittura del tutto!), C'è qualcosa che non va nel tuo design. Ancora una volta, vedi commenti.

    • ON UPDATE CASCADE ON DELETE CASCADEsignifica che se UPDATE O DELETE il genitore, la modifica è in cascata al figlio. Questo è l'equivalente del ANDrisultato delle prime due affermazioni.

  2. LIMITARE

    • RESTRICTsignifica che qualsiasi tentativo di eliminare e / o aggiornare il genitore fallirà nel generare un errore. Questo è il comportamento predefinito nel caso in cui un'azione referenziale non sia specificata esplicitamente.

      Per un ON DELETEo ON UPDATEche non è specificato, l'azione predefinita è sempre RESTRICT`.

  3. NESSUNA AZIONE

    • NO ACTION: Dal manuale . Una parola chiave da SQL standard. In MySQL, equivalente a RESTRICT. Il server MySQL rifiuta l'operazione di eliminazione o aggiornamento per la tabella padre se nella tabella di riferimento è presente un valore di chiave esterna correlato. Alcuni sistemi di database hanno controlli differiti ed NO ACTIONè un controllo differito. In MySQL, i vincoli di chiave esterna vengono controllati immediatamente, quindi NO ACTIONè lo stesso di RESTRICT.
  4. SET NULL

    • SET NULL- di nuovo dal manuale. Elimina o aggiorna la riga dalla tabella padre e imposta la colonna o le colonne della chiave esterna nella tabella figlio su NULL. Questa non è la migliore delle idee IMHO, principalmente perché non esiste alcun modo di "viaggiare nel tempo", ovvero guardare indietro nelle tabelle secondarie e associare i record con i NULLs con il record principale pertinente, CASCADEoppure utilizzare TRIGGERs per popolare le tabelle di registrazione per tracciare modifiche (ma, vedere i commenti).
  5. IMPOSTA DEFAULT

    • SET DEFAULT. Ancora un'altra parte (potenzialmente molto utile) dello standard SQL che MySQL non si è preoccupata di implementare! Consente allo sviluppatore di specificare un valore su cui impostare le colonne della chiave esterna in un AGGIORNAMENTO o un ELIMINA. InnoDB e NDB rifiuteranno le definizioni di tabella con una SET DEFAULTclausola.

Come accennato in precedenza, dovresti passare un po 'di tempo a guardare la documentazione, qui .


8
Mi piace la tua risposta completa ma non sono d'accordo con questa affermazione. "Dovresti tenere traccia di tutti i dati che sono mai stati in un database" - questo dipende in realtà dal design e dagli scopi del database. Ad esempio una definizione di ricetta (non sto parlando di cibo - più come le configurazioni di sistema) quando la definizione di ricetta viene eliminata non ha senso mantenere i figli associati di quella ricetta - che gonfia semplicemente il db senza motivo. Anche tabelle di lavoro per sistemi di macchine - Non ho più bisogno dei dati; elaborare e liberarsene. A parte questo, la tua risposta è fantastica.
StixO,

2
simile a @StixO Mi piace principalmente questa risposta, ma non sono d'accordo con la modifica della chiave primaria. Esistono sicuramente progetti in cui questa sarebbe una cattiva idea, ma quando si entra in un database distribuito può essere molto desiderabile che le chiavi primarie siano libere da riassegnare senza perdere l'identità di un record.
Garet Claborn,

"Questa non è una buona idea secondo me. Dovresti tenere traccia di tutti i dati che sono mai stati in un database." - Non sono sicuro di aver capito il tuo punto. Se stai eseguendo il collegamento a cascata "on delete", hai già deciso di dover eliminare qualcosa. Se decidi di non eliminare mai nulla, non verrà visualizzato nulla. Il vantaggio di averlo però è che nella tua applicazione puoi essere sicuro che quando cerchi un record con un ID esterno, sai che sarà lì e non ci saranno righe orfane che gonfiano il tuo database se dovessi decidere di eliminare qualcosa.
Jeff Ryan,

La logica qui è piuttosto difettosa in alcuni punti, e ancora di più nel nostro nuovo mondo GDPR. Sono d'accordo con l'idea che se cambiano le chiavi primarie, potrebbe essere un segno di qualcosa di sbagliato.
Chuck Le Butt,

Se stai cambiando PRIMARY KEYs con qualsiasi regolarità (o addirittura del tutto!), C'è qualcosa che non va nel tuo design. Vuoi dire ON UPDATE CASCADE cambia il valore della chiave o il nome della chiave?
Billal Begueradj,

8

Queste due azioni sono da eseguire, rispettivamente, quando il record a cui si fa riferimento nella tabella padre cambia il suo ID e quando viene eliminato.

Se esegui:

UPDATE parent SET id = -1 WHERE id = 1;

E c'è almeno un record childcon parent_id = 1, 1) fallirà; nei casi 2) e 3), tutti i record con parent_id = 1 vengono aggiornati a parent_id = -1.

Se esegui:

DELETE FROM parent WHERE id = 1;

E c'è almeno un record childcon parent_id = 1, 2) fallirà; nei casi 1) e 3), tutti i record con parent_id = 1vengono eliminati.

3) è sintatticamente corretto.

La documentazione completa è disponibile nel manuale .


6

Non ho abbastanza reputazione per commentare le risposte precedenti. Quindi ho pensato di elaborare un po '.

1) ON DELETE CASCADE significa se il record padre viene eliminato, anche i record figlio di riferimento vengono eliminati. ON UPDATE viene impostato automaticamente su RESTRICT, il che significa che UPDATE sul record padre non riuscirà.

2) L'opzione ON DELETE è impostata per impostazione predefinita su RESTRICT, il che significa che ELIMINA sul record principale avrà esito negativo. IN AGGIORNAMENTO CASCADE aggiornerà tutti i record figlio di riferimento quando il record padre viene aggiornato.

3) Vedi le azioni CASCADE in 1) e 2) sopra.

Sull'uso degli ID record del genitore come chiavi esterne (nelle tabelle figlio) - l'esperienza dice a) se gli ID sono numeri di sequenza generati automaticamente, quindi NON usarli come chiavi esterne. Utilizzare invece un'altra chiave genitore univoca. b) se gli ID sono GUID, allora va bene usarli come chiavi esterne. Vedrai la saggezza in questo suggerimento quando esporti e importi i record o li copi in un altro database. È troppo ingombrante per gestire i numeri di sequenza generati automaticamente durante la migrazione dei dati quando vengono indicati come chiavi esterne.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.