【问题标题】:SQL Select Error: "ORA-01722: invalid number" only when number is queriedSQL Select Error: "ORA-01722: invalid number" 仅在查询数字时
【发布时间】:2019-07-31 17:33:55
【问题描述】:

有关此错误消息的其他问题似乎是在执行插入或将文本转换为数字的情况下。就我而言,当我从 my_table 中选择特定数字时,我会收到错误“ORA-01722:无效数字”,而当我使用其他数字时却没有。

此代码触发错误消息:

SELECT * FROM my_table WHERE sel_num = 156396255

此代码返回预期结果(my_table 中的 1 行):

SELECT * FROM my_table WHERE sel_num = 156396320

sel_num 字段在 my_table 中定义为:

列名:sel_num,数据类型:VARCHAR2(30 字节),Null?:Y

不幸的是,我无法控制数据类型。

Oracle 声明此错误是由以下原因引起的:

“尝试将字符串转换为数字失败,因为字符串不是有效的数字文字。算术函数或表达式中只能使用数字字段或包含数字数据的字符字段。只能添加数字字段到日期或从日期中减去。”

考虑到我将数字传递给 WHERE 子句,而不是字符串,这很令人困惑。由于 VARCHAR2 数据类型,我尝试将数字作为字符串传递到查询中,这导致错误消息消失。

此代码返回一个没有错误消息的空集:

SELECT * FROM my_table WHERE sel_num = '156396255'

如果 sel_num 的这个特定值在表中不存在,这可能是一个可接受的结果,但我不确定为什么这似乎以它的方式工作。

【问题讨论】:

  • 您应该将字符串与字符串进行比较,而不是数字。

标签: sql oracle


【解决方案1】:

为什么第二个数字有效? 在第二种情况下,提供的值已转换并符合过滤条件,无需尝试对任何其他值进行隐式转换。

如果您使用的是 Oracle 12r2 或更新版本,您可以使用 VALIDATE_CONVERSION()robust cast functions 找到无效行

例子:

WITH test_case AS(
SELECT '1' AS my_field FROM dual UNION ALL
SELECT '2' FROM dual UNION ALL
SELECT 'string' FROM dual )
SELECT
    my_field,
    VALIDATE_CONVERSION(my_field AS NUMBER)AS is_number,
    CAST(my_field AS NUMBER DEFAULT 0 ON CONVERSION ERROR)AS conversion_result
FROM
    test_case;

结果:

【讨论】:

    【解决方案2】:

    在 WHERE 子句中提供数字值的版本没有什么令人困惑的地方。因为您的值是数字,所以 Oracle 尝试将 varchar2 列值转换为数字数据类型以进行比较。某些列不包含有效的数字数据,因此会发生错误。如果您将要搜索的值括在单引号中,那么您现在正在做一个字符来进行比较。如果表数据列在值中存储任何与您的值不匹配的非数字,则会出现问题。因此,您可能必须过滤前导和尾随空格,删除美元符号或逗号等...这是一个示例:1)为什么应始终使用适当的数据库数据类型来存储数据,以及 2)为什么应始终对数据进行规范化(已编辑):大小写、前导和/或尾随空格、零填充等......

    【讨论】:

    • 为什么同一个查询对不同的号码有效?
    • 不同数字的查询是什么样的?在查询的每个版本上运行解释计划。这可能会提供线索。 sel_num 上有索引吗?为两个查询转储 sel_num 的内容(转储函数)。
    【解决方案3】:

    在条件次的列中使用trim(),因为它可能包含空格,否则没有理由返回行

       SELECT * FROM my_table WHERE trim(sel_num) = '156396255'
    

    【讨论】:

      【解决方案4】:

      您正在测试的字段的表格数据中包含字母数字字符。当您使用数字进行测试时,会引发此错误。然后你必须通过添加引号或其他任何可以告诉oracle你有一个字符串的东西来进行测试。如果没有返回任何内容,那么您必须调整您的查询,例如额外的空格。

        SELECT * FROM my_table WHERE TRIM(sel_num) = '156396255'
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-20
        • 2015-04-21
        • 1970-01-01
        • 2020-01-01
        • 2018-10-24
        • 1970-01-01
        相关资源
        最近更新 更多