Oracle sql 错误 ora-01722 无效数字 ora-02063 前一行来自
Oracle sql error ora-01722 invalid number ora-02063 preceding line from
我在 oracle sql 开发人员中 运行 一个 sql 查询,它工作得很好,但是当我使用包装器时,在这种情况下 excel vba,执行相同的查询我得到一个错误。我怀疑 adodb 使用的是不同版本的 oracle,并且优化方式不同。
我运行的查询是:
select (LATITUDE) from db where sin(LATITUDE) <= 45.0;
我收到错误:
ORA-01722: 数字无效
ORA-02063: 来自 db
的前一行
如果我将查询中的 sin(LATITUDE) <= 45.0
更改为:
LATITUDE <= 45.0
(无效)
LATITUDE <= '45.0'
(有效)
sin(LATITUDE) <= '45.0'
(无效)
to_number(sin(LATITUDE)) <= 45.0
(无效)
sin(to_number(LATITUDE)) <= '45.0'
(无效)
我也试过将 LATITUDE 转换为浮点数,但这也不起作用。 运行s 的唯一实例是没有 SIN 并且在条件右侧的浮动值周围有单引号。
我很困惑为什么我不能毫无错误地得到对 运行 的查询,即使它 运行 在 Oracle SQL Developer 中很好。任何帮助将不胜感激。
因此,LATITUDE
似乎存储为数字,而某些值不是数字。
也许像这样的查询可以帮助您找出问题所在:
select latitude
from db
where translate(latitude, '-0123456789.a', 'a') is not null;
这不是一个完美的测试,但它经常有效。
编辑:
更好的方法是使用正则表达式:
select latitude
from db
where not regexp_like(latitutde, '^-?[[:digit:]]*[.]?[[:digit:]]*$')
根据评论调查,这似乎是直接 SQL 客户端和 ADODB 连接之间 NLS 设置的差异。因为您将数字存储为字符串(这总是一个坏主意)并且数字有小数点分隔符,所以不同的 NLS_NUMERIC_CHARACTERS 设置会在一个地方导致错误,但不会在另一个地方导致错误。
当您从字符串隐式转换为数字时,或者如果您有不带格式掩码的显式 to_number()
调用,Oracle 将使用该 NLS 设置。因此,在任何环境中,这些语句中的一个将起作用,而另一个将出现 ORA-01722 错误:
select to_number('0,1') from dual;
select to_number('0.1') from dual;
哪一个失败取决于 NLS 设置。您可以使用显式格式掩码来避免这种情况,并且 to_number()
的第三个参数说明如何解释它:
select to_number('0,1', '99D99999', 'NLS_NUMERIC_CHARACTERS='',.''') from dual;
select to_number('0.1', '99D99999', 'NLS_NUMERIC_CHARACTERS=''.,''') from dual;
这是使用 D
小数分隔符标记,它对应于 NLS 覆盖中的第一个字符 - 请注意这两个语句之间的句点和逗号切换 - 并且 NLS 覆盖必须设置为匹配你的实际数据。当然,您还需要在小数点前后使用适当的数字。
假设您正在处理 decimal degrees,您应该能够使用:
select to_number(latitude, '999D99999999', 'NLS_NUMERIC_CHARACTERS=''.,''')
from irtt_meter_mv@cmomprd;
纬度只需要小数点前两个九,但经度需要三个,所以最好保持一致。
但是您还需要在引用它的任何地方进行显式转换,例如:
select to_number(latitude, '999D99999999', 'NLS_NUMERIC_CHARACTERS=''.,''')
from irtt_meter_mv@cmomprd;
where abs(to_number(latitude, '999D99999999', 'NLS_NUMERIC_CHARACTERS=''.,''')) < 45;
如果您一开始就使用了正确的数据类型,就可以避免这种情况。如果您不能更改列类型,您可以考虑添加一个虚拟列来为您执行相同的转换,或者如果不允许更改类型的视图。
较早的答案给出了 Gordon Linoff 的变体,但结果是转移注意力。
我在 oracle sql 开发人员中 运行 一个 sql 查询,它工作得很好,但是当我使用包装器时,在这种情况下 excel vba,执行相同的查询我得到一个错误。我怀疑 adodb 使用的是不同版本的 oracle,并且优化方式不同。
我运行的查询是:
select (LATITUDE) from db where sin(LATITUDE) <= 45.0;
我收到错误:
ORA-01722: 数字无效
ORA-02063: 来自 db
的前一行如果我将查询中的 sin(LATITUDE) <= 45.0
更改为:
LATITUDE <= 45.0
(无效)
LATITUDE <= '45.0'
(有效)
sin(LATITUDE) <= '45.0'
(无效)
to_number(sin(LATITUDE)) <= 45.0
(无效)
sin(to_number(LATITUDE)) <= '45.0'
(无效)
我也试过将 LATITUDE 转换为浮点数,但这也不起作用。 运行s 的唯一实例是没有 SIN 并且在条件右侧的浮动值周围有单引号。
我很困惑为什么我不能毫无错误地得到对 运行 的查询,即使它 运行 在 Oracle SQL Developer 中很好。任何帮助将不胜感激。
因此,LATITUDE
似乎存储为数字,而某些值不是数字。
也许像这样的查询可以帮助您找出问题所在:
select latitude
from db
where translate(latitude, '-0123456789.a', 'a') is not null;
这不是一个完美的测试,但它经常有效。
编辑:
更好的方法是使用正则表达式:
select latitude
from db
where not regexp_like(latitutde, '^-?[[:digit:]]*[.]?[[:digit:]]*$')
根据评论调查,这似乎是直接 SQL 客户端和 ADODB 连接之间 NLS 设置的差异。因为您将数字存储为字符串(这总是一个坏主意)并且数字有小数点分隔符,所以不同的 NLS_NUMERIC_CHARACTERS 设置会在一个地方导致错误,但不会在另一个地方导致错误。
当您从字符串隐式转换为数字时,或者如果您有不带格式掩码的显式 to_number()
调用,Oracle 将使用该 NLS 设置。因此,在任何环境中,这些语句中的一个将起作用,而另一个将出现 ORA-01722 错误:
select to_number('0,1') from dual;
select to_number('0.1') from dual;
哪一个失败取决于 NLS 设置。您可以使用显式格式掩码来避免这种情况,并且 to_number()
的第三个参数说明如何解释它:
select to_number('0,1', '99D99999', 'NLS_NUMERIC_CHARACTERS='',.''') from dual;
select to_number('0.1', '99D99999', 'NLS_NUMERIC_CHARACTERS=''.,''') from dual;
这是使用 D
小数分隔符标记,它对应于 NLS 覆盖中的第一个字符 - 请注意这两个语句之间的句点和逗号切换 - 并且 NLS 覆盖必须设置为匹配你的实际数据。当然,您还需要在小数点前后使用适当的数字。
假设您正在处理 decimal degrees,您应该能够使用:
select to_number(latitude, '999D99999999', 'NLS_NUMERIC_CHARACTERS=''.,''')
from irtt_meter_mv@cmomprd;
纬度只需要小数点前两个九,但经度需要三个,所以最好保持一致。
但是您还需要在引用它的任何地方进行显式转换,例如:
select to_number(latitude, '999D99999999', 'NLS_NUMERIC_CHARACTERS=''.,''')
from irtt_meter_mv@cmomprd;
where abs(to_number(latitude, '999D99999999', 'NLS_NUMERIC_CHARACTERS=''.,''')) < 45;
如果您一开始就使用了正确的数据类型,就可以避免这种情况。如果您不能更改列类型,您可以考虑添加一个虚拟列来为您执行相同的转换,或者如果不允许更改类型的视图。
较早的答案给出了 Gordon Linoff 的变体,但结果是转移注意力。