Dai*_*Dai 5 sql-server constraint check-constraints
SQL Server 允许在约束中使用用户定义函数 (UDF) CHECK- 它有许多用例 - 我不会深入讨论 - 但我最近面临着实现一个经过验证的重要业务/域约束一个表中的数据基于另一表中的非唯一、非关键数据 - 这意味着该约束不能使用任何内置约束(FOREIGN KEY、UNIQUE或基于普通行值的CHECK约束)来实现。
我立即选择的是TRIGGER,因为微软自己的文档指出TRIGGER对象是实现非平凡约束的预期方式:
当约束支持的功能无法满足应用程序的功能需求时,DML 触发器最有用。[...] 与
CHECK约束不同,DML 触发器可以引用其他表中的列。例如,触发器可以使用SELECT另一个表中的数据来与插入或更新的数据进行比较,并执行其他操作,例如修改数据或显示用户定义的错误消息。
稍等一下:Microsoft 写道“与CHECK约束不同,DML 触发器可以引用其他表中的列” - 但这是误导性的!CHECK约束可以通过 UDF 间接引用其他表中的列。
...所以我认为那里有一些模糊和过时的信息 - 所以让我们做更多的研究来看看CHECKUDF 的约束是否是正确的方法...
...好吧,CHECK约束中的 UDF 似乎名声不好:有关于性能不佳和缺乏形式正确性的批评评论(一个获胜的组合......),但我注意到我读过的文章和帖子,包括实际上,所有有关 UDF 和CHECK约束的 Google 搜索结果都是旧的......
Google 搜索结果中排名第一的“sql server check constraint udf”是一篇可以追溯到2001 年的文章- 它没有提供任何性能建议,但事实上这仍然是最重要的结果,这表明有很多旧的和过时的信息。今天人们可能认为仍然流行。
https://www.itprotoday.com/sql-server/using-udf-check-constraint-validate-column
ANSI SQL 标准允许您在 CHECK 约束中使用子查询,但 SQL Server 不支持此功能。但是,如果您使用的是 SQL Server 2000,则可以编写一个用户定义函数 (UDF),该函数对两个表执行存在性检查,如果任一表中存在行,则返回 1;如果不存在行,则返回 0。
2006 年DevX.com 上一篇关于 SQL Server 2000 和 2005 的文章演示了使用一对基于 UDF 的约束来解决当运行潜在的完整性破坏时不重新验证依赖数据的约束CHECK问题- 然而该文章接着说: SQL Server 2005的快照隔离功能意味着无效数据仍然可以进入数据库。CHECKUPDATE
2009 年StackOverflow 的一篇文章有一个答案,描述了基于 UDF 的CHECK约束,其运行速度比非基于 UDF 的方法慢 100 倍CHECK。
CHECK是“慢”的 - 但大多数评论者没有提供解释或限定 - 他们甚至没有说如果“UDF”指的是确定性的、非表读取函数(例如字符串格式验证函数) - 或包装SELECT函数 - 因为我希望字符串格式验证函数不会显着影响查询或批处理性能。SET STATISTICS数据,但我注意到该文章没有分享完整的查询计划,而且最重要的是:仅查看 128,000 多行语句的性能INSERT- 如果应用程序仅执行单次操作row INSERTDML 那么我希望看到 UDF+ 的CHECK性能与 FK 方法非常相似。
CHECKUPDATE当 UDF 从应用了多行的同一个表中读取时, UDF+方法不起作用。2011 年SpaghettiDba.com 的一篇文章中,作者描述了在CHECK约束中使用标量 UDF 如何导致 UDF 的逐行评估(TRIGGER当然仍然比对象更好)。
2012 年Dba.StackExchange 上的一篇文章也给出了含糊的警告:
通常应该在 CHECK 约束中避免访问其他表的 UDF [...] 几乎没有用例它们的行为完全符合用户的预期,几乎可以肯定没有一个 SQL 引擎可以根据约束标准规定的语义
CHECK。
2014 年StackOverflow 上一篇关于 SQL Server 2008 的帖子获得了高票数答案,该答案链接到前面提到的 SqlBlogs.com 文章。
...这早于SQL Server 关于如何处理 UDF 的重大(尽管是最近的)更改:
然而权威信息很难获得,所以我不确定从 SQL Server 2019 或 SQL Server 2022 开始,UDFs-in-constraints 的当前状态CHECK在性能和正确性方面都处于单一状态。行和多行DML场景:
CHECK不读取任何数据,但在列值上进行参数化(例如仅使用LIKE和 的字符串验证函数CHARINDEX)。CHECKa 中执行 a 的标量 UDF SELECT * FROM $table,其中$table是应用约束的同一个表。CHECKCHECKa 中执行 a 的标量 UDF SELECT * FROM $table,其中是不同的表(即与应用约束的$table表不同)。CHECK作为 UDF-in-a- 的替代方案CHECK CONSTRAINT,我一直在阅读有关使用索引视图作为有效实现某些类数据库范围(即跨表)完整性约束的方法,当任何 DML 修改数据时,这些约束总是强制执行的。任何包含的表,而约束仅对和CHECK生效,但不生效(因此约束不能用于阻止DML) - 但我很好奇是否有人有该技术的经验。INSERTUPDATEDELETECHECKDELETE
| 归档时间: |
|
| 查看次数: |
611 次 |
| 最近记录: |