sql >> Databáze >  >> RDS >> Oracle

spustit SQL dotaz uložený v tabulce

Zdá se, že jde o velmi zvláštní požadavek, který bude obtížné vyřešit robustním způsobem. STMT_OR_VALUE je ztělesněním anti-vzoru One Column Two Usages. Rozložení STMT_OR_VALUE navíc vyžaduje logiku řízení toku a použití dynamického SQL. V důsledku toho to nemůže být čisté řešení SQL:k sestavení a provedení dynamického dotazu musíte použít PL/SQL.

Zde je důkaz koncepce řešení. Rozhodl jsem se pro funkci, kterou můžete volat z SQL. Závisí to na jednom předpokladu:každý řetězec dotazu, který vložíte do TEST1.STMT_OR_VALUE, má projekci jednoho číselného sloupce a každý řetězec hodnot je pouze CSV s číselnými údaji . S touto výhradou je snadné vytvořit funkci, která buď provede dynamický dotaz, nebo tokenizuje řetězec na řadu čísel; oba jsou hromadně shromážděny do vnořené tabulky:

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;
/

Všimněte si, že existuje více než jeden způsob provádění dynamického příkazu SQL a mnoho způsobů, jak tokenizovat CSV na řadu čísel. Moje rozhodnutí jsou svévolná:zde můžete nahradit své preferované metody.

Tuto funkci lze vyvolat pomocí table() zavolejte:

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
/

Velkou výhodou tohoto přístupu je, že zapouzdřuje logiku kolem vyhodnocení STMT_OR_VALUE a skrývá použití dynamického SQL. V důsledku toho je snadné jej použít v jakémkoli SQL příkazu při zachování čitelnosti nebo přidat další mechanismy pro generování sady ID.

Toto řešení je však křehké. Bude fungovat pouze v případě, že hodnoty v test1 stůl dodržovat pravidla. To znamená, že musí být nejen konvertibilní na proud jednotlivých čísel, ale příkazy SQL musí být platné a spustitelné příkazem EXECUTE IMMEDIATE. Například koncový středník ve vzorových datech otázky je neplatný a způsobil by vrhnutí EXECUTE IMMEDIATE. Dynamické SQL je obtížné v neposlední řadě proto, že převádí chyby kompilace na chyby za běhu.



  1. php do while nebude fungovat s next->rowset

  2. MySQL drop tabulky se zástupným znakem pouze pomocí SQL příkazu?

  3. Hromadné vkládání SQL založené na datech vytažených z jiné tabulky

  4. Dva duplicitní indexy se stejnými sloupci