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

12

在使用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个回答

15

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

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'(greatest也适用于字符串和数字) rpad('foo',2) = 'fo' 小于'foo',所以greatest函数选择'foo'。

如果你想要左填充的单词,你不能使用greatest,因为它从左到右进行比较(例如将“oo”与“foo”进行比较),在某些情况下,这将取决于字符串更大或更小。我想你可以反转字符串并使用rpad,然后再反转回来,或者只是使用原始解决方案,该方案两种情况都适用。


8

如果您不想一遍又一遍地编写那些重复的业务逻辑,只需编写自己的函数即可。类似于这样:

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如果$1为空,则会返回NULL,但您可以轻松地调整它们以返回其他内容。


谢谢你的回答。这个方法可以行得通,但是数据库管理员不允许我创建新的函数(至少不为了这么简单的任务,只有在绝对必要的情况下才能创建)。 - dmoebius

4

这个怎么样?

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

1
不错,但比我的多了8个字符。 ;) - dmoebius

0

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

select regexp_replace(format('%5s', 'foo'), '(\s*)(\S*)', '\2\1')
  1. format()函数可以将字符串左对齐至所需宽度。
  2. 随后regexp_replace函数会将任何前导空格移动到末尾。

如果字符串中包含前导空格且您想保留它们,则上述方法可能会失败。另外请注意,当参数为空时,format()函数不会返回null值。


仅需使用“select format('%-5s', 'foo')”即可得到相同的结果。 - Bernhard Barker
此功能在9.3版本之前的版本中似乎不可用。 - Emery Lapinski

0
以下是PostgreSQL语句,用于在列“columnname”上右侧填充三个位值并更改列数据类型为文本。我使用了pycharm IDE来帮助构建语句。该语句将使用000进行填充。
我已经寻找了一段时间来解决相同的问题,只不过是左侧填充,我想分享一下。
alter table 'schema.tablename' alter column 'columnname' type text using rpad('columnname'::text,3,'0')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接