使用rpad在Postgresql中填充字符串而不截断它

时间:2012-08-27 18:40:04

标签: sql string function postgresql string-formatting

使用Postgresql 8.4,如何在没有的情况下用空格对字符串进行右键填充,当它太长时将其截断?

问题是rpad 在字符串实际长于要填充的字符数时截断字符串。例如:

SELECT rpad('foo', 5);  ==> 'foo  ' -- fine
SELECT rpad('foo', 2);  ==> 'fo'    -- not good, I want 'foo' instead.

我找到的最短解决方案根本不涉及rpad

SELECT 'foo' || repeat(' ', 5-length('foo'));  ==> 'foo  ' -- fine
SELECT 'foo' || repeat(' ', 2-length('foo'));  ==> 'foo'   -- fine, too

但这看起来丑陋恕我直言。请注意,我当然不会选择字符串'foo',而是从列中选择:

SELECT colname || repeat(' ', 30-length(colname)) FROM mytable WHERE ...

有更优雅的解决方案吗?

5 个答案:

答案 0 :(得分:7)

如果您不想一直编写repeat业务,只需编写自己的函数即可。像这样:

create or replace function rpad_upto(text, int) returns text as $$
begin
    if length($1) >= $2 then
        return $1;
    end if;
    return rpad($1, $2);
end;
$$ language plpgsql;

或者这个:

create or replace function rpad_upto(text, int) returns text as $$
select $1 || repeat(' ', $2 - length($1));
$$ language sql;

然后你可以这样说:

select rpad_upto(colname, 30) from mytable ...

你可能想要考虑你想要rpad_upto(null, n)生成什么。如果rpad_upto为NULL,则上面$1的两个版本都将返回NULL,但您可以调整它们以返回其他内容而没有太大困难。

答案 1 :(得分:7)

找到了一个稍微优雅的解决方案:

SELECT greatest(colname,rpad(colname, 2));

例如:

SELECT greatest('foo',rpad('foo', 5));  -- 'foo  ' 
SELECT greatest('foo',rpad('foo', 2));  -- 'foo'  


解释它的工作原理: rpad('foo',5)='foo'是> 'foo'(最好用字符串和数字) rpad('foo',2)='fo'是< 'foo',所以'foo'是由最大的功能选择的。

如果你想要左边填充的单词,你不能使用最大的单词,因为它从左到右比较(例如'oo'和'foo'),在某些情况下,根据字符串,这将更大或更小。我想你可以反转字符串并使用rpad并将其反转,或者只使用在两种情况下均适用的原始解决方案。

答案 2 :(得分:3)

这个怎么样

select case when length(col) < x then rpad(col, x)
else col
end
from table

答案 3 :(得分:0)

假设效率不是你最关心的问题:

select regexp_replace(format('%5s', 'foo'), '(\s*)(\S*)', '\2\1')
  1. format()将字符串左键填充到所需的宽度
  2. 然后regexp_replace将任何前导空格移动到结尾。
  3. 如果您在字符串中有前导空格并且想要保留它们,我想这会失败。另请注意,format()在null参数上不会返回null。

答案 4 :(得分:0)

下面的PostgreSQL语句在右边填充三个位置值,并将列数据类型更改为列'columnname'的文本。我使用pycharm IDE来帮助构造语句。该语句将填充000。

我一直在寻找解决同一问题的时间,除了左脚垫,我想我会分享。

alter table 'schema.tablename' alter column 'columnname' type text using rpad('columnname'::text,3,'0')