仅允许基于A列的值在B列中使用某些值

时间:2019-04-18 16:27:25

标签: sql sql-server constraints check-constraints

我想允许仅将一定数量的值插入到列A中,并且根据输入的值,只允许将一定数量的值插入到列B中。例如

例如

  • 如果A = 1,则B可以在1到9之间
  • 如果A = 2,则B可以在10到19之间
  • 如果A = 3,则B可以在20到29之间

我该如何实现?

我认为检查约束是最好的起点。一个简单的约束将确保只能将值1-3添加到列A中。如:

CREATE TABLE dbo.test (
    col_a INT, 
    col_b INT,
    CONSTRAINT ch_col_a_valid_range CHECK (col_a BETWEEN 1 AND 3)
)
GO

然后我认为使用标量函数通过将col_bcol_a中的值传入来确定col_b是否有效。

CREATE FUNCTION dbo.value_is_valid (
    @a INT, 
    @b INT
)
RETURNS BIT
AS 
BEGIN
    IF (@a = 1 AND @b BETWEEN 1 AND 9) RETURN 1;
    IF (@a = 2 AND @b BETWEEN 10 AND 19) RETURN 1;
    IF (@a = 3 AND @b BETWEEN 20 AND 29) RETURN 1;
    RETURN 0;
END
GO

然后将约束添加到表中,并在检查中调用函数。

CREATE TABLE dbo.test (
    col_a INT, 
    col_b INT,
    CONSTRAINT ch_col_a_valid_range CHECK (col_a BETWEEN 1 AND 3),
    CONSTRAINT ch_col_b_valid_based_on_a CHECK(dbo.value_is_valid(col_a, col_b) = 1)
)
GO

但是,以下插入操作失败,抱怨与添加的ch_col_b_valid_based_on_a约束冲突。

INSERT INTO dbo.test (
    col_a, 
    col_b
)
VALUES (1, 9)
  

INSERT语句与CHECK约束“ ch_col_b_valid_based_on_a”冲突。数据库“ MyDB”的表“ dbo.test”中发生了冲突。

该如何解决并获得上述结果?


回头看,这种在检查约束中使用标量函数的方法完全按预期工作。

2 个答案:

答案 0 :(得分:1)

一种方法是check约束:

CREATE TABLE dbo.test (
    col_a INT, 
    col_b INT,
    CONSTRAINT ch_col_a_valid_range CHECK (col_a BETWEEN 1 AND 3),
    CONSTRAINT chk_col_a_colb
        CHECK ( (col_a = 1 AND col_b BETWEEN 1 AND 9) OR
                (col_a = 2 AND col_b BETWEEN 10 AND 19) OR
                (col_a = 3 AND col_b BETWEEN 20 AND 29)
             )

);

但是,我可能倾向于创建一个带有有效对列表的AB_valid表,并使用外键约束。这样,可以动态维护有效值列表,而无需修改表定义。

答案 1 :(得分:0)

您可以使用一些数学方法来创建更简单的约束。

CREATE TABLE dbo.test (
    col_a INT, 
    col_b INT,
    CONSTRAINT ch_col_a_valid_range CHECK (col_a BETWEEN 1 AND 3),
    CONSTRAINT ch_col_b_valid_based_on_a CHECK(col_b/10 + 1 = col_a)
);