Trigger

如何在不使用觸發器的情況下觸發操作

  • October 30, 2012

我只是想問問。我們有一個日曆表,我們在一個數據庫中將其稱為 CAL1,我們將其稱為 DB1。CAL1 是手動填充的。現在在另一個數據庫 DB2 中,有另一個日曆表 CAL2。我需要做的是根據 CAL1 中的值填充 CAL2。我不知道何時會填充 CAL1。其他數據庫中還有一些其他日曆表/表將引用 CAL1,因此我需要創建一個 API,以便在將新數據載入到 CAL1 時填充或至少執行來自其他數據庫(例如 DB2)的過程。我最初考慮使用觸發器,但讀到最好不要使用它。那麼有沒有其他方法可以在不使用觸發器的情況下做到這一點?非常感謝。

這取決於您希望 CAL2 的最新程度。

如果它應該立即反映 CAL1 中的值,那麼觸發器就是要走的路。

如果它可能有幾個 mnutes 不同步,那麼您可以有一個每 5 分鐘執行一次的作業並呼叫一個同步表的儲存過程。

另一個解決方案是創建一個在 CAL1 上執行 CRUD 操作的包。更改、插入或刪除值時,呼叫的過程可以創建一個作業來更新 CAL2,或者將值插入到要傳播到訂閱者數據庫的高級隊列中。

Arwen 詢問更多細節:

有很多方法可以實現這一點,最好的方法必須考慮到您的數據庫和網路。

  • 如果 DB2 在全國范圍內,則可能會因延遲或停機而超時。如果 DB2 位於伺服器機架的另一側,那麼假設 DB1 已啟動,那麼 DB2 也將啟動,您可能會感覺更舒服。
  • 您還應該考慮 DB2 不更新的後果是什麼?這個任務是關鍵任務還是應該在 24 小時內引起注意和修復。任務關鍵型應用程序需要更堅固的解決方案。
  • 有多少交易?每天幾萬,幾千,幾百萬?硬體、網路選擇和編碼解決方案都受此影響。

讓我們從 DB1 上的範例插入開始。這應該是包的一部分

  FUNCTION CREATE_CASE (case_type_id_in   IN NUMBER,
                        created_by_in     IN NUMBER,
                        file_ref_in       IN VARCHAR2:= NULL,
                        file_title_in     IN VARCHAR2:= NULL)
     RETURN NUMBER
  IS
     /******************************************************************************
     PURPOSE: create a case of any type
     ******************************************************************************/
     c_log_case_created CONSTANT   VARCHAR2 (10) := 'LOG_1009';
     v_case_id                     NUMBER (10);
     v_file_ref                    VARCHAR2 (200);
     v_log_message                 VARCHAR2 (200);
     v_contact_date                TIMESTAMP (6) := CURRENT_TIMESTAMP;
  BEGIN

     SELECT   CASE_ID_SEQ.NEXTVAL INTO v_case_id FROM DUAL;

     INSERT INTO APPBASE.CASE (ID,
                               CASE_TYPE_ID,
                               TITLE,
                               CREATED_BY_USER_ID,
                               LAST_MODIFIED_BY_USER_ID,
                               REFERENCE_NUMBER)
       VALUES   (v_case_id,
                 case_type_id_in,
                 file_title_in,
                 created_by_in,
                 created_by_in,
                 v_file_ref);



     v_log_message := v_file_ref || ',' || v_case_id || ',';
     APP_UTIL.APP_LOG (created_by_in,
                                v_case_id,
                                c_log_case_created,
                                v_log_message);

   --notice: no commit, this is done outside the package and no error handling
   -- we want errors to bubble up to the calling application
   -- but we do want a log of what was successful
   --here is where we add the same information to an oracle advanced queue
   --the most bulletproof solution, allows the main transaction to complete
   --and the secondary insert becomes a second transaction
   QUEUE_UTIL.ADD_FILE_TO_QUEUE(case_type_id_in,v_case_id,null);
     RETURN v_case_id;
  END CREATE_CASE;

      --then in another package QUEUE_UTIL dealing with the queue
  PROCEDURE add_file_to_queue (case_type_in   IN NUMBER,
                               d_case_id_in   IN NUMBER,
                               d_other_in     IN VARCHAR2:= NULL)
  IS
     /******************************************************************************
     PURPOSE: when there is a change to a file (create, closed or reopen)   add the    change to queue of changes 
    ******************************************************************************/
     queue_options        SYS.DBMS_AQ.enqueue_options_t;
     message_properties   SYS.DBMS_AQ.message_properties_t;
     message_id           RAW (16);
     my_message           file_action;
     err_text             VARCHAR2 (2000);
     PRAGMA AUTONOMOUS_TRANSACTION;
  BEGIN
     my_message := chrcbase.file_action (case_type_in, d_case_id_in, d_other_in);
     DBMS_AQ.enqueue (queue_name           => 'CASE_QUEUE',
                      enqueue_options      => queue_options,
                      message_properties   => message_properties,
                      payload              => my_message,
                      msgid                => message_id);

     IF g_debugging
     THEN
        q$error_manager.TRACE (
           q$error_manager.MAKE_AN_INFO_MSG ('Inserted case ID'),
              'QUEUE_UTIL.ADD_FILE_TO_QUEUE '
           || ' Case '
           || d_case_id_in
           || ' action '
           || action_in
           || ' Other '
           || d_other_in,
           TRUE
        );
     END IF;

     COMMIT;
  EXCEPTION
     WHEN NO_DATA_FOUND
     THEN
        err_text := SQLERRM;

        INSERT INTO application_error_logging (
                                                          ID,
                                                          request_uri,
                                                          ERROR_CODE,
                                                          user_id,
                                                          stack_trace,
                                                          information,
                                                          TIMESTAMP
                   )
          VALUES   (
                       application_error_logging_seq.NEXTVAL,
                       'QUEUE_UTIL.add_file_to_queue',
                       NULL,
                       g_admin_id,
                          'Failed to insert case ID '
                       || d_case_id_in
                       || ' file '
                       || ' '
                       || TO_CHAR (SYSDATE, 'DD-MON-YYYY HH12:MI'),
                       'Failure:no Data ' || err_text,
                       SYSDATE
                   );

        COMMIT;
     WHEN OTHERS
     THEN
        err_text := SQLERRM;

        INSERT INTO application_error_logging (
                                                          ID,
                                                          request_uri,
                                                          ERROR_CODE,
                                                          user_id,
                                                          stack_trace,
                                                          information,
                                                          TIMESTAMP
                   )
          VALUES   (
                       application_error_logging_seq.NEXTVAL,
                       'QUEUE_UTIL.add_file_to_queue',
                       NULL,
                       g_admin_id,
                          'Failed to insert case ID '
                       || d_case_id_in
                       || ' '
                       || TO_CHAR (SYSDATE, 'DD-MON-YYYY HH12:MI'),
                       'Failure:when Others ' || err_text,
                       SYSDATE
                   );

        COMMIT;
  END add_file_to_queue;

這不是一個完整的解決方案,因為您需要為消息和隊列創建類型,並授予管理隊列的權限。解決方案的最後一部分是將消息從隊列中彈出並將更改插入 DB2。

引用自:https://dba.stackexchange.com/questions/27584