Одинаковый тип данных, другое поведение данных - PullRequest
0 голосов
/ 12 апреля 2019

У меня есть столбец в одной из моих таблиц с типом данных 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-запрос, который я могу использовать, чтобы проверить, где еще в моих таблицах это происходит (если это происходит где-то еще).

1 Ответ

1 голос
/ 12 апреля 2019

Из документации :

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;
/

Два * 1035В предложениях * ищется любая временная метка со значением часового пояса, которая имеет смещение - сообщаемое extract() как 'UNKNOWN' - и которая имеет регион, а динамический запрос, сгенерированный курсором, находит фиктивную таблицу / столбец, только если обаусловия соблюдены (т.е. он имеет оба типа).Отсюда необходимость в обработчике исключений внутри цикла.Если вы действительно хотите найти что-либо, сохраненное со смещениями, просто пропустите второе предложение exists().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...