Різниця між видаленням каскаду та оновленням каскаду в mysql


45

У мене є дві таблиці в MySQL database- parent, child. Я намагаюся додати іноземні ключові посилання до таблиці моєї дитини на основі батьківської таблиці. Чи є істотна різниця між ON UPDATE CASCADEтаON DELETE CASCADE

Мій батьківський стіл

CREATE TABLE parent (
    id INT NOT NULL,
    PRIMARY KEY (id)
) ENGINE=INNODB;

Моє запитання: Яка різниця між наступними запитами sql.

  1. ON DELETE CASCADE

    CREATE TABLE child (
        id INT, 
        parent_id INT,
        INDEX par_ind (parent_id),
        FOREIGN KEY (parent_id) 
            REFERENCES parent(id)
            ON DELETE CASCADE
    ) ENGINE=INNODB;
  2. ON UPDATE CASCADE

    CREATE TABLE child (
        id INT, 
        parent_id INT,
        INDEX par_ind (parent_id),
        FOREIGN KEY (parent_id) 
            REFERENCES parent(id)
            ON UPDATE CASCADE
    ) ENGINE=INNODB;
  3. ON UPDATE CASCADE ON DELETE CASCADE

    CREATE TABLE child (
            id INT, 
            parent_id INT,
            INDEX par_ind (parent_id),
            FOREIGN KEY (parent_id) 
                REFERENCES parent(id)
                ON UPDATE CASCADE ON DELETE CASCADE
        ) ENGINE=INNODB;

Чи є якісь помилки у запитах? Що означають ці запити (1,2 та 3) ?? Вони однакові ???


1
ps <nitpick> для повноти, те, про що ви говорите вище, - це заяви DDL (мова визначення даних) , а не запити. Запитом прийнято вважати DML (мова маніпуляції даними SELECT, INSERT, UPDATE, DELETE) </nitpick>
Vérace,

Ще один ps для повноти, я задумався, що таке за замовчуванням. Тому я створив дитину без оновлення чи видалення. Потім трапляється те, що ви не можете ні оновлювати, ні видаляти батьків, у яких є залежна дитина. Це має ідеальний сенс, однак MySQL не завжди є моделлю саме цієї характеристики :-)
Vérace

Відповіді:


64

Дуже гарну тему на цю тему можна знайти тут і тут . Остаточне керівництво для MySQL - це, звичайно, документація, яку можна знайти тут .

У стандарті SQL 2003 є 5 різних референтних дій:

  1. КАСКАД
  2. ОБМЕЖЕННЯ
  3. НІЯКИХ ДІЙ
  4. Встановити NULL
  5. ВСТАНОВИТИ ЗА ЗАМОВЧУВАННЯМ

Щоб відповісти на запитання:

  1. КАСКАД

    • ON DELETE CASCADEозначає, що якщо батьківський запис видалено, будь-які дочірні записи також видаляються. На мою думку, це не дуже гарна ідея. Ви повинні відслідковувати всі дані, які коли-небудь були в базі даних, хоча це можна зробити за допомогою TRIGGERs. (Однак дивіться застереження в коментарях нижче).

    • ON UPDATE CASCADEозначає, що якщо батьківський первинний ключ буде змінено, дочірнє значення також зміниться для відображення цього. Знову на мою думку, не чудова ідея. Якщо ви змінюєте PRIMARY KEYs з будь-якою регулярністю (або навіть взагалі!), У вашому дизайні щось не так. Знову дивіться коментарі.

    • ON UPDATE CASCADE ON DELETE CASCADEозначає, що якщо ви UPDATE АБО DELETE батько, зміна каскадується для дитини. Це еквівалент ANDрезультатів перших двох тверджень.

  2. ОБМЕЖЕННЯ

    • RESTRICTозначає, що будь-яка спроба видалити та / або оновити батьківську помилку не призведе до помилки. Це поведінка за замовчуванням у випадку, якщо референтна дія чітко не вказана.

      Для ON DELETEабо того, ON UPDATEщо не вказано, дія за замовчуванням завжди RESTRICT`.

  3. НІЯКИХ ДІЙ

    • NO ACTION: З посібника . Ключове слово зі стандартного SQL. У MySQL, що еквівалентно RESTRICT. MySQL Server відхиляє операцію видалення або оновлення для батьківської таблиці, якщо в посиланій таблиці є відповідне значення зовнішнього ключа. Деякі системи баз даних мають відкладені чеки і NO ACTIONє відкладеними чеками. У MySQL обмеження зовнішніх ключів перевіряються негайно, так NO ACTIONсамо як RESTRICT.
  4. Встановити NULL

    • SET NULL- знову з посібника. Видаліть або оновіть рядок із батьківської таблиці та встановіть стовпчик або стовпці з іноземним ключем у дочірній таблиці на NULL. Це не найкраща ідея ІМХО, насамперед тому, що немає способу "подорожувати часом" - тобто оглядатись у дочірні таблиці та пов'язувати записи з NULLs із відповідним батьківським записом - CASCADEабо використовувати TRIGGERs для заповнення таблиць реєстрації для відстеження зміни (але, дивіться коментарі).
  5. ВСТАНОВИТИ ЗА ЗАМОВЧУВАННЯМ

    • SET DEFAULT. Ще одна (потенційно дуже корисна) частина стандарту SQL, яку MySQL не намагався реалізувати! Дозволяє розробнику вказувати значення, на яке потрібно встановити стовпчик (и) із зовнішнім ключем на ОНОВЛЕННЯ або ВИДАЛЕННЯ. InnoDB і NDB відхилять визначення таблиці з SET DEFAULTпунктом.

Як було сказано вище, вам слід витратити деякий час на перегляд документації, тут .


8
Мені подобається ваша повна відповідь, проте я не згоден з цим твердженням. "Ви повинні відслідковувати всі дані, які коли-небудь були в базі даних" - це дійсно залежить від дизайну та цілей бази даних. Наприклад, визначення рецепту (я не говорю про їжу - більше схоже на конфігурації систем), коли визначення рецепту видалено, немає сенсу зберігати асоційованих дітей цього рецепту - це просто роздуває db без причини. Також працюйте таблиці для машинних систем - мені дані вже не потрібні; обробляти і позбуватися від нього. Крім того, ваша відповідь є фантастичною.
StixO

2
подібний до @StixO. Мені подобається ця відповідь, але я маю згоду зі зміною первинного ключа. Однозначно існують конструкції, де це було б поганою ідеєю, але коли ви потрапляєте в розподілену базу даних, може бути дуже бажано, щоб первинні ключі могли бути перепризначені без втрати ідентичності запису.
Гарет Клаборн

"На мою думку, це не дуже гарна ідея. Ви повинні відслідковувати всі дані, які коли-небудь були в базі даних." - Не впевнений, що я розумію вашу думку. Якщо ви робите каскад "видалити", то ви вже вирішили, що вам потрібно щось видалити. Якщо ви вирішите ніколи нічого не видаляти, нічого не буде каскадно. Перевага від того, що це є, полягає в тому, що у вашій програмі ви можете бути впевнені, що, шукаючи запис із закордонним ідентифікатором, ви знаєте, що він буде там, і у вас не буде жодних сирітських рядків, що роздувають вашу базу даних, якщо ви вирішите видалити щось.
Джефф Райан

Логіка тут досить непомітна місцями, а тим більше в нашому новому світі GDPR. Я погоджуюся з думкою, що якщо первинні ключі змінюються, то це може бути ознакою чогось неправильного.
Чак Ле Бут

Якщо ви змінюєте ОСНОВНІ КЛЮЧІ з будь-якою регулярністю (або навіть взагалі!), У вашому дизайні щось не так. Ви маєте на увазі ON UPDATE CASCADE змінити значення ключа або назву ключа?
Billal Begueradj

8

Ці два дії, які слід виконати відповідно, коли згаданий запис у батьківській таблиці змінює свій ідентифікатор та коли він видаляється.

Якщо ви виконуєте:

UPDATE parent SET id = -1 WHERE id = 1;

І є щонайменше один запис childз parent_id = 1, 1) не вдасться; у випадках 2) та 3) усі записи з parent_id = 1 оновлюються до parent_id = -1.

Якщо ви виконуєте:

DELETE FROM parent WHERE id = 1;

І є щонайменше один запис childз parent_id = 1, 2) не вдасться; у випадках 1) та 3) усі записи з parent_id = 1видаляються.

3) синтаксично правильний.

Повну документацію можна знайти в посібнику .


6

У мене недостатньо репутації, щоб коментувати попередні відповіді. Тож я подумав, що трохи допрацюю.

1) ON DELETE CASCADE означає, що якщо батьківський запис видалено, то будь-які довідні записи також видаляються. ON UPDATE за замовчуванням RESTRICT, що означає, що UPDATE в батьківській записі не вдасться.

2) У ВІДКЛЮЧЕННІ за замовчуванням для дії RESTRICT, що означає ВИБРАТИ в батьківській записі не вдасться. ON UPDATE CASCADE оновить усі посилання на дочірні записи, коли оновлений батьківський запис.

3) Дивіться дії CASCADE в пунктах 1) та 2) вище.

Про використання ідентифікаторів батьківських записів як іноземних ключів (у дочірніх таблицях) - досвід говорить а) якщо ідентифікатори автоматично генеруються порядкові номери, то НЕ використовуйте їх як сторонні ключі. Використовуйте замість цього інший унікальний батьківський ключ. б) якщо ідентифікатори - це GUID, тоді добре використовувати їх як сторонні ключі. Мудрість у цій пропозиції ви побачите під час експорту та імпорту записів чи копіювання записів до іншої бази даних. Це занадто громіздко мати справу з автоматично згенерованими порядковими номерами під час міграції даних, коли вони посилаються на сторонні ключі.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.