Как работает внешний ключ Postgres «при обновлении» и «при удалении»?

StackOverflow https://stackoverflow.com/questions/225881

Вопрос

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

Это было полезно?

Решение

Прямо из руководства ...

  

Мы знаем, что внешние ключи запрещают создание заказов, которые не относятся ни к каким продуктам. Но что, если продукт будет удален после создания заказа, который ссылается на него? 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? . Концепции, лежащие в основе вопроса / ответов, одинаковы.

Другие советы

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top