我有一个运行一些集成测试的项目。该项目每次都会创建一个新数据库,并针对这个新数据库运行测试。最近我将此项目移至新服务器,从数据库中删除数据时遇到一些问题。
我执行以下查询:
DELETE FROM TABLE1;
DELETE FROM TABLE2;
DELETE FROM TABLE3;
在服务器 A 上一切都按预期工作,但是使用服务器 B 时出现以下错误:
The DELETE statement conflicted with the REFERENCE constraint "FK_....". The conflict occurred in database "TestDB", table "Table1", column '...'.
两台服务器具有相同版本的 SQL Server
Microsoft SQL Server 2012 (SP1) - 11.0.3401.0 (X64)
Jan 9 2014 13:22:15
Copyright (c) Microsoft Corporation
Standard Edition (64-bit) on Windows NT 6.2 <X64> (Build 9200: ) (Hypervisor)
架构和数据相同,并且使用相同的过程创建数据库。
有什么想法吗?
最佳答案
实际上,两个地方都有可能具有相同的架构,甚至相同的数据,但会经历不同的行为。如何?因为约束(CHECK 和 FOREIGN KEY)可以被禁用。是的。
要查看相关外键是启用还是禁用,只需运行以下命令,并确保将相关外键的名称放入 WHERE 子句中:
SELECT *
FROM sys.foreign_keys
WHERE [name] = N'{name_of_FK_in_question}';
查看名为 is_disabled
的列。我怀疑它在服务器 A 上设置为 1
(一切“工作”),在服务器 B 上设置为 0
(一切“不工作”)。我将“有效”和“无效”放在引号中,因为如果情况确实如此,那么现实与您所经历的相反。意思是,启用了 FK 并收到错误的系统实际上正在工作,这就是 FK 应该做的事情。系统没有收到错误可能是允许孤立(即坏)数据输入。
要启用 FK,请运行以下命令:
ALTER TABLE {table_name}
WITH CHECK -- verifies the data currently in the table
CHECK CONSTRAINT [{name_of_FK_in_question}];
当然,如果存在不良数据,您需要:
先删除坏数据,或者
在
ALTER
上指定WITH NOCHECK
,以便它接受错误数据:ALTER TABLE {table_name} WITH NOCHECK -- accept the bad data aleady there CHECK CONSTRAINT [{name_of_FK_in_question}];
但是,这并不能 100% 解决问题。如果您再次运行该 SELECT 查询(如上所述),您应该会看到
is_disabled
字段现在设置为0
。但是,如果您查看is_not_trusted
字段,它将被设置为1
。如果启用了约束但不可信,它将按预期强制执行其规则,但查询优化器 (Q.O.) 将忽略它,这通常不是一件好事,因为约束实际上不仅用于强制执行数据完整性规则,还用于执行数据完整性规则。也可以作为 Q.O 的线索。从逻辑上减少某些查询中的某些步骤(即它们有时有助于提高性能)。为了使约束“可信”,您必须删除错误数据并通过以下方式验证表上的所有约束:ALTER TABLE {table_name} WITH CHECK -- verifies the data currently in the table CHECK CONSTRAINT [{name_of_FK_in_question}];
但是,如果由于某种原因您需要“坏”数据,那么您将只拥有一个强制数据完整性的外键,但没有提高性能的潜力(这仍然是比没有定义 FK 好得多:)。
有关详细信息,请参阅 ALTER TABLE 的 MSDN 页面.
为了完整起见,我还将提到,在服务器 A(没有错误)上,FK 可能是使用自动删除选项 ON DELETE CASCADE
定义的以及从要删除的表中删除行之前的相关数据,而服务器 B(出现错误)没有指定 ON DELETE
操作(或指定为无操作
)。然而,这是在进行架构比较时应该显示的内容(除非指定忽略ON DELETE
和ON UPDATE
操作),而在架构比较中,约束是启用还是禁用更有可能被忽略。
关于sql-server - 2 个 SQL 服务器中的不同行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27893580/