REGEXP_LIKE中的CHR(0)

时间:2016-05-26 12:49:38

标签: oracle oracle11g oracle10g

我正在使用查询来检查chr(0)在regexp_like中的行为。

CREATE TABLE t1(a char(10));
INSERT INTO t1 VALUES('0123456789');
SELECT CASE WHEN REGEXP_LIKE(a,CHR(0)) THEN 1 ELSE 0 END col, DUMP(a)  
FROM t1;

我得到的输出是这样的 -

col                     dump(a)
-----------             -----------------------------------
 1                     Typ=96 Len=10: 48,49,50,51,52,53,54,55,56,57

我完全感到困惑,如果没有转储(a)所示的chr(0),regexp_like如何在列中找到chr(0)并返回1?它不应该在这里返回0吗?

3 个答案:

答案 0 :(得分:3)

CHR(0)是用于在C编程语言中终止字符串的字符(等等)。

当你将CHR(0)传递给函数时,它会将它传递给更低级别的函数,该函数将解析你传入的字符串并从该字符串构建正则表达式模式。这个正则表达式模式将看到CHR(0)并认为它是字符串终止符并忽略模式的其余部分。

使用REGEXP_REPLACE

更容易看到这种行为
SELECT REGEXP_REPLACE( 'abc' || CHR(0) || 'e', CHR(0), 'd' )
FROM   DUAL;

运行时会发生什么:

  • CHR(0)被编译成正则表达式并成为字符串终止符。
  • 现在模式只是字符串终止符,因此模式是一个零长度字符串。
  • 然后将正则表达式与输入字符串进行匹配,并读取第一个字符a并找到一个零长度字符串,可以在a之前匹配,以便它替换之前匹配的任何内容a d给出输出da
  • 然后重复下一个字符,将b转换为db
  • 等等,直到达到字符串结尾时,它将与零长度模式匹配并附加最终d

你会得到输出:

dadbdcd_ded

其中_是CHR(0)字符。

注意:输入中的CHR(0)不会被替换。

如果您使用的客户端程序也截断了CHR(0)处的字符串,则可能看不到整个输出(这是客户端如何表示字符串而不是Oracle输出的问题)但它也可以使用DUMP()显示:

SELECT DUMP( REGEXP_REPLACE( 'abc' || CHR(0) || 'e', CHR(0), 'd' ) )
FROM DUAL;

输出:

Typ=1 Len=11: 100,97,100,98,100,99,100,0,100,101,100

[TL; DR] 那么

正在发生什么
REGEXP_LIKE( '1234567890', CHR(0) )

它将生成一个零长度的字符串正则表达式模式,它将在1字符之前查找零长度匹配 - 它将找到它,然后返回它已找到匹配项。

答案 1 :(得分:2)

Aleksej打败了我,但是CHR(0)是字符串终结符的值(类似于NULL关键字但不完全相同)。可以把它想象成CHR(0)显然可以看到的内部字符串结尾指示符。请注意,如果您使用关键字NULL尝试查询,它将返回零,因为没有任何东西可以与NULL进行比较,因此比较将失败(正如您所期望的那样)。有趣。或许对内部工作更有经验的人可以进一步解释,我很想知道更多。

答案 2 :(得分:1)

不是答案,只是一些实验,但评论时间太长了。

REGEXP_COUNT似乎被chr(0)混淆,将每个字符计为chr(0);此外,它似乎找到一个超过字符串大小的事件。

SQL> select dump('a'), regexp_count('a', chr(0)) from dual;

DUMP('A')        REGEXP_COUNT('A',CHR(0))
---------------- ------------------------
Typ=96 Len=1: 97                        2

SQL> select dump(chr(0)), regexp_count(chr(0), chr(0)) from dual;

DUMP(CHR(0))   REGEXP_COUNT(CHR(0),CHR(0))
-------------- ---------------------------
Typ=1 Len=1: 0                           2

SQL> select dump('0123456789' || chr(0)), regexp_count('0123456789' || chr(0), chr(0)) from dual;

DUMP('0123456789'||CHR(0))                    REGEXP_COUNT('0123456789'||CHR(0),CHR(0))
--------------------------------------------- -----------------------------------------
Typ=1 Len=11: 48,49,50,51,52,53,54,55,56,57,0                                        12

LIKE似乎有一个好的行为,而它的REGEXP版本似乎失败了:

SQL> select 1 from dual where 'a' like '%' || chr(0) || '%';

no rows selected

SQL> select 1 from dual where regexp_like ('a', chr(0));

         1
----------
         1

INSTRREGEXP_INSTR

也是如此
SQL> select 1 from dual where instr('a', chr(0)) != 0;

no rows selected

SQL> select 1 from dual where regexp_instr('a', chr(0)) != 0;

         1
----------
         1

在11g XE版本11.2.0.2.0上测试 - 64位

相关问题