TO_CHAR function & ORA-01722: invalid number error

Posted on 2014-12-01
Last Modified: 2014-12-01

I receive ORA-01722: invalid number error when running this query.

select TO_CHAR(PRSPRSC/100/2,'fm999.00') NOW_PRICE from prs;

What is the best way around this?
Question by:xbox360dp
  • 3
  • 2
LVL 76

Expert Comment

by:slightwv (䄆 Netminder)
ID: 40474430
>> What is the best way around this?

Is PRSPRSC a number data type or a varchar2 that has numbers in it?

If a varchar2, the best way to fix it is fix the 'bad' data that is likely causing the problem.

The other choice is to write your own to_number function that can deal with non-numeric data the way you want to handle it and use that in the call.

If you create my_to_number then:

You would need to decide on what to return if the data is not a number.

Author Comment

ID: 40474470
PRSPRSC is a varchar2 that has numbers in it.
LVL 76

Expert Comment

by:slightwv (䄆 Netminder)
ID: 40474476
>>PRSPRSC is a varchar2 that has numbers in it.

then see the recommendations above:
1: Fix the data.
2: Write your own function to handle the 'bad' data.
PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

LVL 74

Accepted Solution

sdstuber earned 500 total points
ID: 40474511
I agree, writing your own function would probably be best, but as a temporary measure ,you could try a case.

TO_CHAR(case when regexp_like(PRSPRSC,'^[0-9]*\.?[0-9]+$') then PRSPRSC/100/2 end,'fm999.00')

this will cause your non-numeric strings to return null

alternately, put the conversion inside the case, and return the original string when it's not valid so it's easily visible

           WHEN REGEXP_LIKE(prsprsc, '^[0-9]*\.?[0-9]+$') THEN TO_CHAR(prsprsc / 100 / 2, 'fm999.00')
           ELSE prsprsc

note, these regexps aren't guaranteed to capture all weird data entry, but will probably work for most.
LVL 74

Expert Comment

ID: 40474558
As for a custom function, I would put all of the formatting into that rather than converting to number and then formatting.  That way you can encapsulate all of the rules nicely in one place.

    v_temp NUMBER;
    v_temp := TO_NUMBER(p_str);

    -- If a format is given use it, otherwise use the default format for numbers
    IF p_format IS NOT NULL
        RETURN TO_CHAR(v_temp, p_format);
        RETURN TO_CHAR(v_temp);
    END IF;
        RETURN p_str;  -- change this to whatever you want non-numerics to do.

Open in new window

and then usage would look like this...

select formatter(PRSPRSC/100/2,'fm999.00') NOW_PRICE from prs;
LVL 76

Expert Comment

by:slightwv (䄆 Netminder)
ID: 40475027
The accepted solution is a temporary fix at best and as noted, has potential flaws moving forward in someone enters something that is 'close' to a number but not exactly a number.

If they do that, you are right back where you are now.

Something is allowing 'bad' data into your tables and can lead to very bad results depending on the application.

First thing you really need to do is stop storing numbers in a varchar2 column.  Varchar2 is for strings.  number is for numbers.

Since you likely cannot do that, I would look at a job/script that at least monitors the table for 'bad' data daily/weekly and fix it as it comes in.

Better approach is what I mentioned and sdstuber posted: your own function.

Featured Post

Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
How to free up undo space? 3 50
constraint check 2 48
pl/sql - query very slow 26 71
how to double quote a string for an inline sql statement. 8 73
Truncate is a DDL Command where as Delete is a DML Command. Both will delete data from table, but what is the difference between these below statements truncate table <table_name> ?? delete from <table_name> ?? The first command cannot be …
Background In several of the companies I have worked for, I noticed that corporate reporting is off loaded from the production database and done mainly on a clone database which needs to be kept up to date daily by various means, be it a logical…
This video shows setup options and the basic steps and syntax for duplicating (cloning) a database from one instance to another. Examples are given for duplicating to the same machine and to different machines
This video shows information on the Oracle Data Dictionary, starting with the Oracle documentation, explaining the different types of Data Dictionary views available by group and permissions as well as giving examples on how to retrieve data from th…

856 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question