Sql server 2008 如何使外键约束可信?
我有两张桌子,销售和产品。Sale具有引用产品的外键约束。外键是使用NOCHECK创建的Sql server 2008 如何使外键约束可信?,sql-server-2008,Sql Server 2008,我有两张桌子,销售和产品。Sale具有引用产品的外键约束。外键是使用NOCHECK创建的,并在创建后立即禁用。我想启用并信任外键约束。启用它是可行的,但我不能让它被信任 StackOverflow和各种博客上的类似问题表明,使用CHECK-CHECK约束C运行ALTER TABLE T应该导致被禁用=0和不可信=0,但不可信对我来说总是1。我做错了什么 我尝试将示例代码放在SQL FIDLE上,但它不喜欢“DBCC”命令,因此它是: -- "_Scratch" is just a sandbox
,并在创建后立即禁用。我想启用并信任外键约束。启用它是可行的,但我不能让它被信任
StackOverflow和各种博客上的类似问题表明,使用CHECK-CHECK约束C运行ALTER TABLE T应该导致被禁用=0
和不可信=0
,但不可信
对我来说总是1。我做错了什么
我尝试将示例代码放在SQL FIDLE上,但它不喜欢“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.
根据你的例子,我也尝试过:
- 删除并重新创建外键
- 删除并重新创建表
然后我注意到命令中有一些东西:
NOT FOR REPLICATION
如果约束是使用NOT FOR复制创建的,则它始终不受信任
引述自:
在某些情况下,复制中的用户活动是可取的
拓扑与代理活动的处理方式不同。例如
如果用户在发布服务器上插入了一行,则
如果满足表上的检查约束,则可能不需要
当复制插入行时,强制执行相同的约束
订阅服务器上的代理。“不用于复制”选项允许您
指定以不同方式处理以下数据库对象
复制代理执行操作时:
外键约束
复制代理运行时不强制执行外键约束
执行插入、更新或删除操作
看起来IS\u NOT\u TRUSTED
设置仅与受IS\u NOT\u影响的复制相关,以进行复制
。我想只要在您正在工作的服务器上强制执行约束,就应该可以了。所以我继续确认了这一点:
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.
如果您仍然希望看到不受信任=0
,以便安心,只需在不使用的情况下重新创建外键,而不进行复制
如果你们想知道,我也验证了检查约束的相同效果。Louie,谢谢你花时间做测试,这是一个很好的答案,我希望我能给你不止一次投票:)我试图让约束可信,因为我在某个地方读到不可信的约束会影响某些查询的性能。我继承了数据库,我们不进行复制,但一切似乎都是“不用于复制”,这可能是一种“推测性通用性”的情况。@WileCau当FKs被标记为不受信任时,实际上执行时间得到了改进。我绝不鼓励这种做法。但是,将大量数据从暂存sql移动到生产sql非常有用。在这里查看更多信息@Pathachiever11,您是对的,禁用约束的原因是因为一些表最初是从另一个已知的一致性数据库填充的,所以它们只是减慢了数据迁移。在初始迁移之后,应该重新启用约束以强制新数据的一致性,但它们被忘记了。@WileCau我在我的环境中经历了相同的场景。我们使用BCP工具迁移了大量数据,然后意识到FKs被标记为不可信。它对于大型数据迁移非常方便。