Oracle使用LENGTH和INSTR返回错误的值



我的目标是检索字符串中字符的位置,加上字符串的长度。

对于ticket_id等于1679467247的行,internal_notes表中notes字段的值实际上是"这是一个测试注释"。

当我使用这些函数来处理文本stings时,它们是有效的,但当我直接从表列中检索信息时,值就是错误的。

对可能发生的事情有什么想法吗?

select notes,
LENGTH(notes),
INSTR(notes,' ')
FROM   internal_notes
where  ticket_id = 1679467247
union
select 'this is a test note',
LENGTH('this is a test note'),
INSTR('this is a test note',' ')
from   dual

这将返回以下内容:

NOTES               LENGTH(NOTES) INSTR(NOTES,' ')
------------------- ------------- ----------------
this is a test note            32                11
this is a test note            19                5

如果值中有零宽度字符,则可能会出现这种明显的不一致性;例如:

create table internal_notes(ticket_id number, notes varchar2(32 char));
insert into internal_notes(ticket_id, notes)
values (1679467247, unistr('200c200cthis is a test note200c200c200c200c200c200c200c200c200c200c200c'));
insert into internal_notes(ticket_id, notes)
values (1679467248, unistr('200c200cthis is a test note'));
insert into internal_notes(ticket_id, notes)
values (1679467249, 'this is a test note');
select notes,
LENGTH(notes),
INSTR(notes,' ')
FROM   internal_notes
where  ticket_id = 1679467247;
NOTES                            LENGTH(NOTES) INSTR(NOTES,'')
-------------------------------- ------------- ---------------
‌‌this is a test note‌‌‌‌‌‌‌‌‌‌‌                         32               7

我说"明显不一致"是因为这些数字是正确的;如果你看不到一些角色,他们就不会看。不可见的字符仍然有效。

正如@MTO建议的那样,您可以使用dump()函数来准确查看表中存储的内容,以十进制或十六进制表示,或者与更容易解释的"正常"字符混合:

select notes,
LENGTH(notes),
INSTR(notes,' '),
dump(notes, 1000) as dmp
FROM   internal_notes;
NOTES                            LENGTH(NOTES) INSTR(NOTES,'')
-------------------------------- ------------- ---------------
DMP                                                                                                                                                                   
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
‌‌this is a test note‌‌‌‌‌‌‌‌‌‌‌                         32               7 
Typ=1 Len=58: e2,80,8c,e2,80,8c,t,h,i,s, ,i,s, ,a, ,t,e,s,t, ,n,o,t,e,e2,80,8c,e2,80,8c,e2,80,8c,e2,80,8c,e2,80,8c,e2,80,8c,e2,80,8c,e2,80,8c,e2,80,8c,e2,80,8c,e2,80,
8c                                                                                                                                                                    
‌‌this is a test note                         21               7 
Typ=1 Len=25: e2,80,8c,e2,80,8c,t,h,i,s, ,i,s, ,a, ,t,e,s,t, ,n,o,t,e                                                                                                 
this is a test note                         19               5 
Typ=1 Len=19: t,h,i,s, ,i,s, ,a, ,t,e,s,t, ,n,o,t,e                                                                                                                   

数据库<>fiddle——尽管这是将零宽度字符显示为问号,与SQLDeveloper和SQL*Plus不同。

其他零宽度字符也可用(空格、非joiner、joiner(,您可能会在转储中看到一些不同的东西——它必须是客户端根本不显示的东西。无论其中有什么,如果它影响所有行,而不仅仅是单个票证,那么如何以及为什么填充表可能取决于任何前端/应用程序-可能是由于字符集不匹配,但这可能是故意的。如果只是那张票,那么那张纸条就是一个有趣的测试。。。

最新更新