Kiedy używać „ON UPDATE CASCADE”

420

Używam „ON DELETE CASCADE” regularnie, ale nigdy nie używam „ON UPDATE CASCADE”, ponieważ nie jestem pewien, w jakiej sytuacji będzie to przydatne.

Dla celów dyskusji zobaczmy trochę kodu.

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

W przypadku „PRZY USUWANIU KASKADY”, jeśli rodzic nadrzędny z idzostanie usunięty, zapis podrzędny z parent_id = parent.idzostanie automatycznie usunięty. To nie powinno być problemu.

  1. Oznacza to, że „ON UPDATE CASCADE” zrobi to samo, gdy idrodzic zostanie zaktualizowany?

  2. Jeśli (1) jest prawdą, oznacza to, że nie ma potrzeby używania opcji „ON UPDATE CASCADE”, jeśli parent.idnie można jej aktualizować (lub nigdy nie będzie aktualizowana), tak jak ma to miejsce AUTO_INCREMENTlub zawsze jest ustawione TIMESTAMP. Czy to prawda?

  3. Jeśli (2) nie jest prawdziwe, w jakiej innej sytuacji powinniśmy użyć „ON UPDATE CASCADE”?

  4. Co się stanie, jeśli (z jakiegoś powodu) zaktualizuję child.parent_idcoś, co nie istnieje, czy zostanie to automatycznie usunięte?

Cóż, wiem, niektóre z powyższych pytań można przetestować programowo, aby je zrozumieć, ale chcę również wiedzieć, czy którekolwiek z nich jest zależne od dostawcy bazy danych.

Proszę rzucić trochę światła.

NawaMan
źródło
1
Zobacz także: stackoverflow.com/questions/6894162/…
Xiè Jìléi

Odpowiedzi:

468

Prawdą jest, że jeśli twój klucz podstawowy jest tylko automatycznie zwiększaną wartością tożsamości, nie miałbyś prawdziwego zastosowania do ON UPDATE CASCADE.

Załóżmy jednak, że kluczem podstawowym jest 10-cyfrowy kod kreskowy UPC, a ze względu na rozszerzenie musisz go zmienić na 13-cyfrowy kod kreskowy UPC. W takim przypadku NA AKTUALIZACJI KASKADA umożliwi zmianę wartości klucza podstawowego, a wszelkie tabele zawierające odwołania do klucza obcego do tej wartości zostaną odpowiednio zmienione.

W odniesieniu do # 4, jeśli zmienisz identyfikator podrzędny na coś, co nie istnieje w tabeli nadrzędnej (i masz integralność referencyjną), powinieneś otrzymać błąd klucza obcego.

C-Funt Guru
źródło
6
Po prostu musiałem użyć ON UPDATE CASCADEsiebie, aby zaktualizować klucze podstawowe w starej tabeli, która nie korzysta z klucza automatycznie zwiększanego
BlueRaja - Danny Pflughoeft
86
  1. Tak, oznacza to, że na przykład, jeśli zrobisz UPDATE parent SET id = 20 WHERE id = 10wszystkie dzieci, Parent_id's z 10 również zostanie zaktualizowany do 20

  2. Jeśli nie zaktualizujesz pola, do którego odnosi się klucz obcy, to ustawienie nie jest potrzebne

  3. Nie mogę wymyślić żadnego innego zastosowania.

  4. Nie możesz tego zrobić, ponieważ ograniczenie klucza obcego zawiódłoby.

Zed
źródło
29

Myślę, że prawie nabiłeś punktów!

Jeśli postępujesz zgodnie z najlepszymi praktykami dotyczącymi projektowania baz danych, a klucz podstawowy nigdy nie jest aktualizowalny (co moim zdaniem powinno zawsze tak być), to tak naprawdę nigdy nie potrzebujesz ON UPDATE CASCADEklauzuli.

Zed miał rację , że jeśli użyjesz klucza naturalnego (np. Zwykłego pola z tabeli bazy danych) jako klucza podstawowego, mogą zaistnieć sytuacje, w których musisz zaktualizować klucze podstawowe. Innym niedawnym przykładem byłby ISBN (Międzynarodowe Standardowe Numery Książek), który nie tak dawno zmienił się z 10 na 13 cyfr + znaków.

Nie dzieje się tak, jeśli zdecydujesz się użyć kluczy zastępczych (np. Sztucznie wygenerowanych przez system) jako klucza podstawowego (który byłby moim preferowanym wyborem we wszystkich, oprócz najrzadszych).

Na koniec: jeśli twój klucz podstawowy nigdy się nie zmienia, to nigdy nie potrzebujesz ON UPDATE CASCADEklauzuli.

Marc

marc_s
źródło
Co to są klucze „sztucznie generowane przez system”? UUID?
HPWD,
1
@HPWD: tylko „sztuczny” klucz (wartość, która nie jest oparta na twoich danych lub nie jest z nich uzyskana), który jest generowany przez system - może to być GUID, INT, BIGINT - lub cokolwiek innego - nie nie ważne. Chodzi o to, że ta wartość nie jest w żaden sposób powiązana z twoimi własnymi, rzeczywistymi danymi - a system automatycznie generuje tę wartość dla ciebie.
marc_s
@ marc-s dziękuję za poświęcenie czasu na napisanie tego. Twoja odpowiedź miała doskonały sens.
HPWD,
2
Moim zdaniem jednokolumnowa tabela z naturalnymi kluczami jest dobrą i czystą alternatywą dla wyliczeń (przynajmniej w wersjach MySQL DB). Na przykład, pod uwagę tabelę colorsz wierszy blue, purple, yelloworaz stół productsz product_colorkolumny jest FK'ed do colorstabeli. Ogranicza to opcje jak wyliczanie, ale w przeciwieństwie do liczby całkowitej z auto-inkrementacją nie wymaga łączenia, aby uzyskać nazwę koloru. W takim przypadku on update cascadejest dobrym pomysłem, jeśli zdecydujesz, że zamiast tego purplenależy zadzwonić violet.
okdewit
18

Kilka dni temu miałem problem z wyzwalaczami i doszedłem do wniosku, że ON UPDATE CASCADEmoże to być przydatne. Spójrz na ten przykład (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
);

W moim wydaniu musiałem zdefiniować dodatkowe operacje (wyzwalacz) do aktualizacji tabeli koncertu. Operacje te musiały zmodyfikować nazwę klubu i nazwę zespołu. Nie mogłem tego zrobić z powodu odniesienia. Nie mogłem modyfikować koncertu, a następnie radzić sobie ze stołami klubowymi i zespołowymi. Nie mógłbym tego zrobić również w drugą stronę. ON UPDATE CASCADEbył kluczem do rozwiązania problemu.

Ariel Grabijas
źródło
3
Dobry komentarz Uważam, że kaskada aktualizacji jest również przydatna, w każdym razie musisz zmienić swój identyfikator. Zgadzam się również z innymi, że ta zmiana nie powinna być tak typowa. Na przykład, w przypadku cytowania, myślę, że w dużych ilościach danych, być może powiązanie kluczy obcych za pomocą pól tekstowych może nie spowodować najszybszej wydajności silnika bazy danych. Zauważ, że jeśli relacja zagraniczna na stole koncertowym używa club.SERIAL i zespołu.SERIAL, zmiany nazwy nie wpłyną na relację między stołami. Uważam jednak, że ON UPDATE CASCADE jest doskonałym narzędziem do rozwiązywania sytuacji awaryjnych. Pozdrawiam
David L
4
Jest to jednak wątpliwy projekt, który stanowi raczej wymyślny przykład. Jaki jest sens utrzymywania dwóch SERIALkolumn clubi bandjako kluczy pierwotnych, jeśli odwołać nameS zamiast klucza podstawowego każdego stołu?
sm
Krótko mówiąc, jest to przydatne, jeśli duplikujesz pole z innej tabeli i potrzebujesz go zaktualizować.
Kamil Tomšík,
4

Mój komentarz odnosi się głównie do punktu 3: w jakich okolicznościach NA ZAKTUALIZOWANIU KASKADA ma zastosowanie, jeśli zakładamy, że klucz nadrzędny nie jest aktualizowany? Oto jeden przypadek.

Mam do czynienia ze scenariuszem replikacji, w którym wiele satelitarnych baz danych należy połączyć z masterem. Każdy satelita generuje dane na tych samych tabelach, więc scalenie tabel z modułem głównym prowadzi do naruszenia ograniczenia wyjątkowości. Próbuję użyć ON UPDATE CASCADE jako części rozwiązania, w którym ponownie zwiększam klucze podczas każdego scalania. PRZY AKTUALIZACJI KASKADA powinna uprościć ten proces, automatyzując jego część.

ted.strauss
źródło
3

To doskonałe pytanie, miałem to samo pytanie wczoraj. Myślałem o tym problemie, w szczególności WYSZUKIWANIU, jeśli istniało coś takiego jak „ON UPDATE CASCADE” i na szczęście projektanci SQL również o tym pomyśleli. Zgadzam się z Ted.strauss, a także skomentowałem sprawę Norana.

Kiedy go użyłem? Jak wskazał Ted, kiedy traktujesz kilka baz danych jednocześnie, a modyfikacja jednej z nich, w jednej tabeli, ma jakiekolwiek reprodukcje w czymś, co Ted nazywa „satelitarną bazą danych”, nie może być przechowywane z bardzo oryginalnym Identyfikator i z jakiegokolwiek powodu musisz utworzyć nowy, na wypadek, gdybyś nie mógł zaktualizować danych na starym (na przykład ze względu na uprawnienia lub jeśli szukasz szybkości w sprawie, która jest tak efemeryczna, że nie zasługuje na absolutny i całkowity szacunek dla ogólnych zasad normalizacji, po prostu dlatego, że będzie to bardzo krótkotrwała użyteczność)

Zgadzam się więc w dwóch punktach:

(A.) Tak, w wielu przypadkach lepszy projekt może tego uniknąć; ALE

(B.) W przypadku migracji, replikacji baz danych lub rozwiązywania sytuacji awaryjnych jest to WIELKIE NARZĘDZIE, które na szczęście było tam, kiedy szukałem, czy istnieje.

David L.
źródło