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

时间:2019-06-10 12:15:42

标签: oracle oracle12c unique-constraint

我已经使用了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 个答案:

答案 0 :(得分:3)

在Oracle 11g中基于功能的索引中被允许使用REGEXP_REPLACE的原因似乎是,它仅在Oracle 11g中以及在12.1中才是错误。自Oracle 12.2起,此问题已得到修复,因此不允许您创建直接使用REGEXP_REPLACE的索引。原因是它是不确定性函数。

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