2011-09-27 54 views
5

外鍵約束是否在沒有使用約束更新列的SQL更新語句上檢查? (在MS SQL Server)外鍵約束是否在沒有用約束更新列的SQL更新語句上檢查?

說我有一個以下列的情侶對錶:

OrderItems 

    - OrderItemID 
    - OrderItemTypeID (FK to a OrderItemTypeID column on another table called OrderItemTypes) 
    - ItemName 

如果我只是更新

update [dbo].[OrderItems] 
set [ItemName] = 'Product 3' 
where [OrderItemID] = 2508 

請問FK約束做它的查找/與檢查上面的更新聲明? (甚至認爲更新不會更改該列的值?)

+0

雖然這是一個有效的問題,但我想知道這可能是多麼相關 –

+0

如果未檢查FK,那麼在更新語句中不包括FK列會有性能優勢。 –

回答

8

不,不檢查外鍵。通過檢查兩個不同更新的執行計劃,這很容易看出。

create table a (
    id int primary key 
) 

create table b (
    id int, 
    fkid int 
) 

alter table b add foreign key (fkid) references a(id) 

insert into a values (1) 
insert into a values (2) 

insert into b values (5,1) -- Seek on table a's PK 

enter image description here

update b set id = 6 where id = 5 -- No seek on table a's PK 

enter image description here

update b set fkid = 2 where id = 6 -- Seek on table a's PK 

enter image description here

drop table b 
drop table a 
+1

+1個很好的例子。 – 2011-09-28 00:40:45

3

否。由於SQL更新未更新包含約束的列,因此SQL Server在此情況下檢查的是什麼?這類似於問,「如果我只做更新,插入觸發器會被觸發嗎?」答案是否定的。

+0

你確定知道嗎?還是僅僅是直覺?如果它執行更新檢查 – JNK

+0

@JNK,它不會讓我感到驚訝 - 它會檢查什麼?該列未被更新,並且沒有值檢查。那麼會得到什麼檢查? –

+0

+1一個簡單的測試顯示你是正確的。可以通過檢查更新FK列的執行計劃進行檢查,也可以通過執行計劃進行檢查。 –

1

有當FK不存在會阻止更新到其他列的情況下,即使FK沒有更改,也就是FK創建時使用NOCHECK,因此在創建時不檢查。每聯機叢書:

如果你不想驗證新的CHECK或外鍵約束 對現有的數據,使用WITH NOCHECK。我們不建議這樣做,除非在極少數情況下。新約束將在 以後的所有數據更新中進行評估。當添加約束時,通過WITH NOCHECK抑制 的任何約束違規可能會導致未來更新 在更新行時使用不符合 約束的數據。