Test for numeric value?

2019-02-24 15:21发布

问题:

The vendor data we load in our staging table is rather dirty. One column in particular captures number data but 40% of the time has garbage characters or random strings.

I have to create a report that filters out value ranges in that column. So, I tried playing with a combination of replace/translate like so

select replace(translate(upper(str),' ','all possible char'),' ','')
from table

but it fails whenever it encounters a char I did not code. Therefore, the report can never be automated.

Javascript has the isNaN() function to determine whether a value is an illegal number (True if it is and false if not).

How can I do the same thing with DB2?? Do you have any idea?

Thanks in advance.

回答1:

A fairly reliable (but somewhat hackish) way is to compare the string to its upper- and lower-case self (numbers don't have different cases). As long as your data that is bringing in characters only includes Latin characters, you should be fine:

SELECT input, CASE
    WHEN UPPER(input) = LOWER(input) THEN TO_NUMBER(input)
    ELSE 0
END AS output
FROM source

Another option would be to use the TRANSLATE function:

SELECT input,
    CASE 
        WHEN TRANSLATE(CAST(input as CHAR(10)), '~~~~~~~~~~~~~', '0123456789-. ') = '~~~~~~~~~~' THEN CAST(input AS DECIMAL(12, 2))
        ELSE 0
    END AS num
FROM x


回答2:

WITH x (stringval) AS 
(
VALUES ('x2'),(''),('2.2.'),('5-'),('-5-'),('--5'),('.5'),('2 2'),('0.5-'),(' 1 '),('2  '),('3.'),('-4.0')
)
SELECT stringval,
CASE WHEN (

-- Whitespace must not appear in the middle of a number 
-- (but trailing and/or leading whitespace is permitted)
RTRIM(LTRIM( stringval )) NOT LIKE '% %'

-- A number cannot start with a decimal point
AND LTRIM( stringval ) NOT LIKE '.%'

-- A negative decimal number must contain at least one digit between 
-- the negative sign and the decimal point
AND LTRIM( stringval ) NOT LIKE '-.%'

-- The negative sign may only appear at the beginning of the number
AND LOCATE( '-', LTRIM(stringval)) IN ( 0, 1 )

-- A number must contain at least one digit
AND TRANSLATE( stringval, '0000000000', '123456789') LIKE '%0%'

-- Allow up to one negative sign, followed by up to one decimal point
AND REPLACE( 
    TRANSLATE( RTRIM(LTRIM(stringval)), '000000000', '123456789'), 
    '0', '') IN ('','-','.','-.')
)
THEN 'VALID'
ELSE 'INVALID'
END AS stringisvalidnumber
FROM x
;


回答3:

Check this out:

SELECT Mobile, 
 TRANSLATE(Mobile, '~~~~~~~~~~', '0123456789') AS FirstPass, 
 TRANSLATE(TRANSLATE(Mobile, '~~~~~~~~~~', '0123456789'), '', '~') AS Erroneous, 
REPLACE(TRANSLATE(Mobile, '', TRANSLATE(TRANSLATE(Mobile, '~~~~~~~~~~', '0123456789'), '', '~')), ' ', '') AS Corrected 
 FROM Person WHERE Mobile <> '' FETCH FIRST 100 ROWS ONLY

The table is "Person" and the field that you want to check is "Mobile". If you work a little bit more on this, you can build an UPDATE to fix the entire table



标签: db2