Полагаю, вы знаете, что вы можете связать переменную с PI_N_Dept
, чтобы удалить этот кусок динамического sql. К сожалению, для вашего IN
предложения и sExcludeCategories
вы не можете связать переменную для списка в Oracle (по крайней мере, до 9.2, насколько я знаю)
У вас есть несколько вариантов. Ваше текущее решение самое простое. Другое решение состоит в том, чтобы изменить процедуру для принятия нескольких переменных и создать список операторов AND.
'select c.category
from test_category c
where c.deptid= :PI_N_Dept
and c.category <> :sExcludeCategory1
and c.category <> :sExcludeCategory2
and c.category <> :sExcludeCategory3
';
или иметь фиксированный список значений IN
'select c.category
from test_category c
where c.deptid= :PI_N_Dept
and c.category not in (:sExcludeCategory1 , :sExcludeCategory2, :sExcludeCategory3)';
Вы должны быть осторожны в том случае, если вам нужны только 2 категории. Третий должен быть установлен на какое-то значение, отсутствующее в c.category (обратите внимание: будьте осторожны и тестируйте нулевые значения здесь)
Другое решение представлено в Ask Tom . Это выглядит довольно просто, хотя я не проверял это. Он работает путем создания функции str2tbl (), которая позволяет передавать ряд чисел, разделенных запятыми, и создавать «таблицу» через дуал для выполнения IN.
create or replace type myTableType as table of number;
create or replace function str2tbl( p_str in varchar2 ) return myTableType
as
l_str long default p_str || ',';
l_n number;
l_data myTableType := myTabletype();
begin
loop
l_n := instr( l_str, ',' );
exit when (nvl(l_n,0) = 0);
l_data.extend;
l_data( l_data.count ) := ltrim(rtrim(substr(l_str,1,l_n-1)));
l_str := substr( l_str, l_n+1 );
end loop;
return l_data;
end;
Ваш пример будет выглядеть примерно так:
'select c.category
from test_category c
where c.deptid= :PI_N_Dept
and c.category not in ( select * from INLIST ( select cast( str2tbl( :sExcludeCategories ) as mytableType ) from dual ) )';
Это работало бы, только если sExcludeCategories
был списком чисел. Вам придется изменить str2tbl для обработки кавычек, если они включены в переменную (и вы не можете изменить ее), а также изменить тип с myTableType
на varchar2(10)
или что-то более подходящее.
В целом, если исходный sql не влияет на производительность, то для простоты я бы оставил его как динамический SQL. Это гораздо меньше, чтобы поддерживать головную боль. В противном случае проверьте str2tbl. Должно работать в Oracle 8 и выше.
PS : Просто для полноты, я наткнулся на эту замечательную статью о связывании переменных , в которой рассматриваются простые проблемы, такие как использование переменных для предложений IN.