Quando utilizzare "ON AGGIORNAMENTO CASCADE"


420

Uso regolarmente "ON DELETE CASCADE", ma non utilizzo mai "ON UPDATE CASCADE" in quanto non sono così sicuro in quale situazione sarà utile.

Per motivi di discussione, vediamo un po 'di codice.

CREATE TABLE parent (
    id INT NOT NULL AUTO_INCREMENT,
    PRIMARY KEY (id)
);

CREATE TABLE child (
    id INT NOT NULL AUTO_INCREMENT, parent_id INT,
    INDEX par_ind (parent_id),
    FOREIGN KEY (parent_id)
        REFERENCES parent(id)
        ON DELETE CASCADE
);

Per "ON DELETE CASCADE", se un genitore con un idviene eliminato, un record nel figlio con parent_id = parent.idverrà automaticamente eliminato. Questo non dovrebbe essere un problema.

  1. Ciò significa che "IN AGGIORNAMENTO CASCADE" farà la stessa cosa quando idil genitore viene aggiornato?

  2. Se (1) è vero, significa che non è necessario utilizzare "AGGIORNAMENTO CASCADE" se parent.idnon è aggiornabile (o non verrà mai aggiornato) come quando è AUTO_INCREMENTo è sempre impostato TIMESTAMP. È giusto?

  3. Se (2) non è vero, in quale altro tipo di situazione dovremmo usare "AGGIORNAMENTO CASCADE"?

  4. Che cosa succede se (per qualche motivo) aggiorno child.parent_idper essere qualcosa che non esiste, verrà automaticamente cancellato?

Bene, lo so, alcune delle domande precedenti possono essere testate a livello di codice per capire, ma voglio anche sapere se qualcuno di questi dipende dal fornitore del database o meno.

Per favore, fai luce.


Risposte:


468

È vero che se la tua chiave primaria è solo un valore di identità auto incrementato, non avresti alcun reale utilizzo per ON UPDATE CASCADE.

Tuttavia, supponiamo che la chiave primaria sia un codice a barre UPC a 10 cifre e, a causa dell'espansione, è necessario modificarlo in un codice a barre UPC a 13 cifre. In tal caso, ON UPDATE CASCADE consentirebbe di modificare il valore della chiave primaria e qualsiasi tabella che abbia riferimenti di chiave esterna al valore verrà modificata di conseguenza.

In riferimento a # 4, se si modifica l'ID figlio in qualcosa che non esiste nella tabella padre (e si dispone di integrità referenziale), si dovrebbe ottenere un errore di chiave esterna.


6
Ho dovuto usare ON UPDATE CASCADEme stesso per aggiornare le chiavi primarie in una vecchia tabella che non utilizza una chiave auto-incrementata
BlueRaja - Danny Pflughoeft

86
  1. Sì, significa che, ad esempio, se fai UPDATE parent SET id = 20 WHERE id = 10tutti i figli parent_id di 10 verrà aggiornato anche a 20

  2. Se non si aggiorna il campo a cui fa riferimento la chiave esterna, questa impostazione non è necessaria

  3. Non riesco a pensare a nessun altro uso.

  4. Non è possibile farlo poiché il vincolo di chiave esterna fallirebbe.


29

Penso che tu abbia praticamente inchiodato i punti!

Se segui le migliori pratiche di progettazione del database e la tua chiave primaria non è mai aggiornabile (cosa che penso dovrebbe essere sempre il caso), allora non hai mai davvero bisogno del ON UPDATE CASCADE clausola.

Zed ha sottolineato che se usi un naturale chiave (ad esempio un campo normale dalla tabella del database) come chiave primaria, potrebbero esserci determinate situazioni in cui è necessario aggiornare le chiavi primarie. Un altro esempio recente potrebbe essere il codice ISBN (International Standard Book Numbers) che è cambiato da 10 a 13 cifre + caratteri non molto tempo fa.

Questo non è il caso se si sceglie di utilizzare surrogato chiavi (ad es. Generate artificialmente dal sistema) come chiave primaria (che sarebbe la mia scelta preferita in tutte le occasioni tranne le più rare).

Quindi alla fine: se la tua chiave primaria non cambia mai, allora non hai mai bisogno della ON UPDATE CASCADEclausola.

Marc


Che cosa sono le chiavi "generate artificialmente dal sistema"? UUID?
HPWD,

1
@HPWD: solo una chiave "artificiale" (un valore che non è basato o derivato dai tuoi dati effettivi) che viene generato dal sistema - può essere un GUID, o un INT, o un BIGINT - o qualcosa del genere - no non importa. Il punto è: quel valore non è in alcun modo correlato ai tuoi dati reali, e il sistema sta generando quel valore automaticamente per te.
marc_s,

@ marc-s grazie per aver dedicato del tempo a scriverlo. La tua risposta aveva perfettamente senso.
HPWD

2
Una tabella a colonna singola con chiavi naturali è una buona e pulita alternativa alle enumerazioni secondo me (almeno nelle versioni di MySQL DB). Ad esempio, si consideri una tabella colorscon righe blue, purple, yellow, e una tabella productscon una product_colorcolonna, essendo FK'ed al colorstavolo. Ciò limita le scelte come un enum, ma a differenza di un intero a incremento automatico non richiede un join per ottenere il nome del colore. In tal caso, on update cascadeè una buona idea, se decidi che purpledovrebbe essere chiamato violetinvece.
Okdewit,

18

Qualche giorno fa ho avuto un problema con i trigger e ho capito che ON UPDATE CASCADEpuò essere utile. Dai un'occhiata a questo esempio (PostgreSQL):

CREATE TABLE club
(
    key SERIAL PRIMARY KEY,
    name TEXT UNIQUE
);

CREATE TABLE band
(
    key SERIAL PRIMARY KEY,
    name TEXT UNIQUE
);

CREATE TABLE concert
(
    key SERIAL PRIMARY KEY,
    club_name TEXT REFERENCES club(name) ON UPDATE CASCADE,
    band_name TEXT REFERENCES band(name) ON UPDATE CASCADE,
    concert_date DATE
);

Nel mio problema, ho dovuto definire alcune operazioni aggiuntive (trigger) per l'aggiornamento del tavolo del concerto. Tali operazioni hanno dovuto modificare club_name e band_name. Non sono riuscito a farlo, a causa del riferimento. Non ho potuto modificare il concerto e poi occuparmi dei tavoli di club e band. Non potrei farlo anche nell'altro modo. ON UPDATE CASCADEè stata la chiave per risolvere il problema.


3
Buon commento Trovo utile anche l'aggiornamento a cascata, in ogni caso devi cambiare il tuo ID. Concordo anche con altri sul fatto che questo cambiamento non dovrebbe essere così tipico. Ad esempio, nel caso in cui citi, penso che in grandi volumi di dati, forse mettere in relazione le chiavi esterne utilizzando i campi di testo potrebbe non portare alle prestazioni più veloci del motore di database. Si noti che se la relazione straniera nella tabella del concerto utilizza club.SERIAL e la banda.SERIAL, le modifiche al nome non influirebbero sulla relazione tra le tabelle. Tuttavia, trovo che ON UPDATE CASCADE sia un ottimo strumento per risolvere le emergenze. Saluti
David L

4
Questo è un design discutibile che costituisce tuttavia un esempio piuttosto inventato. Qual è il punto di mantenere due SERIALcolonne clube bandcome chiavi primarie se si fa riferimento a names anziché alla chiave primaria di ogni tabella?
sm

In breve, questo è utile se stai duplicando un campo da un'altra tabella e hai bisogno che sia aggiornato.
Kamil Tomšík,

4

Il mio commento è principalmente in riferimento al punto 3: in quali circostanze è applicabile AGGIORNAMENTO CASCADE se assumiamo che la chiave padre non sia aggiornabile? Ecco un caso.

Ho a che fare con uno scenario di replica in cui più database satellitari devono essere uniti a un master. Ogni satellite sta generando dati sulle stesse tabelle, quindi l'unione delle tabelle con il master porta a violazioni del vincolo di unicità. Sto provando a utilizzare ON UPDATE CASCADE come parte di una soluzione in cui incremento nuovamente le chiavi durante ogni unione. IN AGGIORNAMENTO CASCADE dovrebbe semplificare questo processo automatizzando parte del processo.


3

È un'ottima domanda, ho avuto la stessa domanda ieri. Ho pensato a questo problema, in particolare RICERCA se esistesse qualcosa come "IN AGGIORNAMENTO CASCADE" e per fortuna anche i progettisti di SQL ci avevano pensato. Sono d'accordo con Ted.strauss e ho anche commentato il caso di Noran.

Quando l'ho usato? Come ha sottolineato Ted, quando si trattano più database contemporaneamente e la modifica in uno di essi, in una tabella, ha qualsiasi tipo di riproduzione in quello che Ted chiama "database satellite", non può essere mantenuta con l'originale ID e per qualsiasi motivo devi crearne uno nuovo, nel caso in cui non sia possibile aggiornare i dati su quello vecchio (ad esempio a causa di autorizzazioni o nel caso in cui tu stia cercando solidità in un caso così effimero che non merita il rispetto assoluto e assoluto per le regole totali di normalizzazione, semplicemente perché sarà un'utilità di breve durata)

Quindi, sono d'accordo in due punti:

(A.) Sì, molte volte un design migliore può evitarlo; MA

(B.) In caso di migrazioni, replica di database o risoluzione di emergenze, è UN GRANDE STRUMENTO che fortunatamente era lì quando sono andato a cercare se esistesse.

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.