【问题标题】:Oracle Date Format Mystery - Why is it not an acceptable format?Oracle 日期格式之谜 - 为什么它不是可接受的格式?
【发布时间】:2015-06-29 15:37:16
【问题描述】:

我对 SQL 还很陌生,但仍然编写了一些与我现在正在编写的查询非常相似的查询。无论出于何种原因,当我运行此查询时,都会返回“ORA-01821:日期格式无法识别”错误。我查了一下,并在 Stack 和其他地方四处寻找,我相信我的语法确实有意义,所以我很困惑为什么会出错。

我的查询基于月份中的哪一天运行。如果是第 1 天,则应在上个月的倒数第 15 天运行。如果是 16 号,则应该在当月的 1-15 号运行。

这是我每月第一天的代码:

select 
case
   when to_char(sysdate, 'yyyymmdd') = to_char(sysdate, 'yyyymm' || '01') then (do a lot of things)
   .
   .
   .
end as FirstReportGroup
where *datetable* between between to_char(sysdate, 'yyyymm' || '16') and to_char(last_day(sysdate), 'yyyymmdd');

这是我在 16 号时的代码:

select 
case
   when to_char(sysdate, 'yyyymmdd') = to_char(sysdate, 'yyyymm' || '16') then (do a lot of things again)
   .
   .
   .
end as SecondReportGroup
where *datetable* between to_char(sysdate, 'yyyymm' || '01') and to_char(sysdate, 'yyyymm' || '15')

这一定是某种我没有看到的日期格式语法错误。我真的很感谢这里的一些帮助,我期待着解决这个问题!如果您需要更多信息,请告诉我。

谢谢。

【问题讨论】:

  • sysdate 与 to_char 相比是什么数据类型? (日期到字符对吗?)您需要比较类似的数据类型才能开始。
  • 哦,对了,愚蠢的错误。我刚刚将 sysdate 更改为:to_char(sysdate, 'yyyymmdd') 并解决了这个问题。不过,仍然无法看到日期格式的语法错误。
  • 错误是由'01'和'16'引起的,这不是to_char指令的有效格式,所以,如果你想得到那一天,你应该使用to_char(sysdate,'dd')。这将返回白天部分
  • 将 01 移到字符之外,这不是日期...所以to_char(sysdate, 'yyyymm') | '01'

标签: oracle date oracle11g


【解决方案1】:

两个问题

  • 比较类似的数据类型,所以两者都使用日期或字符串,但不是日期和字符串
  • 两个 to_char 仅适用于日期,因此您需要 to_char(sysdate, 'yyyymm') || '16' 而不是因为 to_char 仅适用于日期,您正在连接的字符串对 to_char 函数无效。所以在函数之后这样做。

【讨论】:

  • 在您回答之前,我已经解决了您的第一点,但无论如何我感谢您的跟进。至于你的第二点,是的,这就是问题所在。像往常一样一个非常小的问题 - 感谢您指出!我会测试并返回。
【解决方案2】:

您可以通过使用 case 语句在 where 子句中生成开始/结束日期,从而避免只使用一个查询。以下是案例陈述的示例:

with dts as (select sysdate dt from dual union all
             select to_date('02/06/2014 15:09:23', 'dd/mm/yyyy hh24:mi:ss') dt from dual)     
select dt,
       case when dt - trunc(dt, 'mm') < 16 then add_months(trunc(dt, 'mm'), -1) + 15 -- goes from 16th of previous month; change to 14 if needing from 15th.
            else trunc(dt, 'mm')
       end start_dt,
       case when dt - trunc(dt, 'mm') < 16 then trunc(dt, 'mm') -- goes from 16th of previous month; change to 14 if needing from 15th.
            else trunc(dt, 'mm') + 15
       end end_dt
from   dts;

DT                    START_DT              END_DT               
--------------------- --------------------- ---------------------
29/06/2015 12:50:00   01/06/2015 00:00:00   16/06/2015 00:00:00  
02/06/2014 15:09:23   16/05/2014 00:00:00   01/06/2014 00:00:00  

请记住,a) Oracle 中的 DATE 也有一个时间元素,b) 您可能不想在两者之间使用,因为这使得开始和结束期间包含在内(您可能会在两个查询中都出现行,或者如果您弄错了 end_date 并且忘记了 end_date 当天午夜之后的任何内容,甚至可能完全错过行!) - 相反,您可能想要执行以下操作:

and datecol >= <case statement generating start_date>
and datecol < <case statement generating end_date>

【讨论】:

    猜你喜欢
    • 2012-04-01
    • 2016-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-31
    • 2014-09-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多