sql-server - 2 个 SQL 服务器中的不同行为

标签 sql-server

我有一个运行一些集成测试的项目。该项目每次都会创建一个新数据库,并针对这个新数据库运行测试。最近我将此项目移至新服务器,从数据库中删除数据时遇到一些问题。

我执行以下查询:

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 DELETEON UPDATE操作),而在架构比较中,约束是启用还是禁用更有可能被忽略。

关于sql-server - 2 个 SQL 服务器中的不同行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27893580/

相关文章:

sql - 如何替换零并输入小数?

sql-server - 无法识别来自 restore-sqldatabase 的 AutoRelocateFile 参数

sql - 为数字编写 SQL 约束脚本使其落在某个范围内?

sql - 在 WHERE 语句中使用子查询的别名

.net - 是否可以使用 SqlException.LineNumber 来识别异常是否与连接相关?

sql-server - ; 之间有什么区别?和 SQL Server 存储过程中的 GO?

mysql - 使用 'like' 查找 sql 中的整个单词

sql-server - SQL Server XQuery - 仅适用于删除命名空间声明的情况

sql-server - 没有可用的 'org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder' 类型的合格 bean

sql - : Store update, 插入或删除语句影响意外行数的解决方案 (0)