T-Sql
SQL Server 會在單個 DELETE 語句中檢查行刪除之間的 FK 限制嗎?
我有一個自引用的表:
CREATE TABLE [dbo].[TestTable] ( [id] [bigint] IDENTITY(100000,1) NOT NULL, [referenced_id] [bigint] NULL, CONSTRAINT [PK_TestTable] PRIMARY KEY CLUSTERED ( [id] ASC ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO ALTER TABLE [dbo].[TestTable] WITH NOCHECK ADD CONSTRAINT [FK_ReferencedId] FOREIGN KEY ([referenced_id]) REFERENCES [dbo].[TestTable] ([id]) GO ALTER TABLE [dbo].[TestTable] CHECK CONSTRAINT [FK_ReferencedId] GO
假設我有幾行相互引用:
id | referenced_id -------|-------------- 100023 | 100024 100024 | 100023 100025 | 100026 100026 | 100023
如果我嘗試
DELETE
使用該行WHERE [id] = 100023
,則 FK 將被違反,因為100024
並100026
引用該行並且該DELETE
行將失敗。但是,如果我只是DELETE FROM [dbo].[TestTable]
,它似乎可以工作並成功刪除所有行。因此,SQL Server 似乎只在單個DELETE
語句中要刪除的所有行都被刪除之後才檢查 FK 約束,而不是在每行刪除之間。我可以依靠這種行為,還是
DELETE
有時會失敗?
SQL Server 似乎僅在刪除單個 DELETE 語句中要刪除的所有行之後才檢查 FK 約束,而不是在每行刪除之間。我可以依靠這種行為嗎?
是的。檢查語句的約束,而不是每一行,也不是在事務結束時檢查。
這是從該表中刪除的查詢計劃。
刪除發生在頂部分支上,但已刪除行的 ID 是假離線的,並且在聚集索引刪除步驟之後,假離線 ID 用於查找引用已刪除行的任何行。如果發現任何一個 DELETE 將被回滾(DML 語句總是在內部的嵌套事務中執行),並引發 FK 錯誤。