sql >> Database teknologi >  >> RDS >> Oracle

udføre en SQL-forespørgsel, der er gemt i en tabel

Dette virker som et meget ejendommeligt krav, og et som vil være svært at løse på en robust måde. STMT_OR_VALUE er udførelsesformen af ​​One Column Two Usages anti-mønsteret. Desuden kræver løsning af STMT_OR_VALUE flowkontrollogik og brug af dynamisk SQL. Det kan derfor ikke være en ren SQL-løsning:du skal bruge PL/SQL til at samle og udføre den dynamiske forespørgsel.

Her er et proof of concept for en løsning. Jeg har valgt en funktion, som du kan kalde fra SQL. Det afhænger af én antagelse:hver forespørgselsstreng, du indsætter i TEST1.STMT_OR_VALUE har en projektion af en enkelt numerisk kolonne og hver værdistreng er en CSV med kun numeriske data . Med dette forbehold er det enkelt at konstruere en funktion, som enten udfører en dynamisk forespørgsel eller tokeniserer strengen til en række tal; som begge er samlet i en indlejret tabel:

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

Bemærk, at der er mere end én måde at udføre en dynamisk SQL-sætning på og en mangfoldighed af måder at tokenisere en CSV til en række tal. Mine beslutninger er vilkårlige:Du er velkommen til at erstatte dine foretrukne metoder her.

Denne funktion kan aktiveres med en table() ring:

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
/

Den store fordel ved denne tilgang er, at den indkapsler logikken omkring evalueringen af ​​STMT_OR_VALUE og skjuler brugen af ​​Dynamic SQL. Det er derfor nemt at anvende det i enhver SQL-sætning, mens læsbarheden bevares, eller at tilføje yderligere mekanismer til generering af et sæt id'er.

Denne løsning er dog skør. Det vil kun fungere, hvis værdierne i test1 bord overholde reglerne. Det vil sige, at de ikke kun skal kunne konverteres til en strøm af enkelte tal, men SQL-sætningerne skal være gyldige og eksekverbare af EXECUTE IMMEDIATE. For eksempel er det efterfølgende semikolon i spørgsmålets eksempeldata ugyldigt og vil få EXECUTE IMMEDIATE til at kaste. Dynamisk SQL er svært, ikke mindst fordi det konverterer kompileringsfejl til runtime-fejl.



  1. Svarende til varchar(max) i MySQL?

  2. Server tager lang tid at svare

  3. Kildekode for det eksisterende objekt i Oracle

  4. hvordan man kopierer et skema i mysql ved hjælp af java