Как позволить хранимой процедуре подождать, пока все отправленные задания будут завершены? - PullRequest
0 голосов
/ 12 марта 2020

Я должен отправить задания здесь.

 dbms_scheduler.create_job(job_name   => 'NewSkus',
                            job_type   => 'PLSQL_BLOCK',
                            job_action => 'begin IC_REFRESH_NEW_SKUS_P(0); end;',
                            start_date => sysdate,
                            enabled    => true,
                            comments   => 'temporary job,will be delete soon after complete!',
                            auto_drop  => true
                            );


  dbms_scheduler.create_job(job_name   => 'LocationHeader',
                            job_type   => 'PLSQL_BLOCK',
                            job_action => 'begin IC_REFRESH_LOCATION_HEADER_P(0); end;',
                            start_date => sysdate,
                            enabled    => true,
                            comments   => 'temporary job,will be delete soon after complete!',
                            auto_drop  => true
                            );  

Теперь у меня есть еще одна хранимая процедура, называемая "ABCDEFG", эту хранимую процедуру необходимо запустить после завершения этих двух заданий. Я пытаюсь написать это условие после отправленных заданий.

WHILE jobNumber > 0
LOOP
    SELECT count(*) INTO jobNumber
    FROM   user_scheduler_jobs srj
    WHERE  srj.job_name IN ('NewSkus','LocationHeader');

    DBMS_LOCK.SLEEP(10);
END LOOP;

К сожалению, в конце хранимая процедура завершена, но одно задание все еще выполняется, поэтому мой блок условий не работает.

Может кто-нибудь мне помочь? Цените !!

1 Ответ

1 голос
/ 12 марта 2020

Я создал универсальный c пакет, который позволяет мне выполнять произвольные SQL в нескольких заданиях, используя несколько ссылок на базы данных. Для синхронизации вывода используется пакет Oracle DBMS_PIPE.

Определите уникальное имя для именованного канала, который вы будете использовать. В конце каждого задания выполняется следующая процедура для уведомления о завершении:

PROCEDURE send_completedmessage( p_pipename   IN pipename_t
                                                 , p_synchid    IN synch_id_t
                                                 , p_errmsg     IN VARCHAR2 DEFAULT NULL ) AS
    l_routine   CONSTANT oracleobj_t := 'send_completedmessage';
    l_status             NUMBER;
BEGIN
    DBMS_PIPE.pack_message( p_synchid );
    DBMS_PIPE.pack_message( p_errmsg );
    l_status   := DBMS_PIPE.send_message( pipename => p_pipename );

    IF l_status <> 0
    THEN
        raise_application_error(
            -20000
          , 'Error writing p_synchid ' || p_synchid || ' to pipe ' || p_pipename );
    END IF;
END send_completedmessage;

Вам нужно будет получить уведомление о том, что задания завершены примерно так:

PROCEDURE get_results( p_pipename   IN     pipename_t
                     , p_dblinks    IN OUT db_link_tt
                     , p_timeout    IN     INTEGER ) AS
    l_routine   CONSTANT oracleobj_t := 'get_results';
    l_result             INTEGER := 0;
    l_db_link            VARCHAR2( 128 );
    l_found              BOOLEAN;
    l_nfound             PLS_INTEGER := 0;
BEGIN
    --        l_result   := DBMS_PIPE.receive_message (pipename => p_pipename, timeout => 10);
    WHILE l_result = 0 AND l_nfound < p_dblinks.COUNT
    LOOP
        l_result   := DBMS_PIPE.receive_message( pipename => p_pipename, timeout => p_timeout );

        -- return if timed out
        IF l_result = 1
        THEN
            make_log_entry( p_routine   => l_routine
                          , p_message   => 'receive message timed out for pipe ' || p_pipename );
            EXIT;
        END IF;

        DBMS_PIPE.unpack_message( l_db_link );
        l_found    := FALSE;

        FOR i IN 1 .. p_dblinks.COUNT
        LOOP
            IF p_dblinks( i ).db_link = l_db_link
            THEN
                p_dblinks( i ).completed   := 1;
                DBMS_PIPE.unpack_message( p_dblinks( i ).errmsg );
                l_found                    := TRUE;
                l_nfound                   := l_nfound + 1;
                EXIT;
            END IF;
        END LOOP;

        IF NOT l_found
        THEN
            raise_application_error(
                -20000
              , 'Non-matching values returned from pipe ' || p_pipename || ': ' || l_db_link );
        END IF;
    END LOOP;

    l_result   := DBMS_PIPE.remove_pipe( pipename => p_pipename );
EXCEPTION
    WHEN OTHERS
    THEN
        make_log_error_entry(
            p_routine   => l_routine
          , p_message   => p_pipename || ': ' || l_db_link || t.crlf || tochar( p_dblinks ) );
        l_result   := DBMS_PIPE.remove_pipe( pipename => p_pipename );
        RAISE;
END get_results;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...