НЕ ДЕФЕРРАБЛЬНО по сравнению с ДЕФЕРРАБЛЕМ - PullRequest
73 голосов
/ 14 марта 2011

Я прочитал это о ключевом слове SQL DEFERRABLE в Системы баз данных - Полная книга .

Последняя [НЕ ОТСУТСТВУЕТ] по умолчаниюи означает, что каждый раз, когда выполняется оператор модификации базы данных, ограничение проверяется сразу после этого, если модификация может нарушать ограничение внешнего ключа.

Однако, если мы объявляем ограничение равным DEFERRABLE, тогда у нас есть возможность подождать до завершения транзакции, прежде чем проверять ограничение.

Мы следуем за ключевым словом DEFERRABLE либо INITIALLY DEFERRED или ПЕРВОНАЧАЛЬНО НЕМЕДЛЕННЫЙ .В первом случае проверка будет отложена до каждой транзакции.В последнем случае проверка будет производиться сразу после каждого утверждения.

Чем NOT DEFERRABLE отличается от DEFERRABLE INITIALLY IMMEDIATE?Кажется, что в обоих случаях любые ограничения проверяются после каждого отдельного оператора.

Ответы [ 5 ]

59 голосов
/ 14 марта 2011

С помощью DEFERRABLE INITIALLY IMMEDIATE вы можете отложить ограничения по требованию, когда вам это нужно.

Это полезно, если вы обычно хотите проверить ограничения во время выписки, но, например, Пакетная загрузка хочет отложить проверку до времени фиксации.

Синтаксис, как отложить ограничения, отличается для разных СУБД.

С NOT DEFERRABLE вы никогда не сможете отложить проверку до времени фиксации.

28 голосов
/ 23 июня 2017

Помимо других (правильных) ответов, , говоря о 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;

Это правильно выводит:

output

Но если мы удалим инструкцию DEFERRABLE INITIALLY IMMEDIATE,

ОШИБКА: двойное значение ключа нарушает уникальное ограничение "example_row_col_key" ПОДРОБНОЕ: Ключ ("строка", столбец) = (2, 2) уже существует.********** Ошибка **********

ОШИБКА: двойное значение ключа нарушает уникальное ограничение «example_row_col_key» Состояние SQL: 23505 Detail: Key («row»,col) = (2, 2) уже существует.


ADDENDUM (12 октября 2017 г.)

Такое поведениедействительно задокументировано здесь , раздел «Совместимость»:

Кроме того, PostgreSQL проверяет неотложные ограничения уникальности немедленно, а не в конце оператора, как предполагает стандарт.

24 голосов
/ 21 декабря 2011

Помимо очевидной способности откладывать, разница на самом деле в производительности. Если бы не было снижения производительности, тогда не было бы необходимости иметь возможность выбирать отсроченный или нет - все ограничения были бы просто отсроченными.

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

3 голосов
/ 12 декабря 2018

Я очень опоздал на вечеринку, но я хотел добавить, что - по состоянию на декабрь 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 имеют разные типы по умолчанию. Может быть, это влияет на производительность.

3 голосов
/ 23 августа 2013

NOT DEFERRABLE - вы не можете изменить проверку ограничений, oracle проверяет ее после каждого оператора (т. Е. Непосредственно после оператора вставки).

DEFERRABLE INITIALLY IMMEDIATE - оракул проверяет ограничение после каждого оператора. НО, вы можете изменить его после каждой транзакции (т.е. после коммита):

set constraint pk_tab1 deferred;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...