我有两张桌子,销售和产品。 Sale具有引用Product的外键约束。外键创建WITH NOCHECK
并在创建后立即禁用。我想启用并信任外键约束。启用它可以工作,但我不能让它被信任。
关于StackOverflow和各种博客的类似问题表明,运行ALTER TABLE T WITH CHECK CHECK CONSTRAINT C
应该会产生is_disabled=0
和is_not_trusted=0
,但is_not_trusted
对我来说总是1。我做错了什么?
我试图将示例代码放在SQL Fiddle上,但它不喜欢“DBCC”命令,所以这里是:
-- "_Scratch" is just a sandbox DB that I use for testing stuff.
USE _Scratch
CREATE TABLE dbo.Product
(
ProductKeyId INT PRIMARY KEY NOT NULL,
Description VARCHAR(40) NOT NULL
)
CREATE TABLE dbo.Sale
(
ProductKeyId INT NOT NULL,
SaleTime DATETIME NOT NULL,
Value MONEY NOT NULL
)
ALTER TABLE dbo.Sale WITH NOCHECK
ADD CONSTRAINT FK_Product_ProductKeyId FOREIGN KEY (ProductKeyId)
REFERENCES dbo.Product (ProductKeyId) NOT FOR REPLICATION;
ALTER TABLE dbo.Sale NOCHECK CONSTRAINT FK_Product_ProductKeyId
INSERT INTO dbo.Product VALUES (1, 'Food')
INSERT INTO dbo.Sale VALUES (1, GETDATE(), 1.00)
-- Check the disabled/trusted state
SELECT name, is_disabled, is_not_trusted
FROM sys.foreign_keys
WHERE name = 'FK_Product_ProductKeyId'
-- name is_disabled is_not_trusted
-- FK_Product_ProductKeyId 1 1
-- Check the FK_Product_ProductKeyId constraint
DBCC CHECKCONSTRAINTS('FK_Product_ProductKeyId')
-- DBCC execution completed.
-- If DBCC printed error messages, contact your system administrator.
-- Check all constraints on Sale table
DBCC CHECKCONSTRAINTS('Sale')
-- DBCC execution completed.
-- If DBCC printed error messages, contact your system administrator.
-- Add the constraint and check existing data
ALTER TABLE Sale WITH CHECK CHECK CONSTRAINT FK_Product_ProductKeyId
-- Check the disabled/trusted state
SELECT name, is_disabled, is_not_trusted
FROM sys.foreign_keys
WHERE name = 'FK_Product_ProductKeyId'
-- name is_disabled is_not_trusted
-- FK_Product_ProductKeyId 0 1
-- Check the FK_Product_ProductKeyId constraint
DBCC CHECKCONSTRAINTS('FK_Product_ProductKeyId')
-- DBCC execution completed.
-- If DBCC printed error messages, contact your system administrator.
-- Check all constraints on Sale table
DBCC CHECKCONSTRAINTS('Sale')
-- DBCC execution completed.
-- If DBCC printed error messages, contact your system administrator.
答案 0 :(得分:18)
根据您的示例,我也尝试过:
然后我注意到命令中有一些东西:
NOT FOR REPLICATION
似乎如果使用NOT FOR REPLICATION创建约束,它始终不受信任。
引自Books Online:
在某些情况下,复制中的用户活动是理想的 拓扑要与代理活动区别对待。例如, 如果用户在发布者和插入处插入了行 满足表上的检查约束,可能不需要 通过复制插入行时强制执行相同的约束 订阅者的代理人。 NOT FOR REPLICATION选项允许您 指定以不同方式处理以下数据库对象 当复制代理执行操作时:
外键约束
复制代理时不强制执行外键约束 执行插入,更新或删除操作。
看起来IS_NOT_TRUSTED
设置仅与受相关。我想只要在您正在处理的服务器上强制执行约束,它应该没问题。所以我继续确认了它:IS_NOT_FOR_REPLICATION
影响的复制
SELECT name, is_disabled, is_not_trusted
FROM sys.foreign_keys
WHERE name = 'FK_Product_ProductKeyId'
name is_disabled is_not_trusted
FK_Product_ProductKeyId 0 1
INSERT INTO dbo.Sale VALUES (2, GETDATE(), 1.00)
Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Product_ProductKeyId". The conflict occurred in database "_Scratch", table "dbo.Product", column 'ProductKeyId'.
The statement has been terminated.
如果您仍希望看到IS_NOT_TRUSTED = 0
让您高枕无忧,只需在没有NOT FOR REPLICATION
的情况下重新创建外键。
如果你们想知道,我也验证了对CHECK约束的相同效果。