我有以下带有正则表达式的查询:
select REGEXP_REPLACE ('TEST 3304 V2', '[`~!@#$%^&*()_+-={}|;.:<>?,./]', ' ') as REG
from dual;
当在 Windows 机器上通过 SQL*Plus 执行时,它返回以下内容:
SQL> select REGEXP_REPLACE ('TEST 3304 V2', '[`~!@#$%^&*()_+-={}|;.:<>?,./]', ' ') as REG from dual;
REG
------------
TEST 3304 V2
在 SunOS 机器上,我得到了不同的结果:
SQL> select REGEXP_REPLACE ('TEST 3304 V2', '[`~!@#$%^&*()_+-={}|;.:<>?,./]', ' ') as REG from dual;
REG
------------
TEST V
这些查询针对同一 Oracle 服务器运行。输出差异有什么原因吗?
Windows 上的 SQL*Plus 版本:
SQL*Plus: Release 11.2.0.1.0 Production on Mar. Oct. 14 15:36:35 2014
Copyright (c) 1982, 2010, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Unix 上的 SQL*Plus 版本:
SQL*Plus: Release 11.2.0.2.0 Production on Tue Oct 14 16:01:26 2014
Copyright (c) 1982, 2010, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
最佳答案
正如 Avinash Raj 在评论中所说,正则表达式模式中的连字符被解释为一个范围。该行为似乎取决于两个客户端使用的排序算法,该算法基于 NLS_LANG 环境变量,该变量会影响 NLS_SORT 值。
使用NLS_LANG=ENGLISH_UNITED KINGDOM.WE8ISO8859P1
:
SQL> select REGEXP_REPLACE ('TEST 3304 V2', '[`~!@#$%^&*()_+-={}|;.:<>?,./]', ' ') as REG from dual;
REG
------------
TEST V
SQL> select value from nls_session_parameters where parameter = 'NLS_SORT';
VALUE
----------
BINARY
冒险外出,因为您的个人资料显示您在摩洛哥,NLS_LANG="ARABIC_MOROCCO.AR8MSWIN1256"
:
SQL> select REGEXP_REPLACE ('TEST 3304 V2', '[`~!@#$%^&*()_+-={}|;.:<>?,./]', ' ') as REG from dual;
REG
------------
TEST 3304 V2
SQL> select value from nls_session_parameters where parameter = 'NLS_SORT';
VALUE
----------
ARABIC
原因是模式段+-=
被视为涵盖从+
到=
的所有字符的范围。在 ISO8859-1 和 Windows 1252 character set 中即字符 43 到 61,并且所有数字都在该范围内 - 例如零是 48 - 都在该范围内,因此正则表达式会替换它们。 Windows 1256 character set 中也是如此。 。 (以及任何基于 ASCII 的内容)。
但是您的 NLS_LANG 也在隐式更改排序顺序,并且从 BINARY 切换到 ARABIC 排序会改变行为。您可以在单个 session 中看到这一点;与NLS_LANG=ENGLISH_UNITED KINGDOM.WE8ISO8859P1
:
SQL> select REGEXP_REPLACE ('TEST 3304 V2', '[`~!@#$%^&*()_+-={}|;.:<>?,./]', ' ') as REG from dual;
REG
------------
TEST V
SQL> alter session set NLS_SORT=ARABIC;
Session altered.
SQL> select REGEXP_REPLACE ('TEST 3304 V2', '[`~!@#$%^&*()_+-={}|;.:<>?,./]', ' ') as REG from dual;
REG
------------
TEST 3304 V2
也可以通过稍微修改范围来判断是范围问题;将 +-=
更改为 +-3
,以便不包含更高的数字,但其他所有内容保持不变:
SQL> alter session set NLS_SORT=BINARY;
Session altered.
SQL> select REGEXP_REPLACE ('TEST 3304 V2', '[`~!@#$%^&*()_+-3{}|;.:<>?,./]', ' ') as REG from dual;
REG
------------
TEST 4 V
Read more about linguistic sorting .
依赖 NLS 设置总是有风险的,因此最好通过更改模式以在开头或结尾使用连字符来完全避免范围问题,这样就根本不会将其视为范围;再次按照 Avinash Raj 的建议。
关于regex - 具有连字符的 Oracle 正则表达式在 Windows 上给出的结果与 Unix 上的结果不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26363671/