LTRIM and TO_CHAR…and a “Strange” Query

February 15, 2011

in Keywords, SQL

LTRIM and TO_CHAR in SQL

A query using LTRIM and TO_CHAR seemed to be behaving oddly, but soon a simple explanation presented itself.

Check out the query below. Can you tell why it gives the answer it does?

First a little background about the two built-in SQL functions used in the query.

LTRIM

LTRIM removes a specified set of characters from the left of a string. If no character set is specified, LTRIM defaults to a single blank.

SQL> -- Remove zeros from the left
SQL> -- of the string till it reaches
SQL> -- a non-zero character
SQL> select ltrim('000102.3', '0')
  2  from dual;

LTRIM
-----
102.3

TO_CHAR

TO_CHAR converts the datatype of non-text data (like NUMBER or DATE) to text in a specified format. This function is generally used to format the output data.

SQL> -- Convert a number to string
SQL> select to_char(102.3, '000000.0')
  2  from dual;

TO_CHAR(1
---------
 000102.3

The “Strange” Query

If we combine the two queries — ie use the output of TO_CHAR(102.3, ‘000000.0’) as the input of the LTRIM function in query #1, we should get the same result = 102.3, right?

Let’s try it.

SQL> -- Convert 102.3 to 000102.3 using
SQL> -- TO_CHAR, then LTRIM it to
SQL> -- remove zeroes from the left
SQL> select ltrim(
  2           to_char(102.3, '000000.0')
  3           , '0')
  4  from dual;

LTRIM(TO_
---------
 000102.3

Why didn’t the zeroes on the left get trimmed? It worked all right when we used the string ‘000102.3’ directly. Then what havoc did using TO_CHAR cause that LTRIM refused to work as we wanted?

The Solution

Look closely at the answer of the “strange” query.
It is not ‘000102.3’, it is ‘ 000102.3’. See the blank space on the left?

TO_CHAR adds a blank space for the sign, when the format is specified with ‘0’.

Applause for Ankur Thakran and N Madhu Sudhan Reddy who got that right.

Some possible solutions:

1. Use TRIM to remove the blank space after TO_CHAR, before applying LTRIM.

SQL> -- Solution I
SQL> -- TRIM before applying LTRIM
SQL> select ltrim(
  2           trim (
  3           to_char(102.3, '000000.0')
  4                )
  5           , '0')
  6  from dual;

LTRIM(TRI
---------
102.3

2. Format TO_CHAR with ‘9’ instead of ‘0’. This does not add a space.

SQL> -- Solution II
SQL> -- TO_CHAR with 9, not 0
SQL> select ltrim(
  2          to_char(102.3, '999999.9')
  3           , '0')
  4  from dual;

LTRIM(TO_
---------
    102.3

3. Add fm (format modifier). This removes unnecessary white space like the leading space.

SQL> -- Solution III
SQL> -- Format mask to remove blank space
SQL> select ltrim(
  2          to_char(102.3, 'fm000000.0')
  3           , '0')
  4  from dual;

LTRIM(TO_
---------
102.3

{ 3 comments… read them below or add one }

1 Ankur Thakran February 27, 2011 at 7:07 am

select to_char(102.3, ‘000000.0’)
from dual
/

The formatted output of to_char is prefixed by a blank i.e., the left
most character of the output is a blank character.

select Decode(Substr(to_char(102.3, ‘000000.0’), 1, 1), ‘ ‘,
‘Left most 1st char is blank.’,
‘Left most 1st char is not blank.’) Left_Most_Char
from dual
/

In your query ltrim is expected to remove all the ‘0’ for the left
most part of the input but only when the left most part begins with
‘0’ (trimming character) but in this case since left most character is
a blank char not a ‘0’ that’s why ltrim could not work as expected.
To make it work we can first remove any leading blanks by putting the output of to_char(102.3, ‘000000.0’) in a trim function though trim function removes blank chars from both the ends of the strings but here we are just concerned from the removal of the leading blank.

–This works as expected.
select ltrim(trim(to_char(102.3, ‘000000.0’)), ‘0’)
from dual
/

2 N MADHU SUDHAN REDDY February 27, 2011 at 10:23 am

hi,
in the above query to_Char function adds a space if format is specified with ‘0’. try it with format ‘9’, which will not add a space.
select ltrim(to_char(102.3, ‘999999.9’), ‘0’) from dual;
🙂

3 chandra August 21, 2021 at 11:41 pm

ltrim ( substring ( to_char ([POP and Coll Release Fields Query].[Bal Prin Original], ‘999999999999990.00’ ), 1,19)) it expects number got char

Leave a Comment

Previous post:

Next post: