Oracle中的日期格式问题
Posted
技术标签:
【中文标题】Oracle中的日期格式问题【英文标题】:Date format issue in Oracle 【发布时间】:2021-10-08 04:19:04 【问题描述】:在我们的package
中,我们有where
子句,如下所示。
pp.start_date >= nvl(TO_DATE('01-JAN-2018', 'RRRR/MM/DD HH24:MI:SS'), pp.start_date)
它在客户环境中运行良好。但由于格式是'RRRR/MM/DD HH24:MI:SS'
,所以我们更改了日期,如下所示。
pp.start_date >= nvl(TO_DATE('2018/01/01', 'RRRR/MM/DD HH24:MI:SS'), pp.start_date)
理想情况下它应该可以工作,因为我们已经给出了正确的格式。在第一种情况下,它返回 679 行,但在第二种情况下,它返回 0 行。我们有 679 个正确的行数。
第二个 NVL 命令有什么问题?
【问题讨论】:
技术上我不认为RRRR
是一个有效的修饰符。 RR
旨在将 2 位数的年份向上或向下舍入以获得正确的世纪。如果您已有 4 位数年份,请使用 YYYY
。
我也检查了 YYYY RR 但只有当我使用 DD-MON-YYYY 格式的日期时才会输出。
请提供可重现的示例。您所说的在技术上或逻辑上都不正确。如果RRRR
给了你一些东西,它并不能保证它是正确的
我看不出TO_DATE('01-JAN-2018','RRRR/MM/DD HH24:MI:SS')
怎么可能“完美运行”。这给了我20-JAN-2001 18:00:00
。另外,既然可以使用标准的date literal,为什么还要硬编码任何TO_DATE
表达式?
【参考方案1】:
在我看来,两者都是错误的。
如果日期值是2018/01/01
,那么它的格式是(我认为)yyyy/mm/dd
(也可以是yyyy/dd/mm
,不能仅仅通过查看来判断)。 hh24:mi:ss
格式从何而来?你从来没用过。
因此,我会使用日期文字(始终为 date 'yyyy-mm-dd'
)(因为您对时间组件不感兴趣):
where pp.start_date >= date '2018-01-01'
没有NVL
功能。为什么?因为日期文字不能是NULL
。
你会使用NVL
,如果它是关于其他列的,例如
where pp.start_date >= nvl(a.some_date, date '2018-01-01')
这意味着:如果a.some_date
列是NULL
,请改用date '2018-01-01'
。
[EDIT] 如果有时间分量,毕竟使用TO_DATE
函数和适当的格式掩码,例如
where pp.start_date >= to_date('2018-01-01 23:09', 'yyyy-mm-dd hh24:mi')
【讨论】:
谢谢@Littlefoot。实际上日期和时间来自 UI。无论客户设置什么日期,我们的查询都会从该日期加载数据。因此日期/时间会自动到来。如果我们想保持时间,我们应该怎么做? 不客气。如果同时涉及日期和时间,请使用 TO_DATE(请参阅编辑后的答案)。 第二个条件失败而不是第一个条件失败的逻辑原因是什么?我的意思是第二个不返回任何行。问是因为,我必须向客户说明理由。 PP.START_DATE 的数据类型是什么? 如果它是 DATE,那么您必须将它与另一个 DATE 进行比较(它是 DATE 数据类型列、DATE 文字、SYSDATE 函数、TO_DATE 函数返回的值)。当您使用 TO_DATE 时,您问题的唯一“答案”是您必须使用适当的格式掩码以及您为函数提供的值。如果是例如2018-01-23,则格式掩码必须是 YYYY-MM-DD,不能是 MM.DD.YYYY 也不能是 RRRR-DD-MM 也不能是 DD.MM.YYYY HH24:MI:SS 也不能是除格式 完全匹配的值。【参考方案2】:如果你这样做:
SELECT TO_DATE('01-JAN-2018', 'RRRR/MM/DD HH24:MI:SS')
FROM DUAL;
那么,来自string-to-date conversion rules:
RRRR
也匹配 RR
匹配 01
,所以年份是 2001 年。
MM
也匹配 MON
匹配 JAN
。
DD
匹配 20
。
HH24
匹配 18
。
所以生成的日期是2001-01-20 18:00:00
如果你使用:
SELECT TO_DATE('2018/01/01', 'RRRR/MM/DD HH24:MI:SS')
FROM DUAL;
然后:
RRRR
匹配 2018
。
MM
匹配 01
。
DD
匹配 01
。
所以生成的日期是2018-01-01 00:00:00
sqlfiddle here
您正在生成两个完全不同的日期,相隔近 17 年。
在第一种情况下,它返回 679 行,但在第二种情况下,它返回 0 行。我们有 679 个正确的行数。
在第一种情况下,您将获得 2001-01-20T18:00:00
之后的 679 行。
在第二种情况下,您将获得 0 行在 2018-01-01T00:00:00
之后。
鉴于使用的日期分别是 01-JAN-2018
和 2018-01-01
,我认为第二个是正确的,您应该得到 0 行而不是 679 行。
【讨论】:
以上是关于Oracle中的日期格式问题的主要内容,如果未能解决你的问题,请参考以下文章
为啥 APEX 和 Oracle SQL Developer 中的日期格式不同?