Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql ORA-01722:Oracle查询中的数字无效,该查询试图在接下来的30秒内拾取计划的信号_Sql_Oracle - Fatal编程技术网

Sql ORA-01722:Oracle查询中的数字无效,该查询试图在接下来的30秒内拾取计划的信号

Sql ORA-01722:Oracle查询中的数字无效,该查询试图在接下来的30秒内拾取计划的信号,sql,oracle,Sql,Oracle,我在Oracle 11G中有一个所谓的signal_表,其列如下: 信号类型VarChar2 信号时间VarChar2 信号时间的格式为HH24:MI:SS,例如15:35:30,这意味着应用程序每天15:35:30发射此类信号 现在,我正在尝试编写一个查询,其中列出了从现在起30秒内将触发的所有信号 我试过类似的东西 select signal_type, signal_time, from signal_table where to_number(to

我在Oracle 11G中有一个所谓的signal_表,其列如下:

信号类型VarChar2 信号时间VarChar2

信号时间的格式为HH24:MI:SS,例如15:35:30,这意味着应用程序每天15:35:30发射此类信号

现在,我正在尝试编写一个查询,其中列出了从现在起30秒内将触发的所有信号

我试过类似的东西

select  
  signal_type,  
  signal_time,  
from  
  signal_table  
where  
  to_number(to_char(substr(signal_time,1,2)))*3600 + to_number(to_char(substr(signal_time,4,2)))*60 + to_number(to_char(substr(signal_time,7,2))) - to_number(to_char(sysdate,'HH24'))*3600 + to_number(to_char(sysdate,'MI'))*60 + to_number(to_char(sysdate,'SS')) < 30
;
有人能解释一下为什么我在where子句中放置to_编号强制转换部分时会出现上述错误吗


更好的是,有没有更优雅的方法来实现这一目标?

只要表中的所有数据确实具有nn:nn:nn格式的值,您所做的工作就可以达到一定程度。该错误表明至少有一行格式不正确。尽管你的第二个查询工作起来很奇怪——也许你有一个where子句没有显示出来

SELECT
TO_CHAR(TO_DATE(signal_time, 'HH24:MI:SS'),  'HH24:MI:SS') - TO_CHAR(NOW(),  'HH24:MI:SS')
;
这是一个例子。它没有错误,但是它显示了今天已经过去的所有信号时间,所以如果我理解的话,你需要将它限制在当前时间和30秒之间。这样做,还可以删除一些不必要的转换:

select  
  signal_type,
  signal_time
from
  signal_table
where  
  (to_number(substr(signal_time,1,2))*3600
    + to_number(substr(signal_time,4,2))*60
    + to_number(substr(signal_time,7,2)))
    - (to_number(to_char(sysdate,'HH24'))*3600
    + to_number(to_char(sysdate,'MI'))*60
    + to_number(to_char(sysdate,'SS'))) >= 0
and
  (to_number(substr(signal_time,1,2))*3600
    + to_number(substr(signal_time,4,2))*60
    + to_number(substr(signal_time,7,2)))
    - (to_number(to_char(sysdate,'HH24'))*3600
    + to_number(to_char(sysdate,'MI'))*60
    + to_number(to_char(sysdate,'SS'))) < 30
;
。这将提取信号_时间、当前时间和当前时间+30秒的时间部分,作为一天的分数

要查找格式不正确的值,快速检查如下:

select
  signal_type,
  signal_time
from
  signal_table
where
  not regexp_like(signal_time, '^\d\d:\d\d:\d\d$')
;
我对正则表达式不太感兴趣,所以这样做可能会更简洁。但这只会发现格式不正确的值,并且不会发现无效时间,例如查询将转换的24:60:60。日期版本会抱怨ORA-01850,但也会更宽容稍微不同的格式,例如其中一个元素缺少前导零。这可能是好事,也可能不是好事

如果您有需要排除但无法更正的不同格式的记录,则除了建议数据模型问题外,您还可以将检查查询用作主查询中的子查询:

select
  signal_type,
  signal_time
from
  (
    select
      *
    from
      signal_table
    where
      regexp_like(signal_time, '^\d\d:\d\d:\d\d$')
  )
where
  to_date(signal_time, 'HH24:MI:SS') - trunc(sysdate, 'MM')
    > sysdate - trunc(sysdate, 'DD')
  and to_date(signal_time, 'HH24:MI:SS') - trunc(sysdate, 'MM')
    < sysdate + interval '30' second - trunc(sysdate, 'DD')
;
显示此操作正常,然后使用相同的数据(包括一条坏记录)显示前面的简单查询失败

如果您的格式有效但时间无效(例如24:60:60),则仍将失败。如果是这样的话,那么您确实需要清理数据,但可能会提出一个更严格的正则表达式,或者使用函数在运行时检查有效的格式


在某些情况下,您可能需要添加提示以停止将筛选器应用于内部select,但我认为在这种情况下这不会是一个问题。

1。您将无法在给定的数据类型varchar2中存储15:35:30。2.您的第一个select查询似乎没有任何错误。3.您的select查询有额外的逗号,这是错误的。您的逻辑在00:00:15的信号时间内工作吗?Oracle中没有now函数。now不是Oracle函数,您需要使用sysdate。更重要的是,从一个字符串中减去另一个字符串会得到什么?Oracle会再次抱怨ORA-01722,因为它会尝试将两个字符串隐式转换为数字,这将失败。感谢您的建议。实际上,我也尝试过将信号时间转换为日期格式,但在转换整个输入字符串之前,得到了ORA-01830:date格式的图片结尾。正如我在Alex的另一个回复线程中发布的评论一样,这可能是由于表中确实有一些不符合格式的记录。到目前为止,我还没能解决这个问题……谢谢亚历克斯的回复。事实上,真正的罪魁祸首可能是不合格的记录。在我编写此查询的实表中,有两条记录的信号时间值格式不同。我尝试了从信号表中选择信号类型、信号时间,其中到日期信号时间,'HH24:MI:SS'-truncsysdate,'MM'>=sysdate-truncsysdate,'DD'和到日期信号时间,'HH24:MI:SS'-truncsysdate,'MM'=sysdate-truncsysdate,'DD'和到日期信号时间,'HH24:MI:SS'-truncsysdate,'MM'select signal_type, signal_time from signal_table where not regexp_like(signal_time, '^\d\d:\d\d:\d\d$') ;
select
  signal_type,
  signal_time
from
  (
    select
      *
    from
      signal_table
    where
      regexp_like(signal_time, '^\d\d:\d\d:\d\d$')
  )
where
  to_date(signal_time, 'HH24:MI:SS') - trunc(sysdate, 'MM')
    > sysdate - trunc(sysdate, 'DD')
  and to_date(signal_time, 'HH24:MI:SS') - trunc(sysdate, 'MM')
    < sysdate + interval '30' second - trunc(sysdate, 'DD')
;