170

I am relatively new to PostgreSQL and I know how to pad a number with zeros to the left in SQL Server but I'm struggling to figure this out in PostgreSQL.

I have a number column where the maximum number of digits is 3 and the min is 1: if it's one digit it has two zeros to the left, and if it's 2 digits it has 1, e.g. 001, 058, 123.

In SQL Server I can use the following:

RIGHT('000' + cast([Column1] as varchar(3)), 3) as [Column2]

This does not exist in PostgreSQL. Any help would be appreciated.

3
  • 2
    Using google is exactly how I found this page. It was my number-one google result.
    – Jason
    Commented Apr 4, 2017 at 22:19
  • Possible duplicate of to_char(number) function in postgres Commented Jun 8, 2017 at 19:54
  • Speaking of SQL Server, they have the format() function, which will let you use format(Column1,'000') as Column2.
    – Manngo
    Commented Oct 23, 2018 at 9:42

5 Answers 5

292

You can use the rpad and lpad functions to pad numbers to the right or to the left, respectively. Note that this does not work directly on numbers, so you'll have to use ::char or ::text to cast them:

SELECT RPAD(numcol::text, 3, '0'), -- Zero-pads to the right up to the length of 3
       LPAD(numcol::text, 3, '0')  -- Zero-pads to the left up to the length of 3
FROM   my_table
3
  • 1
    @Yarin this answer is the standardized one function call method with format strings. Using RPAD/LPAD you're converting to strings and then processing the strings. Using to_char, you're just specifying a different method for stringifying. Commented Aug 19, 2017 at 18:23
  • 3
    @EvanCarroll they're both useful - this one lets you specify a number for the string length - the other requires knowing 'fm' stands for fill mode and lets you specify a format picture Commented Mar 5, 2018 at 10:52
  • 5
    WARNING: Unlike the classic printf, these bone-headed functions will silently chop your string down to size if it doesn't fit. So you might need a case when length(foo) ... around it. Commented May 24, 2019 at 1:11
77

The to_char() function is there to format numbers:

select to_char(column_1, 'fm000') as column_2
from some_table;

The fm prefix ("fill mode") avoids leading spaces in the resulting varchar. The 000 simply defines the number of digits you want to have.

psql (9.3.5)
Type "help" for help.

postgres=> with sample_numbers (nr) as (
postgres(>     values (1),(11),(100)
postgres(> )
postgres-> select to_char(nr, 'fm000')
postgres-> from sample_numbers;
 to_char
---------
 001
 011
 100
(3 rows)

postgres=>

For more details on the format picture, please see the manual:
http://www.postgresql.org/docs/current/static/functions-formatting.html

3
  • 4
    If the number is too long, to_char converts it to ###. O.o Commented May 24, 2019 at 1:13
  • 4
    I'm curious if there is a solution to the issue where if # if longer than specified in to_Char, it converts to ###. Is there anyway to specificy minimum # of zeros and then have larger numbers grow from that ? For example, if you specify 3 for lpad , numbers would be formatted like 001 010 100 .. 1001 Commented Apr 27, 2020 at 17:09
  • @mikehennessy you can use 9's instead, so like SELECT to_char((10 ^ abc), 'FM9999999000') FROM generate_series(0, 9) abc
    – joyleak
    Commented Apr 13, 2022 at 14:50
21

As easy as

SELECT lpad(42::text, 4, '0')

References:

sqlfiddle: http://sqlfiddle.com/#!15/d41d8/3665

2
  • FWIW, it looks like Postgres added right() in 9.1 Commented Oct 15, 2014 at 9:55
  • LPAD quietly truncates any data longer than the length you give it, so be careful.
    – Schneems
    Commented Oct 28, 2023 at 1:12
8

I was frustrated with LPAD and TO_CHAR since they don't work if your string goes above the minimum length. I can't speak for how efficient this is but you can chain FORMAT to give you a minimum sized string, and then replace any spaces with zeros using REPLACE

with sample_numbers (nr) as (
    values (1),(11),(100),(1000)
)
SELECT REPLACE(FORMAT('%3s', nr), ' ', '0')
from sample_numbers;
 replace
---------
 001
 011
 100
 1000
(4 rows)

Versus with other methods TO_CHAR:

with sample_numbers (nr) as (
    values (1),(11),(100),(1000)
)
SELECT to_char(nr, 'fm000')
from sample_numbers;
 to_char
---------
 001
 011
 100
 ###
(4 rows)

(Notice the last value is ### and not 1000)

And LPAD:

with sample_numbers (nr) as (
    values (1),(11),(100),(1000)
)
SELECT LPAD(nr::varchar(255), 3, '0')
from sample_numbers;
 lpad
------
 001
 011
 100
 100
(4 rows)

(Notice the last value is 100 and not 1000)

There are other methods involving using CASE but I like that the REPLACE & FORMAT combo doesn't need any variable repetition.

2

The easiest way:

ltrim(to_char(Column1, '000'))

Not the answer you're looking for? Browse other questions tagged or ask your own question.