数据库包含不存在的外键,即使有外键约束?
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;
如您所见,只有 INSERT
ed 或 UPDATE
d 约束创建后的行(使用 NOCHECK
)已验证;第一行 INSERT
ed 保留原样,引用了不存在的行。
相反,创建未定义 NOCHECK
或 CHECK
的密钥,当您尝试创建它时该语句将失败:
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;
我正在使用一个数据库,其中有一个不存在的外键 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;
如您所见,只有 INSERT
ed 或 UPDATE
d 约束创建后的行(使用 NOCHECK
)已验证;第一行 INSERT
ed 保留原样,引用了不存在的行。
相反,创建未定义 NOCHECK
或 CHECK
的密钥,当您尝试创建它时该语句将失败:
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;