摘要:SQL - 再探停用外部索引鍵(FK)
在 <SQL - 停用外部索引鍵(FK)> 這篇提到用語法的方式來停用與啟用外部索引鍵,可是在啟用時,會有一種情況產生,啥狀況呢!? 以下就來說說這種狀況及解決方式...
環境:請參考 <SQL - 停用外部索引鍵(FK)> 這篇文章
步驟一:在停用外部索引鍵前,使用UI與語法來看看
UI:
語法:
SELECT FK.NAME, FK.KEY_INDEX_ID, FK.IS_DISABLED,
FK.IS_NOT_FOR_REPLICATION, FK.IS_NOT_TRUSTED
FROM SYS.FOREIGN_KEYS FK
WHERE FK.NAME = 'FK_MY_CHILD_TABLE_MY_ROOT_TABLE'
上面兩張圖各有兩個紅色框框,彼此的對應如下:
檢查建立或重新啟用時的現有資料 = is_not_trusted
強制使用外部索引鍵條件約束 = is_disabled
步驟二:使用 T-SQL 語法停用外部索引鍵,得到的結果如下圖
停用語法:ALTER TABLE dbo.MY_CHILD_TABLE NOCHECK CONSTRAINT FK_MY_CHILD_TABLE_MY_ROOT_TABLE
UI:
語法:
SELECT FK.NAME, FK.KEY_INDEX_ID, FK.IS_DISABLED,
FK.IS_NOT_FOR_REPLICATION, FK.IS_NOT_TRUSTED
FROM SYS.FOREIGN_KEYS FK
WHERE FK.NAME = 'FK_MY_CHILD_TABLE_MY_ROOT_TABLE'
步驟三:使用 T-SQL 語法啟用外部索引鍵,得到的結果如下圖
啟用語法:ALTER TABLE dbo.MY_CHILD_TABLE CHECK CONSTRAINT FK_MY_CHILD_TABLE_MY_ROOT_TABLE
UI:
語法:
SELECT FK.NAME, FK.KEY_INDEX_ID, FK.IS_DISABLED,
FK.IS_NOT_FOR_REPLICATION, FK.IS_NOT_TRUSTED
FROM SYS.FOREIGN_KEYS FK
WHERE FK.NAME = 'FK_MY_CHILD_TABLE_MY_ROOT_TABLE'
為什麼啟用後,竟然與停用前不一樣呢!?主要原因是因為我們少了一組關鍵字「WITH CHECK」,若將 步驟三 的啟用外部索引鍵的語法改下列語法,就不會有這樣的話問題...
ALTER TABLE dbo.MY_CHILD_TABLE WITH CHECK CHECK CONSTRAINT FK_MY_CHILD_TABLE_MY_ROOT_TABLE
補充:MSDN的一段話
WITH CHECK | WITH NOCHECK
指定是否要依照新加入或重新啟用的 FOREIGN KEY 或 CHECK 條件約束來驗證資料表中的資料。如果未指定,則假設 WITH CHECK 為新條件約束,並假設 WITH NOCHECK 為重新啟用的條件約束。
如果您不要依照現有的資料來確認新的 CHECK 或 FOREIGN KEY 條件約束,請使用 WITH NOCHECK。除了極少數的狀況外,我們建議您不要這麼做。在以後的所有資料更新中將會評估新條件約束。新增條件約束時,如果 WITH NOCHECK 抑制任何強制違規,當未來的更新作業更新含有不符合該條件約束的資料列時,這些強制違規可能會使這些更新作業失敗。
查詢最佳化工具不考量定義為 WITH NOCHECK 的條件約束。這類條件約束會被忽略,直到利用 ALTER TABLE table CHECK CONSTRAINT ALL 重新啟用為止。
OK,正題談完了,以下再來補充一個小東西
Q:如何將某個資料表的外部索引鍵停用呢!? 看倌可以參考以下語法
A:ALTER TABLE dbo.MY_CHILD_TABLE CHECK CONSTRAINT ALL
參考:
ALTER TABLE (Transact-SQL)
停用索引的指導方針