【问题标题】:How can you tell if a value is not numeric in Oracle?如何判断 Oracle 中的值是否不是数字?
【发布时间】:2015-05-03 09:22:04
【问题描述】:

如果我的值无效,我有以下代码会返回错误消息。如果给定的值不是数字,我想给出相同的错误消息。

IF(option_id = 0021) THEN 
      IF((value<10000) or (value>7200000) or /* Numeric Check */)THEN
          ip_msg(6214,option_name);  -- Error Message
          return;
      END IF;
END IF;      

在 SQL Server 中,我只是使用了ISNUMERIC()。我想在 Oracle 中做类似的事情。比如,

IF((!ISNUMERIC(value)) or (value<10000) or (value>7200000))
    THEN ...

【问题讨论】:

    标签: sql oracle plsql isnumeric


    【解决方案1】:
    REGEXP_LIKE(column, '^[[:digit:]]+$')
    

    如果列只包含数字字符,则返回 TRUE

    【讨论】:

    • 当然,并非所有数字都完全由数字字符组成。 “1.2”是数字,但它包含一个句点(或逗号,具体取决于您的 NLS 设置)。 “-100”是数字,但它包含一个减号。 “1.2.3”不是数字,尽管它完全由数字和句点组成。如果您真的想查看该列是否包含无格式的正整数,regexp_like 可能就足够了。
    • 123e-5 也是一个数字。
    • 这个正则表达式只涵盖正整数值!
    • 用作:SELECT column_with_int_and_string FROM MyTable WHERE NOT REGEXP_LIKE(column_with_int_and_string, ‘^[[:digit:]]+$’);
    • 如果需要的不仅仅是数字,这个正则表达式可以根据需要进行扩展,但我认为这个答案满足了 OP 并且对于任何有类似问题的人来说都是一个很好的开始。这是一个让人们使用更复杂的正则表达式的示例,它应该涵盖所有整数(未经测试):'^[+-]?[[:digit:]]+$'
    【解决方案2】:

    Oracle DB 12c Release 2你可以使用VALIDATE_CONVERSION函数:

    VALIDATE_CONVERSION 确定 expr 是否可以转换为指定的数据类型。如果 expr 可以成功转换,则该函数返回 1;否则,此函数返回 0。如果 expr 计算结果为 null,则此函数返回 1。如果计算 expr 时发生错误,则此函数返回错误。

     IF (VALIDATE_CONVERSION(value AS NUMBER) = 1) THEN
         ...
     END IF;
    

    db<>fiddle demo

    【讨论】:

    • 哦,伙计...几个月来我一直在寻找这个功能。这是一个巨大的帮助!谢谢。
    • @MarvinM 很高兴听到这个消息。另请查看DEFAULT ... ON CONVERSION ERROR
    • 我不明白为什么这个函数在值为空时返回 1。它应该是 0
    • @Salman 这样定义可能是因为SELECT CAST(null AS &lt;datatype&gt;) c FROM dual; 是一个有效的演员表。
    【解决方案3】:

    没有内置函数。你可以写一个

    CREATE FUNCTION is_numeric( p_str IN VARCHAR2 )
      RETURN NUMBER
    IS
      l_num NUMBER;
    BEGIN
      l_num := to_number( p_str );
      RETURN 1;
    EXCEPTION
      WHEN value_error
      THEN
        RETURN 0;
    END;
    

    和/或

    CREATE FUNCTION my_to_number( p_str IN VARCHAR2 )
      RETURN NUMBER
    IS
      l_num NUMBER;
    BEGIN
      l_num := to_number( p_str );
      RETURN l_num;
    EXCEPTION
      WHEN value_error
      THEN
        RETURN NULL;
    END;
    

    你可以这样做

    IF( is_numeric( str ) = 1 AND 
        my_to_number( str ) >= 1000 AND
        my_to_number( str ) <= 7000 )
    

    如果您碰巧使用的是 Oracle 12.2 或更高版本,您可以利用 to_number 函数的增强功能

    IF( to_number( str default null on conversion error ) >= 1000 AND
        to_number( str default null on conversion error ) <= 7000 )
    

    【讨论】:

    • 如果我正确理解 OP(相当于 !ISNUMERIC(value)),我想你想要上面的 is_numeric( str ) = 0
    • @DavidFaber - 我认为这是一个错字。如果字符串不是数字,则将其与数值进行比较是没有意义的。
    • 哦,我明白了,您正在使用 AND,其中 OP 有 OR。过失。
    【解决方案4】:

    我在网上找到的最佳答案:

    SELECT case when trim(TRANSLATE(col1, '0123456789-,.', ' ')) is null
                then 'numeric'
                else 'alpha'
           end
    FROM tab1;
    

    【讨论】:

    【解决方案5】:

    您可以使用以下正则表达式来匹配整数(例如,123)、浮点数(12.3)和带指数的数字(1.2e3):

    ^-?\d*\.?\d+([eE]-?\d+)?$
    

    如果您想接受+ 符号以及- 符号(就像Oracle 对TO_NUMBER() 所做的那样),您可以将上面出现的- 更改为[+-]。因此,您可以将上面的代码块重写如下:

    IF (option_id = 0021) THEN 
        IF NOT REGEXP_LIKE(value, '^[+-]?\d*\.?\d+([eE][+-]?\d+)?$') OR TO_NUMBER(value) < 10000 OR TO_NUMBER(value) > 7200000 THEN
            ip_msg(6214,option_name);
            RETURN;
        END IF;
    END IF;
    

    我不完全确定它会处理所有值,因此您可能想要添加一个 EXCEPTION 块或编写一个自定义的 to_number() 函数,正如 @JustinCave 建议的那样。

    【讨论】:

      【解决方案6】:
      CREATE OR REPLACE FUNCTION IS_NUMERIC(P_INPUT IN VARCHAR2) RETURN INTEGER IS
        RESULT INTEGER;
        NUM NUMBER ;
      BEGIN
        NUM:=TO_NUMBER(P_INPUT);
        RETURN 1;
      EXCEPTION WHEN OTHERS THEN
        RETURN 0;
      END IS_NUMERIC;
      /
      

      【讨论】:

        【解决方案7】:

        此正则表达式将匹配 5、-5、+5、5.44、3.45e-3 等数字

        REGEXP_LIKE('54.55e33', '^[+-]?\d+([.]\d+)?(e[+-]?\d+)?$')
        

        【讨论】:

          【解决方案8】:
          SELECT DECODE(REGEXP_COUNT(:value,'\d'),LENGTH(:value),'Y','N') AS is_numeric FROM dual;
          

          有很多方法,但这个最适合我。

          【讨论】:

            猜你喜欢
            • 2018-08-27
            • 2022-11-24
            • 1970-01-01
            • 2021-09-24
            • 1970-01-01
            • 1970-01-01
            • 2023-03-12
            • 1970-01-01
            • 2017-08-30
            相关资源
            最近更新 更多