在Oracle中执行以下SQL语法时,总是不成功,请帮忙。
40284.3878935185代表'2010-04-16 09:18:34',微秒。
1900年1月1日的纪元日期(如Excel)。
create table temp1 (date1 number2(5,10));
insert into temp1(date1) values('40284.3878935185');
select to_date(date1, 'yyyy-mm-dd hh24:mi:ssxff') from temp1
错误报告:SQL错误:ORA-01861:文字与格式不匹配 串 01861. 00000 - “文字与格式字符串不匹配” *原因:输入中的文字必须与文字中的文字长度相同 格式字符串(前导空格除外)。如果 “FX”修饰符已经打开,文字必须完全匹配, 没有额外的空白。 *操作:更正格式字符串以匹配文字。
感谢Mark Bannister
现在SQL语法是:
select to_char(to_date('1899-12-30','yyyy-mm-dd') +
date1,'yyyy-mm-dd hh24:mi:ss') from temp1
但无法获取日期格式,例如'yyyy-mm-dd hh24:mi:ss.ff'。继续寻求帮助。
答案 0 :(得分:5)
使用1899年12月30日的纪元日期,尝试:
select to_date('1899-12-30','yyyy-mm-dd') + date1
答案 1 :(得分:1)
简单日期添加不适用于时间戳,至少如果您需要保留小数秒。当您执行to_timestamp('1899-12-30','yyyy-mm-dd')+ date1
时(在对Mark的回答的评论中){{3}}在添加之前隐式转换为TIMESTAMP
,整体答案为DATE
,因此没有任何小数秒;那么你使用to_char(..., '... .FF')
抱怨ORA-01821。
您需要将date1
列所占的天数转换为DATE
。幸运的是,Oracle提供了一种功能,interval:
select to_timestamp('1899-12-30','YYYY-MM-DD')
+ numtodsinterval(date1, 'DAY') from temp3;
16-APR-10 09.18.33.999998400
然后,您可以以所需的格式显示该格式,例如(使用CTE提供date1
值):
with temp3 as ( select 40284.3878935185 as date1 from dual)
select to_char(to_timestamp('1899-12-30','YYYY-MM-DD')
+ numtodsinterval(date1, 'DAY'), 'YYYY-MM-DD HH24:MI:SSXFF') from temp3;
2010-04-16 09:18:33.999998400
或限制为千分之一秒:
with temp3 as ( select 40284.3878935185 as date1 from dual)
select to_char(to_timestamp('1899-12-30','YYYY-MM-DD')+
+ numtodsinterval(date1, 'DAY'), 'YYYY-MM-DD HH24:MI:SS.FF3') from temp3;
2010-04-16 09:18:33.999
1899-12-30
的时代听起来很奇怪,并且如你所述,并不符合Excel。您的预期结果似乎更可能是错误的,应该是2010-04-18,所以我会检查您的假设。安德鲁也提出了一些好处,你应该将你的价值存储在TIMESTAMP
列的表格中。如果你收到这样的数据,你仍然需要沿着这些方面的东西将它转换为存储在某些时候。
答案 2 :(得分:0)
不完全知道纪元日期,但尝试类似:
select to_date('19700101','YYYYMMDD')+ :secs_since_epoch/86400 from dual;
或者,转换为时间戳,如:
select cast(to_date('19700101', 'YYYYMMDD') + :secs_since_epoch/86400 as timestamp with local time zone) from dual;
答案 3 :(得分:0)
我希望这不会过于严厉,但你必须在这里完全重新思考你的方法。
你根本没有保持数据类型。示例的每一行都会误用数据类型。
我大约95%确定您认为Oracle使用简单的块数据副本传输此数据。 “既然每个Oracle日期都存储为数字,为什么不将这个数字插入表中呢?”好吧,因为当您将列定义为NUMBER时,您告诉Oracle“这不是日期”。因此,Oracle不会将其作为日期进行管理。
这些类型转换中的每一个都是由Oracle根据您当前的会话变量计算的。如果你在法国,那里的'。' INSERT是千位分隔符而不是基数,INSERT将完全失败。
所有这些带字符串的转换都会被Oracle认为您正在运行的语言环境修改。检查字典视图V $ NLS_PARAMETERS。
日期/时间值会变得更糟。日期/时间值可以遍布地图 - 主要是因为时区。您的数据库服务器在哪个时区?它认为你在哪个时区跑?如果这不能让你的头脑充分旋转,请查看如果您将Oracle的默认日历从Gregorian更改为Thai Buddha会发生什么。
我强烈建议你彻底摆脱这些数字。
要创建日期或日期时间值,请使用具有完全不变且明确的格式的字符串。然后专门分配,比较和计算日期值,例如:
GOODFMT常数VARCHAR2 ='YYYY-MM-DD HH24:MI:SS.FFF ZZZ'
Good_Time DATE = TO_DATE('2012-02-17 08:07:55.000 EST',GOODFMT);