【问题标题】:Create table from many tables with specific data从具有特定数据的许多表中创建表
【发布时间】:2013-10-10 13:10:54
【问题描述】:

我们有 oracle11g。

我需要编写存储过程(或者可能是另一种解决方案,例如创建视图),它将截断旧表并插入新的更新数据。

我们在数据库中有许多名为 %table_name%+number_prefix 的表。

例如:Country_1Country_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 个临时表:CURRENTFOR_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


【解决方案1】:

您无法使用表的动态名称运行查询。

您必须为每个表生成查询,使用 dbms_sql 包或立即执行。

你知道你应该在哪张桌子上工作吗?如果是这样,您可以使用 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';

【讨论】:

  • 谢谢!其实我知道新表的编号。但我希望这件事自动成为某种东西。
  • 好的,但是如果您能够以某种方式动态获取您必须使用的表的编号,您可以使用我在帖子中写的内容。还是我错过了什么?现在是什么阻止您自动完成这项工作?
  • 例如用户添加了几个新表。现在我应该用获得的数字手动运行程序。但我想要每天自动运行一次的程序。如果我(从 country_all 中选择不同的 add_num)并获得我已经拥有的数字怎么办。然后使用previuos代码获取所有数字。我怎样才能比较它们才能得到新的?可以只使用pl/sql吗?
  • 所以您想知道今天创建了哪些表 - 您可以将前一天创建的最后一个表的编号存储在某个配置表中,然后运行您的作业,这将获得新的数字(新等于那些大于记忆值的数字)并在这些表上执行立即执行。然后,当您完成时,将最后一张表的编号更新为等于您在这一天的工作中更新的最后一张表的编号。您还可以检查您正在使用的表的 DDL 时间,但我不推荐这种方法(第一种方法更好)。
猜你喜欢
  • 2012-10-16
  • 2020-06-09
  • 1970-01-01
  • 2022-10-04
  • 1970-01-01
  • 2021-07-26
  • 2021-02-24
  • 2015-02-08
  • 2019-01-10
相关资源
最近更新 更多