использование самореференции на сервере sql - PullRequest
9 голосов
/ 26 марта 2011
create table EMP(Eid int primary key)

insert into EMP values(11e3)

- самоссылка

alter table EMP 
add constraint fk_EMP_Eid 
foreign key (Eid) references EMP(Eid)

- теперь вставка

insert into EMP values(12e2)

Но эта вставка должна завершиться ошибкой, поскольку в Eid=1200 нет предыдущего значениятаблица EMP, поэтому, когда внешний ключ будет ссылаться на этот столбец, он не найдет значение, следовательно, должен произойти сбой вставки.

но почему это удается?

Ответы [ 2 ]

12 голосов
/ 26 марта 2011

Столбец ссылается на себя.

Таким образом, добавление самой строки гарантирует, что есть соответствующая строка.Это ограничение никогда не может выйти из строя.

Фактически, глядя на план выполнения, SQL Server осознает это и даже не беспокоится о его проверке.Оператор assert отсутствует.

Plan

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

create table EMP2(Eid int primary key, boss_id int null);
alter table EMP2 add constraint fk_EMP2_Eid 
 foreign key (boss_id) references EMP2(Eid)

insert into EMP2 values(1,null) /*Can't violate constraint as NULL*/
insert into EMP2 values(2,1)    /*Can violate constraint as NOT NULL*/

Plan

Если вы попробуете несколько строк, блокирующая шпуля будет добавлена ​​в план, чтобы ограничения не возникалине проверяется, пока не будут вставлены все строки.

insert into EMP2 values (3,2),(4,3) /*Can violate constraint - multiple rows*/

Plan

И только для полноты, как это было поднято в комментариях, глядя на случай, когдавставка в таблицу с FK, ссылающимся на другую ...

CREATE TABLE EmpSalaryHistory
(
Eid INT NOT NULL REFERENCES EMP(Eid),
EffectiveDate DATETIME NOT NULL,
Salary INT,
PRIMARY KEY (Eid,EffectiveDate)
)

INSERT INTO EmpSalaryHistory
VALUES    (1,GETDATE(),50000),
          (2,GETDATE(),50000)

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

Plan

0 голосов
/ 26 марта 2011

Ваш FK-столбец fk_EMP_Eid, вероятно, допускает нулевые значения, поэтому взаимосвязь не обязана существовать, но если вы попытаетесь поместить значение в этот столбец, то SQL Server проверит, является ли FK допустимым, иначе произойдет ошибка.

...