Your format model should still consider the sign of the value. It is not possible to tell TO_CHAR() that it can never be negative (if this is true for your values). Even with a 4-digit number that allows formatting, five characters are allowed, as you can see from the column heading:
SQL> SELECT TO_CHAR(1234, 'FM0000') FROM DUAL; TO_CH ----- 1234
Note that the column heading is TO_CH , which is five characters, not four. If you have a negative number (as Florin suggested), you need extra space:
SQL> SELECT TO_CHAR(-1234, 'FM0000') FROM DUAL; TO_CH ----- -1234
Without the FM modifier, you get the leading space in the returned string for positive values, so LENGTH(TO_CHAR(1234, '0000')) is 5, and LENGTH(TO_CHAR(1234, 'FM0000')) is 4, because the leading space (which usually makes the values ββin the column right- justified) suppressed. If the value is negative, the length of the returned string is 5 in any case. The format model determines that the returned data type is varchar2(5) to allow the sign, even if you know that there will never be negative values ββ- there will be no reflection for the format model.
You can also see it with positive values ββif you force the sign to be displayed:
SQL> SELECT TO_CHAR(1234, 'FMS0000') FROM DUAL; TO_CH ----- +1234
There is nothing you can do in the TO_CHAR call. As an alternative to the RPAD you can use SUBSTR to get only the last four characters of the formatted string:
SQL> SELECT SUBSTR(TO_CHAR(12345, 'FM0000'), -4) FROM DUAL SUBSTR(TO_CHAR(1 ----------------
But if you have negative values, you will lose the sign:
SQL> SELECT SUBSTR(TO_CHAR(-1234, 'FM0000'), -4) FROM DUAL SUBSTR(TO_CHAR(- ---------------- 1234
With your RPAD, you retain the sign, but lose the fourth significant digit:
SQL> SELECT RPAD(TO_CHAR(-1234, 'FM0000'), 4) FROM DUAL RPAD(TO_CHAR(-12 ---------------- -123
which is also bad. You may not have to deal with negative numbers; but if you are dealing with a number larger than you expect (i.e. you get the number> = 10000 when you only expect <= 9999), then Iβm not sure that you can be sure you wonβt see (invalid?) negative number at some point too. In any case, this is a data problem, not a formatting problem at any level.
Based on your comment on Ollie, another approach that may be more explicit and obvious to future code developers is to describe it in CASE:
SELECT CASE WHEN n BETWEEN 0 AND 9999 THEN TO_CHAR(n, 'FM0000') ELSE '####' END FROM DUAL
Which will also allow you to leave the row zero column or use another magic value, not #### if you want.
And another way to crop a value, which could also be clearer, is with CAST:
SQL> SELECT CAST(TO_CHAR(12345, 'FM0000') AS VARCHAR2(4)) FROM DUAL; CAST ---- ####