Quand utiliser "ON UPDATE CASCADE"

420

J'utilise régulièrement "ON DELETE CASCADE" mais je n'utilise jamais "ON UPDATE CASCADE" car je ne sais pas trop dans quelle situation il sera utile.

Pour les besoins de la discussion, voyons du code.

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
);

Pour "ON DELETE CASCADE", si un parent avec un idest supprimé, un enregistrement en enfant avec parent_id = parent.idsera automatiquement supprimé. Cela ne devrait pas poser de problème.

  1. Cela signifie que "ON UPDATE CASCADE" fera la même chose lorsque idle parent est mis à jour?

  2. Si (1) est vrai, cela signifie qu'il n'est pas nécessaire d'utiliser "ON UPDATE CASCADE" s'il parent.idn'est pas modifiable (ou ne sera jamais mis à jour) comme lorsqu'il est AUTO_INCREMENTou est toujours défini pour l'être TIMESTAMP. Est-ce correct?

  3. Si (2) n'est pas vrai, dans quel autre type de situation devrions-nous utiliser "ON UPDATE CASCADE"?

  4. Que se passe-t-il si je (pour une raison quelconque) met à jour le child.parent_idpour qu'il ne soit pas quelque chose d'existant, sera-t-il alors automatiquement supprimé?

Eh bien, je sais, certaines des questions ci-dessus peuvent être testées par programme pour comprendre, mais je veux également savoir si tout cela dépend du fournisseur de base de données ou non.

Veuillez faire la lumière.

NawaMan
la source
1
Voir aussi: stackoverflow.com/questions/6894162/…
Xiè Jìléi

Réponses:

468

Il est vrai que si votre clé primaire n'est qu'une valeur d'identité incrémentée automatiquement, vous n'auriez aucune utilité réelle pour ON UPDATE CASCADE.

Cependant, disons que votre clé primaire est un code à barres UPC à 10 chiffres et, en raison de son expansion, vous devez la remplacer par un code à barres UPC à 13 chiffres. Dans ce cas, ON UPDATE CASCADE vous permettra de modifier la valeur de la clé primaire et toutes les tables qui ont des références de clé étrangère à la valeur seront modifiées en conséquence.

En référence à # 4, si vous changez l'ID enfant en quelque chose qui n'existe pas dans la table parent (et que vous avez l'intégrité référentielle), vous devriez obtenir une erreur de clé étrangère.

C-Pound Guru
la source
6
Juste eu à ON UPDATE CASCADEm'utiliser pour mettre à jour les clés primaires dans une ancienne table qui n'utilise pas de clé auto-incrémentée
BlueRaja - Danny Pflughoeft
86
  1. Oui, cela signifie que, par exemple, si vous faites UPDATE parent SET id = 20 WHERE id = 10tous les enfants, parent_id de 10 sera également mis à jour à 20

  2. Si vous ne mettez pas à jour le champ auquel la clé étrangère fait référence, ce paramètre n'est pas nécessaire

  3. Je ne peux penser à aucune autre utilisation.

  4. Vous ne pouvez pas faire cela car la contrainte de clé étrangère échouerait.

Zed
la source
29

Je pense que vous avez à peu près cloué les points!

Si vous suivez les meilleures pratiques de conception de base de données et que votre clé primaire n'est jamais actualisable (ce qui, je pense, devrait toujours être le cas de toute façon), alors vous n'avez jamais vraiment besoin de la ON UPDATE CASCADEclause.

Zed a souligné que si vous utilisez une clé naturelle (par exemple, un champ normal de votre table de base de données) comme clé primaire, il peut y avoir certaines situations où vous devrez mettre à jour vos clés primaires. Un autre exemple récent serait l'ISBN (International Standard Book Numbers) qui est passé de 10 à 13 chiffres + caractères il n'y a pas si longtemps.

Ce n'est pas le cas si vous choisissez d'utiliser des clés de substitution (par exemple générées artificiellement par le système) comme clé primaire (ce qui serait mon choix préféré dans toutes les occasions sauf les plus rares).

Donc au final: si votre clé primaire ne change jamais, alors vous n'avez jamais besoin de la ON UPDATE CASCADEclause.

Marc

marc_s
la source
Qu'est-ce que les clés "générées artificiellement par le système"? UUID?
HPWD
1
@HPWD: juste une clé "artificielle" (une valeur qui n'est pas basée sur ou dérivée de vos données réelles) qui est générée par le système - ce peut être un GUID, ou un INT, ou un BIGINT - ou quelque chose de vraiment - ne fait pas Peu importe. Le point est: cette valeur n'est en aucun cas liée à vos propres données réelles - et le système génère automatiquement cette valeur pour vous.
marc_s
@ marc-s merci d'avoir pris le temps d'écrire ça. Votre réponse était parfaitement logique.
HPWD
2
Une table à une colonne avec des clés naturelles est une bonne et propre alternative aux énumérations à mon avis (au moins dans les versions de base de données MySQL). Par exemple, considérons une table colorsavec des lignes blue, purple, yellowet une table productsavec une product_colorcolonne, étant FK'ed à la colorstable. Cela restreint les choix comme une énumération, mais contrairement à un entier à incrémentation automatique, il ne nécessite pas de jointure pour obtenir le nom de la couleur. Dans un tel cas, on update cascadec'est une bonne idée, si vous décidez que cela purpledevrait être appelé à la violetplace.
okdewit
18

Il y a quelques jours, j'ai eu un problème avec les déclencheurs, et j'ai compris que cela ON UPDATE CASCADEpouvait être utile. Jetez un œil à cet exemple (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
);

Dans mon numéro, j'ai dû définir quelques opérations supplémentaires (déclencheur) pour mettre à jour la table de concert. Ces opérations ont dû modifier club_name et band_name. Je n'ai pas pu le faire, à cause de la référence. Je ne pouvais pas modifier le concert et m'occuper ensuite des tables de club et de groupe. Je ne pouvais pas aussi le faire dans l'autre sens. ON UPDATE CASCADEétait la clé pour résoudre le problème.

Ariel Grabijas
la source
3
Bon commentaire. Je trouve que la mise à jour en cascade est également utile, dans tous les cas vous devez changer votre identifiant. Je suis également d'accord avec d'autres pour dire que ce changement ne devrait pas être si typique. Par exemple, dans le cas que vous citez, je pense que dans de gros volumes de données, peut-être que la mise en relation de clés étrangères à l'aide de champs de texte n'entraînera pas les performances les plus rapides du moteur de base de données. Remarquez que si la relation étrangère dans la table de concert utilise club.SERIAL et le band.SERIAL, les changements de nom n'affecteront pas la relation entre les tables. Cependant, je trouve ON UPDATE CASCADE est un excellent outil pour résoudre les urgences. Cordialement
David L
4
C'est une conception discutable qui en fait un exemple plutôt artificiel, cependant. Quel est l'intérêt de conserver deux SERIALcolonnes dans clubet en bandtant que clés primaires si vous faites référence à des names au lieu de la clé primaire de chaque table?
sm
En bref, cela est utile si vous dupliquez un champ d'une autre table et que vous en avez besoin pour être à jour.
Kamil Tomšík
4

Mon commentaire se réfère principalement au point 3: dans quelles circonstances la MISE À JOUR EN CASCADE est-elle applicable si nous supposons que la clé parent n'est pas modifiable? Voici un cas.

Je fais face à un scénario de réplication dans lequel plusieurs bases de données satellite doivent être fusionnées avec un maître. Chaque satellite génère des données sur les mêmes tables, donc la fusion des tables avec le maître entraîne des violations de la contrainte d'unicité. J'essaie d'utiliser ON UPDATE CASCADE dans le cadre d'une solution dans laquelle je ré-incrémente les clés lors de chaque fusion. ON UPDATE CASCADE devrait simplifier ce processus en automatisant une partie du processus.

ted.strauss
la source
3

C'est une excellente question, j'avais la même question hier. J'ai pensé à ce problème, en particulier SEARCHED s'il existait quelque chose comme "ON UPDATE CASCADE" et heureusement, les concepteurs de SQL y avaient également pensé. Je suis d'accord avec Ted.strauss et j'ai également commenté le cas de Noran.

Quand l'ai-je utilisé? Comme l'a souligné Ted, lorsque vous traitez plusieurs bases de données à la fois, et que la modification dans l'une d'entre elles, dans un tableau, a une sorte de reproduction dans ce que Ted appelle "base de données satellite", ne peut pas être conservée avec la très originale ID, et pour quelque raison que ce soit, vous devez en créer un nouveau, au cas où vous ne pouvez pas mettre à jour les données sur l'ancien (par exemple en raison d'autorisations, ou dans le cas où vous recherchez la solidité dans un cas si éphémère que ne mérite pas le respect absolu et total des règles totales de normalisation, simplement parce que ce sera une utilité de très courte durée)

Je suis donc d'accord sur deux points:

(A.) Oui, dans bien des cas, une meilleure conception peut l'éviter; MAIS

(B.) En cas de migrations, de réplication de bases de données ou de résolution d'urgences, c'est un GRAND OUTIL qui était heureusement là quand je suis allé chercher s'il existait.

David L
la source