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

Oracle PL/SQL-如何使用动态SQL插入多行,oracle,plsql,Oracle,Plsql,我要遍历所有表,并将ID和表名复制到一个表中。 因为我必须使用一个变量作为表名,所以我尝试使用IMMEDIATE EXECUTE。但对于动态SQL,INSERT INTO语句只允许单行 下面的SQL语句就是它,ifIMMEDIATE EXECUTE将允许INSERT INTO with muplitple行 DECLARE sqlStat VARCHAR2(500); BEGIN FOR TName IN ( SELECT TABLE_NAME FROM all_tab_co

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

下面的SQL语句就是它,ifIMMEDIATE EXECUTE将允许INSERT INTO with 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;

如何循环表和收集记录?

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

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

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
中插入的行数与源表中的行数相同


有些不相关,但:


如果当前用户可以访问不同模式中的表,则所有选项卡列都可能多次返回相同的表名。您可以通过从
所有选项卡_列中选择
所有者
并相应地调整动态SQL的
选择
部分来正确处理该问题。如果您只对当前用户拥有的表感兴趣,请使用
user\u tab\u cols`。

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

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

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
中插入的行数与源表中的行数相同


有些不相关,但:


如果当前用户可以访问不同模式中的表,则所有选项卡列都可能多次返回相同的表名。您可以通过从
所有选项卡_列中选择
所有者
并相应地调整动态SQL的
选择
部分来正确处理该问题。或者,如果您只对当前用户拥有的表感兴趣,请使用
user\u tab\u cols`。

我更喜欢使用user\u tab\u列,因为不需要在表名后附加架构名。如果我们使用的是所有标签,那么最好使用OWNER

您还可以使用“用户”选项卡上的列按如下方式框显查询

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;
或者在从所有选项卡获取时

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 ;

我更喜欢使用USER_TAB_列,因为不需要在表名中附加模式名。如果我们使用的是所有标签,那么最好使用OWNER

您还可以使用“用户”选项卡上的列按如下方式框显查询

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;
或者在从所有选项卡获取时

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 ;

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