【问题标题】:String to date conversion in query查询中的字符串到日期转换
【发布时间】:2016-09-20 18:49:04
【问题描述】:

我在列中有以下“时间戳”

Mon Aug 10 12:24:46 CDT 2016

所以要转换为日期,我正在执行以下操作。

select * from 
(select TO_DATE(SUBSTR(t.timestamp,9,2) || '-' || SUBSTR(t.timestamp,5,3) ||             
'-' || SUBSTR(t.timestamp,27,2), 'DD-MON-YY')  from table t where 
 t.LENGTH(TRIM(t.timestamp)) = 28 as date) where date <= sysdate;

这样做的原因是,“Oracle sysdate”以以下格式返回当前日期

20-SEP-16

所以为了比较oracle sysdate,我使用的是上面的方法。

有没有更好的方法来做到这一点,我知道在 select 语句中使用一组子字符串效率很低,并且由于我的“时间戳”值太长,我无法转换为 ORACLE 日期。

我使用 oracle 11 作为我的数据库。任何帮助表示赞赏。

【问题讨论】:

  • 如何切换到原生时间戳格式并将当前格式的计算列作为文本?
  • 附注:默认日期格式是可配置的,不可依赖。
  • @KamilG。要切换到原生时间戳格式,我们仍然需要对时间戳进行一些子字符串转换
  • @ylnsagar 对不起,我不明白你的问题。时间戳很容易被截断为日期。
  • 列是什么数据类型?它是正确的“带有时区的时间戳”还是 varchar2 或类似的字符串类型?另外,您需要什么输出...您只需要与当前日期/时间进行比较吗?或者,实际上,您似乎正在从时间戳中截断时间,这是您的要求吗?如果时间戳是 22:30 而当前时间是 14:30 呢?您确实意识到“SYSDATE”有一个时间组件,对吧?

标签: sql oracle


【解决方案1】:

这是一个概念证明,假设所谓的“时间戳”实际上是一个字符串。如果它是带有时区的正确时间戳(因为它应该是),那么它就更简单了,您可以直接与日期进行比较。

注意两点:在我的映射中,出于某种原因,我没有“CDT”,但我有标准时区,CST。我可能错过了一个我不想寻找和安装的夏令时文件。 2016 年 8 月 10 日是星期三;星期一不行,你不能愚弄甲骨文。想知道您为什么不费心使用实际的正确日期(包括正确的星期几)。

编辑:其实我没有遗漏任何“时区代码文件”;相反,要将 CDT 识别为有效时区,需要将下面模型中的 TZR 组件更改为 TZD。

概念证明:

select 'x' as col1
from   dual
where  to_timestamp_tz('Wed Aug 10 12:24:46 CST 2016', 
                       'Dy Mon dd hh24:mi:ss TZR yyyy') <=   sysdate
;



COL1
-----
x

1 row selected.

【讨论】:

  • 感谢您的回复。您的查询非常适合时区 CST,但在我的时间戳中提到了“CDT”。所以预言机抱怨“找不到时区”。
  • 对不起,我应该早点研究这个的。请在格式模型中将 TZR 更改为 TZD,然后重试。我也会将此添加到我的答案中。
  • 很好的解决方案。我不知道 TO_TIMESTAMP_TZ 。添加第三个参数以匹配字符串中使用的语言,例如'NLS_DATE_LANGUAGE=AMERICAN'。 “Wed”和“Aug”是在会话的语言设置中可能没有意义的缩写。
  • @mathguy :: 感谢您的解决方案。它与 TZD 合作。太好了,感谢您的帮助
【解决方案2】:
  1. as date 放错了位置。
  2. 'Aug' 是某种语言的月份名称缩写。在 to_char 中指定该语言,以确保它独立于您当前的设置而工作。
  3. 不要只在有 YYYY 可用时才使用 YY。
  4. 终于有了“CDT”时区。它总是“CDT”还是可以是其他东西?如果您需要从一个时区到另一个时区,则必须先转换为带时区的时间戳,然后移动到另一个时区,然后再转换为日期。

这里是查询:

select * 
from
(
  select 
    cast(from_tz(cast("date" as timestamp), zone) at time zone 'CDT' as date) as "date"
  from 
  (
    select to_date(substr(t.timestamp,9,2) || '-' || 
                   substr(t.timestamp,5,3) || '-' || 
                   substr(t.timestamp,25,4), 
                   'DD-MON-YY', 
                   'NLS_DATE_LANGUAGE=AMERICAN') as "date",
           substr(t.timestamp,21,3) as zone
    from table t 
    where t.length(trim(t.timestamp)) = 28
  ) 
)
where "date" <= sysdate;

尽管它的名字from_tz 不会时区转换,而是从没有时区的时间戳转换为时区的时间戳。因此,我们使用它来输入我们的时区信息。另一方面,timestamp at time zone 'xyz' 将时区移动到指定的时区(我们解释要居住的日期的那个)。 cast 用于从日期到时间戳,反之亦然。

【讨论】:

  • 感谢您的回复。但是您仍然在查询中使用子字符串函数,有没有办法没有该子字符串函数
【解决方案3】:

您可以使用 TO_CHAR 函数来提取日期格式 https://docs.oracle.com/database/121/SQLRF/functions216.htm

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-26
  • 2019-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多