web-dev-qa-db-fra.com

Quand utiliser "ON UPDATE CASCADE"

J'utilise régulièrement "ON DELETE CASCADE" mais je n'utilise jamais "ON UPDATE CASCADE" car je ne suis pas sûr de savoir dans quelle situation il sera utile.

Pour des raisons de 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 id est supprimé, un enregistrement dans enfant avec parent_id = parent.id sera automatiquement supprimé. Cela ne devrait pas poser de problème.

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

  2. Si (1) est vrai, cela signifie qu'il n'est pas nécessaire d'utiliser "ON UPDATE CASCADE" si parent.id n'est pas modifiable (ou ne sera jamais mis à jour) comme s'il était AUTO_INCREMENT ou toujours défini sur ê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, pour une raison quelconque, je mets à jour le child.parent_id pour qu’il n’existe pas, il sera automatiquement supprimé?

Eh bien, je sais, certaines des questions ci-dessus peuvent être testées par programmation pour comprendre, mais je veux aussi savoir si l’une de ces données dépend du fournisseur de la base de données ou non.

S'il vous plaît jeter un peu de lumière.

395
NawaMan

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

Cependant, supposons que votre clé primaire soit un code à barres UPC à 10 chiffres et que, du fait de son expansion, vous devez le remplacer par un code à barres UPC à 13 chiffres. Dans ce cas, ON UPDATE CASCADE vous permettrait de modifier la valeur de la clé primaire et toutes les tables contenant des références de clé étrangère à la valeur seront modifiées en conséquence.

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

444
C-Pound Guru
  1. Oui, cela signifie que, par exemple, si vous faites UPDATE parent SET id = 20 WHERE id = 10 tous les enfants dont l'ID parent sur 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.

80
Zed

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 ne peut jamais être mise à jour (ce qui, à mon avis, devrait toujours l'être), vous n'avez jamais vraiment besoin de la clause ON UPDATE CASCADE.

Zed a bien expliqué que, si vous utilisiez une clé naturelle (par exemple, un champ normal de votre table de base de données) comme clé primaire, il pourrait arriver que vous besoin de mettre à jour vos clés primaires. Un autre exemple récent serait l'ISBN (International Standard Book Numbers), 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 les cas les plus rares).

Donc à la fin: si votre clé primaire ne change jamais, vous n’avez jamais besoin de la clause ON UPDATE CASCADE.

Marc

27
marc_s

Il y a quelques jours, j'ai eu un problème avec les déclencheurs et j'ai compris que ON UPDATE CASCADE peut être utile. Regardez 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, je devais définir quelques opérations supplémentaires (déclencheur) pour mettre à jour la table de concert. Ces opérations devaient modifier club_name et band_name. J'étais incapable de le faire, à cause de la référence. Je ne pouvais pas modifier un concert et ensuite traiter avec les 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.

16
Ariel Grabijas

Mon commentaire porte principalement sur le point 3: dans quelles circonstances est-ce que ON UPDATE CASCADE est applicable si nous supposons que la clé parente n'est pas modifiable? Voici un cas.

Je suis confronté à un scénario de réplication dans lequel plusieurs bases de données satellites doivent être fusionnées avec un maître. Chaque satellite génère des données sur les mêmes tables. Par conséquent, la fusion des tables avec le maître entraîne la violation 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 à chaque fusion. ON UPDATE CASCADE devrait simplifier ce processus en automatisant une partie du processus.

4
ted.strauss

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

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

Donc, je suis d'accord sur deux points:

(A.) Oui, bien souvent, une meilleure conception peut l’éviter; MAIS

(B.) Dans les cas de migrations, de réplication de bases de données ou de résolution des urgences, c’est un GRAND OUTIL qui, heureusement, était là lorsque j’ai cherché à savoir s’il existait.

3
David L