查询中的Oracle to_char无效

时间:2016-06-22 11:34:55

标签: oracle

我试图运行以下查询,但它似乎是错误

对于这些数据类型是varchar

查询

select * 
  from RP_REPORT_TEMP 
 where to_char(START_DATE,'FM DD YYYY HH24:MI:SS AM') 
          >= 'May 01 2016 00:00:00' 
   and to_char(END_DATE,'FM DD YYYY HH24:MI:SS PM') 
          <= 'May 31 2016 11:59:00' 
   and lower(rid) like '%a001%' 
 order by CAST(cid as INTEGER) asc

表格

|RID                 |START_DATE                 |END_DATE                     |
|--------------------|-------------------------- |-----------------------------|
|A001                |May  1 2016 12:00:00:000AM |May  31 2016 12:00:00:000PM  |
|A001                |May  1 2016 12:00:00:000AM |May  31 2016 12:00:00:000PM  |
|A001                |May  1 2016 12:00:00:000AM |May  31 2016 12:00:00:000PM  |

虽然我试图执行此查询。查询返回一些错误。我该如何解决这个问题?

错误

SQL Error [1722] [42000]: ORA-01722: invalid number
java.sql.SQLSyntaxErrorException: ORA-01722: invalid number

4 个答案:

答案 0 :(得分:1)

为什么不在日期使用TO_DATE()

select * from RP_REPORT_TEMP 
where START_DATE >= to_date('May 01 2016 12:00:00 AM','MON DD YYYY HH:MI:SS AM')
  and END_DATE <= to_date('May 31 2016 11:59:00 AM','MON DD YYYY HH24:MI:SS AM')
  and lower(rid) like '%a001%'

答案 1 :(得分:0)

试试这个..

 select * 
      from RP_REPORT_TEMP 
     where TO_date(START_DATE,'MON DD YYYY HH:MI:SS AM') 
              >= to_Date('May 01 2016 12:00:00 AM' ,'MON DD YYYY HH:MI:SS AM') 
       and TO_DATE(END_DATE,'MON DD YYYY HH:MI:SS PM') 
              <= TO_DATE('May 31 2016 11:59:00 AM' ,'MON DD YYYY HH:MI:SS PM') 
       and lower(rid) like '%a001%' 
     order by CAST(cid as INTEGER) asc
select * 
      from RP_REPORT_TEMP 
     where TO_date(START_DATE,'MON DD YYYY HH24:MI:SS') 
              >= to_Date('May 01 2016 12:00:00' ,'MON DD YYYY HH24:MI:SS') 
       and TO_DATE(END_DATE,'MON DD YYYY HH24:MI:SS') 
              <= TO_DATE('May 31 2016 11:59:00' ,'MON DD YYYY HH24:MI:SS') 
       and lower(rid) like '%a001%' 
     order by CAST(cid as INTEGER) asc

答案 2 :(得分:0)

假设START_DATEEND_DATE实际上是日期,我可以在您的代码中发现两个主要问题:

  1. 将每一行转换为字符串的速度很慢,也会阻止Oracle使用索引(除非您有一个精心构建的基于函数的索引)。

  2. 词典排序(又名“A到Z”)不会在日期为“5月1日”的情况下呈现有意义的结果。想想这个列表有什么意义:Apr, Aug, Dec, Feb, Jan, Jul, Jun, Mar, May, Nov, Oct, Sep

  3. 我的建议是:

    • 避免将日期转换为字符串,另存为显示用途
    • 必须从字符串转换为日期时使用更稳定的格式

    结果:

    select * 
      from RP_REPORT_TEMP 
     where START_DATE
              >= TO_DATE('2016-05-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
       and END_DATE
              <= TO_DATE('2016-05-31 11:59:00', 'YYYY-MM-DD HH24:MI:SS')
       and lower(rid) like '%a001%' 
     order by CAST(cid as INTEGER) asc
    

    P.S。 START_DATEEND_DATE毕竟不是日期

答案 3 :(得分:0)

这是您的查询应该是这样的:

select   * 
from     rp_report_temp 
where    to_date(start_date,'FM Mon DD YYYY HH:MI:SS"FMMon DD YYYY HH:MI:SS":000"AM', 'nls_date_language = english') 
            >= to_date('01/05/2016 00:00:00', 'dd/mm/yyyy hh24:mi:ss')
and      to_date(end_date,'FM Mon DD YYYY HH:MI:SS":000"AM', 'nls_date_language = english') 
            <= to_date('31/05/2016 23:59:59', 'dd/mm/yyyy hh24:mi:ss')
and      lower(rid) like '%a001%' 
order by cast(cid as integer) asc;

在这里,我已经将您的开始和结束日期列转换为日期,基于该列中的示例字符串看起来像&#34; 2016年5月1日12:00:00:000AM&#34; - 还有额外的&#34;:000&#34;几秒钟之后;我假设这总是&#34;:000&#34;。

注意我通过在to_date()内专门设置该值,使我的代码nls_date_language参数独立。这意味着如果其他人的客户端设置为不是英语的东西,那么sql语句仍将适用于他们。

您注意到我并不需要为您正在测试的值执行此操作,因为我将字符串的格式更改为使用数字来表示月份的内容。

你也有一些基本的数据建模问题 - 通过将所有内容存储为varchar2你已经为自己制作了一根杆 - 你已经失去了所有可用的验证(如果有人放了一个字符串会发生什么那列中的Feb 30 2015 39:99:99 AM?AWOOGA,AWOOGA,错误!)。您已经使您的查询必须更加努力(现在我们已经在各处尝试将数据转换为正确的数据类型)。

您应该以正确的数据类型存储数据。日期应存储为DATE,时间戳记为TIMESTAMP,数字为NUMBER(有或没有特定的精度和比例)等。

如果您的数据存储正确,那么您的查询将是:

select   *
from     rp_report_temp
where    start_date >= to_date('01/05/2016 00:00:00', 'dd/mm/yyyy hh24:mi:ss')
and      end_date <= to_date('31/05/2016 23:59:59', 'dd/mm/yyyy hh24:mi:ss')
and      lower(rid) like '%a001%'
order by cid asc;