Когда использовать " 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
);

для "on DELETE CASCADE", если родитель с id удаляется, запись в ребенком с parent_id = parent.id будет автоматически удален. Это не должно быть проблемой.

  1. это означает, что "ON UPDATE CASCADE" будет делать то же самое, когда id of родитель обновлен?

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

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

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

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

пожалуйста, пролейте свет.

6 ответов


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

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

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


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

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

  3. не могу придумать другого применения.

  4. вы не можете этого сделать, так как ограничение внешнего ключа не сработает.


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

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

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

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

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

Марк


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

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


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

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


Это отличный вопрос, у меня вчера был тот же вопрос. Я думал об этой проблеме, в частности, искал, существует ли что-то вроде "на каскаде обновлений", и, к счастью, дизайнеры SQL также подумали об этом. Я согласен с Тедом.Штраус и я также прокомментировали дело Норана.

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

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

(А.) Да, во многих раз лучший дизайн может избежать этого; но

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