有没有办法在 PL/SQL 中背靠背地运行多个过程,以便创建一个表,然后按照我的代码中的结构进行填充?
Posted
技术标签:
【中文标题】有没有办法在 PL/SQL 中背靠背地运行多个过程,以便创建一个表,然后按照我的代码中的结构进行填充?【英文标题】:Is there anyway to run multiple-procedures back-to-back in PL/SQL so that a table is created and then filled in as structured in my code? 【发布时间】:2020-04-22 22:32:47 【问题描述】:我正在使用 Oracle SQL Developer,我正在尝试让下面的代码工作,但无法弄清楚。我尝试了多种不同的方法,包括实现 for 循环、立即执行、调度和重新编译。
BEGIN
ORDER_STATUS_1_DROP_TABLE; -- If the table exist, drop it
ORDER_STATUS_2_CREATE_TABLE; -- Create the table
GRANT_NEWANALYTICS; -- Grant users select access
ORDER_STATUS_3_SCRIPT; -- Run script to insert data into table
END;
代码试图做的是:
过程 1:如果存在则丢弃,否则跳过。如果在没有表的情况下运行此过程,我不想看到任何警告错误指出不存在表。此过程本身确实按预期工作。
create or replace PROCEDURE ORDER_STATUS_1_DROP_TABLE IS
table_does_not_exist EXCEPTION;
PRAGMA EXCEPTION_INIT(table_does_not_exist, -942);
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE <Table Name>';
EXCEPTION
WHEN table_does_not_exist then
dbms_output.put_line( 'table dose not exist');
END ORDER_STATUS_1_DROP_TABLE;
过程 2:一旦表被删除,这个过程就会用正确的 .我不希望看到“此表已存在”的任何错误,这就是过程 1 存在的部分原因。这本身就可以按预期工作。
create or replace PROCEDURE ORDER_STATUS_2_CREATE_TABLE IS
v_sql LONG;
BEGIN
v_sql:= 'create table <Table Name>
(<parameters>)';
EXECUTE IMMEDIATE v_sql;
END ORDER_STATUS_2_CREATE_TABLE;
过程 3:这只是让用户选择访问在最后一个过程中创建的表。此过程按预期工作。
create or replace PROCEDURE GRANT_NEWANALYTICS IS
BEGIN
EXECUTE IMMEDIATE
'GRANT SELECT ON <Table Name> TO <UserID>';
END;
过程 4:这是一个复杂的查询。这是一个插入全选(表左连接到基于字段和条件等的其他几个表)。程序1-3运行后,这个程序本身没有问题运行,而是自己运行。
create or replace PROCEDURE ORDER_STATUS_3_SCRIPT IS
BEGIN
DELETE FROM <Table Name>;
INSERT INTO <Table Name>
SELECT * FROM(<Multiple Table Joins>);
END ORDER_STATUS_3_SCRIPT;
当我运行这样的程序时:
BEGIN
ORDER_STATUS_1_DROP_TABLE; -- If the table exist, drop it
ORDER_STATUS_2_CREATE_TABLE; -- Create the table
GRANT_NEWANALYTICS; -- Grant users select access
ORDER_STATUS_3_SCRIPT; -- Run script to insert data into table
END;
我收到以下错误报告:
Error report -
ORA-04068: existing state of packages has been discarded
ORA-04065: not executed, altered or dropped stored procedure "<user>.ORDER_STATUS_3_SCRIPT"
ORA-06508: PL/SQL: could not find program unit being called: "<user>.ORDER_STATUS_3_SCRIPT"
ORA-06512: at line 5
04068. 00000 - "existing state of packages%s%s%s has been discarded"
*Cause: One of errors 4060 - 4067 when attempt to execute a stored procedure.
*Action: Try again after proper re-initialization of any application's state.
现在,如果我单独运行这些,它可以工作。所以如果我第一次运行这个:
BEGIN
ORDER_STATUS_1_DROP_TABLE; -- If the table exist, drop it
ORDER_STATUS_2_CREATE_TABLE; -- Create the table
GRANT_NEWANALYTICS; -- Grant users select access
END;
<OUTPUT> PL/SQL procedure successfully completed.
然后是这个:
BEGIN
ORDER_STATUS_3_SCRIPT; -- Run script to insert data into table
END;
<OUTPUT> <Query runs>
我没有问题。我想在一次扫描中运行这些程序集,并且可以在这样的想法上使用一些帮助。有人有想法么?
【问题讨论】:
为什么要删除表? 最好使用@Justin Cave 建议的包含上述过程和动态 SQL 的包 【参考方案1】:如果您想将所有这些过程作为单个 PL/SQL 块的一部分运行,那么对您的表的每个引用都需要通过动态 SQL。所以ORDER_STATUS_3_SCRIPT
需要使用动态 SQL 来构建插入语句来填充表,而不是使用简单的静态 SQL。这显然是可能的,但它确实增加了脚本的复杂性。可能大幅。
拥有两个 PL/SQL 块,您已经证明了它们的工作原理,看起来要简单得多。
【讨论】:
删除和重新创建表在 Oracle 中基本上是一种反模式,而且从来没有必要。它将您用作一次性使用表(您的 3_script)在重新填充之前删除所有行。因此,与 insead 3_script 中的截断相比,删除和重新创建没有任何优势。这会将您的整个过程减少到 1 个脚本。另一种选择,取决于在 3_script 之后如何处理数据,可能只是创建一个全局临时表。无论哪种方式,ORDER_STATUS_3_SCRIPT 都是您需要的唯一脚本。 嗨贾斯汀。是的,我明白了。有时某些源字段不能从上游源获得,我是这样设计的,所以在过程中我可以注释掉当月不可用的任何字段。也许我可以想办法说如果字段不可用则为空。不得不考虑一些。感谢您的反馈!以上是关于有没有办法在 PL/SQL 中背靠背地运行多个过程,以便创建一个表,然后按照我的代码中的结构进行填充?的主要内容,如果未能解决你的问题,请参考以下文章