FORALL + EXECUTE IMMEDIATE + INSERT进入tbl SELECT

use*_*270 0 oracle forall

我被困在下面并且语法错误 - 请帮忙.基本上我使用一个集合来存储几个部门ID,然后想要在FORALL语句中将数据插入到emp表中时使用这些部门ID作为过滤条件.

下面是示例代码:在编译此代码时我收到错误,我的要求是使用INSERT INTO表select*from table并且无法避免它所以请建议.

create or replace Procedure abc(dblink VARCHAR2)
 CURSOR dept_id is select dept_ids from dept;
 TYPE nt_dept_detail IS TABLE OF VARCHAR2(25);
 l_dept_array nt_dept_detail;
Begin
 OPEN dept_id;
 FETCH dept_id BULK COLLECT INTO l_dept_array;
 IF l_dept_array.COUNT() > 0 THEN

    FORALL i IN 1..l_dept_array.COUNT SAVE EXCEPTIONS
      EXECUTE IMMEDIATE 'INSERT INTO stg_emp SELECT
      Dept,''DEPT_10'' FROM dept_emp'||dblink||' WHERE
      dept_id = '||l_dept_array(i)||'';      
      COMMIT;
 END IF;
 CLOSE dept_id;
 end abc;
Run Code Online (Sandbox Code Playgroud)

Bon*_*ist 5

你为什么要首先使用游标,数组等?为什么你不能只选择一个简单的插入?

上面列出的程序问题:

  1. 您不会声明过程,例如Procedure abc ()- 对于独立过程,您可以执行create or replace procedure abc as或在包中:procedure abc is

  2. 您引用了一个名为"dblink"的变量,该变量未在任何地方声明.

  3. 你没有把end abc;你的程序结束(我希望这只是一个错误的c&p?)

  4. 你有效地做了一个简单的插入作为选择,但是你过于复杂,加上你的代码性能降低.

  5. 您没有列出您尝试插入的列名; 如果stg_emp有两列以上或者最后添加了列,则代码将失败.


假设你的dblink名称直到运行时才知道,那么这就是你要做的事情:

create Procedure abc (dblink in varchar2)
is
begin
  execute immediate 'insert into stg_emp select dept, ''DEPT_10'' from dept_emp@'||dblink||
                    ' where  dept_id in (select dept_ids from dept)';
  commit;
end abc;
/
Run Code Online (Sandbox Code Playgroud)

但是,如果您确实知道dblink名称,那么您只需删除execute immediate并执行:

create Procedure abc (dblink in varchar2)
is
begin
  insert into stg_emp -- best to list the column names you're inserting into here
  select dept, 'DEPT_10'
  from dept_emp@dblink
  where  dept_id in (select dept_ids from dept);
  commit;
end abc;
/
Run Code Online (Sandbox Code Playgroud)

  • 同时引用`FORALL`中的`l_l_dept_array`,而不是`l_dept_array`. (2认同)