0

我有一个场景,我的oracle数据库有大约 20 个表,所有表都有一个名为itemId的索引字段。我想从所有 20 个表中复制具有 id(称为 101)的记录,并使用新的 id(称为 102)插入它们。我不想有 20 个或 20 个游标,functions/procedures因为表列表将来可能会增长。帮助我以更好的方式实现这一目标。

4

1 回答 1

0

由于表的数量可能可变,因此您需要使用动态 SQL 来实现您的目标。像下面这样的东西应该会有所帮助:

DECLARE
  l_insert_column_list      VARCHAR2(4000);
  l_select_column_list      VARCHAR2(4000);
BEGIN
  FOR table_rec IN (SELECT table_name
                      FROM user_tab_columns
                     WHERE UPPER(column_name) = 'ITEMID')
  LOOP
    l_insert_column_list := '';
    l_select_column_list := '';
    FOR col_rec IN (SELECT column_name
                      FROM user_tab_columns
                     WHERE table_name = table_rec.table_name)
    LOOP
      l_insert_column_list := l_insert_column_list || col_rec.column_name || ',';
      IF UPPER(col_rec.column_name) = 'ITEMID' THEN
        l_select_column_list := l_select_column_list || '102,';
      ELSE
        l_select_column_list := l_select_column_list || col_rec.column_name || ',';
      END IF;
    END LOOP;

    l_insert_column_list := RTRIM(l_insert_column_list, ',');
    l_select_column_list := RTRIM(l_select_column_list, ',');

    EXECUTE IMMEDIATE 'INSERT INTO ' || table_rec.table_name || ' (' 
        || l_insert_column_list || ') SELECT ' || l_select_column_list ||
        ' FROM ' || table_rec.table_name || ' WHERE ITEMID = 101';

  END LOOP;
END;
/

这里的想法是使用user_tab_columns数据字典视图列出所有具有ITEMID列的表。然后,对于每个这样的表,我们使用user_tab_columns列出表中的所有列,然后构建一个 SQL 字符串来复制数据。

我在这里做了一些假设:

  • 您的所有表都在同一个模式中。如果不是,您可能需要使用all_tab_columns而不是user_tab_columns,并将架构所有者包含在也使用table_rec的 SQL 字符串中。table_rec.table_name

  • 您的表名或列名都没有需要用双引号括起来的名称。(如果是这样,您必须调整 SQL 字符串以包含双引号。)

  • 对于表中的所有列名,4000 个字符就足够了。(由于列名限制为 30 个字符,您需要超过 100 列才能触发此问题。)

在你让这个脚本在你的数据库上松动之前,我强烈建议你EXECUTE IMMEDIATE用一个调用来替换,dbms_output.put_line这样你就可以看到正在生成的 SQL 字符串。

于 2013-10-08T08:48:11.453 回答