Home » SQL & PL/SQL » SQL & PL/SQL » TO_NUMBER conversion on NVARCHAR2 column throws ORA-01722: invalid number (12c, 12.1.0.1, Windows 7)
TO_NUMBER conversion on NVARCHAR2 column throws ORA-01722: invalid number [message #623855] |
Mon, 15 September 2014 08:34 |
Lalit Kumar B
Messages: 3174 Registered: May 2013 Location: World Wide on the Web
|
Senior Member |
|
|
Hi Folks,
The issue is that there is column of NVARCHAR2 datatype which has numbers stored(with or without decimal part). I suggested the respective team to change the data type to number, however, it is a legacy system so they cannot change the data type as of now, unless I come up with a permanent fix.
When TO_NUMBER is applied on the NVARCHAR2 column with required number format and nls numeric characters, it throws ORA-01722: invalid number :
Test case :
SQL> SELECT banner
2 FROM v$version
3 WHERE ROWNUM = 1;
BANNER
--------------------------------------------------------------------------------
Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
SQL>
SQL> DROP TABLE t purge;
Table dropped.
SQL>
SQL> CREATE TABLE t
2 (
3 col NVARCHAR2(100)
4 );
Table created.
SQL>
SQL> INSERT INTO t
2 VALUES ('0.5');
1 row created.
SQL>
SQL> INSERT INTO t
2 VALUES ('1.0');
1 row created.
SQL>
SQL> COMMIT;
Commit complete.
SQL>
SQL> SELECT To_number(col, '999D99', 'NLS_NUMERIC_CHARACTERS = ,.') val
2 FROM t
3 /
ERROR:
ORA-01722: invalid number
no rows selected
What I found after reserching on the data is that, it only happens when we have pure decimal number(such as 0.5) in the NVARCHAR2 column. If I filter them out, the query is executed successfully.
SQL> SELECT To_number(col, '999D99', 'NLS_NUMERIC_CHARACTERS = ,.') val
2 FROM t
3 WHERE Substr(col, 1, 2) <> '0.'
4 /
VAL
----------
10
SQL>
And interesting thing is, if I modify the datatype from NVARCHAR2 to VARCHAR2, the query works perfectly.
SQL> DROP TABLE t purge;
Table dropped.
SQL>
SQL> CREATE TABLE t
2 (
3 col VARCHAR2(100)
4 );
Table created.
SQL>
SQL> INSERT INTO t
2 VALUES ('0.5');
1 row created.
SQL>
SQL> INSERT INTO t
2 VALUES ('1.0');
1 row created.
SQL>
SQL> COMMIT;
Commit complete.
SQL>
SQL> SELECT To_number(col, '999D99', 'NLS_NUMERIC_CHARACTERS = ,.') val
2 FROM t
3 /
VAL
----------
5
10
So, as a workaround, I suggested the developers to apply TO_CHAR before applying TO_NUMBER :
SQL> DROP TABLE t purge;
Table dropped.
SQL>
SQL> CREATE TABLE t
2 (
3 col VARCHAR2(100)
4 );
Table created.
SQL>
SQL> INSERT INTO t
2 VALUES ('0.5');
1 row created.
SQL>
SQL> INSERT INTO t
2 VALUES ('1.0');
1 row created.
SQL>
SQL> COMMIT;
Commit complete.
SQL>
SQL> SELECT To_number(To_char(col), '999D99', 'NLS_NUMERIC_CHARACTERS = ,.') val
2 FROM t
3 /
VAL
----------
5
10
I tried searching MOS, but got a Bug ID which talks just the opposite of my issue, Bug 13794591. Has any of you come across such an issue Or any idea what's going on? Any help/suggestion is welcome.
The create and insert statements to replicate :
DROP TABLE t purge;
CREATE TABLE t
(
col VARCHAR2(100)
);
INSERT INTO t
VALUES ('0.5');
INSERT INTO t
VALUES ('1.0');
COMMIT;
SELECT To_number(To_char(col), '999D99', 'NLS_NUMERIC_CHARACTERS = ,.') val
FROM t
WHERE Substr(col, 1, 2) <> '0.';
Regards,
Lalit
|
|
|
|
|
Re: TO_NUMBER conversion on NVARCHAR2 column throws ORA-01722: invalid number [message #623892 is a reply to message #623863] |
Tue, 16 September 2014 00:27 |
Lalit Kumar B
Messages: 3174 Registered: May 2013 Location: World Wide on the Web
|
Senior Member |
|
|
I followed your suggestion, doesn't seem to work in general when I add more values(though it worked in your test case with just two values) :
SQL> INSERT INTO t
2 VALUES ('1.5');
1 row created.
SQL>
SQL> COMMIT;
Commit complete.
SQL> select * from t
2 /
COL
---------
0.5
1.0
1.5
SQL> SELECT To_number(col, '999D99', 'NLS_NUMERIC_CHARACTERS = .,')
2 FROM t
3 /
ERROR:
ORA-01722: invalid number
no rows selected
If I filter out '0.5', it executes without throwing error, but the result is incorrect since it returns 15 instead of 1.5 :
SQL> SELECT To_number(col, '999D99', 'NLS_NUMERIC_CHARACTERS = .,') val
2 FROM t
3 WHERE Substr(col, 1, 2) <> '0.'
4 /
VAL
----------
1
15
If I use VARCHAR2 instead of NVARCHAR2, this is the result :
SQL> CREATE TABLE t
2 (
3 col VARCHAR2(100)
4 );
Table created.
SQL>
SQL> INSERT INTO t
2 VALUES ('0.5');
1 row created.
SQL>
SQL> INSERT INTO t
2 VALUES ('1.0');
1 row created.
SQL>
SQL> INSERT INTO t
2 VALUES ('1.5');
1 row created.
SQL>
SQL> COMMIT;
Commit complete.
SQL>
SQL> SELECT To_number(col, '999D99', 'NLS_NUMERIC_CHARACTERS = .,') val
2 FROM t
3 /
VAL
----------
.5
1
1.5
I guess, the safe workaround would be to use TO_CHAR before applying TO_NUMBER. I couldn't find anything else that would work in general.
Thank you for your time.
[Updated on: Tue, 16 September 2014 00:27] Report message to a moderator
|
|
|
|
Goto Forum:
Current Time: Wed Apr 24 04:42:18 CDT 2024
|