Oracle PL / SQL - 如何使用动态SQL插入多行

时间:2016-09-22 13:57:56

标签: oracle plsql

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

以下SQL语句就是这样,如果 IMMEDIATE EXECUTE允许INSERT INTO使用muplitple行。

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;

如何循环访问表并收集记录?

2 个答案:

答案 0 :(得分:5)

insert ... select可以插入多行,无论是否通过" plain" 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可能会多次返回相同的表名。如果您只对当前用户对拥有的表感兴趣,请从owner选择all_tab_columns and adjust the user_tab_cols`中选择part of the dynamic SQL accordingly. Or use来正确处理。

答案 1 :(得分:0)

我更喜欢使用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 ;