暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 与CHAR值比较后,选定的VARCHAR2值会更改?

askTom 2017-09-07
233

问题描述

希亚,汤姆斯

我偶然发现了一件我觉得有点奇怪的事情。我在LiveSQL做了这个测试脚本:

create table ch ( ch char(10) );

create table vc ( vc varchar2(10) );

insert into ch values ('MICKEY');

insert into ch values ('MICKEY  ');

insert into ch values ('MICKEY    ');

insert into vc values ('MICKEY');

insert into vc values ('MICKEY  ');

insert into vc values ('MICKEY    ');

commit;

select ch, dump(ch) as ch_dump
from ch;

select vc, dump(vc) as vc_dump
from vc;

select ch, dump(ch) as ch_dump
     , vc, dump(vc) as vc_dump
from ch
join vc
   on vc.vc = ch.ch;
复制


当我选择CH列的转储时,我得到的预期输出都是10个字符长 (米奇加4个空格。)

CH         CH_DUMP
MICKEY     Typ=96 Len=10: 77,73,67,75,69,89,32,32,32,32
MICKEY     Typ=96 Len=10: 77,73,67,75,69,89,32,32,32,32
MICKEY     Typ=96 Len=10: 77,73,67,75,69,89,32,32,32,32
复制


当我选择VC列的转储时,我还分别得到6、8和10个字符的预期输出。

VC         VC_DUMP
MICKEY     Typ=1 Len=6: 77,73,67,75,69,89
MICKEY     Typ=1 Len=8: 77,73,67,75,69,89,32,32
MICKEY     Typ=1 Len=10: 77,73,67,75,69,89,32,32,32,32
复制


join返回意外输出 (至少对我来说是意外的;-)

CH         CH_DUMP                                      VC         VC_DUMP
MICKEY     Typ=96 Len=10: 77,73,67,75,69,89,32,32,32,32 MICKEY     Typ=1 Len=10: 77,73,67,75,69,89,32,32,32,32
MICKEY     Typ=96 Len=10: 77,73,67,75,69,89,32,32,32,32 MICKEY     Typ=1 Len=10: 77,73,67,75,69,89,32,32,32,32
MICKEY     Typ=96 Len=10: 77,73,67,75,69,89,32,32,32,32 MICKEY     Typ=1 Len=10: 77,73,67,75,69,89,32,32,32,32
复制


首先,使用空白填充的比较语义执行联接比较。文档 (http://docs.oracle.com/database/122/SQLRF/Data-Type-Comparison-Rules.htm#GUID-A114F1F4-A08D-4107-B679-323DC7FEA31C) 在数据类型比较规则状态:

“仅当比较中的两个值都是数据类型CHAR,NCHAR,文本文字或用户函数返回的值的表达式时,Oracle才使用空白填充的比较语义。”

“每当比较中的一个或两个值具有数据类型VARCHAR2或nvarchar2时,Oracle都会使用非填充比较语义。”

由于我的一个值是VARCHAR2,我期望非填充比较语义,所以只有每个表的第三行将被连接。但它使用的是连接所有三行的空白填充比较语义。

可能是-可能是文档错误。(或者我误读了文档,并且在其他地方说明了如何执行此联接。)

因此,出于比较目的,它将空格附加到VC值,以便将它们与CH值进行比较。但是,当我然后选择VC值时,我没有得到存储在VC列中的实际数据,我得到了 “比较值”-带有附加空格的VC值。

这是预期的行为吗?

谢谢

啦啦队
/金

专家解答

我想你已经过度考虑了这个金;)

So for comparison purposes it is appending spaces to the VC values in order to compare them with the CH values. But when I then SELECT the VC values, I do not get the actual data stored in the VC column, I get the "comparison value" - the VC value with appended spaces.

不要。

最后一个插入在VC列中存储附加空格的值。你说过 “这个字符串的末尾有空格”。所以它有十个字符。数据库会自动将这些空格附加到所有char值的末尾。

所以对于最后一列VC,你are比较存储的值

(VC) “米奇” 到 (CH) “米奇”

将ID列添加到表中可能会使此更容易看到:

create table ch ( chid int, ch char(10) );

create table vc ( vcid int, vc varchar2(10) );

insert into ch values (1, 'MICKEY');
insert into ch values (2, 'MICKEY  ');
insert into ch values (3, 'MICKEY    ');
insert into vc values (4, 'MICKEY');
insert into vc values (5, 'MICKEY  ');
insert into vc values (6, 'MICKEY    ');

commit;

select chid, vcid, ch, vc
from ch
join vc
on vc.vc = ch.ch;

CHID  VCID  CH          VC          
3     6     MICKEY      MICKEY      
2     6     MICKEY      MICKEY      
1     6     MICKEY      MICKEY 
复制


如果将char转换为连接中的较短的varchar2,它将修剪末端的空格。它只与您存储在VC中具有该长度的行匹配:

select chid, vcid, ch, vc
from ch
join vc
on vc.vc = cast(ch.ch as varchar2(8));

CHID  VCID  CH          VC        
3     5     MICKEY      MICKEY    
2     5     MICKEY      MICKEY    
1     5     MICKEY      MICKEY   

select chid, vcid, ch, vc
from ch
join vc
on vc.vc = cast(ch.ch as varchar2(7));

no rows selected
复制


如果你把VC转换为char,你会得到九行:

select chid, vcid, ch, vc
from ch
join vc
on cast(vc.vc as char(10)) = ch.ch;

CHID  VCID  CH          VC          
3     4     MICKEY      MICKEY      
2     4     MICKEY      MICKEY      
1     4     MICKEY      MICKEY      
3     5     MICKEY      MICKEY      
2     5     MICKEY      MICKEY      
1     5     MICKEY      MICKEY      
3     6     MICKEY      MICKEY      
2     6     MICKEY      MICKEY      
1     6     MICKEY      MICKEY 
复制

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论