У меня есть таблица со столбцом даты, который, как я знаю, хранится в GMT. У меня есть процедура, которая принимает ввод даты и идентификатор учетной записи. Процедура:
1) получает идентификатор аккаунта часового пояса (хранится в таблице аккаунта)
2) определяет начальный и конечный диапазон в GMT следующим образом:
v_start_time: = cast (from_tz (cast (i_date как отметка времени), v_tz) в часовом поясе c_gmt как дата); - где вводится i_date, v_tz - это «US / Eastern» или любое другое tzname из v $ timezone_names, а c_gmt - это строка «GMT»
v_end_time: = v_start_time + 1; - Добавить ровно один день до даты начала
3) вернуть sys_refcursor вызывающей стороне как:
open o_cur for
select gmt_col, some_value
from my_table
where account_id = i_account_id
and gmt_col between v_start_time and v_end_time;
Однако разработчик хотел бы указывать и gmt_date, и местное время в курсоре. Сначала я попытался использовать точно такой же метод преобразования, как и для определения v_start_time, то есть:
open o_cur for
select gmt_col,
cast( from_tz( cast( gmt_col as timestamp ), c_gmt ) at time zone v_tz as date ) as local_time, some_value
from my_table
where account_id = i_account_id
and gmt_col between v_start_time and v_end_time;
Однако при компиляции это приводит к ORA-00905: отсутствует ключевое слово. Я попытался добавить одинарные кавычки вокруг "v_tz", например: chr (39) || v_tz || chr (39), но это не работает - процесс компилируется, но когда я открываю курсор, я получаю ORA-01882: область часового пояса не найдена. После небольшого количества экспериментов вот два решения, которые позволяют "в часовом поясе" работать гладко в sql:
РЕШЕНИЕ 1:
open o_cur for
select gmt_col,
cast( from_tz( cast( gmt_col as timestamp ), c_gmt ) at time zone ( select v_tz from dual ) as date ) as local_time, some_value
from my_table
where account_id = i_account_id
and gmt_col between v_start_time and v_end_time;
РЕШЕНИЕ 2:
в спецификации пакета:
function echo( i_sound in varchar2 ) return varchar2;
pragma restrict_references( echo, wnps, rnps, wnds, rnds );
в упаковке:
function echo( i_sound in varchar2 ) return varchar2 is begin return i_sound; end;
в процедуре:
open o_cur for
select gmt_col,
cast( from_tz( cast( gmt_col as timestamp ), c_gmt ) at time zone echo( v_tz ) as date ) as local_time, some_value
from my_table
where account_id = i_account_id
and gmt_col between v_start_time and v_end_time;
Производительность представляется сопоставимой для каждого. Второе решение намекает на то, что я начал делать недавно, а именно на использование функций для возврата «констант» с прагмой restrict_references, поэтому я могу гибко использовать константы между pl / sql и sql. Например:
function c_gmt return varchar2;
прагма restrict_references (c_gmt, wnds, rnds, wnps, rnps);
выберите * из v $ timezone_names, где tzabbrev = c_gmt;
выберите c_gmt из двойного;
v_start_time: = бла-бла-бла || c_gmt;
и т.д ...