2016-04-01 48 views
0

我有一個包含了需要創建動態SQL中使用的配置表

SEEDING_TABLE 
------------- 
KEYVALUE|VIEW_TO_BE_CREATED|FROMTABLE|NOOFCOLS 
1|A|A1|3 
2|B|B1|4 
3|C|C1|5 

其中包含了上述播種表

ORDERCOLS_FORVIEW 
KEYVALUE|FROMTABLE|COLSAVAILABLE 
1|A1|NUM1 
1|A1|NUM2 
1|A1|NUM3 
2|B1|NUM1 
2|B1|NUM2 
2|B1|NUM3 
2|B1|NUM4 
3|C1|NUM1 
3|C1|NUM2 
3|C1|NUM3 
3|C1|NUM4 
3|C1|NUM5 
實際列名的其他表的動態SQL視圖列表的表表FROMTABLEs的

定義如下

A1 -> KEYVALUE|NUM1|NUM2|NUM3 
B1 -> KEYVALUE|NUM1|NUM2|NUM3|NUM4 
C1 -> KEYVALUE|NUM1|NUM2|NUM3|NUM4|NUM5 

做所有我們的邏輯和MAG後IC的結果應該是其應該產生以下觀點陳述

DYNAMIC_ENTRIES -> TEXT|TABLE|RANK 
TEXT              |TABLE | RANK 
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 

假設在播種表中的每個條目動態SQL,我們在查找可用列的完整列表。邏輯是,對於種子表中的每個條目,我們需要將條目插入到最終的動態SQL表中,以使用FROMTABLE爲VIEW_TO_BE_CREATED列中的條目創建視圖。對於FROMTABLE中具有像NUM1 ... NUMn這樣的序列的每一列,它們需要像樹一樣連接起來。

我很困惑如何解決這個問題。我們可以創建任意數量的中間表或視圖來實現這一點。任何指針,這將非常感激?

+1

你的問題是什麼? – CathalMF

+0

此數據是否定期刷新?即這是一批ETL作業嗎?帶入它,改變它並通過一個視圖提供? – kevinsky

+0

可能會在一個月內更改一次,並且手動注意配置表 – SriniV

回答

1

這是一個有點亂,但你可以做到這一點在普通的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爲基表列,按字母順序或其他。您只需要連接子句的連續數字序列。

然後,您可以使用兩個聯合來獲取這些列和路徑值的文本部分(因爲它們需要在最終表中爲單獨的行),再加上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_tableordercols_forview_cte之間的加入另一個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播種表之間的連接如上面提到的,但你coudl只需更換使用遞歸一個分層查詢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 
+0

Alex有辦法使用ANSI Sql語法而不是使用oracle特定的分層查詢語法 – SriniV

+0

@realspirituals - 當然,重新使用Oracle 11g或更高版本,可以使用遞歸CTE而不是分層查詢。希望這就是你的意思!我已經添加了一個用於我的答案的版本。 –

+0

優秀的回答隊友。這給了我一個很好的開始挖掘。 – SriniV