Коли використовувати “ON UPDATE CASCADE”


420

Я використовую "ON DELETE CASCADE" регулярно, але ніколи не використовую "ON UPDATE CASCADE", оскільки я не дуже впевнений, у якій ситуації це буде корисно.

Заради обговорення давайте подивіться якийсь код.

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

У розділі "ON DELETE CASCADE", якщо батько із запитом idвидалено, запис у дитини, що має, parent_id = parent.idбуде автоматично видалений. Це не повинно бути жодних проблем.

  1. Це означає, що "ON UPDATE CASCADE" зробить те саме, коли idоновлення батьків буде оновлено?

  2. Якщо (1) вірно, це означає, що немає необхідності використовувати "ON UPDATE CASCADE", якщо parent.idвін не може бути оновлений (або ніколи не буде оновлюватися), як коли він є AUTO_INCREMENTабо завжди встановлений TIMESTAMP. Це так?

  3. Якщо (2) не відповідає дійсності, в якій іншій ситуації ми повинні використовувати "НА ПОНОВНІЙ КАСКАД"?

  4. Що робити, якщо я (з якихось причин) оновлюю файл на child.parent_idщось, що не існує, воно буде автоматично видалено?

Ну, я знаю, деякі з питань, поданих вище, можна перевірити програмно, щоб зрозуміти, але я також хочу знати, чи щось від цього залежить від постачальника баз даних чи ні.

Будь ласка, пролийте трохи світла.


Відповіді:


468

Це правда, що якщо ваш первинний ключ є лише автоматичним збільшенням значення ідентичності, ви не матимете реального використання для ПОНОВНОГО КАСКАДУ.

Однак скажімо, що ваш основний ключ - це 10-значний штрих-код UPC, і через розширення вам потрібно змінити його на 13-значний штрих-код UPC. У такому випадку ON UPDATE CASCADE дозволить вам змінити значення первинного ключа, і будь-які таблиці, які мають посилання на зовнішній ключ, будуть змінені відповідно.

Посилаючись на №4, якщо ви зміните ідентифікатор дитини на те, що не існує в батьківській таблиці (і у вас є референтна цілісність), ви повинні отримати помилку із зовнішнім ключем.


6
Просто довелося використовувати ON UPDATE CASCADEсебе для оновлення первинних ключів у старій таблиці, в якій не використовується ключ з автоматичним збільшенням
BlueRaja - Danny Pflughoeft,

86
  1. Так, це означає, що, наприклад, якщо ви робите UPDATE parent SET id = 20 WHERE id = 10всіх дітей parent_id з 10, також буде оновлено до 20

  2. Якщо ви не оновлюєте поле, на яке посилається зовнішній ключ, це налаштування не потрібно

  3. Не можу придумати жодного іншого використання.

  4. Ви не можете цього зробити, оскільки обмеження зовнішнього ключа не вдасться.


29

Я думаю, ти вже майже прибив очки!

Якщо ви дотримуєтесь найкращих практик проектування баз даних, і ваш первинний ключ ніколи не оновлюється (що, на мою думку, все одно має бути так), тоді ця ON UPDATE CASCADEпропозиція ніколи не потрібна .

Зед наголосив на тому, що якщо ви використовуєте природний ключ (наприклад, звичайне поле з таблиці бази даних) як свій основний ключ, то можуть виникнути певні ситуації, коли вам потрібно оновити свої первинні ключі. Іншим останнім прикладом може бути ISBN (Міжнародні стандартні книжкові номери), який не так давно змінився від 10 до 13 цифр + символів.

Це не так, якщо ви вирішили використовувати сурогатні (наприклад, штучно згенеровані системою) ключі в якості основного ключа (що було б моїм кращим вибором у всіх, крім самих рідкісних випадках).

Отже, врешті-решт: якщо ваш первинний ключ ніколи не змінюється, тоді вам ніколи не потрібне ON UPDATE CASCADEположення.

Марк


Що таке "штучно створені системи" ключі? UUID?
HPWD

1
@HPWD: просто "штучний" ключ (значення, яке не ґрунтується на фактичних даних та не походить від нього), що генерується системою - це може бути GUID, INT або BIGINT - або що-небудь справді - не має значення Неважливо. Суть полягає в тому, що це значення жодним чином не пов'язане з вашими власними, фактичними даними - і система автоматично генерує це значення для вас.
marc_s

@ marc-s дякую, що знайшли час, щоб виписати це. Ваша відповідь мала ідеальний сенс.
HPWD

2
Таблиця з одним стовпчиком з натуральними ключами є гарною та чистою альтернативою переліків на мою думку (принаймні, в ароматах MySQL DB). В якості прикладу розглянемо таблицю colorsз рядками blue, purple, yellow, і стіл productsз product_colorколонки, будучи FK'ed до colorsстолу. Це обмежує вибір на зразок перерахунку, але на відміну від ціле число, що збільшується автоматично, воно не вимагає з'єднання, щоб отримати ім'я кольору. У такому випадку, on update cascadeце гарна ідея, якщо ви вирішите, що purpleслід зателефонувати violetзамість цього.
okdewit

18

Кілька днів тому у мене виникла проблема з тригерами, і я зрозумів, що ON UPDATE CASCADEможе бути корисним. Погляньте на цей приклад (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
);

У своєму випуску мені довелося визначити деякі додаткові операції (тригер) для оновлення таблиці концерту. Ці операції повинні були змінити ім'я клубу та ім'я групи. Я не зміг цього зробити через довідку. Я не зміг змінити концерт, а потім мати справу з клубними та груповими столами. Я не міг зробити це інакше. ON UPDATE CASCADEбуло ключем до вирішення проблеми.


3
Хороший коментар. На каскаді оновлень я вважаю також корисним, у будь-якому випадку вам потрібно змінити свій ідентифікатор. Я також погоджуюся з іншими, що ця зміна не повинна бути настільки типовою. Наприклад, у випадку, який ви цитуєте, я думаю, що при великих обсягах даних, можливо, пов'язані зовнішні ключі з використанням текстових полів можуть не призвести до найшвидшої роботи двигуна бази даних. Зауважте, що якщо в зовнішньому співвідношенні за концертним столом використовуються club.SERIAL і band.SERIAL, зміни в назві не вплинуть на співвідношення між столами. Однак я вважаю, що ПОНОВНЕ КАСКАД є чудовим інструментом для вирішення надзвичайних ситуацій. З повагою
Девід L

4
Це сумнівна конструкція, яка дає досить надуманий приклад. Який сенс зберігати два SERIALстовпці у clubта bandв якості первинних ключів, якщо ви посилаєтесь на names замість первинного ключа кожної таблиці?
см

Коротше кажучи, це корисно, якщо ви дублюєте поле з іншої таблиці і вам потрібно, щоб воно було актуальним.
Каміль Томшик

4

Мій коментар в основному посилається на пункт №3: за яких обставин застосовується НАДНІЙ КАСКАД, якщо ми припускаємо, що батьківський ключ не можна оновити? Ось один випадок.

Я маю справу зі сценарієм реплікації, в якому кілька баз даних супутників потрібно об'єднати з ведучим. Кожен супутник генерує дані в одних і тих же таблицях, тому злиття таблиць з ведучим призводить до порушень обмеження унікальності. Я намагаюся використовувати ON UPDATE CASCADE як частину рішення, в якому я повторно збільшую ключі під час кожного злиття. НА ОНОВЛЕННЯ CASCADE повинен спростити цей процес, автоматизуючи частину процесу.


3

Це відмінне запитання, у мене було те саме питання вчора. Я подумав над цією проблемою, зокрема ПОШУК, якщо існувало щось на кшталт "ON UPDATE CASCADE", і, на щастя, дизайнери SQL також думали про це. Я погоджуюся з Ted.strauss, і я також прокоментував справу Норана.

Коли я ним користувався? Як зазначив Тед, коли ви обробляєте декілька баз даних одночасно, і модифікація в одній із них, в одній таблиці, має будь-яке відтворення в тому, що Тед називає "супутниковою базою даних", не може бути збережено з дуже оригінальним Ідентифікатор, і з будь-якої причини вам доведеться створити новий, якщо ви не можете оновити дані на старій (наприклад, через дозволи, або якщо ви шукаєте швидкість у випадку, який є настільки ефемерним, що не заслуговує на абсолютну і повну повагу до загальних правил нормалізації, просто тому, що це буде дуже недовговічною корисністю)

Отже, я згоден у двох пунктах:

(А.) Так, багато разів кращий дизайн може цього уникнути; АЛЕ

(B.) У випадках міграції, копіювання баз даних або вирішення надзвичайних ситуацій, ВЕЛИКИЙ ІНСТРУМЕНТ, який, на щастя, був там, коли я пішов шукати, чи існує.

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