Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

SQL dinamis menggunakan tabel konfigurasi

Ini agak berantakan, tetapi Anda bisa melakukannya dalam SQL biasa, dimulai dengan kueri hierarkis untuk mendapatkan string yang digabungkan:

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  

Saya berasumsi tabel Anda benar-benar memiliki kolom lain yang belum Anda tunjukkan yang memberikan posisi kolom. Jika tidak, Anda dapat membuatnya entah bagaimana - mungkin berdasarkan column_id untuk kolom tabel dasar, menurut abjad, atau apa pun. Anda hanya perlu urutan nomor yang berdekatan untuk klausa connect-by.

Anda kemudian dapat menggunakan dua gabungan untuk mendapatkan bagian teks untuk nilai kolom dan jalur tersebut (karena mereka harus menjadi baris terpisah di tabel akhir Anda), ditambah yang tambahan untuk SELECT ... dan FROM ... garis. Masing-masing membutuhkan nomor peringkat lain yang dihasilkan. Itu dapat dihasilkan dari peringkat di CTE:

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;

Yang dengan data awal Anda menghasilkan:

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

Anda dapat sedikit memvariasikannya, memiliki CTE lain dengan gabungan antara seeding_table dan ordercols_forview_cte dan menggunakannya untuk serikat pekerja. Anda juga bisa mendapatkan jalur dari CTE rekursif (dari Oracle 11g):

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;

Dan kemudian dapat menggunakannya sebagai gantinya; ini menggabungkan antara CTE rekursif dan tabel seeding di CTE lain seperti yang disebutkan di atas, tetapi Anda dapat mengganti CTE hierarkis-kueri dengan yang rekursif:

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;

Yang mendapatkan hasil yang sama:

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



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Mengapa saya mendapatkan Kesalahan saat mencoba mengganti nama tabel setelah FROM?

  2. ORA-12170:TNS:Terjadi timeout koneksi

  3. Bagaimana cara men-debug prosedur tersimpan di Toad?

  4. Daftar nama kolom untuk tampilan pengguna di Oracle

  5. Tidak dapat menemukan tabel v$parameter di Oracle