1. 程式人生 > >學習ORACLE Scheduler特性(8)Application丟擲的Events

學習ORACLE Scheduler特性(8)Application丟擲的Events

4.2 Application丟擲的Events

  首先要說明,這裡所說的Application是個代詞,即可以表示ORACLE資料庫之外的應用程式,也可以是ORACLE資料庫中的PROCEDURE等物件,總之你就將其理解成使用者自己建立的物件就好了。

  Scheduler 能夠丟擲Events讓外部應用處理,外部的應用也可以丟擲Events讓Scheduler啟動job處理,不過並不是任何job都能夠對外部應用丟擲的Events做出響應,必須在建立jobs時明確指定響應的事件。那麼如何指定呢?依靠下列兩個附加的引數:

  • queue_spec :指定外部應用丟擲的events訊息入隊的佇列名;
  • event_condition :指定觸發job啟動的條件,這一引數的引數值在設定時應當基於事件訊息的自身屬性,因為事件訊息在入隊時,訊息的屬性都是由application定義的,因此在設定觸發條件時,也應該根據這些屬性值就行設定。

  下面,我們就演示建立一個由event觸發啟動的job,在此之前,首先需要進行一些準備工具,比如建立佇列,由於佇列需要基於一個隊列表,因此在建立佇列之前,首先要建立一個隊列表,考慮到隊列表需要依賴一個物件型別,因此在建立隊列表之前,先得建立一個type.......複雜,具體的操作步驟如下,客官可要看仔細了:

SQL> create or replace type jss_type 1  as object

  2  (

  3    event_type         VARCHAR2( 1 0),

  4    object_owner       VARCHAR2( 30 ),

  5    object_name        VARCHAR2( 3 0)

  6  );

  7  /

Type created.

SQL> begin

  2    dbms_aqadm.create_queue_table(

  3      queue_table        => 'my_queue_tbl1',

  4      queue_payload_type => 'JSS_TYPE1',

  5      multiple_consumers => true);

  6  end;

  7  /

PL/SQL procedure successfully completed.

SQL> begin

  2    dbms_aqadm.create_queue(

  3      queue_name  => 'event_t1',

  4      queue_table => 'my_queue_tbl1');

  5  end;

  6  /

PL/SQL procedure successfully completed.

  OK, 準備工作完成,下面就來建立一個event觸發啟動的job,建立指令碼如下:

SQL> BEGIN

  2  DBMS_SCHEDULER.CREATE_JOB (

  3     job_name            =>  'EVENT_JOB_T1',

  4     job_type            =>  'STORED_PROCEDURE',

  5     job_action          =>  'P_INSERTINTOTEST',

  6     event_condition     =>  'tab.user_data.event_type = ''OP_INSERT''',

  7     queue_spec          =>  'EVENT_T1',

  8     enabled             =>  TRUE);

  9  END;

 10  /

PL/SQL procedure successfully completed.

  上述指令碼僅做演示,因此建立的job仍然執行P_INSERTINTOTEST過程。

  三思並不準備再編寫一套外部的應用來觸發,這裡僅為了演示application觸發job啟動的示例,因此三思決定通過pl/sql直接向event_t1佇列中新增訊息的方式,觸發job的啟動,具體操作如下。

  首先要執行DBMS_AQADM.START_QUEUE過程,將event_t1置於允許入隊和出隊狀態(預設情況下建立的佇列是不允許出隊和入隊操作的),指令碼如下:

SQL> exec dbms_aqadm.start_queue(queue_name => 'event_t1',enqueue => true,dequeue => true);

PL/SQL procedure successfully completed.

  執行入隊操作:

SQL> declare

  2    v_Message           jss_type1;

  3    v_EnqueueOptions    dbms_aq.enqueue_options_t;

  4    v_MessageProperties dbms_aq.message_properties_t;

  5    v_msg_handle        raw(16);

  6  begin

  7    v_message := jss_type1('OP_ SELECT ', user, 'tmpObj');

  8

  9    dbms_aq.enqueue(queue_name         => 'event_t1',

 10                    enqueue_options    => v_enqueueOptions,

 11                    message_properties => v_messageproperties,

 12                    payload            => v_message,

 13                    msgid              => v_msg_handle);

 14    commit;

 15

 16  end;

 17  /

PL/SQL procedure successfully completed.

  查詢隊列表中的資料:

SQL> select user_data from my_queue_tbl1;

USER_DATA(EVENT_TYPE, OBJECT_OWNER, OBJECT_NAME)

---------------------------------------------------------

JSS_TYPE1('OP_SELECT', 'TEST', 'tmpObj')

  然後查詢job

SQL> select to_char(created,'yyyy-mm-dd hh24:mi:ss') from jss_1;

TO_CHAR(CREATED,'YY

-------------------

2009-08-25 12:49:29

  看起來jss_1表中並未有新增加記錄,似乎job沒有執行啊。這很正常,還記得咱們建立job時指定的 event_condition 條件嗎:

  •   6     event_condition     =>  'tab.user_data.event_type = ''OP_INSERT''',

  沒錯,只有當event_type為'OP_INSERT'時才會觸發job的執行,前面入隊時指定的是 OP_ SELECT ,當然沒有觸發job中指定的procedure啦,下面再次執行入隊操作:

SQL> declare

  2    v_Message           jss_type1;

  3    v_EnqueueOptions    dbms_aq.enqueue_options_t;

  4    v_MessageProperties dbms_aq.message_properties_t;

  5    v_msg_handle        raw(16);

  6  begin

  7    v_message := jss_type1('OP_INSERT', user, 'tmpObj');

  8

  9    dbms_aq.enqueue(queue_name         => 'event_t1',

 10                    enqueue_options    => v_enqueueOptions,

 11                    message_properties => v_messageproperties,

 12                    payload            => v_message,

 13                    msgid              => v_msg_handle);

 14    commit;

 15

 16  end;

 17  /

  再次檢視jss_1表看看:

SQL> select to_char(created,'yyyy-mm-dd hh24:mi:ss') from jss_1;

TO_CHAR(CREATED,'YY

-------------------

2009-08-25 12:49:29

2009-08-25 13:21:21

  多了一條記錄,說明job已經被自動觸發。

  最後再補充一句,基於event的job不能通過DBMS_SCHEDULER.RUN_JOB過程執行,否則會觸發ORA-00942: table or view does not exist錯誤。

==============================================