我正在使用Oracle 11g。我正在使用Scott帐户和演示EMP
表。我用ENAME
BRUCE WILLIAM插入了一条记录。我的目标是在两列中显示名字和姓氏。我用了这段代码:
select trim rpad(ename, instr(ename,' '))) "First Name",
trim(substr(ename, instr(ename,' '))) "Last Name"
from emp;
这给出了一个奇怪的结果。 First Name
扩展到第二行。我用了
select trim(substr(ename, 1, instr(ename,' '))),
trim(substr(ename, instr(ename, ' ')))
from emp;
我得到了预期的输出。我的问题是为什么第一行查询提供额外的空格?
答案 0 :(得分:1)
你的字符串中没有多余的空格,如果你那么trim()
会再次删除它们。 SQL * Plus只是以您不期望的方式格式化结果。 documentation提到了列类型的默认格式,并且通常可以将其用于系统函数(尽管characterset可以使它比预期的更大)。
似乎就像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-char列。如果你在SQL Developer中这样做,你会看到该列的标题确实是4000个字符。 SQL * Plus通过将显示的列标题减少到line size来帮助一点,并将下一列包装到一个单独的行上。
答案 1 :(得分:0)
lpad ('string', n [, 'string_pad')
rpad ('string', n [, 'string_pad')
使用string_pad将字符串填充到长度为n。如果省略string_pad,将使用空格作为默认值 rpad是相似的,但垫右而不是左。
来自http://www.adp-gmbh.ch/ora/sql/rpad.html
这是理解
的好例子begin
for i in 1 .. 15 loop
dbms_output.put_line(
rpad('string', i) || '<'
);
end loop;
end;