【问题标题】:Oracle SQL casting string as dateOracle SQL 将字符串转换为日期
【发布时间】:2016-12-07 21:29:45
【问题描述】:

这个sql有什么问题?

这给了我 0 个结果:

Select * from DOC where CREATION_TIME > to_TIMESTAMP('01-Jan-69 11.59.16 AM','dd-Mon-YY HH12.mi.ss.FF3AM');

当我运行它时:

Select * from DOC where CREATION_TIME > '01-JAN-69 11.59.16.000000000 AM';

我得到的结果很好。表模式设置为 CREATION_TIME 作为 Timestamp 类型,格式在第二个查询中看到。

【问题讨论】:

  • 明智的做法是使用to_timestamp() 而不要依赖隐式转换(最多50% 的时间正确)。不要让这个事件(“Y2K 问题”)阻止您使用最佳实践,即按照您的尝试使用 to_timestamp()。这是编写查询的正确方法。

标签: sql oracle


【解决方案1】:

这是因为,

select TO_TIMESTAMP('01-Jan-69 11.59.16 AM','dd-Mon-YY HH12.mi.ss.FF3AM') from dual

返回 01.01.2069 11:59:16(注意这里是 2069 而不是 1969)

要转换为正确的年份使用,

TO_TIMESTAMP('01-Jan-69 11.59.16 AM','dd-Mon-RR HH12.mi.ss.FF3AM')

来自documentation

RR 日期时间格式元素类似于 YY 日期时间格式元素,但它为存储其他世纪的日期值提供了额外的灵活性。 RR 日期时间格式元素允许您通过仅指定年份的最后两位数字将 20 世纪的日期存储在 21 世纪。

如果您将 TO_DATE 函数与 YY 日期时间格式元素一起使用,则返回的年份始终与当前年份具有相同的前 2 位数字。如果使用 RR 日期时间格式元素,则返回值的世纪根据指定的两位数年份和当前年份的最后两位数而变化。

如果指定的两位数年份是00到49,那么

  • 如果当前年份的后两位数字为 00 到 49,则返回的年份与当前年份的前两位数字相同。

  • 如果当前年份的后两位是 50 到 99,则返回年份的前 2 位比当前年份的前 2 位大 1。

如果指定的两位数年份是50到99,那么

  • 如果当前年份的后两位是00到49,则返回年份的前2位比当前年份的前2位小1。

  • 如果当前年份的后两位数字是 50 到 99,则返回的年份与当前年份的前两位数字相同。

【讨论】:

  • 当使用月份名称时,应在 TO_TIMESTAMP 的第三个参数中指定 NLS_DATE_LANGUAGE。
  • @vkp 非常感谢您提供的信息非常丰富且易于修复。让我发疯的时间比它应有的时间长得多。
【解决方案2】:

假设一个字符串可以被正确翻译为时间戳,您可能会感到非常幸运。

表示时间戳文字的 ANSI/ISO 方法是 timestamp yyyy-mm-dd[.ff] hh24:mi:ss,例如-

select timestamp '1969-01-01 11:59:16' from dual;

select timestamp '1969-01-01 11:59:16.123' from dual;

【讨论】:

  • 两个观察结果都是正确的,但它们没有回答 OP 的问题,即:to_timestamp() 调用有什么问题。
  • @mathguy,实际上问题是“这个 sql 有什么问题?”。 OP 试图标注时间戳的方式是错误的,今天它导致了一个世纪问题,明天它将是无效月份。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-14
  • 2019-03-29
  • 1970-01-01
  • 1970-01-01
  • 2013-07-12
相关资源
最近更新 更多