我有两个日期字段如下(我知道它们设计不正确,但DBA不会改变它)
order_tag varchar(2) dt_changed timestamp(6)
06:35:13 27-MAR-17 06.10.31.036561
我知道找到timestamp_field
和varchar(2)
字段之间的时差。
我尝试了下面的sql并得到一个ora错误:
ORA-01850:小时必须介于0到23之间
select orq.order_tag,
rt.dt_changed,
(to_date(rt.dt_changed,'hh24:mi:ss') -
(to_date (orq.order_tag, 'hh24:mi:ss'))) time_differ
from order_request orq,route rt
where orq.rt_id = rt.rt_id
ORA-01850:小时必须介于0到23之间
答案 0 :(得分:0)
TO_DATE( date_string, format_mask )
将字符串作为第一个值,并传入DATE
数据类型。要解决此问题,Oracle将在日期隐式调用TO_CHAR( date_value, format_mask )
将其转换为字符串,并使用您的NLS_DATE_FORMAT
会话参数作为格式掩码。
如果你这样做:
SELECT * FROM NLS_SESSION_PARAMETERS WHERE PARAMETER = 'NLS_DATE_FORMAT';
您将看到Oracle正在使用的格式掩码,它几乎肯定与您在HH24:MI:SS
中使用的TO_DATE
掩码不匹配。
相反,您可以尝试显式调用TO_CHAR
并指定格式掩码:
select orq.order_tag,
rt.dt_changed,
to_date( TO_CHAR( rt.dt_changed, 'HH24:MI:SS' ),'hh24:mi:ss') -
to_date (orq.order_tag, 'hh24:mi:ss') time_differ
from order_request orq,route rt
where orq.rt_id = rt.rt_id
答案 1 :(得分:0)
您似乎希望结果为INTERVAL
数据类型,而不是NUMBER
。如果您将这两个值都转换为DATE
,则差异为NUMBER
(以天计),然后您需要转换为所需的格式。顺便说一句,要将时间戳转换为日期,您不应该使用TO_CHAR;它比这简单得多,只需使用CAST( your_timestamp AS DATE )
。
但你不需要那样做。相反,只需使用TO_TIMESTAMP( ..., format_model)
将VARCHAR2转换为TIMESTAMP即可。两个时间戳的区别是INTERVAL,正是您想要的。
设置(注意 - 您的第一列肯定不是varchar(2)!)
create table test_data (order_tag varchar2(20), dt_changed timestamp(6));
Table TEST_DATA created.
insert into test_data
values ('06:35:13', to_timestamp('27-MAR-17 06.10.31.036561', 'dd-MON-rr hh24.mi.ss.ff'));
1 row inserted.
查询(请注意天数 - 您的ORDER_TAG
列没有日期,因此默认情况下它是当月的第一天。如果这对您的业务没有好处,那么您还应该存储日期,而不仅仅是一天中的时间。)
select to_timestamp(order_tag, 'hh24:mi:ss') - dt_changed as time_diff from test_data;
TIME_DIFF
-------------------
-25 23:35:18.036561
如果你必须"附上"从DT_CHANGED到ORDER_TAG中的字符串的日期,你可以做这样的愚蠢的事情(不推荐):
select to_timestamp(to_char(dt_changed, 'dd-MON-rr') || order_tag, 'dd-MON-yyhh24:mi:ss')
- dt_changed as time_diff from test_data;
TIME_DIFF
-------------------
+00 00:24:41.963439