check if “it's a number” function in Oracle

后端 未结 16 2598
一整个雨季
一整个雨季 2020-11-28 10:31

I\'m trying to check if a value from a column in an oracle (10g) query is a number in order to compare it. Something like:

select case when ( is_number(myTab         


        
相关标签:
16条回答
  • 2020-11-28 10:58

    Assuming that the ID column in myTable is not declared as a NUMBER (which seems like an odd choice and likely to be problematic), you can write a function that tries to convert the (presumably VARCHAR2) ID to a number, catches the exception, and returns a 'Y' or an 'N'. Something like

    CREATE OR REPLACE FUNCTION is_number( p_str IN VARCHAR2 )
      RETURN VARCHAR2 DETERMINISTIC PARALLEL_ENABLE
    IS
      l_num NUMBER;
    BEGIN
      l_num := to_number( p_str );
      RETURN 'Y';
    EXCEPTION
      WHEN value_error THEN
        RETURN 'N';
    END is_number;
    

    You can then embed that call in a query, i.e.

    SELECT (CASE WHEN is_number( myTable.id ) = 'Y' AND myTable.id > 0 
                   THEN 'Number > 0'
                 ELSE 'Something else'
             END) some_alias
      FROM myTable
    

    Note that although PL/SQL has a boolean data type, SQL does not. So while you can declare a function that returns a boolean, you cannot use such a function in a SQL query.

    0 讨论(0)
  • 2020-11-28 10:59

    Function for mobile number of length 10 digits and starting from 9,8,7 using regexp

    create or replace FUNCTION VALIDATE_MOBILE_NUMBER
    (   
       "MOBILE_NUMBER" IN varchar2
    )
    RETURN varchar2
    IS
      v_result varchar2(10);
    
    BEGIN
        CASE
        WHEN length(MOBILE_NUMBER) = 10 
        AND MOBILE_NUMBER IS NOT NULL
        AND REGEXP_LIKE(MOBILE_NUMBER, '^[0-9]+$')
        AND MOBILE_NUMBER Like '9%' OR MOBILE_NUMBER Like '8%' OR MOBILE_NUMBER Like '7%'
        then 
        v_result := 'valid';
        RETURN v_result;
          else 
          v_result := 'invalid';
           RETURN v_result;
           end case;
        END;
    
    0 讨论(0)
  • 2020-11-28 11:01

    This is my query to find all those that are NOT number :

    Select myVarcharField
    From myTable
    where not REGEXP_LIKE(myVarcharField, '^(-)?\d+(\.\d+)?$', '')
    and not REGEXP_LIKE(myVarcharField, '^(-)?\d+(\,\d+)?$', '');
    

    In my field I've . and , decimal numbers sadly so had to take that into account, else you only need one of the restriction.

    0 讨论(0)
  • 2020-11-28 11:03

    Here's a simple method which :

    • does not rely on TRIM
    • does not rely on REGEXP
    • allows to specify decimal and/or thousands separators ("." and "," in my example)
    • works very nicely on Oracle versions as ancient as 8i (personally tested on 8.1.7.4.0; yes, you read that right)
    SELECT
        TEST_TABLE.*,
    
        CASE WHEN
            TRANSLATE(TEST_TABLE.TEST_COLUMN, 'a.,0123456789', 'a') IS NULL
        THEN 'Y'
        ELSE 'N'
        END
        AS IS_NUMERIC
    
    FROM
        (
        -- DUMMY TEST TABLE
            (SELECT '1' AS TEST_COLUMN FROM DUAL) UNION
            (SELECT '1,000.00' AS TEST_COLUMN FROM DUAL) UNION
            (SELECT 'xyz1' AS TEST_COLUMN FROM DUAL) UNION
            (SELECT 'xyz 123' AS TEST_COLUMN FROM DUAL) UNION
            (SELECT '.,' AS TEST_COLUMN FROM DUAL)
        ) TEST_TABLE
    

    Result:

    TEST_COLUMN IS_NUMERIC
    ----------- ----------
    .,          Y
    1           Y
    1,000.00    Y
    xyz 123     N
    xyz1        N
    
    5 rows selected.
    

    Granted this might not be the most powerful method of all; for example ".," is falsely identified as a numeric. However it is quite simple and fast and it might very well do the job, depending on the actual data values that need to be processed.

    For integers, we can simplify the Translate operation as follows :

    TRANSLATE(TEST_TABLE.TEST_COLUMN, 'a0123456789', 'a') IS NULL
    

    How it works

    From the above, note the Translate function's syntax is TRANSLATE(string, from_string, to_string). Now the Translate function cannot accept NULL as the to_string argument. So by specifying 'a0123456789' as the from_string and 'a' as the to_string, two things happen:

    • character a is left alone;
    • numbers 0 to 9 are replaced with nothing since no replacement is specified for them in the to_string.

    In effect the numbers are discarded. If the result of that operation is NULL it means it was purely numbers to begin with.

    0 讨论(0)
  • 2020-11-28 11:05

    Saish's answer using REGEXP_LIKE is the right idea but does not support floating numbers. This one will ...

    Return values that are numeric

    SELECT  foo 
    FROM    bar
    WHERE   REGEXP_LIKE (foo,'^-?\d+(\.\d+)?$');
    

    Return values not numeric

    SELECT  foo 
    FROM    bar
    WHERE   NOT REGEXP_LIKE (foo,'^-?\d+(\.\d+)?$');
    

    You can test your regular expressions themselves till your heart is content at http://regexpal.com/ (but make sure you select the checkbox match at line breaks for this one).

    0 讨论(0)
  • 2020-11-28 11:06

    You can use the regular expression function 'regexp_like' in ORACLE (10g)as below:

    select case
           when regexp_like(myTable.id, '[[:digit:]]') then
            case
           when myTable.id > 0 then
            'Is a number greater than 0'
           else
            'Is a number less than or equal to 0'
         end else 'it is not a number' end as valuetype
    from table myTable
    
    0 讨论(0)
提交回复
热议问题