2012-08-16 74 views
1

這將會是一個難以回答的問題,這就是爲什麼我已經在這個包上工作了3天(我的第一個包),我一直在猶豫。創建包時需要第一個定時器的幫助

下面是我的包裝規格和正文的佈局。在你看這之前,我正在努力完成。我很接近完成,所以沒有必要擔心這個問題不值得你花時間。

您也可以在代碼中看到我自己的一些個人筆記。

我的代碼是不完整的,目前不編譯,但在它停止編譯之前,我可以告訴你它也沒有工作。 DROP和CREATE過程起作用。不需要接觸這些。我的主要問題是LOG_PROC,我的例外,我的ARCHIVE_ALL_TABLES ......據我所知

這裏是我想要做的事:

創建可用於「存檔」新包裝以格式「TEST_TABLE_A_13AUG2012」創建表格到歸檔表格中。這個軟件包將使用視圖我創建了一個名爲VW_TEST_TABLES其中有這樣的數據:

TEST_TABLE_A 
TEST_TABLE_B 
TEST_TABLE_C 
TEST_TABLE_D 

這項一攬子計劃將需要刪除所有先前歸檔的表,那麼創建新的之前。因此,我的包需要在其中包含DROP_ARCHIVE_TABLES和CREATE_ARCHIVE_TABLES過程。除了DROP和CREATE過程之外,我的包還有一個叫做ARCHIVE_ALL_TABLES的主要過程。這是需要調用的過程(例如調度程序)並執行實際歸檔。我需要在這些程序中包含適當的異常處理。 (例如,當我放棄時不在意桌子是否存在)。

最後,爲了正確地跟蹤每個歸檔運行,我想構建一個日誌記錄機制。爲了實現這一點,我在我的模式中建立了一個名爲TEST_PACKAGE_LOG_TBL的表。此表應具有以下列:ARCHIVE_DATE(DATE),TABLE_NAME(VARCHAR2(30)),STATUS_CODE(VARCHAR2(1)),COMMENTS(VARCHAR2(4000))。對於我存檔的每個表,我想記錄日期和表名,成功爲'S'或錯誤爲'E',如果我在表的刪除或創建中遇到錯誤,那麼SQLERRM應該是什麼被顯示。

最後,我的ARCHIVE_ALL_TABLES過程在完成時應檢查此日誌表以確定是否有任何表未正確存檔。我創建了一個函數ERRORS_FOUND(返回布爾值),它接受一個I​​N參數(今天的日期)並檢查日誌表中的錯誤。如果這個函數返回true,我的ARCHIVE_ALL_TABLES過程應該解釋這個和'通知管理員'(現在我要離開這個未觸及但最終它會簡單說明這一點與評論,說我會通知管理員和地方NULL;在所述如果然後結束塊)

總之,我的封裝結構必須含有(至少)以下過程:

ARCHIVE_ALL_TABLES, DROP_ARCHIVE_TABLE, CREATE_ARCHIVE_TABLE, ERRORS_FOUND(功能)

--package specification 
CREATE OR REPLACE PACKAGE PKG_TEST_TABLES IS 

      -- Author : 
      -- Created : 8/14/2012 8:40:18 AM 
      -- Purpose : For storing procedures to drop, create, and archive new tables 

      /* Package specification*/ 
      PROCEDURE ARCHIVE_ALL_TABLES; 
      PROCEDURE DROP_ARCHIVE_TABLES; --2nd 
      PROCEDURE CREATE_ARCHIVE_TABLES; --1st and call both from archive tables first assuming it works 
      PROCEDURE LOG_PROC 
      (
         P_PROCESS_START_TIMESTAMP TIMESTAMP 
         ,P_ARCHIVE_DATE DATE 
         ,P_TABLE_NAME VARCHAR2 
         ,P_STATUS_CODE VARCHAR2 
         ,P_COMMENTS VARCHAR2 
     ); 
      PROCEDURE W(STR VARCHAR2); 

      FUNCTION ERRORS_FOUND(P_JOB_RUN_TIMESTAMP TIMESTAMP) RETURN BOOLEAN; 

END PKG_TEST_TABLES; 


--package body 
CREATE OR REPLACE PACKAGE BODY PKG_TEST_TABLES IS 
      /* Package body*/ 

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

      /* Procedure 'W' is a wrapper for DBMS output. Placed at top of package to make globally available*/ 
      PROCEDURE W(STR VARCHAR2) IS 
         L_STRING VARCHAR2(4000); 
      BEGIN 

         L_STRING := STR; 
         DBMS_OUTPUT.PUT_LINE(STR); 
      END; 

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

      PROCEDURE DROP_ARCHIVE_TABLES AS 

         /* Purpose: For dropping previously archived tables so that new ones can be created */ 

         L_NO_TABLES_TO_DROP EXCEPTION; 
       BEGIN 
         /* Will drop previously archived tables not current ones*/ 
          FOR STMT IN (SELECT 'DROP TABLE mySchema.' || TABLE_NAME AS STR 
            FROM VW_TEST_TABLES 
            WHERE REGEXP_LIKE(TABLE_NAME, '.+[0...9]')) 
         LOOP 
             EXECUTE IMMEDIATE STMT.STR; --so that I don't need ';' at the end of each dynamically created SQL 

         END LOOP; 

         W('Done'); --put the W back in here when in package scope 

      EXCEPTION 
         WHEN L_NO_TABLES_TO_DROP THEN 
             NULL; 

      END; 

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

      PROCEDURE CREATE_ARCHIVE_TABLES AS 
      /* purpose: setting variable to equal the creation of my 4 tables. Recreating the archive tables */ 

      L_NO_TABLES_TO_CREATE EXCEPTION; 
      L_TABLES_NOT_SUCCESSFULLY_CREATED EXCEPTION; 

BEGIN 

      FOR STMT IN (SELECT 'CREATE TABLE ' || TABLE_NAME || '_' || TO_CHAR(SYSDATE, 'ddMONyyyy') || ' AS SELECT * FROM ' || TABLE_NAME AS STR 
         FROM VW_TEST_TABLES) 
      --LOG_PROC(,TO_CHAR(SYSDATE, 'ddMONyyyy') , TABLE_NAME ,'E' ,'TABLE ARCHIVED SUCCESSFULLY') 

      LOOP 
         --DBMS_OUTPUT.PUT_LINE(STMT.STR); --want to do a dbms output first before using 'execute immediate'. Hit test, and run it 
         EXECUTE IMMEDIATE STMT.STR; --so that I don't need ';' at the end of each dynamically created SQL 

      END LOOP; 

-- DBMS_OUTPUT.PUT_LINE('Done'); --put the W back in here when in package scope 

EXCEPTION 
       WHEN L_NO_TABLES_TO_CREATE THEN 
          NULL; --logging can go here 
       --can call logging procedure here for dml don't need execute immediate, just use insert into 
       WHEN L_TABLES_NOT_SUCCESSFULLY_CREATED THEN 
          NULL; --W('ERROR: ' || SQLERRM); 
END; 

--PROCEDURE IS NOT CREATING TABLES YET 

------------------------------------------------------------------------------------------------- ------------------------------------------------------------------ 
------------------------------------------------------------------------------------------------- ------------------------------------------------------------------ 
PROCEDURE LOG_PROC(P_PROCESS_START_TIMESTAMP TIMESTAMP, P_ARCHIVE_DATE DATE, P_TABLE_NAME  VARCHAR2, P_STATUS_CODE VARCHAR2, P_COMMENTS VARCHAR2) AS 

PRAGMA AUTONOMOUS_TRANSACTION; 

/* variables */ 

L_PROCESS_START_TIMESTAMP TIMESTAMP; L_ARCHIVE_DATE DATE; L_TABLE_NAME VARCHAR2(4000);  L_STATUS_CODE VARCHAR2(1); L_COMMENTS VARCHAR2(4000); 

BEGIN 

L_PROCESS_START_TIMESTAMP := P_PROCESS_START_TIMESTAMP; L_ARCHIVE_DATE := P_ARCHIVE_DATE;  L_TABLE_NAME := P_TABLE_NAME; L_STATUS_CODE := P_STATUS_CODE; L_COMMENTS := P_COMMENTS; 

INSERT INTO TEST_PACKAGE_LOG_TBL(PROCESS_START_TIMESTAMP, ARCHIVE_DATE, TABLE_NAME, STATUS_CODE,  COMMENTS) VALUES(L_PROCESS_START_TIMESTAMP, L_ARCHIVE_DATE, L_TABLE_NAME, L_STATUS_CODE, L_COMMENTS); 

RETURN; 
END; 

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

FUNCTION ERRORS_FOUND(P_JOB_RUN_TIMESTAMP TIMESTAMP) RETURN BOOLEAN IS 
L_JOB_RUN_TIMESTAMP TIMESTAMP; ERROR_COUNT NUMBER; ERROR_BOOL BOOLEAN; 
BEGIN 
L_JOB_RUN_TIMESTAMP := P_JOB_RUN_TIMESTAMP; 

SELECT COUNT(*) INTO ERROR_COUNT FROM TEST_PACKAGE_LOG_TBL WHERE STATUS_CODE = 'E' AND  PROCESS_START_TIMESTAMP = L_JOB_RUN_TIMESTAMP; IF ERROR_COUNT > 0 THEN ERROR_BOOL := TRUE; ELSE  ERROR_BOOL := FALSE; 
END IF; 

RETURN ERROR_BOOL; 
END; 
------------------------------------------------------------------------------------------------- ------------------------------------------------------------------ 
------------------------------------------------------------------------------------------------- ------------------------------------------------------------------ 

PROCEDURE ARCHIVE_ALL_TABLES AS 

/* 
          Original Author: 
          Created Date: 13-Aug-2012 
          Purpose: To drop all tables before recreating and archiving newly  created tables 
          NOTE: in package - do not use create or replace and 'as' would be  alternative to 'is' 
          */ 

/*variables*/ 
L_DROP_ARCHIVE_TABLES VARCHAR2(4000); L_SQL_CREATE_ARCHIVED_TABLES VARCHAR2(4000);  L_PREVENT_SQL_INJECTION 
EXCEPTION 
; 
--L_NOTIFY_ADMINISTRATOR VARCHAR(4000); --TO BE DONE AT A LATER TIME 

BEGIN 

RETURN; 

EXCEPTION 

WHEN L_PREVENT_SQL_INJECTION THEN NULL; 

WHEN OTHERS THEN W('ERROR: ' || SQLERRM); 

END; 

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

BEGIN 
-- Initialization 
/*archive all tables is like my 'driver' that calls drop then create while logging to the table.  Pragma_auto prevents a rollback which would prevent table logging 
       FIRST: This package will need to drop all previously archived tables before it creates new ones. call drop func first*/ 

/* calling ARCHIVE_ALL_TABLES */ 
BEGIN 
-- Call the function 
NULL; 

END; 

RETURN; 
END PKG_TEST_TABLES; 

回答

1
  1. 您的LOG_PROC是一個自主交易,所以您需要在那裏有一個COMMIT

  2. 您定義了一些例外情況,但是您不會在代碼中的任何位置將它們提升。例如,我猜你需要的是這樣的:

    PROCEDURE CREATE_ARCHIVE_TABLES AS 
        L_NO_TABLES_TO_CREATE EXCEPTION; 
        l_count number := 0; 
    BEGIN 
        FOR STMT IN (SELECT ...) 
        LOOP 
         l_count := l_count + 1; 
         EXECUTE IMMEDIATE STMT.STR; 
        END LOOP; 
        IF l_count = 0 THEN 
        RAISE L_NO_TABLES_TO_CREATE; 
        END IF; 
    EXCEPTION 
         WHEN L_NO_TABLES_TO_CREATE THEN 
            NULL; --logging can go here 
    END; 
    
+0

非常感謝你的提示 – Shades 2012-08-16 05:18:03

+0

,我會接受你的建議,並嘗試了這一點 – Shades 2012-08-16 05:18:56