Как работает внешний ключ Postgres «при обновлении» и «при удалении»? - PullRequest
21 голосов
/ 22 октября 2008

Кто-нибудь может дать четкое объяснение / пример того, что делают эти функции, и когда уместно их использовать?

Ответы [ 4 ]

25 голосов
/ 22 октября 2008

Прямо от инструкция ...

Мы знаем, что внешние ключи запрещают создание заказов, которые не относятся ни к каким продуктам. Но что, если продукт будет удален после создания заказа, который ссылается на него? SQL позволяет вам справиться и с этим. Интуитивно, у нас есть несколько вариантов:

Запретить удаление указанного продукта

Удалить также и заказы

Что-то еще?

CREATE TABLE order_items (
 product_no integer REFERENCES products ON DELETE RESTRICT,
 order_id integer REFERENCES orders ON DELETE CASCADE,
 quantity integer,
 PRIMARY KEY (product_no, order_id)
);

Ограничение и каскадное удаление являются двумя наиболее распространенными вариантами. RESTRICT предотвращает удаление указанной строки. НЕТ ДЕЙСТВИЯ означает, что если при проверке ограничения все еще существуют какие-либо ссылочные строки, возникает ошибка; это поведение по умолчанию, если вы ничего не указали. (Существенное различие между этими двумя вариантами заключается в том, что NO ACTION позволяет отложить проверку до более поздней стадии транзакции, а RESTRICT - нет.) CASCADE указывает, что при удалении ссылочной строки строки, ссылающиеся на нее, должны быть автоматически удалены также. Есть два других варианта: SET NULL и SET DEFAULT. Это приводит к тому, что ссылочные столбцы устанавливаются в нулевые значения или значения по умолчанию, соответственно, при удалении ссылочной строки. Обратите внимание, что это не освобождает вас от соблюдения каких-либо ограничений. Например, если действие указывает SET DEFAULT, но значение по умолчанию не удовлетворяет внешнему ключу, операция завершится неудачей.

По аналогии с ON DELETE также есть ON UPDATE, которая вызывается при изменении (обновлении) ссылочного столбца. Возможные действия одинаковы.

edit: Возможно, вы захотите взглянуть на этот связанный вопрос: Когда / Почему использовать каскадирование в SQL Server? . Концепции, лежащие в основе вопроса / ответов, одинаковы.

0 голосов
/ 08 июля 2010

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

0 голосов
/ 22 октября 2008

То, что Даок говорит, правда ... это может быть довольно удобно. С другой стороны, автоматическое выполнение действий в базе данных может быть реальной проблемой, особенно когда речь идет об удалении данных. Вполне возможно, что в будущем кто-то будет рассчитывать на то, что FK обычно предотвращают удаление родителей, когда есть дети, и не осознают, что использование каскада при удалении не только не предотвращает удаление, но и создает огромные объемы данных в десятках другие таблицы исчезают благодаря водопаду каскадных удалений.

@ Комментарий Артура.

Чем чаще «скрытые» вещи происходят в базе данных, тем меньше вероятность того, что кто-либо когда-либо будет хорошо разбираться в происходящем. Триггеры (и это, по сути, триггер) могут привести к тому, что мое простое действие по удалению строки будет иметь самые разные последствия для всей моей базы данных. Я выполняю оператор Delete, и на 17 таблиц влияют каскады триггеров и ограничений, и ни один из них не является очевидным для автора команды. OTOH, если я помещу удаление родителя и всех его потомков в процедуру, то для любого очень легко и ясно увидеть ТОЧНО, что произойдет, когда я выполню команду.

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

0 голосов
/ 22 октября 2008

У меня есть база данных PostGreSQL, и я использую «Удалить», когда у меня есть пользователь, которого я удаляю из базы данных, и мне нужно удалить его информацию из другой таблицы. Таким образом, мне нужно сделать только 1 удаление, и FK, который имеет ON удалить, удалит информацию из другой таблицы.

Вы можете сделать то же самое с ON Update. Если вы обновите таблицу и у поля появится FK с обновлением, если в FK внесено изменение, вы увидите заметку в таблице FK.

...