查询:
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
(无错误)
这是我在Oracle面临的一个奇怪的情况。任何人都能说明为什么会这样吗?列qty
是NUMBER
类型。因此,很难想象它包含无效数字,但它确实发生了
我想澄清它发生在列中的特定值,尽管我们在同一列中有数千条记录
添加更多:如果我使用TO_CHAR(qty)
函数,则会出现相同的错误。 qty
列NUMBER
类型不是VARCHAR2
。实际上我们正在使用显示错误的SUM(qty)
函数。因此,我去解剖,发现这一行是罪魁祸首。
答案 0 :(得分:4)
我假设qty
中的varchar2
定义为my_table
- 否则,通过调用to_number
无法达到目的。如果这个假设是正确的,我会打赌表格中有一些其他行qty
中有非数字数据。
SQL是一种基于集合的语言,因此Oracle(或任何其他数据库)可以完全自由地按照它认为合适的顺序评估事物。这意味着在应用to_number(qty)
谓词之前,Oracle完全可以自由地评估id=12345
表达式。如果Oracle碰巧遇到qty
值无法转换为数字的行,则会引发错误。
在特定行中可能存在一些非数字数据,其中id = 12345
恰好不显示(例如控制字符)。您可以通过运行查询来检查
SELECT dump(qty, 1016)
FROM my_table
WHERE id = 12345
(如果你想要十进制而不是十六进制,使用1010作为dump
的第二个参数)并检查数据中是否有任何意外。
答案 1 :(得分: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()
运行它会抛出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
也可能导致腐败。因此,加载过程的细节可能很重要,确切的数据库版本和平台也是如此。
答案 2 :(得分:1)
我遇到了几乎相同的问题。我发现神秘数字的行为与dump()
之后的正常数字不同。例如,假设我的qty = 500(数据类型: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
希望有人解释深层机制。
答案 3 :(得分:0)
试试这个:
Select To_Number(trim(qty)) From my_table Where Id=12345;