简体   繁体   English

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

[英]How to give a unique constraint to a combination of a column and a fixed value in Oracle?

I have a table with with 3 columns: A (number), B (number) and C (boolean).我有一个包含 3 列的表格:A(数字)、B(数字)和 C(布尔值)。

I would need to create a rule that would prevent records from being created with columns A and B and with C equal to true.我需要创建一个规则,以防止使用列 A 和 B 以及 C 等于 true 创建记录。 For example.例如。

This would be allowed:这将被允许:

A  B  C
1  2  true
1  2  false
1  2  false

But this, no:但是这个,不:

A  B  C
1  2  true
1  2  true
1  2  false

Use unique function based index , that process only rows with C = 'true' .使用基于唯一函数的 index ,仅处理C = 'true'

You must somehow combine the columns A and B - I use the string concatenation.您必须以某种方式组合A列和B列 - 我使用字符串连接。

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  

Slight variation on MarmiteBomber's approach, to avoid concatenating the values (which could cause accidental clashes with non-integer values): 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

Quick example of why non-integers (if they can exist) might be a problem:为什么非整数(如果它们可以存在)可能是一个问题的快速示例:

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 

... because for both '1.1' ||'.'|| '2' ... 因为对于'1.1' ||'.'|| '2' '1.1' ||'.'|| '2' and '1' ||'.'|| '1.2' '1.1' ||'.'|| '2''1' ||'.'|| '1.2' '1' ||'.'|| '1.2' resolve to the same string, '1.1.2' . '1' ||'.'|| '1.2'解析为相同的字符串'1.1.2'

This can also be a problem when combining string values rather than numbers.在组合字符串值而不是数字时,这也可能是一个问题。 In either case you can avoid it by using a delimiter which cannot exist in either value;在任何一种情况下,您都可以通过使用任何一个值中都不能存在的分隔符来避免它; harder to do with strings, but with numbers any punctuation other than a period (or comma to be safe) would probably do - unless someone has a weird setting for nls_numeric_characters ...处理字符串更难,但对于数字,除了句号(或逗号是安全的)之外的任何标点符号都可能会做 - 除非有人对nls_numeric_characters有一个奇怪的设置......

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

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