SQL ON DELETE CASCADE, auf welche Weise erfolgt das Löschen?

156

Wenn ich zwei Beziehungen in einer Datenbank habe, wie folgt:

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

und ich stelle eine Fremdschlüsselbeziehung zwischen den beiden her, wie folgt:

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

Dann können Sie sehen, dass das CourseAttribut in der BookCoursesBeziehung auf das CodeAttribut in der CoursesBeziehung verweist .

Meine Frage ist, wann eine Löschung in einer der beiden Beziehungen auftritt. Auf welche Weise kaskadiert die Löschung? Wenn ich ein Tupel in der CoursesBeziehung lösche, werden dann alle referenzierenden Tupel in der BookCoursesBeziehung gelöscht , oder ist es umgekehrt?

Oliver Spryn
quelle
11
Man wundert sich nur, warum die CategoriesTabelle einen CourseIDals Primärschlüssel hat, während die CoursesTabelle den hat EntryID. Sie müssen Ihre Namensentscheidungen ernsthaft überdenken.
Ypercubeᵀᴹ
7
Bitte verwenden Sie die richtigen Spaltennamen, um Verwirrung zu vermeiden und die DB-Struktur zu löschen.
Gunjan Shah

Antworten:

185

Cascade funktioniert, wenn Sie etwas in der Tabelle löschen Courses. Jeder Datensatz in einer Tabelle BookCourses, der auf eine Tabelle verweist, Courseswird automatisch gelöscht.

Wenn Sie jedoch versuchen, eine Tabelle zu löschen, ist BookCoursesnur die Tabelle selbst betroffen und nicht dieCourses

Anschlussfrage: Warum haben Sie CourseIDauf Tabelle Kategorie?

Vielleicht sollten Sie Ihr Schema in dieses umstrukturieren,

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
quelle
5
Toll! Danke dir. Follow-up-Antwort: Weil ich es mir überlegt habe. Jetzt
behoben
59
Diese Antwort hat andere Tabellennamen und -strukturen als die Frage ... Dies macht sie weitaus weniger nützlich.
Daniel Beardsley
4
@ DanielBeardsley, ich stimme nicht zu, dass diese Antwort nicht nützlich ist. Das ist, wenn Sie lesen, was es sagt. Ich stimme jedoch zu, dass die Antwort formatiert werden könnte, sodass klar ist, was Teil der eigentlichen Antwort ist und was eine andere Diskussion ist. Das oben hervorgehobene Schema bezieht sich auf die Folgefrage , nicht jedoch auf die Antwort auf die eigentliche Frage.
Baldur
26

Hier ist ein einfaches Beispiel für andere, die diesen alten Beitrag besuchen, aber das Beispiel in der Frage verwirrt:

Lieferung -> Paket (Eins -> Viele)

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
)

Der Eintrag mit dem Fremdschlüssel Delivery_Id (Package) wird mit der referenzierten Entität in der FK-Beziehung (Delivery) gelöscht.

Wenn also eine Lieferung gelöscht wird, werden auch die Pakete, auf die verwiesen wird, gelöscht. Wenn ein Paket gelöscht wird, passiert nichts mit Lieferungen.

Morten Holmgaard
quelle
Vielen Dank für das leicht verständliche Beispiel!
Tom Spencer