动态 SQL 使用配置表
Dynamic SQL using config tables
我有一个 table,其中包含需要创建的动态 SQL 视图列表
SEEDING_TABLE
-------------
KEYVALUE|VIEW_TO_BE_CREATED|FROMTABLE|NOOFCOLS
1|A|A1|3
2|B|B1|4
3|C|C1|5
另一个 table 包含上述种子设定的实际列名 table
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
table FROMTABLE 的定义如下
A1 -> KEYVALUE|NUM1|NUM2|NUM3
B1 -> KEYVALUE|NUM1|NUM2|NUM3|NUM4
C1 -> KEYVALUE|NUM1|NUM2|NUM3|NUM4|NUM5
在完成我们所有的逻辑和魔术之后,结果应该是一个动态的SQL,它应该产生下面的视图语句
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
假设对于种子设定中的每个条目 table,我们在查找中都有可用的完整列列表。逻辑是,对于种子 table 中的每个条目,我们需要将条目插入到最终动态 SQL table 中,以通过使用为 VIEW_TO_BE_CREATED 列中的条目创建视图从表。对于 FROMTABLE 中具有类似 NUM1...NUMn 序列的每一列,它们需要像树一样连接起来。
我对如何处理这个问题感到困惑。我们可以创建任意数量的中间 tables 或视图来实现这一点。对此的任何指示将不胜感激?
有点乱,但您可以简单地做到这一点 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
我假设您的 table 确实有另一列您没有显示,它给出了列位置。如果没有,您可以以某种方式生成它 - 可能基于 column_id 作为基础 table 列,按字母顺序或其他方式。您只需要 connect-by 子句的连续数字序列。
然后您可以使用两个联合来获取这些列和路径值的文本部分(因为它们需要在您的最终 table 中是单独的行),以及 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
您可以稍微改变一下,让另一个 CTE 在 seeding_table
和 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 中的播种 table 之间进行连接,但是您可以将分层查询 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
我有一个 table,其中包含需要创建的动态 SQL 视图列表
SEEDING_TABLE
-------------
KEYVALUE|VIEW_TO_BE_CREATED|FROMTABLE|NOOFCOLS
1|A|A1|3
2|B|B1|4
3|C|C1|5
另一个 table 包含上述种子设定的实际列名 table
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
table FROMTABLE 的定义如下
A1 -> KEYVALUE|NUM1|NUM2|NUM3
B1 -> KEYVALUE|NUM1|NUM2|NUM3|NUM4
C1 -> KEYVALUE|NUM1|NUM2|NUM3|NUM4|NUM5
在完成我们所有的逻辑和魔术之后,结果应该是一个动态的SQL,它应该产生下面的视图语句
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
假设对于种子设定中的每个条目 table,我们在查找中都有可用的完整列列表。逻辑是,对于种子 table 中的每个条目,我们需要将条目插入到最终动态 SQL table 中,以通过使用为 VIEW_TO_BE_CREATED 列中的条目创建视图从表。对于 FROMTABLE 中具有类似 NUM1...NUMn 序列的每一列,它们需要像树一样连接起来。
我对如何处理这个问题感到困惑。我们可以创建任意数量的中间 tables 或视图来实现这一点。对此的任何指示将不胜感激?
有点乱,但您可以简单地做到这一点 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
我假设您的 table 确实有另一列您没有显示,它给出了列位置。如果没有,您可以以某种方式生成它 - 可能基于 column_id 作为基础 table 列,按字母顺序或其他方式。您只需要 connect-by 子句的连续数字序列。
然后您可以使用两个联合来获取这些列和路径值的文本部分(因为它们需要在您的最终 table 中是单独的行),以及 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
您可以稍微改变一下,让另一个 CTE 在 seeding_table
和 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 中的播种 table 之间进行连接,但是您可以将分层查询 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