SQL ON DELETE CASCADE, w jaki sposób następuje usunięcie?

156

Jeśli mam dwie relacje w bazie danych, na przykład:

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

i ustalam relację klucza obcego między nimi, na przykład:

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

Wtedy możesz zobaczyć, że Courseatrybut w BookCoursesrelacji odwołuje się do Codeatrybutu w Coursesrelacji.

Moje pytanie brzmi: kiedy następuje usunięcie w którejkolwiek z dwóch relacji, w jaki sposób przebiega kaskada usuwania? Jeśli usunę krotkę w Coursesrelacji, czy spowoduje to usunięcie wszystkich odwołujących się krotek w BookCoursesrelacji, czy też jest odwrotnie?

Oliver Spryn
źródło
11
Można się tylko zastanawiać, dlaczego Categoriestabela ma CourseIDjako klucz podstawowy, podczas gdy Coursesstół ma EntryID. Musisz poważnie przemyśleć swoje wybory dotyczące nazewnictwa.
ypercubeᵀᴹ
7
Proszę używać odpowiednich nazw kolumn, aby uniknąć nieporozumień i przejrzystej struktury bazy danych.
Gunjan Shah

Odpowiedzi:

185

Kaskada zadziała, gdy usuniesz coś ze stołu Courses. Każdy rekord w tabeli, BookCoursesktóry ma odniesienie do tabeli, Courseszostanie automatycznie usunięty.

Ale kiedy próbujesz usunąć z tabeli, dotyczy to BookCoursestylko samej tabeli, a nieCourses

pytanie uzupełniające: dlaczego masz CourseIDkategorię tabeli?

Może powinieneś zmienić swój schemat w ten sposób,

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
źródło
5
Wspaniały! Dziękuję Ci. następna odpowiedź: Ponieważ przemyślałem to. Naprawiono teraz ... iw moim DB
Oliver Spryn
59
Ta odpowiedź ma inne nazwy i struktury tabel niż pytanie ... Co czyni ją znacznie mniej użyteczną.
Daniel Beardsley
4
@DanielBeardsley, nie zgadzam się, że ta odpowiedź jest nieprzydatna. To znaczy, jeśli przeczytasz, co mówi. Zgadzam się jednak, że odpowiedź może być sformatowana, aby było jasne, co jest częścią rzeczywistej odpowiedzi, a co jest inną dyskusją. Schemat wyróżniony powyżej odnosi się do pytania uzupełniającego, ale nie dotyczy odpowiedzi na pytanie rzeczywiste.
Baldur
26

Oto prosty przykład dla innych odwiedzających ten stary post, ale jest zdezorientowany przykładem w pytaniu:

Dostawa -> Pakiet (jeden -> wiele)

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
)

Wpis z kluczem obcym Delivery_Id (pakiet) jest usuwany z przywoływaną jednostką w relacji FK (dostawa).

W związku z tym, gdy przesyłka zostanie usunięta, związane z nią paczki również zostaną usunięte. Jeśli paczka zostanie usunięta, nic się nie stanie z żadną dostawą.

Morten Holmgaard
źródło
Dziękuję za łatwy do zrozumienia przykład!
Tom Spencer