简体   繁体   English

多列的唯一约束-允许单个null

[英]Unique constraint on multiple columns - allow for single null

I found this: 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

I want to create a constraint that allows to enter several (X,null) values, so that the constraint only kicks in when BOTH values that the constraint is about are not null. 我想创建一个允许输入多个(X,null)值的约束,以便仅在该约束所涉及的两个值都不为null时才启动该约束。 Is this possible? 这可能吗?

Note that you can insert multiple (NULL,NULL), but not multiple (1,NULL). 请注意,您可以插入多个(NULL,NULL),但不能插入多个(1,NULL)。 This is how indexes work in Oracle; 这就是索引在Oracle中的工作方式。 when all columns are null, then there is no entry in the index. 当所有列都为null时,索引中没有条目。

So rather than building a normal index on (id1,id2) we must build a function index that makes both values null when at least one is null. 因此,不是在(id1,id2)上构建正常索引,而是必须构建一个函数索引,当至少一个为null时,使两个值都为null。 We need deterministic functions for this. 我们需要确定性的功能。 First DECODE to check for null. 首先进行DECODE以检查是否为空。 Then GREATEST, making use of it resulting in null when at least one value is null: 然后是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) 
);

EDIT (after acceptance :-) I just see, you don't need deterministic functions, but can also use case constructs. 编辑(接受后:-)我只是看,你不需要确定性函数,但也可以使用案例结构。 Maybe that was always the case, maybe not, I don't know. 也许情况总是如此,也许不是,我不知道。 However, you can also write the index as follows, if you find it more readable: 但是,如果您发现索引更具可读性,也可以按如下方式编写索引:

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
);

You need a CHECK constraint in this case: 在这种情况下,您需要CHECK约束:

ALTER TABLE t ADD CONSTRAINT chk_t CHECK (id1 is null or id2 is null);

If you need a unique constraint behaviour you may try this: 如果您需要独特的约束行为,则可以尝试以下操作:

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);

A unique function based index 基于唯一功能的索引

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM