Я читал об этом ключевом слове SQL DEFERRABLE
в книге «Системы баз данных - Полная книга» .
Последнее [NOT DEFERRABLE] используется по умолчанию и означает, что каждый раз, когда выполняется оператор модификации базы данных, ограничение проверяется сразу же после этого, если модификация может нарушить ограничение внешнего ключа.
Однако, если мы объявляем ограничение как ОТЛОЖЕННОЕ , у нас есть возможность дождаться завершения транзакции перед проверкой ограничения.
Мы следуем за ключевым словом ОТЛОЖЕННЫЙ либо на НАЧАЛЬНО ОТЛОЖЕННЫЙ, либо на НАЧАЛЬНО НЕМЕДЛЕННО . В первом случае проверка будет отложена непосредственно перед фиксацией каждой транзакции. В последнем случае проверка будет производиться сразу после каждой выписки.
Чем NOT DEFERRABLE
отличается от DEFERRABLE INITIALLY IMMEDIATE
? В обоих случаях, похоже, любые ограничения проверяются после каждого отдельного утверждения.
DEFERRABLE
заявляет о намерении разработчика, что отсрочка ограничения является стоящим или необходимым действием. Это не относится к подавляющему большинству ограничений базы данных и маркировке всех, так какDEFERRABLE
это полезное различие потеряно.NOT DEFERRABLE
обычно самый быстрый.Помимо других (правильных) ответов, говоря о PostgreSQL , необходимо указать, что:
с NOT DEFERRABLE каждая строка проверяется во время вставки / обновления
с DEFERRABLE (в настоящее время IMMEDIATE ) все строки проверяются в конце вставки / обновления
с DEFERRABLE (в настоящее время DEFERRED ) все строки проверяются в конце транзакции
Поэтому неправильно говорить, что ограничение DEFERRABLE действует как NOT DEFERRABLE, когда оно установлено на IMMEDIATE.
Давайте подробнее остановимся на этом различии:
CREATE TABLE example( row integer NOT NULL, col integer NOT NULL, UNIQUE (row, col) DEFERRABLE INITIALLY IMMEDIATE ); INSERT INTO example (row, col) VALUES (1,1),(2,2),(3,3); UPDATE example SET row = row + 1, col = col + 1; SELECT * FROM example;
Это правильно выводит:
Но если мы удалим инструкцию DEFERRABLE INITIALLY IMMEDIATE,
ДОБАВЛЕНИЕ (12 октября 2017 г.)
Это поведение действительно задокументировано здесь , в разделе «Совместимость»:
источник
NOT DEFERRABLE
- скорость ( см. Здесь , раздел « Неотложенные ограничения уникальности» , «Имейте в виду, что это может быть значительно медленнее, чем немедленная проверка уникальности» ).DEFERRABLE
ограничение нельзя ссылаться как на внешние ключи в других таблицах ( см. Здесь , раздел Параметры , «Связанные столбцы должны быть столбцами неотложного ограничения уникального или первичного ключа в указанной таблице» ).NOT DEFERRABLE
просто потому, что оно работает лучше?NOT DEFERRABLE
2) если хотя бы один FK ссылается на ограничение, мы также используемNOT DEFERRABLE
3) в других случаях мы используемDEFERRABLE INITIALLY IMMEDIATE
. Это может немного снизить производительность этих ограничений, но гарантирует максимальную совместимость с другими СУБД, которые мы используем (Oracle, SqlServer). PK и FK не являются проблемой, потому что мы никогда не обновляем их значения (что, на мой взгляд, является хорошей привычкой программирования для БД).Помимо очевидной возможности откладывать, разница на самом деле заключается в производительности. Если бы не было снижения производительности, тогда не было бы необходимости иметь возможность выбирать откладываемый или нет - все ограничения были бы просто откладываемыми.
Падение производительности связано с оптимизацией, которую база данных может выполнять, зная, как ограничиваются данные. Например, индекс, созданный для поддержки уникального ограничения в Oracle, не может быть уникальным индексом, если ограничение откладывается, поскольку временное разрешение дублирования должно быть разрешено. Однако, если ограничение нельзя отложить, индекс может быть уникальным.
источник
Я очень опаздываю на вечеринку, но хочу добавить, что по состоянию на декабрь 2018 года только две базы данных, о которых я знаю (их может быть больше), предлагают некоторый уровень реализации этой стандартной функции SQL :
Database NOT DEFERRABLE DEFERRABLE DEFERRABLE INITIALLY IMMEDIATE INITIALLY DEFERRED ---------- -------------- ------------------- ------------------ Oracle N/A *1 Yes (default) Yes PostgreSQL Yes (default) Yes Yes DB2 - - - SQL Server - - - MySQL - - - MariaDB - - - SAP Sybase - - - HyperSQL - - - H2 - - - Derby - - -
* 1 Несмотря на то, что Oracle 12c принимает
NOT DEFERRABLE
состояние ограничения , он фактически игнорирует его и заставляет работать какDEFERRABLE INITIALLY IMMEDIATE
.Как видите, Oracle не реализует первый тип (
NOT DEFERRABLE
), и поэтому разработчики, использующие Oracle (в данном случае OP), могут запутаться и посчитать первые два типа эквивалентными.Интересно, что Oracle и PostgreSQL имеют разные типы по умолчанию. Может быть, это сказывается на производительности.
источник
НЕ ОТЛОЖЕННЫЙ - вы не можете изменить проверку ограничений, oracle проверяет ее после каждого оператора (т.е. непосредственно после оператора вставки).
ОТЛОЖЕННЫЙ НАЧАЛЬНО НЕМЕДЛЕННО - oracle проверяет ограничение после каждого оператора. НО, вы можете изменить его на после каждой транзакции (т.е. после фиксации):
set constraint pk_tab1 deferred;
источник