基于另一个表中另一列的值对列的约束

1 database sql-server constraints

我有表 A,它有两列策略和规则。表值如下:

policy | rule
-------------
1  | A
-------------
1  | B
-------------
2  | C
-------------
3  | D 
-------------
Run Code Online (Sandbox Code Playgroud)

我有另一个带有列(id)的表 B。

我想在这个表 B 的列 (id) 上写一个约束,这样如果表 A 中的不同策略的数量等于 1,那么 (id) 的值应该始终为 NULL。

我正在使用 SQL Server,并且正在寻找基于查询的解决方案(不是通过 GUI 步骤)。

小智 5

将 CHECK 约束添加到表中

create table tableA (policy int , [rule] char(1)) 
create table tableB (Id int , policy int ) 
GO
Run Code Online (Sandbox Code Playgroud)

检查约束的函数

CREATE FUNCTION CheckFnctn(@policy int) -- Adapt if necessary
RETURNS bit
AS 
BEGIN
DECLARE @retval bit = 1
IF EXISTS(SELECT TOP 1 1 FROM tableA WHERE policy = @policy and policy = 1)
BEGIN
    RETURN 0
END
RETURN @retval

END;
GO
Run Code Online (Sandbox Code Playgroud)

将约束添加到表中

ALTER TABLE tableB ADD CONSTRAINT ck_id_policy_1 CHECK (dbo.CheckFnctn(policy) = 1) 
Run Code Online (Sandbox Code Playgroud)

测试

    INSERT tableA Values
     (1,'A')
    ,(1,'B')
    ,(2,'B')
    ,(2,'D')
GO
    (4 row(s) affected)


INSERT tableB (Id, policy) values (1,2)
GO
(1 row(s) affected)


INSERT tableB (Id, policy) values (1,1)
GO
Msg 547, Level 16, State 0, Line 2
The INSERT statement conflicted with the CHECK constraint "ck_id_policy_1". The conflict occurred in database "XXXX", table "dbo.tableB", column 'policy'.
The statement has been terminated.
Run Code Online (Sandbox Code Playgroud)

如果您需要检查策略 1 是否存在,则永远不能插入与 null 不同的 Id。使用这个函数和约束

CREATE FUNCTION CheckFnctn(@Id int)
RETURNS bit
AS 
BEGIN
DECLARE @retval bit = 1
IF EXISTS(SELECT TOP 1 1 FROM tableA WHERE  policy = 1 AND @Id IS NOT NULL)
BEGIN
    RETURN 0
END
RETURN @retval

END;
GO



ALTER TABLE tableB ADD CONSTRAINT ck_id_policy_1 CHECK (dbo.CheckFnctn(Id) = 1) 

INSERT tableB (Id, policy) values (1,2)
GO
Msg 547, Level 16, State 0, Line 3
The INSERT statement conflicted with the CHECK constraint "ck_id_policy_1". The conflict occurred in database "XXXXX", table "dbo.tableB", column 'Id'.
The statement has been terminated.

INSERT tableB (Id, policy) values (NULL,1)
GO
(1 row(s) affected)
Run Code Online (Sandbox Code Playgroud)