Oracle REGEXP_INSTR()和“ a-z”字符范围与预期不匹配

时间:2019-09-18 07:02:37

标签: sql regex oracle

我想在oracle数据库中使用REGEXP_INSTR()来检查小写/大写字符。我知道[:upper:][:lower:] POSIX字符类,但是我选择了a-z,这给了我我不明白的结果。有人可以解释吗?

SELECT REGEXP_INSTR('abc','[A-Z]',1,1,0,'c') FROM DUAL
-- Got 2, expected 0

SELECT REGEXP_INSTR('zyx','[A-Z]',1,1,0,'c') FROM DUAL
-- Got 1, expected 0

SELECT REGEXP_INSTR('ABC','[a-z]',1,1,0,'c') FROM DUAL
-- Got 1, expected 0

SELECT REGEXP_INSTR('ZYX','[a-z]',1,1,0,'c') FROM DUAL
-- Got 2, expected 0

SELECT REGEXP_INSTR('a3','[A-F0-9]',1,1,0,'c') FROM DUAL
-- Got 2, expected 2

SELECT REGEXP_INSTR('b3','[A-F0-9]',1,1,0,'c') FROM DUAL
-- Got 1, expected 2

SELECT REGEXP_INSTR('b3','[A-F0-9]') FROM DUAL
-- Got 1, expected 1 or 2

SELECT REGEXP_INSTR('a3','[A-F0-9]') FROM DUAL
-- Got 2, expected same as above

2 个答案:

答案 0 :(得分:1)

该行为的原因是排序规则。参见NLS_SORT documentation

  
      
  • 如果该值为BINARY,则ORDER BY查询的整理顺序基于字符的数字值(需要较少系统开销的二进制排序)。
  •   
  • 如果该值是命名的语言排序,则排序基于定义的语言排序的顺序。 NLS_LANGUAGE参数支持的大多数(但不是全部)语言也支持同名的语言排序。
  •   

NLS_SORT设置为BINARY,以便可以按与ASCII表相同的顺序来解析[A-Z]

alter session set nls_sort = 'BINARY'

然后,您将获得一致的结果。

请参见online demo

答案 1 :(得分:-1)

好的,NLS_SORT导致此行为的答案是正确的,但我认为它不能以一种可以理解的方式对其进行解释。我发现的任何文档都没有做到这一点……

您必须想象[a-z]定义的字符范围实际上是由所有可能的字符的单个子字符串派生的,这些子字符串根据NLS_SORT进行了排序。

让我们假设整个字母只是字母数字字符。按BINARY排序,这会产生类似于0123456789abcdefgh...xyzABCDE...XYZ的基本字符串。 因此,[0-6]扩展到[0123456][a-f]扩展到[abcdef][5-b]扩展到[56789ab]等。

linguistic_definition排序,但是会产生不同的基本字符串,例如0123456789aAbBcCdDeF...xXyYzZ。 因此,[0-6]仍扩展为[0123456],但是[a-f]现在扩展为[aAbBcCdDeEf][5-b]扩展为[56789aAb]等...

这就是a[A-Z]不匹配但b相匹配的原因。 [A-Z]实际上扩展为[AbBcC...yYzZ],其中包括z但不包括a

实际上,[A-Z]甚至可能包含更多字符,例如[aAàáâÀÁÂ...]等。