Sql server 两台SQL Server中的不同行为

Sql server 两台SQL Server中的不同行为,sql-server,Sql Server,我有一个项目,运行一些集成测试。项目每次都会创建一个新数据库,并对这个新数据库运行测试。最近我把这个项目移到了一个新的服务器上,在从数据库中删除数据时遇到了一些问题 我执行以下查询: DELETE FROM TABLE1; DELETE FROM TABLE2; DELETE FROM TABLE3; 在服务器A上,一切正常,但使用服务器B时,我遇到以下错误: DELETE语句与引用约束冲突 “FK!。数据库中发生冲突 “测试数据库”,表“表1”,第列 “…” 两台服务器都有相同版本的SQL

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

我执行以下查询:

DELETE FROM TABLE1;
DELETE FROM TABLE2;
DELETE FROM TABLE3;
在服务器A上,一切正常,但使用服务器B时,我遇到以下错误:

DELETE语句与引用约束冲突 “FK!。数据库中发生冲突 “测试数据库”,表“表1”,第列 “…”

两台服务器都有相同版本的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)
Microsoft SQL Server 2012(SP1)-11.0.3401.0(X64)
2014年1月9日13:22:15
版权所有(c)微软公司
Windows NT 6.2(构建9200:)上的标准版(64位)(虚拟机监控程序)
架构和数据都是相同的,数据库是使用相同的过程创建的。

有什么想法吗?

有一个外键(在错误消息中命名),它阻止您从
表1
中删除项目,因为它会违反外键(即,另一个表中会有一行引用您要删除的行)

这两个数据库之间的区别可能是:

  • 第一个数据库没有外键
  • 第一个数据库表中没有任何受外键约束的行
要查找外键所在的表,请参见问题


正如Justin所说,键或数据都不相同,如果它适用于您的情况,那么将键设置为级联删除将解决这一问题,但您必须首先识别键。

实际上,在两个位置都可能有相同的模式,甚至相同的数据,并经历不同的行为。怎么用?因为可以禁用约束(检查和外键)。是的

要查看相关外键是启用还是禁用,只需运行以下命令,确保在WHERE子句中输入相关FK的名称:

SELECT *
FROM sys.foreign_keys
WHERE [name] = N'{name_of_FK_in_question}';
请看名为
的列已禁用
。我怀疑它在服务器A上设置为
1
(所有东西都“工作”),在服务器B上设置为
0
(所有东西都“不工作”)。我把“有效”和“无效”放在引号里,因为如果这是真的,那么现实与你所经历的恰恰相反。也就是说,启用FK并获得错误的系统实际上正在工作,因为FKs应该这样做。系统未获得错误可能是因为允许孤立(即坏)数据进入

要启用FK,请运行以下操作:

ALTER TABLE {table_name}
   WITH CHECK -- verifies the data currently in the table
   CHECK CONSTRAINT [{name_of_FK_in_question}];
当然,如果存在错误数据,您需要:

  • 先删除坏数据,或

  • ALTER
    上使用NOCHECK指定
    ,以便它接受坏数据:

    ALTER TABLE {table_name}
       WITH NOCHECK -- accept the bad data aleady there
       CHECK CONSTRAINT [{name_of_FK_in_question}];
    
    然而,这并不能100%解决问题。如果再次运行SELECT查询(如上所述),您应该会看到
    已禁用
    字段现在设置为
    0
    。但是,如果查看
    不受信任
    字段,它将被设置为
    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要好得多:)

有关更多信息,请参阅MSDN页面以了解更多信息



为完整起见,我还将提到,在服务器A(无错误)上,FK可能是通过删除级联上的
选项定义的,该选项在从要删除的表中删除行之前自动删除和相关数据,而在服务器B(有错误)上没有指定删除时的
操作(或指定为
无操作
)。但是,这是在进行架构比较时应该显示的内容(除非指定忽略删除时的
和更新时的
操作),而在架构比较中,约束是启用还是禁用更可能被忽略。

两台服务器之间的架构不同。它们不相同。一台有外键,另一台没有。@Joe可能它们不同,但不一定。有关详细信息,请参阅我的答案:).DB是用相同的过程创建的,我比较了架构,两者都是相同的。@那么数据必须是different@estebane97贾斯汀:可以使用相同的模式,甚至可以插入相同的数据,但只能在一个地方看到FK冲突。我解释了其中的区别。
ALTER TABLE {table_name}
   WITH CHECK -- verifies the data currently in the table
   CHECK CONSTRAINT [{name_of_FK_in_question}];