sql >> データベース >  >> RDS >> Oracle

構成テーブルを使用した動的SQL

    少し面倒ですが、連結文字列を取得するための階層クエリから始めて、プレーンSQLで実行できます。

    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  
    

    あなたのテーブルには、列の位置を示す、表示していない別の列が実際にあると仮定しました。そうでない場合は、何らかの方法でそれを生成できます。おそらく、ベーステーブル列のcolumn_idに基づいて、アルファベット順などです。 connect-by句には連続した数列が必要です。

    次に、2つのユニオンを使用して、これらの列とパスの値のテキスト部分(最終的なテーブルでは別々の行である必要があるため)に加えて、SELECT ...の追加の部分を取得できます。 およびFROM ... 行。それらのそれぞれは、別の生成されたランク番号を必要とします。これらは、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;
    

    開始データで生成されるもの:

    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
    

    seeding_table間の結合で別のCTEを使用して、少し変更することができます。 およびordercols_forview_cte そしてそれを組合に使う。再帰CTE(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;
    

    そして、代わりにそれを使用できます。これにより、上記のように、その再帰CTEと別のCTEのシードテーブルが結合されますが、階層クエリCTEを再帰クエリCTEに置き換えるだけです。

    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;
    

    同じ結果が得られます:

    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. mysqlクエリの実行時にURLが正しくありません(phpのヘッダーの場所の指示に従わない)

    2. SQLiteで現在の日付を取得する方法

    3. float LARAVELでメンバー関数addEagerConstraints()を呼び出す

    4. PHPのmysqlデータベースに複数の画像をアップロード/保存する方法