如何使外键约束受信任?

时间:2013-05-01 04:46:45

标签: sql-server-2008

我有两张桌子,销售和产品。 Sale具有引用Product的外键约束。外键创建WITH NOCHECK并在创建后立即禁用。我想启用并信任外键约束。启用它可以工作,但我不能让它被信任。

关于StackOverflow和各种博客的类似问题表明,运行ALTER TABLE T WITH CHECK CHECK CONSTRAINT C应该会产生is_disabled=0is_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.

1 个答案:

答案 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约束的相同效果。