Mysql
 sql >> база данни >  >> RDS >> Mysql

Ограничения за външния ключ:Кога да използвате ON UPDATE и ON DELETE

Не се колебайте да поставите ограничения върху базата данни. Ще бъдете сигурни, че имате последователна база данни и това е една от добрите причини да използвате база данни. Особено ако имате няколко приложения, които го изискват (или само едно приложение, но с директен режим и пакетен режим, използващи различни източници).

С MySQL нямате разширени ограничения, както бихте имали в postgreSQL, но поне ограниченията за външния ключ са доста напреднали.

Ще вземем пример, фирмена таблица с потребителска таблица, съдържаща хора от тези компании

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;

Нека да разгледаме АКТУАЛИЗИРАНЕ клауза:

  • С ОГРАНИЧЕНИЕТО НА АКТУАЛИЗИРАНЕТО :по подразбиране :ако се опитате да актуализирате company_id в таблица COMPANY, машината ще отхвърли операцията, ако поне един ПОТРЕБИТЕЛ постави връзки към тази компания.
  • ПРИ АКТУАЛИЗИРАНЕ НЯМА ДЕЙСТВИЕ :същото като RESTRICT.
  • В КАСКАДА ЗА АКТУАЛИЗИРАНЕ :най-добрият обикновено :ако актуализирате company_id в ред на таблица COMPANY, механизмът ще го актуализира съответно за всички USER редове, отнасящи се до тази КОМПАНИЯ (но няма активирани тригери в таблицата USER, предупреждение). Двигателят ще проследи промените вместо вас, добре е.
  • ПРИ АКТУАЛИЗИРАНЕ ЗАДАДЕТЕ НУЛВО :ако актуализирате company_id в ред на таблица COMPANY, механизмът ще зададе идентификатор на компанията на свързани ПОТРЕБИТЕЛИ на NULL (трябва да е наличен в полето USER company_id). Не виждам нищо интересно за това при актуализация, но може да греша.

И сега на ЗА ИЗТРИВАНЕ страна:

  • ЗА ОГРАНИЧЕНИЕ ЗА ИЗТРИВАНЕ :по подразбиране :ако се опитате да изтриете идентификатор на company_id в таблицата COMPANY, двигателят ще отхвърли операцията, ако един ПОТРЕБИТЕЛ поне линкове към тази компания, може да ви спаси живота.
  • ПРИ ИЗТРИВАНЕ НЯМА ДЕЙСТВИЕ :същото като RESTRICT
  • ЗА ИЗТРИВАНЕ НА КАСКАДА :опасно :ако изтриете фирмен ред в таблица COMPANY, двигателят ще изтрие и свързаните ПОТРЕБИТЕЛИ. Това е опасно, но може да се използва за автоматично почистване на вторични таблици (така че може да е нещо, което искате, но със сигурност не за КОМПАНИЯ<->ПОТРЕБИТЕЛ пример)
  • ЗА ИЗТРИВАНЕ ЗАДАДЕТЕ НУЛВО :шепа :ако изтриете ред COMPANY, свързаните ПОТРЕБИТЕЛИ автоматично ще имат отношението NULL. Ако Null е вашата стойност за потребители без компания, това може да бъде добро поведение, например може би трябва да запазите потребителите в приложението си като автори на някакво съдържание, но премахването на компанията не е проблем за вас.

обикновено по подразбиране ми е:ЗА ОГРАНИЧЕНИЕ НА ИЗТРИВАНЕ ПРИ КАСКАДА НА АКТУАЛИЗИРАНЕ . с някои ON DELETE CASCADE за таблици за проследяване (регистрационни файлове--не всички регистрационни файлове--, неща като това) и ON DELETE SET NULL когато главната таблица е „прост атрибут“ за таблицата, съдържаща външния ключ, като таблица JOB за таблицата USER.

Редактиране

Мина много време, откакто го написах. Сега мисля, че трябва да добавя едно важно предупреждение. MySQL има едно голямо документирано ограничение с каскади. Каскадите не са задействащи задействания . Така че, ако сте били достатъчно уверени в този двигател, за да използвате тригери, трябва да избягвате каскадни ограничения.

==> Вижте по-долу последната редакция, нещата се движат в този домейн

И не мисля, че това ще се поправи един ден. Ограниченията на външния ключ се управляват от хранилището на InnoDb, а тригерите се управляват от MySQL SQL двигателя. И двамата са разделени. Innodb е единственото хранилище с управление на ограниченията, може би един ден те ще добавят тригери директно в механизма за съхранение, може би не.

Но имам собствено мнение за това кой елемент трябва да изберете между лошото изпълнение на тригера и много полезните поддържани ограничения за външни ключове. И след като свикнете с последователността на базата данни, ще харесате PostgreSQL.

12/2017-Актуализиране на тази редакция относно MySQL:

както е посочено от @IstiaqueAhmed в коментарите, ситуацията се промени по този въпрос. Затова следвайте връзката и проверете реалната актуална ситуация (която може да се промени отново в бъдеще).



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Тези две функции излишни ли са за дезинфекция?

  2. Изберете редове от таблица, където ред в друга таблица със същия идентификатор има определена стойност в друга колона

  3. Създайте таблица, ако не съществува от mysqldump

  4. Проектиране на събития за дата и час, които не се припокриват

  5. Командата Mysql не е намерена в OS X 10.7