(8)使用Events之Aapplication拋出的Events |
[君三思] 2009-8-26 |
4.2 Application拋出的Events首先要說明,這里所說的Application是個代詞,即可以表示ORACLE數據庫之外的應用程序,也可以是ORACLE數據庫中的PROCEDURE等對象,總之你就將其理解成用戶自己創建的對象就好了。 Scheduler 能夠拋出Events讓外部應用處理,外部的應用也可以拋出Events讓Scheduler啟動job處理,不過并不是任何job都能夠對外部應用拋出的Events做出響應,必須在創建jobs時明確指定響應的事件。那么如何指定呢?依靠下列兩個附加的參數:
下面,我們就演示創建一個由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 條件嗎:
沒錯,只有當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錯誤。 |