【问题标题】:Oracle PL/SQL - How can I insert multiple rows using dynamic SQLOracle PL/SQL - 如何使用动态 SQL 插入多行
【发布时间】:2017-01-31 03:43:01
【问题描述】:

我想遍历所有表并将 ID 和表名复制到一个表中。 由于我必须使用变量作为表名,因此我尝试使用 IMMEDIATE EXECUTE。但是对于动态 SQL,INSERT INTO 语句只允许单行。

下面的 SQL 语句就是它,if IMMEDIATE EXECUTE 将允许 INSERT INTO 多行。

DECLARE
    sqlStat VARCHAR2(500);

BEGIN 
  FOR TName IN (
  SELECT TABLE_NAME FROM all_tab_cols WHERE column_name='ID'
  )

  LOOP
    sqlStat := 'INSERT INTO storeTab (ID,TABLE_NAME) SELECT ID, '' :1 '' FROM :2';
    EXECUTE IMMEDIATE sqlStat USING TName.TABLE_NAME,TName.TABLE_NAME;
  END LOOP;
END;

如何循环遍历表并收集记录?

【问题讨论】:

    标签: oracle plsql


    【解决方案1】:

    insert ... select 可以插入多行,无论是通过“普通”SQL、PL/SQL 还是动态 SQL 执行。

    但您不能在动态 SQL 中为标识符(名称)使用占位符。您需要连接查询。如果您通过 USING 子句传递值,则不需要使用单引号:

    DECLARE
        sqlStat VARCHAR2(500);
    BEGIN 
      FOR TName IN (SELECT TABLE_NAME FROM all_tab_cols WHERE column_name='ID' and table_name = 'FOO')
      LOOP
        sqlStat := 'INSERT INTO storetab (ID,TABLE_NAME) SELECT ID, :1 FROM '||tname.table_name;
        EXECUTE IMMEDIATE sqlStat USING TName.TABLE_NAME;
      END LOOP;
    END;
    /
    

    storetab 中插入与源表中的行一样多的行。


    有点不相关,但是:

    all_tab_columns 可能会多次返回相同的表名,前提是当前用户可以访问不同模式中的这些表。如果您只对当前用户拥有的表感兴趣,则应该通过从all_tab_columns and adjust theselectpart of the dynamic SQL accordingly. Or useuser_tab_cols` 中选择owner 来正确处理该问题。

    【讨论】:

    • 连接查询确实有效,我能够检索多行。感谢您的快速解决方案!
    【解决方案2】:

    我更喜欢使用 USER_TAB_COLUMNS,因为不需要在表名中附加模式名称。如果我们使用 ALL_TAB_COLS,那么最好使用 OWNER。

    您还可以使用 USER_TAB_COLUMNS 将查询框定如下。

    DECLARE
        sqlStat VARCHAR2(500);
    BEGIN 
      FOR TName IN (SELECT TABLE_NAME FROM USER_TAB_COLUMNS WHERE column_name='ID')
      LOOP
        sqlstat := 'INSERT INTO storeTab (ID,TABLE_NAME) SELECT ID, ''' ||TName.TABLE_NAME|| ''' FROM '||Tname.TABLE_NAME ;
        EXECUTE IMMEDIATE sqlStat ;
      END LOOP;
    END;
    

    或者在从 ALL_TAB_COLS 获取时

    DECLARE
        sqlStat VARCHAR2(500);
    BEGIN 
      FOR TName IN (SELECT OWNER,TABLE_NAME FROM ALL_TAB_COLS WHERE column_name='ID')
      LOOP
        sqlStat := 'INSERT INTO storeTab (ID,TABLE_NAME) SELECT ID, ''' ||TName.TABLE_NAME|| ''' FROM '||Tname.OWNER||'.'||Tname.TABLE_NAME;
        EXECUTE IMMEDIATE sqlStat  ;
      END LOOP ;
    END ;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-18
      • 2019-02-02
      • 1970-01-01
      • 1970-01-01
      • 2012-04-03
      • 2013-08-16
      • 1970-01-01
      • 2017-10-18
      相关资源
      最近更新 更多