Oracle 18c - REGEXP_REPLACE 的替代方案

use*_*907 5 regex oracle indexing ddl oracle18c

迁移到Oracle 18c企业版后,无法创建基于函数的索引。

这是我的索引 DDL:

CREATE INDEX my_index ON my_table
(UPPER( REGEXP_REPLACE ("DEPT_NUM",'[^[:alnum:]]',NULL,1,0)))
TABLESPACE my_tbspace
PCTFREE    10
INITRANS   2
MAXTRANS   255
STORAGE    (
            INITIAL          64K
            MINEXTENTS       1
            MAXEXTENTS       UNLIMITED
            PCTINCREASE      0
            BUFFER_POOL      DEFAULT
           );
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

ORA-01743: only pure functions can be indexed
01743. 00000 -  "only pure functions can be indexed"
*Cause:    The indexed function uses SYSDATE or the user environment.
*Action:   PL/SQL functions must be pure (RNDS, RNPS, WNDS, WNPS).  SQL
           expressions must not use SYSDATE, USER, USERENV(), or anything
           else dependent on the session state.  NLS-dependent functions
           are OK.
Run Code Online (Sandbox Code Playgroud)

这是 18c 中的已知错误吗?如果不再支持这个基于函数的索引,那么编写这个函数的另一种方法是什么?

Chr*_*xon 5

问题是regexp_replace不是确定性的。更改 NLS 设置时会出现问题:

\n\n
alter session set nls_language = english;\n\nwith rws as (\n  select 'ST\xc3\x9cFF' v\n  from   dual\n)\n  select regexp_replace ( v, '[A-Z]+', '#' )\n  from   rws;\n\nREGEXP_REPLACE(V,'[A-Z]+','#')   \n#\xc3\x9c#  \n\nalter session set nls_language = german;\n\nwith rws as (\n  select 'ST\xc3\x9cFF' v\n  from   dual\n)\n  select regexp_replace ( v, '[A-Z]+', '#' )\n  from   rws;\n\nREGEXP_REPLACE(V,'[A-Z]+','#')   \n#     \n
Run Code Online (Sandbox Code Playgroud)\n\n

U-umlaut 位于英语字母表的末尾。但在德语的“U”之后。所以第一个语句没有取代它。第二个是。

\n\n

在 Oracle Database 12.1 及更早版本中,regexp_replace错误地标记为确定性。12.2 通过使其不确定来解决这个问题。

\n\n

仔细考虑任何解决方法是否可以正确管理变音符号。

\n\n

MOS 注释 2592779.1 进一步讨论了这一点。

\n


use*_*907 1

我发现最简单的解决方法是使用 NLS_UPPER 而不是 UPPER 创建索引:

CREATE INDEX my_index ON my_table
( REGEXP_REPLACE (NLS_UPPER("DEPT_NUM"),'[^[:alnum:]]',NULL,1,0)))
TABLESPACE my_tbspace
PCTFREE    10
INITRANS   2
MAXTRANS   255
STORAGE    (
            INITIAL          64K
            MINEXTENTS       1
            MAXEXTENTS       UNLIMITED
            PCTINCREASE      0
            BUFFER_POOL      DEFAULT
           );
Run Code Online (Sandbox Code Playgroud)