CHECK CONSTRAINT文本由SQL Server更改。我该如何避免或解决这个问题?

时间:2013-03-15 02:19:29

标签: sql-server-2008-r2 constraints

当我在表上定义CHECK CONSTRAINT时,我发现存储的条件子句可能与我输入的不同。
例如:

Alter table T1 add constraint C1 CHECK (field1 in (1,2,3))

查看存储的内容:

select cc.Definition from sys.check_constraints cc
inner join sys.objects o on o.object_id = cc.parent_object_id
where cc.type = 'C' and cc.name = 'T1';

我明白了:

([field1]=(3) OR [field1]=(2) OR [field1]=(1))

虽然这些是等效的,但它们不是同一文本。 (使用BETWEEN子句时会出现类似的行为。)

我希望这一点没有发生的原因是我试图通过比较我用来定义的文本,以编程方式确保我的所有CHECK约束都是正确的 存储在sys.check_constraints中的约束 - 如果不同则删除并重新创建约束。

然而,在这些情况下,它们总是不同的,因此程序总是认为需要重新创建约束。

问题是:

  1. SQL Server执行此转换有任何已知原因吗?它只是删除一些语法糖并以更简单的形式存储子句?
  2. 有没有办法避免这种行为(除了以长格式编写我的约束条款以匹配SQL Server将其更改为什么)?
  3. 还有另一种方法可以判断我的检查约束是否“过时”并需要重新创建吗?

1 个答案:

答案 0 :(得分:2)

  

SQL Server是否有任何已知原因进行此转换?它只是删除了一些语法糖并以更简单的形式存储子句吗?

我不知道在线图书或其他地方记录的任何原因。但是,我的猜测是,它已针对SQL Server内部的某些目的进行了规范化。它可能允许SQL Server在定义表达式时稍微宽松一些(例如使用Database作为列名),但保证列名总是被适当地转义为任何引擎需要解析表达式(即, [Database])。

  

有没有办法避免这种行为(除了以长格式编写我的约束子句以匹配SQL Server将其更改为什么)?

可能不是。但是如果你的约束并不是非常复杂,那么以长篇形式重写约束条款这么糟糕吗?

  

还有另一种方法可以判断我的检查约束是否“过时”并需要重新创建吗?

在我直接回答之前,我会指出这里涉及到一些编程哲学。 SQL Server为CHECK约束的文本提供的API仅保证您将获得与原始表达式等效的内容。虽然您当然可以构建一些花哨的方法来确保您始终能够重现SQL Server的表达式的规范化版本,但无法保证Microsoft将来不会更改其规范化规则。实际上,可能无法保证两个等效表达式将始终相同地进行标准化!

因此,我首先建议您重新检查您的体系结构,看看您是否可以在不依赖于未记录的API行为的情况下完成相同的结果。

话虽如此,this question(和答案)中列出了许多方法。

另一个替代方案,它可能更具蛮力但可能是可接受的,总是假设表达式是“过时的”并且每次都只是删除/重新创建约束你检查。除非你期望这些约束经常变得过时(或表格非常大),否则这似乎是一个不错的解决方案。您甚至可以在事务中运行它,因此如果已经违反了新约束,只需回滚事务并报告错误。