【发布时间】:2013-10-10 13:10:54
【问题描述】:
我们有 oracle11g。
我需要编写存储过程(或者可能是另一种解决方案,例如创建视图),它将截断旧表并插入新的更新数据。
我们在数据库中有许多名为 %table_name%+number_prefix 的表。
例如:Country_1、Country_2。
这是来自该表的数据:
id code country
103858 834 TZ
103878 834 UA
103859 800 UG
103860 894 ZM
103861 716 ZW
103862 24 AO
我们还有表 Country_all,其中包含所有这些表中的特定信息。
如果用户从 web gui new Country_%prefix% 表中添加新表,我必须更新 Country_all 表。此表应按代码分组并将所有国家/地区放在一行中(TZ、UA、UG ...):
table code countries
91 2005202000 ,AD,AL,AQ,AS,AT,
91 2005400000 ,AD,AL,AQ,AS,AT,
91 2005995000 ,AD,AL,AQ,AS,AT,
91 2005997000 ,AD,AL,AQ,AS,AT,
91 2006003100 ,AD,AL,AQ,AS,AT,
这里的91表示这个数据来自表Country_91
我用它从表中获取前缀:
EXECUTE IMMEDIATE 'truncate table COUNTRY_ALL';
FOR r IN (SELECT regexp_replace(table_name,'(.*)_', '\1') ADD_NUM
FROM all_tables
WHERE upper(table_name)
LIKE ('COUNTRY_%'))
但是当我尝试使用r.ADD_NUM 时,我遇到了麻烦。
INSERT INTO COUNTRY_ALL
SELECT r.ADD_NUM, code, listagg(code, ',') WITHIN GROUP (ORDER BY code) AS GI_COUNTRIES
FROM 'COUNTRY_' || r.ADD_NUM
GROUP BY code;
我也尝试声明一些变量并将COUNTRY_ || r.ADD_NUM分配给变量,但它也不想从变量中查询。
更新
我昨天终于做到了!
我通过两种方式做到了。 第一个正是我要问的:
BEGIN
EXECUTE IMMEDIATE 'truncate table Countries_ALL';
FOR r IN (SELECT regexp_replace(table_name,'_(.*)', '\1') ADD_NUM
FROM all_tables
WHERE upper(table_name)
LIKE ('COUNTRY_%')
AND owner='owner_name')
loop
EXECUTE IMMEDIATE 'INSERT COUNTRIES_ALL
SELECT '|| r.ADD_NUM ||' as ADD_NUM, code, listagg(countries, '','') WITHIN GROUP (ORDER BY countries) AS COUNTRIES
FROM COUNTRY_' || r.ADD_NUM || '
GROUP by code;
END loop;
END;
第二个更好。我创建了 2 个临时表:CURRENT 和 FOR_UPDATING。
填写CURRENT:
INSERT INTO CURRENT
SELECT DISTINCT ADD_NUM FROM COUNTRIES_ALL;
与前一个不同,只更新不存在的表的过程:
DECLARE
BEGIN
execute IMMEDIATE 'TRUNCATE table for_updating';
INSERT INTO for_updating
SELECT regexp_replace(table_name,'_(.*)', '\5 ') as ADD_NUM
FROM all_tables
WHERE owner='owner_name'
AND table_name LIKE 'COUNTRY_%';
for num in (
SELECT b.add_num FROM CURRENT A
RIGHT JOIN for_updating b
ON A.add_num=b.add_num
WHERE A.add_num IS NULL)
loop
EXECUTE IMMEDIATE 'INSERT INTO COUNTRIES_ALL
SELECT '||num.add_num||' as ADD_NUM, code, listagg(countries, '','') WITHIN GROUP (ORDER BY countries) AS GI_COUNTRIES
FROM COUNTRY_' || num.ADD_NUM || '
GROUP by code';
end loop;
END;
在这个过程中,我比较了 COUNTRIES_ALL 中已有的表和 all_tables 中的表。然后将插入所有新表。
感谢 Przemyslaw Kruglej 的耐心等待!
【问题讨论】:
-
删除 ADD_NUM 之前的
r.- 这有帮助吗? -
不,它没有。我认为问题出在 listagg(code, '','')
-
您能否将此查询作为独立查询运行(没有 EXECUTE IMMEDIATE)?那它有用吗?
-
是的,它可以在没有立即执行的情况下工作,它表示匿名块已完成,我还必须删除一对单引号 '','' -> ','
-
啊.. 删除右撇号前的分号,如下所示:
EXECUTE IMMEDIATE 'INSERT INTO COUNTRY_ALL SELECT r.ADD_NUM, code, listagg(code, '','') WITHIN GROUP (ORDER BY code) AS GI_COUNTRIES FROM COUNTRY_' || tab_number || ' GROUP BY code';
标签: sql oracle stored-procedures plsql