Выбрать несколько значений в одной переменной и использовать их для сравнения с одним значением в другой переменной
У меня есть требование извлекать несколько значений через запрос выбора и в одну переменную, а затем сравнивать значение этой переменной с другой переменной, имеющей только одно значение.
Я новичок в программировании на PL/SQL. Я искал этот форум и получил результаты для использования ТИПА / коллекций, но не уверен, как использовать то же самое в моем коде.
Ниже приведен фрагмент моего кода:
CREATE OR REPLACE PROCEDURE MNTH_SNAPSHOT AS
arg1 varchar2(10) ;
TYPE snap IS TABLE OF GDWARC_JPN.DIM_ORG_UNIT_HIST.snapshot_period%TYPE;
BEGIN
SELECT (to_char(trunc(sysdate, 'MM'), 'MON-yyyy')) INTO arg1 FROM dual;
SELECT (to_char(snapshot_period,'MON-yyyy')) BULK collect into snap FROM GDWARC_JPN.DIM_ORG_UNIT_HIST; -- multiple values like DEC-2016, JAN-2016 etc . snapshot_period is date column
if arg1 in (snap ) then
execute immediate 'alter table GDWARC_JPN.DIM_ORG_UNIT_HIST truncate partition arg1';
3 ответа
Вы можете просто использовать цикл, чтобы проверить все значения, возвращаемые из вашего запроса:
CREATE OR REPLACE PROCEDURE MNTH_SNAPSHOT AS
arg1 varchar2(10) ;
BEGIN
arg1 := to_char(sysdate,'MON-yyyy'); /* you do not need to trunc and/or a query here */
--
/* you can use a loop to scan all your values */
for i in (
SELECT (to_char(snapshot_period,'MON-yyyy')) val
FROM GDWARC_JPN.DIM_ORG_UNIT_HIST
)
loop
if i.val = arg1 then
/* arg1 must be out of the fixed string */
execute immediate 'alter table GDWARC_JPN.DIM_ORG_UNIT_HIST truncate partition ' || arg1;
end if;
end loop;
end;
Однако ваш код, кажется, проходит через таблицу, но вы усекаете только раздел, соответствующий sysdate; Итак, ваш код может быть упрощен:
CREATE OR REPLACE PROCEDURE MNTH_SNAPSHOT AS
arg1 varchar2(10) ;
vCheck number;
BEGIN
arg1 := to_char(sysdate,'MON-yyyy'); /* you do not need to trunc and/or a query here */
/* you only need to check whether a value for sysdate exists or not */
select count(1)
into vCheck
from GDWARC_JPN.DIM_ORG_UNIT_HIST
where to_char(snapshot_period,'MON-yyyy') = arg1;
--
if vCheck > 0 then
/* arg1 must be out of the fixed string */
execute immediate 'alter table GDWARC_JPN.DIM_ORG_UNIT_HIST truncate partition ' || arg1;
end if;
end;
Также обратите внимание, что вам не нужен varchar2
чтобы проверить ваши даты, но вы можете просто trunc
они оба в месяц и проверить результаты trunc
и что у вас есть ошибка в динамической строке, учитывая, что arg1
должно быть значением переменной, а не жестко закодировано в строку.
Я не могу комментировать, поэтому я напишу новый ответ
Спасибо Prabhat, ваш код скомпилирован нормально, но когда я попытался запустить процесс, он выдал ошибку как: Отчет об ошибке - ORA-01858: не числовой символ был найден, где ожидалось числовое значение ORA-06512: в "GDWARC_JPN.MNTH_SNAPSHOT", строка 9 ORA-06512: в строке 1 01858. 00000 - "не числовой символ был найден там, где ожидалось число". Не могли бы вы помочь.
Ваша проблема в том, что вы используете разные типы данных.
SELECT (to_char(snapshot_period,'MON-yyyy')) BULK collect into snap_tab/*changed*/ FROM GDWARC_JPN.DIM_ORG_UNIT_HIST;
Для начала вы используете дату, конвертируете ее в символ и затем снова сохраняете ее в дату. Не знаю, как вы можете скомпилировать это
SELECT (to_char(trunc(sysdate, 'MM'), 'MON-yyyy')) INTO arg1 FROM dual;
Когда вы конвертируете sysdate в желаемый формат и сохраняете его в переменную varchar, это больше не дата. Затем вы сравниваете его с датой, и поскольку у вас есть формат даты, он не распознается. Так что либо используйте дату во всех переменных и опцию TRUNC, чтобы извлечь из нее только месяц и год (хотя я не уверен, что вы можете приводить членов таблицы в член, возможно, вам придется использовать для в этой ситуации) или поверните привязку таблица к типу varchar
ПРИМЕР
CREATE OR REPLACE PROCEDURE MNTH_SNAPSHOT AS
arg1 varchar2(10) ;
TYPE snap IS TABLE OF varchar2(10);
snap_tab snap := snap() ; --declare a new collection variable and use this
BEGIN
SELECT (to_char(trunc(sysdate, 'MM'), 'MON-yyyy')) INTO arg1 FROM dual;
SELECT (to_char(snapshot_period,'MON-yyyy')) BULK collect into snap_tab/*changed*/ FROM GDWARC_JPN.DIM_ORG_UNIT_HIST; -- multiple values like DEC-2016, JAN-2016 etc . snapshot_period is date column
if arg1 member of snap_tab /*changed*/ then
execute immediate 'alter table GDWARC_JPN.DIM_ORG_UNIT_HIST truncate partition arg1';
Вы можете использовать член предложения, чтобы проверить, является ли элемент частью коллекции
if some_value member of arg1 then
` dbms_output.put_line('Member') ;
end if ;
В опубликованном вами коде есть несколько проблем, связанных с объявлением и использованием переменной коллекции, ниже приведена более правильная версия.
CREATE OR REPLACE PROCEDURE MNTH_SNAPSHOT AS
arg1 varchar2(10) ;
TYPE snap IS TABLE OF GDWARC_JPN.DIM_ORG_UNIT_HIST.snapshot_period%TYPE;
snap_tab snap := snap() ; --declare a new collection variable and use this
BEGIN
SELECT (to_char(trunc(sysdate, 'MM'), 'MON-yyyy')) INTO arg1 FROM dual;
SELECT (to_char(snapshot_period,'MON-yyyy')) BULK collect into snap_tab/*changed*/ FROM GDWARC_JPN.DIM_ORG_UNIT_HIST; -- multiple values like DEC-2016, JAN-2016 etc . snapshot_period is date column
if arg1 member of snap_tab /*changed*/ then
execute immediate 'alter table GDWARC_JPN.DIM_ORG_UNIT_HIST truncate partition arg1';