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 中的已知错误吗?如果不再支持这个基于函数的索引,那么编写这个函数的另一种方法是什么?
问题是regexp_replace不是确定性的。更改 NLS 设置时会出现问题:
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# \nRun Code Online (Sandbox Code Playgroud)\n\nU-umlaut 位于英语字母表的末尾。但在德语的“U”之后。所以第一个语句没有取代它。第二个是。
\n\n在 Oracle Database 12.1 及更早版本中,regexp_replace被错误地标记为确定性。12.2 通过使其不确定来解决这个问题。
仔细考虑任何解决方法是否可以正确管理变音符号。
\n\nMOS 注释 2592779.1 进一步讨论了这一点。
\n我发现最简单的解决方法是使用 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)