数据库包含不存在的外键,即使有外键约束?

Database contains foreign key that doesn exist even though there is a foreign key constraint?

我正在使用一个数据库,其中有一个不存在的外键 ID,即使有外键约束。

有一个名为“Workplace”的 table,其中一个名为“AddressID”的外键列指向另一个名为“Address”的 table

外键如下:

ALTER TABLE [dbo].[Workplace]  WITH NOCHECK ADD  CONSTRAINT [FK_Workplace_Address] FOREIGN KEY([AddressID])
REFERENCES [dbo].[Address] ([ID])
GO

ALTER TABLE [dbo].[Workplace] CHECK CONSTRAINT [FK_Workplace_Address]
GO

对于 Workplace 中的某一特定行 table,AddressID 的值为“1”。 当我运行select * from Address where ID = 1没有结果。

然后我 运行 update Workplace set AddressID = 3 where Workplace.ID = 20 值更改为 3 并且我已验证 ID 为 3 的地址存在。

然后我 运行 update Workplace set AddressID = 1 where Workplace.ID = 20 再次得到错误

The UPDATE statement conflicted with the FOREIGN KEY constraint "FK_Workplace_Address". The conflict occurred in database db_name, table "dbo.Address", column 'ID'.

我不明白值 1 最初是怎么放在那里的。 ID=1 的地址在约束到位后无法删除。如果记录首先被删除,约束创建也会失败。有谁知道这怎么可能?

这是 Windows 服务器 2016 上的数据库,SQL 服务器 12.0.4237.0

您使用 NOCHECK 创建了 FOREIGN KEY,因此 table 中已经存在的值 未被检查 。这可以通过以下方式复制:

CREATE TABLE dbo.Address (ID int NOT NULL CONSTRAINT PK_Address PRIMARY KEY);
GO
CREATE TABLE dbo.Workplace (ID int NOT NULL CONSTRAINT PK_Workplace PRIMARY KEY,
                            AddressID int)
GO

INSERT INTO dbo.Workplace
VALUES(1,3); --Works
GO

ALTER TABLE dbo.WorkPlace  WITH NOCHECK ADD CONSTRAINT FK_Workplace_Address FOREIGN KEY (AddressID) REFERENCES dbo.Address(ID);
GO

ALTER TABLE dbo.Workplace CHECK CONSTRAINT FK_Workplace_Address;
GO

INSERT INTO dbo.Workplace
VALUES(2,3); --Fails
GO

UPDATE dbo.Workplace
SET AddressID = 2
WHERE ID = 1; --Fails
GO

DROP TABLE dbo.Workplace;
DROP TABLE dbo.Address;

如您所见,只有 INSERTed 或 UPDATEd 约束创建后的行(使用 NOCHECK)已验证;第一行 INSERTed 保留原样,引用了不存在的行。

相反,创建未定义 NOCHECKCHECK 的密钥,当您尝试创建它时该语句将失败:

CREATE TABLE dbo.Address (ID int NOT NULL CONSTRAINT PK_Address PRIMARY KEY);
GO
CREATE TABLE dbo.Workplace (ID int NOT NULL CONSTRAINT PK_Workplace PRIMARY KEY,
                            AddressID int)
GO

INSERT INTO dbo.Workplace
VALUES(1,3); --Works
GO

ALTER TABLE dbo.WorkPlace  WITH CHECK ADD CONSTRAINT FK_Workplace_Address FOREIGN KEY (AddressID) REFERENCES dbo.Address(ID); --Fails
GO
DROP TABLE dbo.Workplace;
DROP TABLE dbo.Address;

这会产生以下错误:

The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_Workplace_Address". The conflict occurred in database "Sandbox", table "dbo.Address", column 'ID'.

或者,在创建 table 时创建密钥;虽然现在可能为时已晚。

CREATE TABLE dbo.Address (ID int NOT NULL CONSTRAINT PK_Address PRIMARY KEY);
GO

CREATE TABLE dbo.Workplace (ID int NOT NULL CONSTRAINT PK_Workplace PRIMARY KEY,
                            AddressID int CONSTRAINT FK_Workplace_Address FOREIGN KEY REFERENCES dbo.Address(ID));
GO

INSERT INTO dbo.Workplace
VALUES(1,3); --Fails

GO

DROP TABLE dbo.Workplace;
DROP TABLE dbo.Address;