Това изглежда много странно изискване и такова, което ще бъде трудно да се реши по стабилен начин. STMT_OR_VALUE е въплъщение на анти-модела Една колона Две употреби. Освен това разрешаването на STMT_OR_VALUE изисква логика за контрол на потока и използването на динамичен SQL. Следователно това не може да бъде чисто SQL решение:трябва да използвате PL/SQL, за да сглобите и изпълните динамичната заявка.
Ето доказателство за концепция за решение. Избрах функция, която можете да извикате от SQL. Зависи от едно предположение:всеки низ на заявка, който вмъквате в TEST1.STMT_OR_VALUE, има проекция на една цифрова колона и всеки низ със стойност е CSV само с числови данни . С тази уговорка е лесно да се конструира функция, която или изпълнява динамична заявка, или токенизира низа в поредица от числа; и двете са групово събрани във вложена таблица:
create or replace function get_ids (p_name in test1.name%type)
return sys.odcinumberlist
is
l_rec test1%rowtype;
return_value sys.odcinumberlist;
begin
select * into l_rec
from test1
where name = p_name;
if l_rec.type = 'SQL_QUERY' then
-- execute a query
execute immediate l_rec.stmt_or_value
bulk collect into return_value;
else
-- tokenize a string
select xmltab.tkn
bulk collect into return_value
from ( select l_rec.stmt_or_value from dual) t
, xmltable( 'for $text in ora:tokenize($in, ",") return $text'
passing stmt_or_value as "in"
columns tkn number path '.'
) xmltab;
end if;
return return_value;
end;
/
Имайте предвид, че има повече от един начин за изпълнение на динамичен SQL оператор и множество начини за токенизиране на CSV в поредица от числа. Моите решения са произволни:можете да замените предпочитаните от вас методи тук.
Тази функция може да бъде извикана с table()
обаждане:
select *
from data
where id in ( select * from table(get_ids('first'))) -- execute query
or id in ( select * from table(get_ids('second'))) -- get string of values
/
Голямото предимство на този подход е, че той капсулира логиката около оценката на STMT_OR_VALUE и скрива използването на Dynamic SQL. Следователно е лесно да се използва във всеки SQL израз, като същевременно се запази четливостта, или да се добавят допълнителни механизми за генериране на набор от идентификатори.
Това решение обаче е крехко. Ще работи само ако стойностите в test1
масата се подчинява на правилата. Това означава, че не само трябва да могат да се преобразуват в поток от единични числа, но SQL изразите трябва да са валидни и изпълними от EXECUTE IMMEDIATE. Например точката и запетая в края на примерните данни на въпроса е невалидна и би довела до хвърляне на EXECUTE IMMEDIATE. Динамичният SQL е труден не на последно място, защото преобразува грешките при компилиране в грешки по време на изпълнение.