繁体   English   中英

无法从包装过程异步调用主过程

[英]unable to call main procedure from wrapper procedure asynchronously

我想从包装程序调用主程序。 包装程序我可以使用 dbms output 打印行 output 但我无法在主过程中打印,看起来主过程不是从包装程序调用的。 请帮我

下面是表格脚本

CREATE TABLE ASYNC_SAMPLE_TAB
( attribute1 varchar2(50),
  attribute2 varchar2(50)
);

下面是我的 package 规格

CREATE OR REPLACE PACKAGE XX_ASYNC_DEMO_PKG
IS
    PROCEDURE MAIN_PROC( 
        attribute1          IN      VARCHAR2,
        attribute2          IN      VARCHAR2
    );
    
    PROCEDURE WRAPPER_MAIN_PROC( 
        attribute1          IN      VARCHAR2,
        attribute2          IN      VARCHAR2
    );
  
END XX_ASYNC_DEMO_PKG;

下面是我的 package bofy

CREATE OR REPLACE PACKAGE BODY XX_ASYNC_DEMO_PKG
IS
    PROCEDURE WRAPPER_MAIN_PROC( 
            attribute1          IN      VARCHAR2,
            attribute2          IN      VARCHAR2
        )
    AS
    BEGIN
        DBMS_OUTPUT.PUT_LINE('-- START OF WRAPPER PROC---' || SYSTIMESTAMP);
        dbms_scheduler.create_job(
            job_name   => 'ASYNC_MAIN_PROC' || '_' || attribute1, 
            job_type   => 'PLSQL_BLOCK', 
            job_action => 'BEGIN 
                              MAIN_PROC(''' || attribute1 || ''', ''' || attribute2 || ''');
                           END;', 
            start_date => systimestamp , 
            auto_drop  => true,
            enabled    => true
        );
        DBMS_OUTPUT.PUT_LINE('-- END OF WRAPPER PROC---' || SYSTIMESTAMP);
    END;
    

PROCEDURE MAIN_PROC( 
        attribute1          IN      VARCHAR2,
        attribute2          IN      VARCHAR2
    )
    AS
        sql_stmt    VARCHAR2(200);
    BEGIN
        DBMS_OUTPUT.PUT_LINE('-- START OF MAIN PROC---' || SYSTIMESTAMP);
        DBMS_SESSION.sleep(10);
        sql_stmt := 'INSERT INTO ASYNC_SAMPLE_TAB VALUES (:1, :2)';
        EXECUTE IMMEDIATE sql_stmt USING attribute1, attribute2;
        DBMS_OUTPUT.PUT_LINE('-- END OF MAIN PROC---' || SYSTIMESTAMP);
    END;
END XX_ASYNC_DEMO_PKG;

下面是我试图用来测试上述解决方案的命令

exec XX_ASYNC_DEMO_PKG.WRAPPER_MAIN_PROC('Test101_1', 'Test101_2');

文档中所述, DBMS_OUTPUT的主要目的是调试消息以跟踪执行流程。 那里还说它不会立即向调用者返回任何内容,但文本会被放入缓冲区中,并且可以由调用者或程序本身从那里检索(尽管你不能“进入”任何其他程序流程和从执行代码中获取任何东西,直到被调用单元完成)。

调度程序在完成作业后不会检索缓冲区的内容,因此在后台作业中调用的DBMS_OUTPUT.PUT*没有任何效果,您也看不到任何结果。

您可以使用一些日志记录表(在自治事务中执行单独的日志记录过程,不影响或受主事务影响)或外部文件和UTL_FILE将结果发送到此处。 或者使用应该由作业处理的通用表,并在完成后检查结果。

UPD :下面是一个完整的设置,用于演示如何将参数传递给可调用对象并查看其结果。

  • 我们会将结果记录到此表中:
create table log_table (
    ts timestamp,
    val number,
    job_name varchar2(30)
)
  • 然后这个过程将被用来执行一个动作:
create or replace procedure proc_insert(
    p_val in number,
    p_job_name in varchar2
) as
begin
    insert into log_table(ts, val, job_name)
    values (systimestamp, p_val, p_job_name);
    commit;
end;
  • 该程序将在后台作业中调用我们的操作程序。 在创建作业时,我们需要指定一些参数来覆盖可调用对象中的默认值。 然后根据参数类型使用DBMS_SCHEDULER.SET_JOB_[ARGUMENT|ANYDATA]_VALUE
 create or replace procedure proc_insert_async( p_call_id varchar2, p_val number, r_job_name out varchar2 ) as l_job_prefix constant varchar2(20):= 'LOG_TABLE_'; l_job_name varchar2(100):= l_job_prefix || p_call_id; begin dbms_scheduler.create_job( job_name => l_job_name, job_type => 'STORED_PROCEDURE', /*Callable unit - out API procedure*/ job_action => 'TEST_EAS.PROC_INSERT', /*Number of args to be passed to the proc*/ number_of_arguments => 2, /*Run immediately*/ start_date => sysdate, enabled => false, auto_drop => true ); /*Pass parameters to the callable*/ dbms_scheduler.set_job_anydata_value ( job_name => l_job_name, argument_position => 1, argument_value => sys.anydata.convertNumber(p_val) ); dbms_scheduler.set_job_argument_value( job_name => l_job_name, argument_position => 2, argument_value => l_job_name ); /*Start job*/ dbms_scheduler.enable( name => l_job_name ); r_job_name:= l_job_name; end;
  • 最后,实际测试(由于插入等待结果的异步性质,添加了睡眠)。
 declare l_job_name varchar2(100); begin proc_insert_async( p_call_id => 'test1', p_val => 1, r_job_name => l_job_name ); dbms_output.put_line(l_job_name); proc_insert_async( p_call_id => 'test2', p_val => 10, r_job_name => l_job_name ); dbms_output.put_line(l_job_name); dbms_session.sleep(3); end; / LOG_TABLE_test1 LOG_TABLE_test2 PL/SQL procedure successfully completed.
select *
from log_table
TS JOB_NAME
25.11.22 10:52:37,310403000 10 LOG_TABLE_test2
25.11.22 10:52:37,302992000 1个 LOG_TABLE_test1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM