2010-11-11 1 views
1

У меня есть таблица с столбцом даты, который, как я знаю, хранится в GMT. У меня есть процедура, которая принимает ввод даты и идентификатор учетной записи. Процедура: 1) получает часовой пояс ID учетной записи (хранится в табличной учетной записи) 2) определяет начальный и конечный диапазон в GMT следующим образом: v_start_time: = cast (from_tz (cast (i_date as timestamp), v_tz) во времени zone c_gmt как дата); - где вводится i_date, v_tz - «US/Eastern» или любое другое имя tz из v $ timezone_names, а c_gmt - строка «GMT» v_end_time: = v_start_time + 1; - Добавить ровно один день, чтобы начать Дата 3) возвращение SYS_REFCURSOR абоненту как:Использование функции Oracle «в часовом поясе» в sql - проблема и решение

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), но это не работает - proc компилируется, но когда я открываю курсор, я получаю 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; 

Производительность оказывается сравнимой для каждого. Второе решение намекает на то, что я недавно начал делать, а именно использовать функции для возврата «констант» с pragma restrict_references, поэтому я могу использовать постоянные значения гибко между pl ​​/ sql и sql. Например:

Функция c_gmt return varchar2; pragma restrict_references (c_gmt, wnds, rnds, wnps, rnps);

выберите * из v $ timezone_names где tzabbrev = c_gmt; выберите c_gmt из dual; v_start_time: = blah blah blah || c_gmt; и т. Д.

ответ

4

Вам не нужен дополнительный выбор из двойного. Просто поместите переменную в круглые скобки, чтобы сделать трюк (не спрашивайте меня, почему):

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; 
+0

Прохладный, работает. Gracias. –