Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Ograniczenia klucza obcego:kiedy używać ON UPDATE i ON DELETE?

Nie wahaj się nakładać ograniczeń na bazę danych. Będziesz mieć pewność, że będziesz mieć spójną bazę danych, a to jeden z dobrych powodów, aby korzystać z bazy danych. Zwłaszcza jeśli masz kilka aplikacji, które tego żądają (lub tylko jedną aplikację, ale z trybem bezpośrednim i trybem wsadowym korzystającym z różnych źródeł).

W MySQL nie masz zaawansowanych ograniczeń, jakie miałbyś w PostgreSQL, ale przynajmniej ograniczenia dotyczące kluczy obcych są dość zaawansowane.

Weźmy na przykład tabelę firmową z tabelą użytkowników zawierającą osoby z tej firmy

CREATE TABLE COMPANY (
     company_id INT NOT NULL,
     company_name VARCHAR(50),
     PRIMARY KEY (company_id)
) ENGINE=INNODB;

CREATE TABLE USER (
     user_id INT, 
     user_name VARCHAR(50), 
     company_id INT,
     INDEX company_id_idx (company_id),
     FOREIGN KEY (company_id) REFERENCES COMPANY (company_id) ON...
) ENGINE=INNODB;

Spójrzmy na PO AKTUALIZACJI klauzula:

  • OGRANICZENIE AKTUALIZACJI :domyślny :jeśli spróbujesz zaktualizować identyfikator firmy w tabeli COMPANY, silnik odrzuci operację, jeśli co najmniej jeden UŻYTKOWNIK łączy się z tą firmą.
  • PO AKTUALIZACJI ŻADNEJ AKCJI :tak samo jak RESTRICT.
  • PO KASKADZIE AKTUALIZACJI :zazwyczaj najlepszy :jeśli zaktualizujesz Company_id w wierszu tabeli COMPANY, silnik zaktualizuje go odpowiednio we wszystkich wierszach USER odwołujących się do tej COMPANY (ale żadne wyzwalacze nie są aktywowane w tabeli USER, ostrzeżenie). Silnik będzie śledzić zmiany za Ciebie, to dobrze.
  • NULL USTAWIENIA AKTUALIZACJI :jeśli zaktualizujesz company_id w wierszu tabeli COMPANY, silnik ustawi powiązanych USER company_id na NULL (powinien być dostępny w polu USER company_id). Nie widzę nic ciekawego, co mogłoby z tym zrobić w aktualizacji, ale mogę się mylić.

A teraz na PO USUNIĘCIU strona:

  • PO USUNIĘCIU OGRANICZENIA :domyślny :jeśli spróbujesz usunąć identyfikator firmy z tabeli FIRMA, silnik odrzuci operację, jeśli co najmniej jeden UŻYTKOWNIK łączy się z tą firmą, może uratować ci życie.
  • PO USUNIĘCIU ŻADNEJ AKCJI :tak samo jak OGRANICZENIE
  • PO USUWANIU KASKADY :niebezpieczne :jeśli usuniesz wiersz firmy w tabeli COMPANY, silnik usunie również powiązanych UŻYTKOWNIKÓW. Jest to niebezpieczne, ale może być użyte do automatycznego czyszczenia tabel pomocniczych (więc może to być coś, czego chcesz, ale na pewno nie dla przykładu FIRMA<->UŻYTKOWNIK)
  • PO USUNIĘCIU ZESTAW NULL :garść :jeśli usuniesz wiersz COMPANY, powiązani UŻYTKOWNICY automatycznie będą mieli związek z NULL. Jeśli wartość Null jest twoją wartością dla użytkowników bez firmy, może to być dobre zachowanie, na przykład może musisz zatrzymać użytkowników w swojej aplikacji jako autorów niektórych treści, ale usunięcie firmy nie stanowi dla ciebie problemu.

zwykle moje ustawienie domyślne to:POD USUWANIE OGRANICZENIE PRZY KASKADZIE AKTUALIZACJI . z niektórymi ON DELETE CASCADE dla tabel śledzenia (dzienniki -- nie wszystkie logi --, tego typu rzeczy) i ON DELETE SET NULL gdy tabela główna jest „prostym atrybutem” dla tabeli zawierającej klucz obcy, jak tabela JOB dla tabeli USER.

Edytuj

Minęło dużo czasu, odkąd to napisałem. Teraz myślę, że powinienem dodać jedno ważne ostrzeżenie. MySQL ma jedno duże udokumentowane ograniczenie związane z kaskadami. Kaskady nie uruchamiają wyzwalaczy . Więc jeśli byłeś wystarczająco pewny w tym silniku, aby używać wyzwalaczy, powinieneś unikać ograniczeń kaskadowych.

==> Zobacz poniżej ostatnią zmianę, rzeczy się poruszają w tej domenie

I nie sądzę, że zostanie to kiedyś naprawione. Ograniczenia klucza obcego są zarządzane przez magazyn InnoDb, a wyzwalacze są zarządzane przez silnik MySQL SQL. Oba są rozdzielone. Innodb to jedyna pamięć masowa z zarządzaniem ograniczeniami, być może pewnego dnia doda ona wyzwalacze bezpośrednio w silniku pamięci masowej, a może nie.

Ale mam własne zdanie na temat tego, który element należy wybrać między słabą implementacją wyzwalacza a bardzo przydatną obsługą ograniczeń kluczy obcych. A kiedy już przyzwyczaisz się do spójności bazy danych, pokochasz PostgreSQL.

12/2017-Aktualizacja tej edycji o MySQL:

jak stwierdził @IstiaqueAhmed w komentarzach, sytuacja na ten temat uległa zmianie. Więc kliknij link i sprawdź aktualną sytuację (która może się zmienić w przyszłości).



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Błąd krytyczny MySQL:nie można otworzyć i zablokować tabel uprawnień:Nieprawidłowy format pliku „użytkownik”

  2. MySQL INSERT IF (niestandardowe instrukcje if)

  3. Wybierz Wszystkie wydarzenia z wydarzeniem->Harmonogram->Data między datą rozpoczęcia i zakończenia w CakePHP

  4. Skuteczne ustalanie, czy firma jest otwarta, czy nie, na podstawie godzin pracy sklepu

  5. Jak radzić sobie z ogromnymi długościami linii stworzonymi przez mysqldump