在 SQL Server 的 CHECK 约束中使用 UDF 的当前状态(2022)是什么?

Dai*_*Dai 5 sql-server constraint check-constraints

SQL Server 允许在约束中使用用户定义函数 (UDF) CHECK- 它有许多用例 - 我不会深入讨论 - 但我最近面临着实现一个经过验证的重要业务/域约束一个表中的数据基于另一表中的非唯一、非关键数据 - 这意味着该约束不能使用任何内置约束(FOREIGN KEYUNIQUE或基于普通行值的CHECK约束)来实现。

我立即选择的是TRIGGER,因为微软自己的文档指出TRIGGER对象是实现非平凡约束的预期方式:

当约束支持的功能无法满足应用程序的功能需求时,DML 触发器最有用。[...] 与CHECK约束不同,DML 触发器可以引用其他表中的列。例如,触发器可以使用SELECT另一个表中的数据来与插入或更新的数据进行比较,并执行其他操作,例如修改数据或显示用户定义的错误消息。

稍等一下:Microsoft 写道“与CHECK约束不同,DML 触发器可以引用其他表中的列” - 但这是误导性的!CHECK约束可以通过 UDF 间接引用其他表中的列。

...所以我认为那里有一些模糊和过时的信息 - 所以让我们做更多的研究来看看CHECKUDF 的约束是否是正确的方法...

...好吧,CHECK约束中的 UDF 似乎名声不好:有关于性能不佳和缺乏形式正确性的批评评论(一个获胜的组合......),但我注意到我读过的文章和帖子,包括实际上,所有有关 UDF 和CHECK约束的 Google 搜索结果都是旧的......

...这早于SQL Server 关于如何处理 UDF 的重大(尽管是最近的)更改:

然而权威信息很难获得,所以我不确定从 SQL Server 2019 或 SQL Server 2022 开始,UDFs-in-constraints 的当前状态CHECK在性能和正确性方面都处于单一状态。行和多行DML场景:

  • a 中的确定性标量 UDFCHECK不读取任何数据,但在列值上进行参数化(例如仅使用LIKE和 的字符串验证函数CHARINDEX)。
  • CHECKa 中执行 a 的标量 UDF SELECT * FROM $table,其中$table是应用约束的同一个表。CHECK
  • CHECKa 中执行 a 的标量 UDF SELECT * FROM $table,其中是不同的表(即与应用约束的$table表不同)。CHECK

作为 UDF-in-a- 的替代方案CHECK CONSTRAINT我一直在阅读有关使用索引视图作为有效实现某些类数据库范围(即跨表)完整性约束的方法,当任何 DML 修改数据时,这些约束总是强制执行的。任何包含的表,而约束仅对和CHECK生效,但不生效(因此约束不能用于阻止DML) - 但我很好奇是否有人有该技术的经验。INSERTUPDATEDELETECHECKDELETE

Zik*_*ato 2

部分答案。对内联标量函数的要求明确指出它不能位于计算列或检查约束中。

UDF 未在计算列或检查约束定义中使用