如何在 Oracle 中为列和固定值的组合提供唯一约束?

del*_*via 2 sql oracle constraints composite-key unique-constraint

我有一个包含 3 列的表格:A(数字)、B(数字)和 C(布尔值)。

我需要创建一个规则,以防止使用列 A 和 B 以及 C 等于 true 创建记录。例如。

这将被允许:

A  B  C
1  2  true
1  2  false
1  2  false
Run Code Online (Sandbox Code Playgroud)

但是这个,不:

A  B  C
1  2  true
1  2  true
1  2  false
Run Code Online (Sandbox Code Playgroud)

Mar*_*ber 5

使用基于唯一函数的索引,该索引仅处理带有C = 'true'.

您必须以某种方式组合列AB- 我使用字符串连接。

create unique index uq_true on test(case when c = 'true' then a||'.'||b end);

insert into test(a,b,c) values (1,2,'true');
insert into test(a,b,c) values (1,2,'false');
insert into test(a,b,c) values (1,2,'false');
insert into test(a,b,c) values (1,2,'true');
ORA-00001: unique constraint (DWH.UQ_TRUE) violated

select * from test;

         A          B C        
---------- ---------- ----------
         1          2 true       
         1          2 false      
         1          2 false  
Run Code Online (Sandbox Code Playgroud)


Ale*_*ole 5

MarmiteBomber 的方法略有不同,以避免连接值(这可能会导致与非整数值意外冲突):

create table t (a number, b number, c varchar2(5),
  constraint t_chk check (c in ('true', 'false'))
);

create unique index t_unq
on t (case when c = 'true' then a end, case when c = 'true' then b end);

insert into t(a,b,c) values (1,2,'true');

1 row inserted.

insert into t(a,b,c) values (1,2,'false');

1 row inserted.

insert into t(a,b,c) values (1,2,'false');

1 row inserted.

insert into t(a,b,c) values (1,2,'true');

ORA-00001: unique constraint (MY_SCHEMA.T_UNQ) violated

select * from t;

         A          B C    
---------- ---------- -----
         1          2 true 
         1          2 false
         1          2 false
Run Code Online (Sandbox Code Playgroud)

为什么非整数(如果可以存在)可能会成为问题的简单示例:

create unique index uq_true on test(case when c = 'true' then a||'.'||b end);

insert into test(a,b,c) values (1.1, 2,'true');

1 row inserted.

insert into test(a,b,c) values (1, 1.2,'true');

ORA-00001: unique constraint (MY_SCHEMA.UQ_TRUE) violated

select * from test;

         A          B C    
---------- ---------- -----
       1.1          2 true 
Run Code Online (Sandbox Code Playgroud)

...因为对于两者'1.1' ||'.'|| '2''1' ||'.'|| '1.2'解析为相同的字符串,'1.1.2'.

当组合字符串值而不是数字时,这也可能是一个问题。在任何一种情况下,您都可以通过使用不能存在于任一值中的分隔符来避免这种情况;对于字符串来说很难做到,但是对于数字来说,除了句点(或者安全起见,逗号)之外的任何标点符号都可能会做 - 除非有人有一个奇怪的设置nls_numeric_characters......