1

查询:
Select To_Number(qty) From my_table Where Id=12345;
输出:
ORA-01722: invalid number
01722. 00000 - "invalid number"

查询:Select qty From my_table Where Id=12345;
输出:0.00080

查询:
Select To_Number(0.00080) From Dual;
输出:(
0.00080无错误)

这是我在甲骨文面临的一个奇怪的情况。任何人都可以提出为什么会这样吗?该列qtyNUMBER类型。因此很难想象它包含无效数字,但它确实发生了。
我想澄清一下,尽管我们在同一列中有数千条记录,但它发生在列中的特定值上。添加更多:如果我使用函数,
则会出现相同的错误。TO_CHAR(qty)qty列是NUMBER类型 not VARCHAR2。事实上,我们正在使用SUM(qty)显示错误的函数。因此,我进行了解剖,发现这一行是罪魁祸首。

4

4 回答 4

4

我假设它qty被定义为varchar2in my_table- 否则,调用to_number. 如果这个假设是正确的,我敢打赌,表中还有一些其他行qty包含非数字数据。

SQL 是一种基于集合的语言,因此 Oracle(或任何其他数据库)可以完全自由地以它认为合适的任何顺序评估事物。这意味着 Oracle在应用谓词to_number(qty)之前可以完全自由地评估表达式。id=12345如果Oracle碰巧遇到qty无法将值转换为数字的行,则会抛出错误。

也有可能在特定行中有一些非数字数据id = 12345恰好没有显示(例如控制字符)。您可以通过运行查询来检查

SELECT dump(qty, 1016) 
  FROM my_table
 WHERE id = 12345

(如果您想要十进制而不是十六进制,请使用 1010 作为 的第二个参数dump)并检查数据中是否有任何意外。

于 2013-10-09T13:46:53.067 回答
2

qty鉴于它确实是一个字段,我可以看到您可以获得所显示结果的唯一方法number是它是否包含损坏的数据(这就是为什么人们对该假设持怀疑态度的原因)。我还假设您的客户正在用前导零格式化值,但没有强制尾随零,这通常不会出现;你当然可以用 强制它to_char(.0008, '0.00000'),但你似乎没有这样做;仍然,前导零让我想知道。

无论如何,为了证明损坏,您可以通过 PL/SQL 将无效值强制输入字段 - 不要使用真实数据或您关心的表尝试此操作:

create table t42(qty number);

table T42 created.

declare
  n number;
begin
  dbms_stats.convert_raw_value('bf0901', n);
  insert into t42 (qty) values (n);
end;
/

anonymous block completed

select qty from t42;

       QTY
----------
    .00080 

select to_number(qty) from t42;

Error starting at line : 12 in command -
select to_number(qty) from t42
Error report -
SQL Error: ORA-01722: invalid number
01722. 00000 -  "invalid number"

请注意,普通查询按预期显示数字 - 尽管有一个尾随零,并且没有前导零 - 并通过to_number()throws ORA-01722 运行它。除了前导零之外,这就是您所展示的。

它也失败了to_char(),如您的问题标题所示:

select to_char(qty) from t42;

Error starting at line : 13 in command -
select to_char(qty) from t42
Error report -
SQL Error: ORA-01722: invalid number

...这是有道理的;你to_number()正在做一个隐式转换,所以它真的是,我认为to_number(to_char(qty))它是实际产生错误的隐式。to_char()

您的评论表明您有一个加载和删除数据的过程。看看它到底在做什么,以及它是否会引入腐败,将会很有趣。这种效果可以通过 OCI 实现,因为数据库会相信它传递的数据是有效的,就像上面的 PL/SQL 示例一样。有错误报告表明imp也可能导致损坏。因此,加载过程的详细信息可能很重要,确切的数据库版本和平台也可能很重要。

于 2013-10-09T15:55:25.510 回答
1

我遇到了几乎相同的问题。而且我发现神秘数字之后的行为与正常数字不同dump()。例如,假设我的 qty=500 (datatype: number(30,2)) ,那么:

select dump(qty) from my_table where Id=12345;

Typ=2 Len=3: 194,6,1

select dump(500.00) from dual;

Typ=2 Len=2: 194,6

如果我们知道如何存储数字数据类型(如果不知道,请访问http://translate.google.com/translate?langpair=zh-CN%7Cen&hl=zh-CN&ie=UTF8&u=http%3A//www.eygle.com /archives/2005/12/how_oracle_stor.html),我们可以发现Typ=2 Len=3: 194,6,1神秘数字中有一个尾随零(最后一个额外的“1”)。

所以我做了一个技巧来消除拖尾零,它可以解决这个问题。

select dump(trunc(qty+0.001,2)) from my_table where Id=12345;

Typ=2 Len=2: 194,6

希望有人解释深层机制。

于 2014-10-09T13:22:08.397 回答
0

try this:

Select To_Number(trim(qty)) From my_table Where Id=12345;
于 2013-10-09T13:41:16.083 回答