Когда использовать "ON UPDATE CASCADE"

Я использую "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
);

Для "ВКЛ. УДАЛИТЬ КАСКАД", если родитель с id удален, запись в дочернем элементе с parent_id = parent.id будет автоматически удалена. Это не должно быть проблемой.

  • Это означает, что "ON UPDATE CASCADE" будет делать то же самое, когда обновляется id родителя?

  • Если (1) истинно, это означает, что нет необходимости использовать "ON UPDATE CASCADE", если parent.id не обновляется (или никогда не обновляется), например, когда он равен AUTO_INCREMENT или всегда значение TIMESTAMP. Это правильно?

  • Если (2) неверно, в какой другой ситуации мы должны использовать "ON UPDATE CASCADE"?

  • Что делать, если я (по какой-то причине) обновляю child.parent_id, чтобы быть чем-то не существующим, будет ли он автоматически удален?

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

Просветите свет.

Ответ 1

Верно, что если ваш первичный ключ - это просто значение, автоматически увеличиваемое, вы бы не использовали его для ON UPDATE CASCADE.

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

В отношении # 4, если вы измените дочерний ID на то, что не существует в родительской таблице (и у вас есть ссылочная целостность), вы должны получить ошибку внешнего ключа.

Ответ 2

  • Да, это означает, что, например, если вы делаете UPDATE parent SET id = 20 WHERE id = 10, все дети parent_id из 10 также будут обновлены до 20

  • Если вы не обновляете поле, на которое ссылается внешний ключ, этот параметр не нужен

  • Нельзя думать о другом использовании.

  • Вы не можете сделать это, поскольку ограничение внешнего ключа завершится с ошибкой.

Ответ 3

Я думаю, что вы довольно много прикрепили точки!

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

Zed сделал хороший вывод, что если вы используете в качестве основного ключа натуральный (например, регулярное поле из таблицы базы данных), то может быть определен ситуации, когда вам нужно обновить основные ключи. Еще один недавний пример - это ISBN (Международные стандартные номера книг), который не так давно изменился с 10 до 13 цифр + символов.

Это не тот случай, если вы решите использовать суррогатный (например, искусственно сгенерированный системой) ключ в качестве основного ключа (который был бы моим предпочтительным выбором во всех, кроме самых редких случаев).

Итак, в конце: если ваш первичный ключ никогда не изменяется, вам никогда не понадобится предложение ON UPDATE CASCADE.

Марк

Ответ 4

Несколько дней назад у меня была проблема с триггерами, и я понял, что 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 был ключом к решению проблемы.

Ответ 5

Мой комментарий в основном относится к пункту № 3: при каких обстоятельствах ON UPDATE CASCADE применим, если мы предполагаем, что родительский ключ не является обновляемым? Вот один случай.

Я имею дело с сценарием репликации, в котором несколько спутниковых баз данных необходимо объединить с мастером. Каждый спутник генерирует данные в одних и тех же таблицах, поэтому слияние таблиц с мастером приводит к нарушениям ограничений уникальности. Я пытаюсь использовать ON UPDATE CASCADE как часть решения, в котором я повторно увеличиваю ключи во время каждого слияния. ON UPDATE CASCADE должен упростить этот процесс, автоматизируя часть процесса.

Ответ 6

Это отличный вопрос, вчера у меня был тот же вопрос. Я подумал об этой проблеме, в частности, ПОИСКОМ, если существует нечто вроде "ON UPDATE CASCADE", и, к счастью, разработчики SQL также подумали об этом. Я согласен с Ted.strauss, и я также прокомментировал дело Норана.

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

Итак, я согласен в двух моментах:

(A). Да, во многих случаях лучший дизайн может избежать этого; НО

(B.) В случаях миграции, репликации баз данных или решения чрезвычайных ситуаций это БОЛЬШОЙ ИНСТРУМЕНТ, который, к счастью, был там, когда я пошел искать, если он существует.