15

Using Postgresql 8.4, how can I right-pad a string with blanks without truncating it when it's too long?

The problem is that rpad truncates the string when it is actually longer than number of characters to pad. Example:

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

The shortest solution I found doesn't involve rpad at all:

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

but this looks ugly IMHO. Note that I don't actually select the string 'foo' of course, instead I select from a column:

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

Is there a more elegant solution?

5 Answers 5

19

found a slightly more elegant solution:

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

eg:

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

.


To explain how it works: rpad('foo',5) = 'foo ' which is > 'foo' (greatest works with strings as well as numbers) rpad('foo',2) = 'fo' which is < 'foo', so 'foo' is selected by greatest function.

if you want left-padded words you cant use greatest because it compares left-to-right (eg 'oo' with 'foo') and in some cases this will be greater or smaller depending on the string. I suppose you could reverse the string and use the rpad and reverse it back, or just use the original solution which works in both cases.

Sign up to request clarification or add additional context in comments.

Comments

8

If you don't want to write that repeat business all the time, just write your own function for it. Something like this:

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;

or this:

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

Then you can say things like:

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

You might want to consider what you want rpad_upto(null, n) to produce while you're at it. Both versions of rpad_upto above will return NULL if $1 is NULL but you can tweak them to return something else without much difficulty.

1 Comment

Thanks for your answer. It would work, but db admins do not allow me to create new functions (at least not for such a trivial task, only when absolutely neccessary).
4

how about this

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

1 Comment

Nice, but 8 chars more than mine. ;)
0

Assuming efficiency is not your biggest concern here:

select regexp_replace(format('%5s', 'foo'), '(\s*)(\S*)', '\2\1')
  1. format() left-pads the string to the desired width
  2. then regexp_replace moves any leading spaces to the end.

I guess that would fail if you have leading spaces in the strings and you want to preserve them. Also note that format() doesn't return null on null params.

2 Comments

Simply select format('%-5s', 'foo') would give the same result.
this feature appears to be unavailable in versions prior to 9.3
0

PostgreSQL statement below is to right pad three place values and alter column data type to text for column 'columnname.' I used pycharm IDE to help construct statement. The statement will pad with 000.

I have been looking for a while to solve the same issue, except for left pad and I thought I would share.

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.