Sql RPAD中的意外结果
我正在使用Oracle11g。我正在使用Scott帐户和演示Sql RPAD中的意外结果,sql,oracle,Sql,Oracle,我正在使用Oracle11g。我正在使用Scott帐户和演示EMP表。我用ENAMEbrucewilliam插入了一条记录。我的目标是在两列中显示名字和姓氏。我使用了以下代码: select trim rpad(ename, instr(ename,' '))) "First Name", trim(substr(ename, instr(ename,' '))) "Last Name" from emp; 这会产生一个奇怪的结果。名字扩展到第二行。我曾经 selec
EMP
表。我用ENAME
brucewilliam插入了一条记录。我的目标是在两列中显示名字和姓氏。我使用了以下代码:
select trim rpad(ename, instr(ename,' '))) "First Name",
trim(substr(ename, instr(ename,' '))) "Last Name"
from emp;
这会产生一个奇怪的结果。名字
扩展到第二行。我曾经
select trim(substr(ename, 1, instr(ename,' '))),
trim(substr(ename, instr(ename, ' ')))
from emp;
我得到了预期的输出。我的问题是为什么查询的第一行会给出额外的空格
lpad ('string', n [, 'string_pad')
rpad ('string', n [, 'string_pad')
用线绳垫将线绳填充至长度n。如果使用字符串填充,将使用空格作为默认值
rpad与之类似,但它是向右而不是向左移动
从
这是一个很好的理解例子
begin
for i in 1 .. 15 loop
dbms_output.put_line(
rpad('string', i) || '<'
);
end loop;
end;
开始
因为我在1。。15圈
dbms_output.put_行(
rpad('string',i)| |'
字符串用字符串填充板左填充至长度n。如果字符串填充板为ommited,将使用空格作为默认值
rpad与之类似,但它是向右而不是向左移动
从
这是一个很好的理解例子
begin
for i in 1 .. 15 loop
dbms_output.put_line(
rpad('string', i) || '<'
);
end loop;
end;
开始
对于1..15循环中的i
dbms_output.put_行(
rpad('string',i)| |'字符串中没有多余的空格,如果是,则trim()
将再次删除这些空格。SQL*Plus只是以一种您意想不到的方式格式化结果。它提到了列类型的默认格式,通常可以为系统函数计算出来(尽管角色集可以使其比您预期的更大)
SQL*Plus和SQL Developer似乎无法为rpad
案例确定合理的默认值,但可以为substr
案例确定默认值。SQL*Plus实际上只是从数据库中获取一个结果集游标,并使用游标元数据来确定应用于要显示的字段的默认宽度,因此它无法获得您期望从该元数据获得的长度。但它应该使用什么长度
如果填充长度是一个简单的值,数据库只知道rpad
值可以有多大-它甚至不介意为零(它返回null,这是您所依赖的)。如果填充长度由函数确定,则除了在返回元数据和实际数据之前计算结果集中的每个值之外,无法判断结果的大小,这是不实际的,并且会随着数据的更改而产生不一致的输出
试图确定一个理论上的最大值也是不现实的,即使在你的例子中它看起来很简单。substr
永远不能返回比原始值更长的值;但是rpad
即使输入值很短,也可能产生巨大的结果,因此它必须考虑到这种可能性如果无法轻松确定限值(即,从固定值),则不可用
因此,它很安全,并允许它达到varchar2
的最大长度,即4000个字符,如此动态SQL所示:
declare
l_curid integer;
l_desctab dbms_sql.desc_tab3;
l_colcnt integer;
begin
l_curid := dbms_sql.open_cursor;
dbms_sql.parse(l_curid, 'select rpad(ename, instr(ename,'' '')), '
|| 'rpad(ename, 4), '
|| 'substr(ename, 1, instr(ename,'' '')) '
|| 'from emp where ename like ''B%''' , dbms_sql.native);
dbms_sql.describe_columns3(l_curid, l_colcnt, l_desctab);
for i in 1 .. l_colcnt loop
dbms_output.put_line('column ' || i
|| ' ' || l_desctab(i).col_name
|| ' type ' || l_desctab(i).col_type
|| ' length ' || l_desctab(i).col_max_len
);
end loop;
dbms_sql.close_cursor(l_curid);
end;
/
column 1 RPAD(ENAME,INSTR(ENAME,'')) type 1 length 4000
column 2 RPAD(ENAME,4) type 1 length 16
column 3 SUBSTR(ENAME,1,INSTR(ENAME,'')) type 1 length 40
如您所见,它知道固定长度rpad
和substr
的长度(注意,由于多字节字符集,大小是实际字符串长度的四倍),但使用函数返回到rpad
的最大值
您看到的是SQL*Plus显示了一个4000字符的列。如果您在SQL Developer中这样做,您将看到该列的标题实际上是4000个字符。SQL*Plus将显示的列标题缩减为,并将下一列包装到单独的行中,这会有所帮助。您不会在字符串中获得额外的空格,如果您需要然后,trim()
会再次删除它们。SQL*Plus只是以一种您意想不到的方式格式化结果。它提到了列类型的默认格式,通常可以为系统函数计算出来(尽管字符集可以使其比您预期的大)
SQL*Plus和SQL Developer似乎无法为rpad
案例确定合理的默认值,但可以为substr
案例确定默认值。SQL*Plus实际上只是从数据库中获取一个结果集游标,并使用游标元数据来确定应用于要显示的字段的默认宽度,因此它无法获得您期望从该元数据获得的长度。但它应该使用什么长度
如果填充长度是一个简单的值,数据库只知道rpad
值可以有多大-它甚至不介意为零(它返回null,这是您所依赖的)。如果填充长度由函数确定,则除了在返回元数据和实际数据之前计算结果集中的每个值之外,无法判断结果的大小,这是不实际的,并且会随着数据的更改而产生不一致的输出
试图确定一个理论上的最大值也是不现实的,即使在你的例子中它看起来很简单。substr
永远不能返回比原始值更长的值;但是rpad
即使输入值很短,也可能产生巨大的结果,因此它必须考虑到这种可能性如果无法轻松确定限值(即,从固定值),则不可用
因此,它很安全,并允许它达到varchar2
的最大长度,即4000个字符,如此动态SQL所示:
declare
l_curid integer;
l_desctab dbms_sql.desc_tab3;
l_colcnt integer;
begin
l_curid := dbms_sql.open_cursor;
dbms_sql.parse(l_curid, 'select rpad(ename, instr(ename,'' '')), '
|| 'rpad(ename, 4), '
|| 'substr(ename, 1, instr(ename,'' '')) '
|| 'from emp where ename like ''B%''' , dbms_sql.native);
dbms_sql.describe_columns3(l_curid, l_colcnt, l_desctab);
for i in 1 .. l_colcnt loop
dbms_output.put_line('column ' || i
|| ' ' || l_desctab(i).col_name
|| ' type ' || l_desctab(i).col_type
|| ' length ' || l_desctab(i).col_max_len
);
end loop;
dbms_sql.close_cursor(l_curid);
end;
/
column 1 RPAD(ENAME,INSTR(ENAME,'')) type 1 length 4000
column 2 RPAD(ENAME,4) type 1 length 16
column 3 SUBSTR(ENAME,1,INSTR(ENAME,'')) type 1 length 40
如您所见,它知道固定长度rpad
和substr
的长度(注意,由于多字节字符集,大小是实际字符串长度的四倍),但使用函数返回到rpad
的最大值
您看到的是SQL*Plus显示了一个4000字符的列。如果您在SQL Developer中这样做,您将看到该列的标题实际上是4000个字符。SQL*Plus通过将显示的列标题减少为,并将下一列包装到单独的行中来帮助您。好的,我知道为什么以及如何使用空格,但我的问题是