Oracle UNIQUE 约束允许在不同情况下使用相同的值

Oracle UNIQUE constraint allows same value in different case

我对 Oracle 数据库中的列有一个 UNIQUE 约束 table。允许保存大小写相同的值。

例如; 首先,我将 M100 插入到 table 的 UNIQUE 列中。然后,当我再次尝试插入 M100 时,我可以看到违反唯一约束的错误。

但是当我尝试插入 m100 时,数据库接受并保存到 table.

我该如何解决这个问题。无论如何我都需要限制该值。

我用的是以下版本

"Oracle Database 18c Express Edition Release 18.0.0.0.0 - Production
Version 18.4.0.0.0"

这里是Live SQL

尝试将基于函数的索引添加到 table

CREATE UNIQUE INDEX some_index_name
ON tablename(UPPER(column_name));

由于您使用的是 Oracle 18,因此您可以使用新功能,例如不可见列和虚拟列或 collation:

虚拟不可见列+唯一约束: 例如,您有一个 table T 列 STR:

create table t(str varchar2(10));

因此您可以添加不可见的虚拟列 str_lower 生成为 lower(str):

alter table t add 
      str_lower varchar2(10) invisible generated always as (lower(str)) ;

由于此列是不可见的和虚拟的,因此不会破坏您现有的代码。 现在您可以对其添加 unique 约束:

alter table t add
      constraint t_str_unique_lower
         unique(str_lower) using index;

正在测试:

SQL> insert into t values('M100');

1 row created.

SQL> insert into t values('m100');
insert into t values('m100')
*
ERROR at line 1:
ORA-00001: unique constraint (XTENDER.T_STR_UNIQUE_LOWER) violated

此外,它可以让您轻松地按较低的值查找值:

SQL> select * from t where str_lower='m100';

STR
----------
M100

SQL> select str,str_lower from t where str_lower='m100';

STR        STR_LOWER
---------- ----------
M100       m100

如您所见,如果您未在 select-list:

中指定它,则它没有 return str_lower 列

另一种可能的解决方案是为您的列指定collation,但它需要将数据库参数MAX_STRING_SIZE设置为EXTENDED,否则你会得到 ORA-43929: Collation cannot be specified if parameter MAX_STRING_SIZE=STANDARD is set.

alter table t modify str COLLATE BINARY_CI;
alter table t add constraint t_str_unique unique(str);

更多相关信息: https://oracle-base.com/articles/12c/column-level-collation-and-case-insensitive-database-12cr2

之前的两个答案都很好,但根据业务案例,还有另一个可能有意义的选项。有时您的数据不区分大小写(例如电子邮件地址),因此请始终使用触发器将其存储在相同的大小写中。

那么唯一约束将起作用并且您的数据更清晰。这种触发器的一个例子是:

create or replace TRIGGER t_biu BEFORE
  INSERT OR UPDATE ON t
  FOR EACH ROW
DECLARE
BEGIN
  :NEW.column_name := UPPER(:NEW.column_name);
END t_biu;