Oracle
 sql >> база данни >  >> RDS >> Oracle

изпълни SQL заявка, съхранена в таблица

Това изглежда много странно изискване и такова, което ще бъде трудно да се реши по стабилен начин. 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 е труден не на последно място, защото преобразува грешките при компилиране в грешки по време на изпълнение.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL:вмъкване на редове с обобщени стойности

  2. Какъв е смисълът на ORM, ако трябва да дефинирам всяко поле в app.config за Oracle .net Entity Framework

  3. Как да създадете съхранена процедура на Oracle, която може да връща конкретни обекти, както и всички обекти

  4. Какво е качествена среда за разработка за писане на Oracle SQL?

  5. Изтрийте дублиращи се редове в Oracle SQL, оставяйки най-новите записи