首页 > 解决方案 > 是否可以实现特定于行的检查约束?

问题描述

我有一个表,其中每一行代表一个键值对,其中包含特定于应用程序的设置(例如保留警报的天数等)。这些键值对中的每一个都具有不同范围的有效值,因此没有单一的检查约束将同样适用于所有行。有些行可能根本不需要验证,而其他行可能有需要特别考虑的字符串值。有什么方法可以在每行的基础上创建一个检查约束,并在更新该行时强制执行该约束?

我曾多次尝试实现这一目标,但每次都遇到障碍。每次尝试都依赖于表上是否存在 [Check] 列,其中为该行定义了约束,类似于普通的基于表的约束(例如“((CAST Value AS INTEGER) <= 60)”) .

我的第一次尝试是创建一个普通的检查约束,它调用一个用户定义的函数,该函数读取 [Check] 列的内容(基于标识值),执行约束测试,并返回真/假结果,取决于是否违反了约束。这种方法的问题是它需要编写动态 SQL 来获取 [Check] 列的内容以及执行它包含的代码。但当然,函数中不允许使用动态 SQL。

接下来,我尝试将函数更改为存储过程,但似乎无法通过检查约束调用存储过程。

最后,我尝试创建一个函数和一个存储过程,并从函数中调用存储过程,但这也是不允许的。

我知道可行的唯一方法是编写一个巨大的整体检查约束,包含按标识值对每一行进行的检查,所有 OR'ed 在一起,如下所示:

(ID = 1 AND (CAST Value AS INTEGER) <= 100) OR (ID = 2 AND Value IN ('yes', 'no')) OR...

但这是一个容易出错的维护噩梦。有没有人知道一种方法来完成我想要的,而不诉诸整体检查约束?

根据要求,考虑下表定义和一些示例行:

CREATE TABLE [dbo].[GenericSetting]
(
  [ID] [INT] IDENTITY(1,1) NOT NULL,
  [Name] [NVARCHAR](50) NOT NULL,
  [Value] [NVARCHAR](MAX) NULL,
  [Check] [NVARCHAR](MAX) NULL,
  CONSTRAINT [PK_GenericSetting] PRIMARY KEY CLUSTERED ([ID])
)

INSERT INTO [dbo].[GenericSetting] ([Name],[Value],[Check]) VALUES ('AlertRetentionDays', 60, 'CAST(Value AS INTEGER) <= 60');
INSERT INTO [dbo].[GenericSetting] ([Name],[Value],[Check]) VALUES ('ExampleMode', 60, 'CAST(Value AS INTEGER) IN (1,2,5)');

标签: sqlsql-servercheck-constraints

解决方案


您需要在此表上创建触发器才能完成此任务。


推荐阅读