SQL(在我的例子中是 SQL Server)如何评估多个列上的唯一约束?

Cat*_*han 1 sql-server check-constraints unique-constraint

给出下表

CREATE TABLE example (
    id int NOT NULL IDENTITY(1,1),
    strA NVARCHAR(10) NULL,
    strB NVARCHAR(10) NULL,
  CONSTRAINT [pk_id] PRIMARY KEY (id)
  CONSTRAINT [unq_str_combo] UNIQUE (strA, strB)
  CONSTRAINT [chk_one_is_null] CHECK ((strA IS NULL AND strB IS NOT NULL) OR (strA IS NOT NULL AND strB IS NULL))
);
Run Code Online (Sandbox Code Playgroud)

SQL 如何确定 strA 和 strB 列中的值组合是否是唯一组合?

以下任何INSERT陈述是否会失败?

INSERT INTO dbo.example (strA, strB) VALUES ('abc', NULL);    -- A
INSERT INTO dbo.example (strA, strB) VALUES (NULL, 'def');    -- B
INSERT INTO dbo.example (strA, strB) VALUES (NULL, 'abc');    -- C
INSERT INTO dbo.example (strA, strB) VALUES ('def', NULL);    -- D
Run Code Online (Sandbox Code Playgroud)

有没有办法在表创建期间(或通过ALTER TABLE)添加检查或其他一些约束,以使INSERT语句 forCD失败?

Pau*_*ite 7

SQL 如何确定 strA 和 strB 列中的值组合是否是唯一组合?

两列分别进行比较。如果对于两个不同的行,两个strA值比较相等且两个strB值比较相等,则违反 ( strA , strB ) 上的唯一性。

在 SQL Server 中,在检查唯一索引和约束时,NULL 与另一个 NULL 进行比较。这不是 SQL 标准规定的 NULL 行为,但它不会改变。

有没有办法在表创建期间(或通过ALTER TABLE)添加检查或其他一些约束,以使INSERT语句 forCD失败?

这可以通过计算列上的唯一约束来完成:

CREATE TABLE example 
(
    id int NOT NULL IDENTITY(1,1),
    strA nvarchar(10) NULL,
    strB nvarchar(10) NULL,
    string AS COALESCE(strA, strB) 
        CONSTRAINT [unique strA strB] UNIQUE,

    CONSTRAINT [pk_id] PRIMARY KEY (id),
    CONSTRAINT [chk_one_is_null] CHECK (
        (strA IS NULL AND strB IS NOT NULL) 
        OR (strA IS NOT NULL AND strB IS NULL))
);
Run Code Online (Sandbox Code Playgroud)


Dan*_*man 6

对互斥的 StrA 和 StrB 列实现唯一约束的一种方法是在计算列上使用唯一索引。下面的示例使用此方法而不是问题中的复合列唯一约束。

CREATE TABLE example (
    id int NOT NULL IDENTITY(1,1),
    strA NVARCHAR(10) NULL,
    strB NVARCHAR(10) NULL,
    str_combo AS COALESCE(strA,strB)
  CONSTRAINT [pk_id] PRIMARY KEY (id)
  ,CONSTRAINT [unq_str_combo] UNIQUE (str_combo)
  ,CONSTRAINT [chk_one_is_null] CHECK ((strA IS NULL AND strB IS NOT NULL) OR (strA IS NOT NULL AND strB IS NULL))
);

INSERT INTO dbo.example (strA, strB) VALUES ('abc', NULL);    -- A
INSERT INTO dbo.example (strA, strB) VALUES (NULL, 'def');    -- B
INSERT INTO dbo.example (strA, strB) VALUES (NULL, 'abc');    -- C
INSERT INTO dbo.example (strA, strB) VALUES ('def', NULL);    -- D
Run Code Online (Sandbox Code Playgroud)

结果:

(1 row affected)

(1 row affected)
Msg 2627, Level 14, State 1, Line 14
Violation of UNIQUE KEY constraint 'unq_str_combo'. Cannot insert duplicate key in object 'dbo.example'. The duplicate key value is (abc).
The statement has been terminated.
Msg 2627, Level 14, State 1, Line 15
Violation of UNIQUE KEY constraint 'unq_str_combo'. Cannot insert duplicate key in object 'dbo.example'. The duplicate key value is (def).
The statement has been terminated.
Run Code Online (Sandbox Code Playgroud)