忽略空间的Oracle唯一约束和唯一索引

Posted

技术标签:

【中文标题】忽略空间的Oracle唯一约束和唯一索引【英文标题】:Oracle unique constraint and unique index which ignoreing space 【发布时间】:2019-06-10 12:15:42 【问题描述】:

我使用过 Oracle 11g 和一些表,使用下面的命令在忽略所有空白的特定列上创建唯一索引。

CREATE UNIQUE INDEX UK_LOCATION_NAME ON LOCATION(UPPER(REGEXP_REPLACE("FARSI_NAME",'\s+','')));

最近Oracle数据库更新到12c,执行上述命令报错:

[2019-06-08 19:44:08] [42000][1743] ORA-01743:只能索引纯函数

如何定义一个忽略空格(空格、制表符、...)的唯一索引?

【问题讨论】:

【参考方案1】:

在 Oracle 11g 中允许您在基于函数的索引中使用 REGEXP_REPLACE 的原因似乎是它仅在 Oracle 11g 中是一个错误,并且可能在 12.1 中也是如此。它自 Oracle 12.2 以来已得到修复,因此它不允许您创建直接使用 REGEXP_REPLACE 的索引。原因是它是一个 Non-deterministic 函数。

CHECK 约束也存在类似问题,已在 this post 上进行了详细讨论。

在您的情况下,如果您只是替换空格,则使用 REPLACE 的更简单方法就足够了。

CREATE UNIQUE INDEX UK_LOCATION_NAME 
     ON LOCATION(UPPER(replace("FARSI_NAME",' ')));

当您的替换模式很复杂时,解决此问题的另一个选择是使用替代函数DETERMINISTIC。这是一种解决方法,对于复杂的场景可能效率不高。

create or replace function my_regex_rep(txt_in VARCHAR2) 
return VARCHAR2 DETERMINISTIC IS
 BEGIN
   return regexp_replace(txt_in,'\s+','');
 END;
 /

现在,您可以在INDEX 中使用此功能。

CREATE UNIQUE INDEX UK_LOCATION_NAME ON 
     LOCATION(UPPER(my_regex_rep("FARSI_NAME")));

测试

INSERT INTO LOCATION(FARSI_NAME) values('ABCD EFGH');
1 row inserted.

INSERT INTO LOCATION(FARSI_NAME) values('   ABCD      efgh  ');
                                              --spaces
ORA-00001: unique constraint (HR.UK_LOCATION_NAME) violated

INSERT INTO LOCATION(FARSI_NAME) values('ABCD   EFGh');
                                           --tab

ORA-00001: unique constraint (HR.UK_LOCATION_NAME) violated

Oracle 18c DEMO

【讨论】:

第一个解决方案不好,因为无法检查\n,\t。但第二种解决方案有效。能否详细描述一下您的意思,它对于复杂的场景可能效率不高? @M-Razavi :我的意思是,与 replacetranslate 等内置函数相比,REGEXP 的处理速度较慢。因此,对于包含此索引的大表,虽然选择可能会改进,DML(更新和插入)将大大减慢,因为为保持行的唯一性而评估的表达式变得复杂。因此,更好的方法是重新设计表结构以使用不依赖于用户输入的备用unique key。另一种选择是保持列表达式更简单,并使用应用程序控制插入和更新以过滤掉此类记录。

以上是关于忽略空间的Oracle唯一约束和唯一索引的主要内容,如果未能解决你的问题,请参考以下文章

Oracle数据库主键约束与唯一索引有啥区别?

Oracle数据库主键约束与唯一索引有啥区别?

Oracle索引总结- Oracle唯一索引普通索引及约束的关系

oracle唯一索引与普通索引的区别和联系以及using index用法

唯一性约束和唯一性索引的区别

oracle 数据库中主键索引和唯一索引有啥区别