我的一个表中有一列,数据类型为TIMESTAMP(6) WITH TIME ZONE
。但是,此列中的数据显示方式不同,例如:
某些记录显示诸如02-NOV-17 02.26.22.000000000 PM -04:00
和其他一些数据显示数据,例如19-APR-18 10.31.15.000000000 PM AMERICA/NEW_YORK
为什么会这样?还有一个SQL查询,我可以用来检查表中的其他地方是否正在发生(如果它发生在其他地方)。
答案 0 :(得分:1)
TIMESTAMP WITH TIME ZONE
是TIMESTAMP
的一种变体,在其值中包含时区区域名称或时区偏移。
表中的值包含区域和偏移量。您的客户将显示所有带有其“区域”的值,但只有在其实际具有一个值的情况下,它才可以这样做。如果它有一个偏移量,则会显示出来。
输入了各种值的演示,包括会话时区的隐式转换:
alter session set time_zone = 'Europe/London';
create table t42 (test timestamp(6) with time zone);
insert into t42 (test) values (timestamp '2018-11-02 14:26:22.0 -04:00');
insert into t42 (test) values (timestamp '2018-04-19 22:31:15.0 America/New_York');
insert into t42 (test) values (systimestamp);
insert into t42 (test) values (sysdate);
insert into t42 (test) values (current_timestamp);
insert into t42 (test) values (current_date);
alter session set time_zone = 'America/New_York';
insert into t42 (test) values (systimestamp);
insert into t42 (test) values (sysdate);
insert into t42 (test) values (current_timestamp);
insert into t42 (test) values (current_date);
如果您使用sysdate
,它将使用您的会话时区(可能是区域或偏移量)进行隐式转换。如果您使用systimestamp
,它将保留时区信息,通常是(如果不是总是)偏移量而不是区域,它是来自服务器操作系统。
然后使用区域格式为TZR的格式模型进行查询:
alter session set nls_timestamp_tz_format = 'SYYYY-MM-DD HH24:MI:SS.FF3 TZR';
select * from t42;
TEST
--------------------------------------------------
2018-11-02 14:26:22.000 -04:00
2018-04-19 22:31:15.000 AMERICA/NEW_YORK
2019-04-12 16:36:30.441 +01:00
2019-04-12 16:36:30.000 EUROPE/LONDON
2019-04-12 16:36:30.622 EUROPE/LONDON
2019-04-12 16:36:30.000 EUROPE/LONDON
2019-04-12 16:36:30.862 +01:00
2019-04-12 16:36:30.000 AMERICA/NEW_YORK
2019-04-12 11:36:31.052 AMERICA/NEW_YORK
2019-04-12 11:36:31.000 AMERICA/NEW_YORK
您可以使用TZD:TZH而不是TZR来一致地显示所有带有偏移的内容。
alter session set nls_timestamp_tz_format = 'SYYYY-MM-DD HH24:MI:SS.FF3 TZH:TZM';
select * from t42;
TEST
--------------------------------------------------
2018-11-02 14:26:22.000 -04:00
2018-04-19 22:31:15.000 -04:00
2019-04-12 16:36:30.441 +01:00
2019-04-12 16:36:30.000 +01:00
2019-04-12 16:36:30.622 +01:00
2019-04-12 16:36:30.000 +01:00
2019-04-12 16:36:30.862 +01:00
2019-04-12 16:36:30.000 -04:00
2019-04-12 11:36:31.052 -04:00
2019-04-12 11:36:31.000 -04:00
但是您不能仅从偏移量推断区域,因为它们不是唯一的。
我想知道是否可以运行查询以获取所有包含区域和偏移量的表?
不是简单的查询;可以使用XML技巧来实现,但是我似乎正在遇到一个错误,因此,在我弄清楚这一点之前,您可以使用运行动态SQL的匿名块来做到这一点:
set serveroutput on -- or equivalent for your client
declare
l_table_name user_tab_columns.table_name%type;
l_column_name user_tab_columns.column_name%type;
begin
for r in (
select 'select ''' || table_name || ''', ''' || column_name || ''''
|| ' from dual '
|| ' where exists (select * from "' || table_name || '" where extract(timezone_region from "' || column_name || '") = ''UNKNOWN'')'
|| ' and exists (select * from "' || table_name || '" where extract(timezone_region from "' || column_name || '") != ''UNKNOWN'')'
as query
from user_tab_columns
where data_type like 'TIMESTAMP(_) WITH TIME ZONE'
)
loop
begin
execute immediate r.query into l_table_name, l_column_name;
dbms_output.put_line('Both TZR and TZH:TZM in table ' || l_table_name || '.' || l_column_name);
exception
when no_data_found then
null;
end;
end loop;
end;
/
这两个exists()
子句查找具有时区值的,具有偏移量的任何时间戳记-由extract()
报告为'UNKNOWN'-并具有一个区域,以及由游标生成的动态查询仅在同时满足两个条件(即,同时具有两种类型)的情况下,才为表/列查找虚拟对象。因此,在循环内需要异常处理程序。如果您实际上想查找任何带有偏移量的存储,则只需省略第二个exists()
子句。