sql-server-2008 – 如何使外键约束受信任?

前端之家收集整理的这篇文章主要介绍了sql-server-2008 – 如何使外键约束受信任?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有两张桌子,销售和产品. Sale具有引用Product的外键约束.外键是使用NOCHECK创建的,并在创建后立即禁用.我想启用并信任外键约束.启用它可以工作,但我不能让它值得信任.

StackOverflow和各种博客上的类似问题表明,运行ALTER TABLE T WITH CHECK CHECK CONSTRAINT C应该导致is_disabled = 0和is_not_trusted = 0,但is_not_trusted对我来说总是1.我究竟做错了什么?

我试图将示例代码放在sql Fiddle上,但它不喜欢“DBCC”命令,所以这里是:

  1. -- "_Scratch" is just a sandBox DB that I use for testing stuff.
  2. USE _Scratch
  3.  
  4. CREATE TABLE dbo.Product
  5. (
  6. ProductKeyId INT PRIMARY KEY NOT NULL,Description VARCHAR(40) NOT NULL
  7. )
  8.  
  9. CREATE TABLE dbo.Sale
  10. (
  11. ProductKeyId INT NOT NULL,SaleTime DATETIME NOT NULL,Value MONEY NOT NULL
  12. )
  13.  
  14. ALTER TABLE dbo.Sale WITH NOCHECK
  15. ADD CONSTRAINT FK_Product_ProductKeyId FOREIGN KEY (ProductKeyId)
  16. REFERENCES dbo.Product (ProductKeyId) NOT FOR REPLICATION;
  17.  
  18. ALTER TABLE dbo.Sale NOCHECK CONSTRAINT FK_Product_ProductKeyId
  19.  
  20. INSERT INTO dbo.Product VALUES (1,'Food')
  21. INSERT INTO dbo.Sale VALUES (1,GETDATE(),1.00)
  22.  
  23. -- Check the disabled/trusted state
  24. SELECT name,is_disabled,is_not_trusted
  25. FROM sys.foreign_keys
  26. WHERE name = 'FK_Product_ProductKeyId'
  27.  
  28. -- name is_disabled is_not_trusted
  29. -- FK_Product_ProductKeyId 1 1
  30.  
  31. -- Check the FK_Product_ProductKeyId constraint
  32. DBCC CHECKCONSTRAINTS('FK_Product_ProductKeyId')
  33.  
  34. -- DBCC execution completed.
  35. -- If DBCC printed error messages,contact your system administrator.
  36.  
  37. -- Check all constraints on Sale table
  38. DBCC CHECKCONSTRAINTS('Sale')
  39.  
  40. -- DBCC execution completed.
  41. -- If DBCC printed error messages,contact your system administrator.
  42.  
  43. -- Add the constraint and check existing data
  44. ALTER TABLE Sale WITH CHECK CHECK CONSTRAINT FK_Product_ProductKeyId
  45.  
  46. -- Check the disabled/trusted state
  47. SELECT name,is_not_trusted
  48. FROM sys.foreign_keys
  49. WHERE name = 'FK_Product_ProductKeyId'
  50.  
  51. -- name is_disabled is_not_trusted
  52. -- FK_Product_ProductKeyId 0 1
  53.  
  54. -- Check the FK_Product_ProductKeyId constraint
  55. DBCC CHECKCONSTRAINTS('FK_Product_ProductKeyId')
  56.  
  57. -- DBCC execution completed.
  58. -- If DBCC printed error messages,contact your system administrator.

解决方法

根据您的示例,我也尝试过:

>删除并重新创建外键.
>删除并重新创建表格.

然后我注意到命令中有一些东西:

  1. NOT FOR REPLICATION

看起来如果使用NOT FOR REPLICATION创建约束,它始终不受信任.

引自Books Online

In some cases,it is desirable for user activity in a replication
topology to be treated differently from agent activity. For example,
if a row is inserted by a user at the Publisher and that insert
satisfies a check constraint on the table,it might not be required to
enforce the same constraint when the row is inserted by a replication
agent at the Subscriber. The NOT FOR REPLICATION option allows you to
specify that the following database objects are treated differently
when a replication agent performs an operation:

Foreign key constraints

The foreign key constraint is not enforced when a replication agent
performs an insert,update,or delete operation.

看起来IS_NOT_TRUSTED设置仅与受IS_NOT_FOR_REPLICATION影响的复制相关.我想只要在您正在处理的服务器上强制执行约束,它应该没问题.所以我继续并证实了这一点:

  1. SELECT name,is_not_trusted
  2. FROM sys.foreign_keys
  3. WHERE name = 'FK_Product_ProductKeyId'
  4.  
  5. name is_disabled is_not_trusted
  6. FK_Product_ProductKeyId 0 1
  7.  
  8. INSERT INTO dbo.Sale VALUES (2,1.00)
  9.  
  10. Msg 547,Level 16,State 0,Line 1
  11. The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Product_ProductKeyId". The conflict occurred in database "_Scratch",table "dbo.Product",column 'ProductKeyId'.
  12. The statement has been terminated.

如果您仍然希望看到IS_NOT_TRUSTED = 0以便高枕无忧,那么只需重新创建外键,而不要使用NOT FOR REPLICATION.

如果你们想知道,我已经验证了对CHECK约束的相同效果.

猜你在找的MsSQL相关文章