學習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錯誤。
==============================================