Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/86.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql RPAD中的意外结果_Sql_Oracle - Fatal编程技术网

Sql RPAD中的意外结果

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

我正在使用Oracle11g。我正在使用Scott帐户和演示
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通过将显示的列标题减少为,并将下一列包装到单独的行中来帮助您。

好的,我知道为什么以及如何使用空格,但我的问题是