1

数据库列(VARCHAR2数据类型)将日期/时间存储为 13 位(毫秒)unixtimestamp 格式。现在,当我想将该列与 Oracle 日期(有问题)进行比较时,抛出的错误为“无效数字”

两种方法都试过了

  • 将 13 位数字转换为日期并与相关日期进行比较,如下所示。表达式似乎有效,因为它们在选择查询中打印,但如果我包含在 where 部分中,它会抛出“无效数字”

这里的“值”是数据类型的第 13 位 unixtimestamp 列 VARCHAR2

select
TO_DATE('1970-01-01', 'YYYY-MM-DD') + value/86400000,
TO_DATE('2014-04-21', 'YYYY-MM-DD')
from dummytable 

-- where and TO_DATE('1970-01-01', 'YYYY-MM-DD') + value/86400000 > TO_DATE('2014-04-21', 'YYYY-MM-DD')
  • 将相关日期转换为 13 位 unixtimestamp 并与数据库列进行比较。表达式似乎有效,因为它们在选择查询中打印,但如果我包含在 where 部分中,则会抛出“无效数字”

.

select
value,
(to_date('2013-04-21', 'YYYY-MM-DD') - to_date('1970-01-01', 'YYYY-MM-DD')) * (1000*24*60*60)
from dummytable 

-- where value > ((to_date('2013-04-21', 'YYYY-MM-DD') - to_date('1970-01-01', 'YYYY-MM-DD')) * (1000*24*60*60))

任何指针?提前致谢。

[编辑- 1 天后] 我现在看到了问题。“值”列有一些非数字数据(其他行)。但我有另一列说字段,其中总是 field='date' 返回值作为 13 位时间戳。现在我认为当 'where' 条件执行时,虽然 field='date' 在条件中,但它仍在验证 'value' 的其他非数字值。有没有办法避免这种情况?

4

1 回答 1

3

你的代码工作得很好。问题出在您的数据中。你的一些values不是数字。

create table test
(value varchar2(13));

insert into test(value) values('2154534689000');
--insert into test(value) values('2 54534689000');

select TO_DATE('1970-01-01', 'YYYY-MM-DD') + value/86400000
from test
where TO_DATE('1970-01-01', 'YYYY-MM-DD') + value/86400000 > TO_DATE('2014-04-21', 'YYYY-MM-DD');

这段代码工作正常。但是如果你取消注释第二个插入,你会得到与你得到的完全相同的invalid number错误。

UPD。艾伦给了你一个很好的提示,但我觉得向你解释一下观点会很好。您从视图中选择的事实可以产生影响。视图不会物理存储在某个地方,当您从中选择时,它只是“添加到您的查询中”。然后 Oracle 查询优化器开始工作。除其他外,它可以更改where评估谓词的顺序。例如,您的视图查询可以有一行where value is not null,它通常只显示“好”值。但是如果你的查询有一个谓词where to_date(value,'ddmmyyyy') > sysdate,Oracle 可以决定更早地评估您的谓词,因为 Oracle 预测它将“切断”更多的行,从而使整个查询更快,消耗更少的内存。当然,由于尝试将空字符串转换为日期,执行会崩溃。我相信,艾伦在他给出链接的答案中给出了解决这个问题的好方法:将您的查询“包装”在 Oracle 无法“解包”的子查询中:

select value
from
  (select value
  from my_view
  where rownum > 0)
where to_date(value,'ddmmyyyy') > sysdate

希望有帮助。

于 2014-05-14T15:27:08.087 回答