我正在使用查询来检查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吗?
答案 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
INSTR
和REGEXP_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位