我有要求在同一时间跨多个数据库运行SP,其中一部分是从每个数据库中删除一些重复记录。现在,由于SP可以多次运行,我已经包含了一个备份表以及在SP连续运行两次的情况下截断和删除它所需的内容。Oracle - 使用dbms_utility.exec_ddl_statement不能正确执行的游标
现在,因为我通过DBLINK创建表,我研究过我需要使用dbms_utility.exec_ddl_statement - 但在这种情况下,即使过程执行,截断和放置查询似乎什么都不做,因为当我第二次运行SP时,它告诉我备份表的名称已被使用(即使我在CREATE之前包含了DROP执行)。
loop
fetch v_data into v_database_name;
exit when v_data%NOTFOUND;
sql_update := 'BEGIN'
||' EXECUTE IMMEDIATE ''truncate table iSecurity2_dupes_bak'';'
||' EXCEPTION'
||' WHEN OTHERS THEN'
||' IF SQLCODE != -942 THEN'
||' RAISE;'
||' END IF;'
||' END;';
execute immediate 'begin [email protected]'||v_database_name||'(:sql_update); end;' using sql_update;
commit;
sql_update := 'BEGIN'
||' EXECUTE IMMEDIATE ''DROP TABLE iSecurity2_dupes_bak'';'
||' EXCEPTION'
||' WHEN OTHERS THEN'
||' IF SQLCODE != -942 THEN'
||' RAISE;'
||' END IF;'
||' END;';
execute immediate 'begin [email protected]'||v_database_name||'(:sql_update); end;' using sql_update;
commit;
sql_update := 'create table iSecurity2_dupes_bak as select * from iSecurity2';
execute immediate 'begin [email protected]'||v_database_name||'(:sql_update); end;' using sql_update;
commit;
.................
ORA-00955: name is already used by an existing object
ORA-06512: at "SYS.DBMS_UTILITY", line 478
ORA-06512: at line 1
ORA-06512: at "database.procedure_name", line 53
ORA-06512: at line 2
包括GLOBAL TEMP表删除,插入,更新和创建的游标的其余部分似乎工作得很好,一切都执行。如果我手动删除备份表,即使执行失败的CREATE。
我困惑:(
UPDATE 2016年8月12日
与@乔恩海勒提供帮助,我能够改变我的代码在其下方,只要工程,我使用一个静态名称为DB_LINK但是当我尝试使用该变量失败 尝试了以下两个版本,但仍然不能运行,但我一直在修改它们 - 我在这里丢失了什么?
注意:现在,我添加了alter session,因为没有它,重新运行orig由于ORA-04062,进程程序保持失败:过程“cw_drop_table”的时间戳已更改;
1版
loop
fetch v_data into v_database_name;
exit when v_data%NOTFOUND;
sql_update := 'alter session set REMOTE_DEPENDENCIES_MODE=SIGNATURE';
execute immediate 'begin [email protected]'||v_database_name||'(:sql_update); end;' using sql_update;
commit;
begin
[email protected]_database_name (
q'[
create or replace procedure cw_drop_table is sql_drop varchar2(2000);
begin
sql_drop := 'BEGIN'
||' EXECUTE IMMEDIATE ''DROP TABLE iSecurity2_dupes_bak'';'
||' EXCEPTION'
||' WHEN OTHERS THEN IF SQLCODE != -942 THEN NULL; END IF; END;';
execute immediate sql_drop;
commit;
end; ]');
execute immediate 'begin [email protected]'||v_database_name||'; end;';
end;
sql_update := 'create table iSecurity2_dupes_bak as select * from iSecurity2';
execute immediate 'begin [email protected]'||v_database_name||'(:sql_update); end;' using sql_update;
commit;
PLS-00352: Unable to access another database 'V_DATABASE_NAME'
PLS-00201: identifier '[email protected]_DATABASE_NAME' must be declared
PL/SQL: Statement ignored
第二版
loop
fetch v_data into v_database_name;
exit when v_data%NOTFOUND;
sql_update := 'alter session set REMOTE_DEPENDENCIES_MODE=SIGNATURE';
execute immediate 'begin [email protected]'||v_database_name||'(:sql_update); end;' using sql_update;
commit;
declare v_db_name varchar2(100);
begin select v_database_name into v_db_name from dual;
execute immediate '[email protected]'||v_db_name||' ('
||' q''[ '
||' create or replace procedure cw_drop_table is sql_drop varchar2(2000);'
||' begin '
||' sql_drop := ''BEGIN'' '
||' ||'' EXECUTE IMMEDIATE ''DROP TABLE iSecurity2_dupes_bak'';'' '
||' ||'' EXCEPTION'' '
||' ||'' WHEN OTHERS THEN IF SQLCODE != -942 THEN NULL; END IF; END;''; '
||' execute immediate sql_drop;'
||' commit;'
||' end; ]''); '
||' execute immediate ''begin [email protected]'||v_db_name||'; end;''; ';
end;
sql_update := 'create table iSecurity2_dupes_bak as select * from iSecurity2';
execute immediate 'begin [email protected]'||v_database_name||'(:sql_update); end;' using sql_update;
commit;
PLS-00103: Encountered the symbol "DROP" when expecting one of the following:
* & = - + ; </> at in is mod remainder not rem
<an exponent (**)> <> or != or ~= >= <= <> and or like LIKE2_
LIKE4_ LIKEC_ between || member SUBMULTISET_
SOLUTION
多沉思后和淋浴我放弃了上述方法,并与下面去了。不知道为什么我没有早点考虑它:|
注:如果有人通过这个啰嗦的问题永远读,知道我做错了什么在2016年8月12日更新,我很想找到:)
loop
fetch v_data into v_database_name;
exit when v_data%NOTFOUND;
sql_update := 'alter session set REMOTE_DEPENDENCIES_MODE=SIGNATURE';
execute immediate 'begin [email protected]'||v_database_name||'(:sql_update); end;' using sql_update;
commit;
begin
sql_update:='DROP TABLE iSecurity2_dupes_bak';
execute immediate 'begin [email protected]'||v_database_name||'(:sql_update); end;' using sql_update;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -942 THEN
NULL; -- suppresses ORA-00942 exception
ELSE
RAISE;
END IF;
END;
感谢虽然我的困惑在于为什么CREATE临时表PL/SQL块与TRUNCATE和DROP所述表一起工作得很好,而上面的静默失败了? – EkeshOkor
@EkeshOkor CREATE ...是DDL,但是BEGIN ...不是DDL,尽管它可能包含* DDL。您可能想查看[SQL语句类型](http://docs.oracle.com/database/121/SQLRF/statements_1001.htm#SQLRF30001)。它不包含PL/SQL,但是从手册的其他部分来看,它暗示'PLSQL_BLOCK'是一个单独的语句类型。 –
嗯..这是有道理的。 :) – EkeshOkor