我发现了这个:Unique constraint on multiple columns
SQL> CREATE TABLE t (id1 NUMBER, id2 NUMBER);
Table created
SQL> ALTER TABLE t ADD CONSTRAINT u_t UNIQUE (id1, id2);
Table altered
SQL> INSERT INTO t VALUES (1, NULL);
1 row inserted
SQL> INSERT INTO t VALUES (1, NULL);
INSERT INTO t VALUES (1, NULL)
ORA-00001: unique constraint (VNZ.U_T) violated
我想创建一个允许输入多个(X,null)值的约束,以便约束仅在约束所涉及的BOTH值不为空时启动。这可能吗?
答案 0 :(得分:3)
在这种情况下你需要一个CHECK约束:
ALTER TABLE t ADD CONSTRAINT chk_t CHECK (id1 is null or id2 is null);
如果您需要一个独特的约束行为,您可以尝试这样做:
drop table t1;
create table t1 (n number, m number);
create unique index t_inx on t1(case when n is null then null when m is null then null else n || '_' || m end);
insert into t1 values (1, null);
insert into t1 values (1, null);
insert into t1 values (null, 1);
insert into t1 values (null, 1);
insert into t1 values (1, 1);
insert into t1 values (1, 1);
insert into t1 values (1, 2);
基于唯一函数的索引
答案 1 :(得分:3)
请注意,您可以插入多个(NULL,NULL),但不能插入多个(1,NULL)。这就是索引在Oracle中的工作方式;当所有列都为null时,索引中没有条目。
因此,不是在(id1,id2)上构建正常索引,而是必须构建一个函数索引,当至少一个为null时,使两个值都为null。我们需要确定性的功能。第一个要检查null的DECODE。然后使用GREATEST,当至少有一个值为null时,使用它会导致null:
create unique index idx_t_unique on t
(
decode(greatest(id1,id2),null,null,id1),
decode(greatest(id1,id2),null,null,id2)
);
编辑(接受后:-)我只是看,你不需要确定性函数,但也可以使用案例结构。也许情况总是如此,也许不是,我不知道。但是,如果您发现索引更具可读性,也可以按如下方式编写索引:
create unique index idx_t_unique on t
(
case when id1 is null or id2 is null then null else id1 end,
case when id1 is null or id2 is null then null else id2 end
);