Oracle SQL convert string to number with exceptions to treat text as 0

隐身守侯 提交于 2021-02-11 09:50:31

问题


I would like to convert a string column to number, with ability to handle exceptions, such as text, in Oracle SQL.

The target is to convert text to 0, and number in string format into number.

Example Input:

ID   Column1
1    01A
2    02A
3    1.30
4    1,30
5    100000
6           (Note: 1 empty space)
7           (Note: Null)

Expected output

ID   Column1
1    0
2    0
3    1.3
4    1.3
5    100000
6    0
7    0

I tried the following SQL command:

select ID, to_number(Column1) As Column1 
from Table1

The error code is ORA-01722 if there is any non-numeric output.

The expected result is to get rid of error ORA-01722, even when input has null, space, text (i.e. anything non-numeric)


回答1:


This requires two measures:

  1. Check if there are any non-numeric characters (see this solution)
    You could use regex functions instead of TRANSLATE but I expect them to be slower.
  2. Convert to number, accepting both ',' and '.' as decimal markers (see this solution)

Query:

WITH test_data AS
(
  SELECT '01A' AS column1 FROM dual UNION ALL
  SELECT '02A' AS column1 FROM dual UNION ALL
  SELECT '1.30' AS column1 FROM dual UNION ALL
  SELECT '1,30' AS column1 FROM dual UNION ALL
  SELECT '100000' AS column1 FROM dual UNION ALL
  SELECT ' ' AS column1 FROM dual UNION ALL
  SELECT NULL AS column1 FROM dual
)
SELECT
    '''' || column1 || '''' AS column1, -- only to show result, distinct between '' and ' '
    -- Check if there are only numeric characters
    CASE WHEN TRIM( TRANSLATE( column1, '0123456789-,.', ' ') ) IS NULL
      THEN
          NVL(  -- replace NULL by 0
              TO_NUMBER(
                  -- both ',' and '.' should work as decimal marker so replace
                  REPLACE( TRIM( column1 ), ',', '.' ),
                  -- second parameter necessary to allow third
                  '99999999999999999999D99999999999999999999',
                  -- do not rely on NLS settings, use '.' as decimal marker
                  'NLS_NUMERIC_CHARACTERS=''. '''
              ),
          0 )
      ELSE 0  -- default value if not numeric
    END AS result
FROM test_data;

Results:

COLUMN1      RESULT
-------- ----------
'01A'             0
'02A'             0
'1.30'          1.3
'1,30'          1.3
'100000'     100000
' '               0
''                0



回答2:


In order to cast a column to number, we will need to eliminate/replace the text we can use a case statement with regex to achieve this.

Please try running this

    Select ID ,
      CASE 
         WHEN NOT regexp_like (   NVL ( trim (replace(column1 , ',' ,'.')) , 0 )  ,         
                '^[0-9]+[\.0-9]*$'     )   
         THEN 0
        ELSE  TO_NUMBER ( NVL ( trim (replace(column1 , ',' ,'.')) , 0 ) )
      END column1
    from table1

Logic by regexp look for anything that's not like a number change it to 0 if its a number cast as number , trim and nvl is to handle space and null.

Note : replace ',' to '.' is to handle 1,3 = 1.2 , but this is bound to fail if there are multiple comma's in the column (we can write a more complex logic to check the comma count , but seems unnecessary ) , ideally 1,3 should be denoted as text and made 0

Hope this helps




回答3:


You can achieve this using the following query:

alter session set NLS_NUMERIC_CHARACTERS = '.,';
SELECT
    YOUR_COLUMN,
    CASE
        WHEN REGEXP_COUNT(YOUR_COLUMN, '[A-Za-z]') > 0 OR TRIM(YOUR_COLUMN) IS NULL THEN 0
        ELSE TO_NUMBER(REPLACE(YOUR_COLUMN, ',', '.'))
    END AS MY_NUMBER
FROM
    YOUR_TABLE

db<>fiddle demo

Cheers!!




回答4:


You can use regexp_like() and case logic:

SELECT (CASE WHEN REGEXP_LIKE(column1, '[0-9]*[.,]+[0-9]+')
             THEN REPLACE(column1, ',', '.')
             ELSE '0'
        END)
FROM test_data;

This is rather careful about handling edge cases:

  • Only one ./, is allowed.
  • If there is a decimal point, then there needs to be a digit afterwards (this can be adjusted).

Here is a db<>fiddle. It adds an additional test case of just '.'.



来源:https://stackoverflow.com/questions/57884039/oracle-sql-convert-string-to-number-with-exceptions-to-treat-text-as-0

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!