Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Dynamisches SQL mit Konfigurationstabellen

Es ist ein bisschen chaotisch, aber Sie könnten es in einfachem SQL tun, beginnend mit einer hierarchischen Abfrage, um die verketteten Zeichenfolgen zu erhalten:

select keyvalue, fromtable, colsavailable, rnk,
  ltrim(sys_connect_by_path(colsavailable, '||''|''||'), '||''|''||') as path
from ordercols_forview
start with rnk = 1
connect by keyvalue = prior keyvalue
and rnk = prior rnk + 1
and prior dbms_random.value is not null
order by keyvalue, fromtable, colsavailable, rnk;

  KEYVALUE FR COLS        RNK PATH                                             
---------- -- ---- ---------- --------------------------------------------------
         1 A1 NUM1          1 NUM1                                              
         1 A1 NUM2          2 NUM1||'|'||NUM2                                   
         1 A1 NUM3          3 NUM1||'|'||NUM2||'|'||NUM3                        
         2 B1 NUM1          1 NUM1                                              
         2 B1 NUM2          2 NUM1||'|'||NUM2                                   
         2 B1 NUM3          3 NUM1||'|'||NUM2||'|'||NUM3                        
         2 B1 NUM4          4 NUM1||'|'||NUM2||'|'||NUM3||'|'||NUM4             
         3 C1 NUM1          1 NUM1                                              
         3 C1 NUM2          2 NUM1||'|'||NUM2                                   
         3 C1 NUM3          3 NUM1||'|'||NUM2||'|'||NUM3                        
         3 C1 NUM4          4 NUM1||'|'||NUM2||'|'||NUM3||'|'||NUM4             
         3 C1 NUM5          5 NUM1||'|'||NUM2||'|'||NUM3||'|'||NUM4||'|'||NUM5  

Ich bin davon ausgegangen, dass Ihre Tabelle wirklich eine andere Spalte hat, die Sie nicht gezeigt haben und die die Spaltenposition angibt. Wenn nicht, können Sie das irgendwie generieren - vielleicht basierend auf column_id für die Spalte der Basistabelle, alphabetisch oder was auch immer. Sie benötigen lediglich eine zusammenhängende Nummernfolge für die Connect-by-Klausel.

Sie können dann zwei Vereinigungen verwenden, um die Textteile für diese Spalten- und Pfadwerte zu erhalten (da sie separate Zeilen in Ihrer endgültigen Tabelle sein müssen), plus zusätzliche für SELECT ... und FROM ... Linien. Jede davon benötigt eine andere generierte Rangnummer. Diese können aus dem Ranking im CTE generiert werden:

with ordercols_forview_cte as (
  select keyvalue, fromtable, colsavailable, rnk,
    ltrim(sys_connect_by_path(colsavailable, '||''|''||'), '||''|''||') as path
  from ordercols_forview
  start with rnk = 1
  connect by keyvalue = prior keyvalue
  and rnk = prior rnk + 1
  and prior dbms_random.value is not null
)
select 'CREATE OR REPLACE VIEW ' || s.view_to_be_created || ' AS SELECT ' as text,
  s.view_to_be_created, 1 as rnk
from seeding_table s
union all
select 'KEYVALUE,' as text,
  s.view_to_be_created, 2 as rnk
from seeding_table s
union all
select o.path || ' AS KEY' || o.rnk
  || case when o.rnk < s.noofcols then ',' end,
  s.view_to_be_created, (o.rnk * 2) + 1 as rnk
from seeding_table s
join ordercols_forview_cte o on o.keyvalue = s.keyvalue
union all
select o.colsavailable || ' AS NO' || o.rnk
  || case when o.rnk < s.noofcols then ',' end as text,
  s.view_to_be_created, (o.rnk * 2) + 2 as rnk
from seeding_table s
join ordercols_forview_cte o on o.keyvalue = s.keyvalue
union all
select 'FROM ' || o.fromtable || ';' as text,
  s.view_to_be_created, (s.noofcols * 2) + 3 as rnk
from seeding_table s
join ordercols_forview_cte o on o.keyvalue = s.keyvalue
where o.rnk = s.noofcols
order by view_to_be_created, rnk;

Was mit Ihren Ausgangsdaten erzeugt:

TEXT                                                         V        RNK
------------------------------------------------------------ - ----------
CREATE OR REPLACE VIEW A AS SELECT                           A          1
KEYVALUE,                                                    A          2
NUM1 AS KEY1,                                                A          3
NUM1 AS NO1,                                                 A          4
NUM1||'|'||NUM2 AS KEY2,                                     A          5
NUM2 AS NO2,                                                 A          6
NUM1||'|'||NUM2||'|'||NUM3 AS KEY3                           A          7
NUM3 AS NO3                                                  A          8
FROM A1;                                                     A          9
CREATE OR REPLACE VIEW B AS SELECT                           B          1
KEYVALUE,                                                    B          2
NUM1 AS KEY1,                                                B          3
NUM1 AS NO1,                                                 B          4
NUM1||'|'||NUM2 AS KEY2,                                     B          5
NUM2 AS NO2,                                                 B          6
NUM1||'|'||NUM2||'|'||NUM3 AS KEY3,                          B          7
NUM3 AS NO3,                                                 B          8
NUM1||'|'||NUM2||'|'||NUM3||'|'||NUM4 AS KEY4                B          9
NUM4 AS NO4                                                  B         10
FROM B1;                                                     B         11
CREATE OR REPLACE VIEW C AS SELECT                           C          1
KEYVALUE,                                                    C          2
NUM1 AS KEY1,                                                C          3
NUM1 AS NO1,                                                 C          4
NUM1||'|'||NUM2 AS KEY2,                                     C          5
NUM2 AS NO2,                                                 C          6
NUM1||'|'||NUM2||'|'||NUM3 AS KEY3,                          C          7
NUM3 AS NO3,                                                 C          8
NUM1||'|'||NUM2||'|'||NUM3||'|'||NUM4 AS KEY4,               C          9
NUM4 AS NO4,                                                 C         10
NUM1||'|'||NUM2||'|'||NUM3||'|'||NUM4||'|'||NUM5 AS KEY5     C         11
NUM5 AS NO5                                                  C         12
FROM C1;                                                     C         13

Sie könnten es ein wenig variieren, indem Sie einen anderen CTE mit dem Join zwischen seeding_table haben und ordercols_forview_cte und das für die Gewerkschaft verwenden. Sie können die Pfade auch von einem rekursiven CTE (von Oracle 11g) erhalten:

with r (keyvalue, fromtable, colsavailable, rnk, path) as (
  select keyvalue, fromtable, colsavailable, rnk, colsavailable
  from ordercols_forview
  where rnk = 1
  union all
  select ocfv.keyvalue, ocfv.fromtable, ocfv.colsavailable, ocfv.rnk,
    r.path || q'[||'|'||]' || ocfv.colsavailable
  from r
  join ordercols_forview ocfv
  on ocfv.keyvalue = r.keyvalue
  and ocfv.fromtable = r.fromtable
  and ocfv.rnk = r.rnk + 1
)
select * from r;

Und kann das dann stattdessen verwenden; Dies führt die Verbindung zwischen diesem rekursiven CTE und der Seeding-Tabelle in einem anderen CTE wie oben erwähnt durch, aber Sie könnten einfach den hierarchischen Abfrage-CTE durch den rekursiven ersetzen:

with r (keyvalue, fromtable, colsavailable, rnk, path) as (
  select keyvalue, fromtable, colsavailable, rnk, colsavailable
  from ordercols_forview
  where rnk = 1
  union all
  select ocfv.keyvalue, ocfv.fromtable, ocfv.colsavailable, ocfv.rnk,
    r.path || q'[||'|'||]' || ocfv.colsavailable
  from r
  join ordercols_forview ocfv
  on ocfv.keyvalue = r.keyvalue
  and ocfv.fromtable = r.fromtable
  and ocfv.rnk = r.rnk + 1
),
combined_cte as (
  select s.keyvalue, s.view_to_be_created, s.noofcols,
    r.fromtable, r.colsavailable, r.rnk, r.path
  from seeding_table s
  join r on r.keyvalue = s.keyvalue
)
select 'CREATE OR REPLACE VIEW ' || c.view_to_be_created || ' AS SELECT ' as text,
  c.view_to_be_created, c.rnk
from combined_cte c
where c.rnk = 1
union all
select 'KEYVALUE,' as text,
  c.view_to_be_created, c.rnk + 1 as rnk
from combined_cte c
where c.rnk = 1
union all
select c.path || ' AS KEY' || c.rnk
  || case when c.rnk < c.noofcols then ',' end,
  c.view_to_be_created, (c.rnk * 2) + 1 as rnk
from combined_cte c
union all
select c.colsavailable || ' AS NO' || c.rnk
  || case when c.rnk < c.noofcols then ',' end as text,
  c.view_to_be_created, (c.rnk * 2) + 2 as rnk
from combined_cte c
union all
select 'FROM ' || c.fromtable || ';' as text,
  c.view_to_be_created, (c.noofcols * 2) + 3 as rnk
from combined_cte c
where c.rnk = c.noofcols
order by view_to_be_created, rnk;

Was zum gleichen Ergebnis führt:

TEXT                                                         V        RNK
------------------------------------------------------------ - ----------
CREATE OR REPLACE VIEW A AS SELECT                           A          1
KEYVALUE,                                                    A          2
NUM1 AS KEY1,                                                A          3
NUM1 AS NO1,                                                 A          4
NUM1||'|'||NUM2 AS KEY2,                                     A          5
NUM2 AS NO2,                                                 A          6
...
NUM1||'|'||NUM2||'|'||NUM3 AS KEY3,                          C          7
NUM3 AS NO3,                                                 C          8
NUM1||'|'||NUM2||'|'||NUM3||'|'||NUM4 AS KEY4,               C          9
NUM4 AS NO4,                                                 C         10
NUM1||'|'||NUM2||'|'||NUM3||'|'||NUM4||'|'||NUM5 AS KEY5     C         11
NUM5 AS NO5                                                  C         12
FROM C1;                                                     C         13