Search code examples
oracle-databaseoracle12cunique-constraint

Oracle unique constraint and unique index which ignoreing space


I've used Oracle 11g and for some of the tables, used below command to create a unique index on specific column which ignores all white space.

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

Recently, The Oracle database is updated to 12c and executing the mentioned command raise an error:

[2019-06-08 19:44:08] [42000][1743] ORA-01743: only pure functions can be indexed

How can define a unique index which ignores white spaces(spaces, tab, ...)?


Solution

  • It seems the reason you were allowed to use REGEXP_REPLACE in a function based index in Oracle 11g was that it was a bug only in Oracle 11g and probably in 12.1 as well. It has been fixed since Oracle 12.2 and hence it won't allow you to create an index that uses REGEXP_REPLACE directly. The reason being it's a Non-deterministic function.

    A similar issue exists with CHECK constraint too and has been discussed in detail over this post.

    In your case, a simpler approach using REPLACE should be sufficient if you're only replacing spaces.

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

    The Other option to get around this problem when your replacement pattern is complex is to use an alternative function that's DETERMINISTIC. This is a workaround and may not be efficient for complex scenarios.

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

    Now, you are allowed to use this function in the INDEX.

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

    Testing

    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