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;
我对 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;