SQL ON DELETE CASCADE, de quelle manière la suppression se produit-elle?

156

Si j'ai deux relations dans une base de données, comme ceci:

CREATE TABLE Courses (
  CourseID int NOT NULL PRIMARY KEY,
  Course VARCHAR(63) NOT NULL UNIQUE,
  Code CHAR(4) NOT NULL UNIQUE
);

CREATE TABLE BookCourses (
  EntryID int NOT NULL PRIMARY KEY,
  BookID int NOT NULL,
  Course CHAR(4) NOT NULL,
  CourseNum CHAR(3) NOT NULL,
  CourseSec CHAR(1) NOT NULL
);

et j'établis une relation de clé étrangère entre les deux, comme ceci:

ALTER TABLE BookCourses
ADD FOREIGN KEY (Course)
REFERENCES Courses(Code)
ON DELETE CASCADE;

Ensuite, vous pouvez voir que l' Courseattribut dans la BookCoursesrelation fait référence à l' Codeattribut dans la Coursesrelation.

Ma question est lorsqu'une suppression se produit dans l'une des deux relations, de quelle manière la suppression en cascade? Si je supprime un tuple dans la Coursesrelation, supprimera-t-il tous les tuples référençant dans la BookCoursesrelation, ou est-ce l'inverse?

Oliver Spryn
la source
11
On se demande seulement pourquoi la Categoriestable a CourseIDcomme clé primaire alors que la Coursestable a le EntryID. Vous devez sérieusement repenser vos choix de dénomination.
ypercubeᵀᴹ
7
Veuillez utiliser les noms de colonne appropriés pour éviter toute confusion et clarifier la structure de la base de données.
Gunjan Shah

Réponses:

185

Cascade fonctionnera lorsque vous supprimerez quelque chose sur la table Courses. Tout enregistrement de la table BookCoursesfaisant référence à la table Coursessera automatiquement supprimé.

Mais lorsque vous essayez de supprimer sur la table, BookCoursesseule la table elle-même est affectée et non sur leCourses

question de suivi: pourquoi avez-vous CourseIDsur la table Catégorie?

Peut-être devriez-vous restructurer votre schéma en ceci,

CREATE TABLE Categories 
(
  Code CHAR(4) NOT NULL PRIMARY KEY,
  CategoryName VARCHAR(63) NOT NULL UNIQUE
);

CREATE TABLE Courses 
(
  CourseID INT NOT NULL PRIMARY KEY,
  BookID INT NOT NULL,
  CatCode CHAR(4) NOT NULL,
  CourseNum CHAR(3) NOT NULL,
  CourseSec CHAR(1) NOT NULL,
);

ALTER TABLE Courses
ADD FOREIGN KEY (CatCode)
REFERENCES Categories(Code)
ON DELETE CASCADE;
John Woo
la source
5
Génial! Je vous remercie. Réponse de suivi: Parce que j'ai beaucoup réfléchi. Corrigé maintenant ... et dans ma DB
Oliver Spryn
59
Cette réponse a des noms de table et des structures différents de ceux de la question ... La rendant beaucoup moins utile.
Daniel Beardsley
4
@DanielBeardsley, je ne suis pas d'accord pour dire que cette réponse n'est pas utile. C'est si vous lisez ce qu'il dit. Je suis cependant d'accord pour dire que la réponse pourrait être formatée de façon à ce que ce qui fait partie de la réponse réelle et ce qui constitue une autre discussion soit clair. Le schéma mis en évidence ci-dessus est lié à la question de suivi mais pas à la réponse à la question réelle.
Baldur
26

Voici un exemple simple pour les autres qui visitent cet ancien message, mais qui est confondu par l'exemple de la question:

Livraison -> Paquet (un -> plusieurs)

CREATE TABLE Delivery(
    Id INT IDENTITY PRIMARY KEY,
    NoteNumber NVARCHAR(255) NOT NULL
)

CREATE TABLE Package(
    Id INT IDENTITY PRIMARY KEY,
    Status INT NOT NULL DEFAULT 0,
    Delivery_Id INT NOT NULL,
    CONSTRAINT FK_Package_Delivery_Id FOREIGN KEY (Delivery_Id) REFERENCES Delivery (Id) ON DELETE CASCADE
)

L'entrée avec la clé étrangère Delivery_Id (Package) est supprimée avec l'entité référencée dans la relation FK (Delivery).

Ainsi, lorsqu'une livraison est supprimée, les packages qui la référencent seront également supprimés. Si un package est supprimé, aucune livraison ne se produit.

Morten Holmgaard
la source
Merci pour l'exemple facile à comprendre!
Tom Spencer