我在oracle sql开发人员中运行了一个sql查询,它运行得很好但是当我使用包装器,在这种情况下excel vba中的adodb时,为了执行相同的查询,我得到一个错误。我怀疑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投射到浮子上,这也不起作用。它运行的唯一实例是没有SIN,并且条件右侧的浮点值附近有单引号。
我无法理解为什么即使在Oracle SQL Developer中运行得很好,我也无法在没有任何错误的情况下运行查询。任何帮助将不胜感激。
答案 0 :(得分:3)
因此,似乎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:]]*$')
答案 1 :(得分:0)
在评论中进行调查后,这似乎是直接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;
对于纬度,你只需要在小数点前有两个9,但是经度需要三个,所以你也可以保持一致。
但是你还需要在引用它的任何地方进行显式转换,例如:
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的一个变种,但结果证明是一个红鲱鱼。