這將會是一個難以回答的問題,這就是爲什麼我已經在這個包上工作了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(返回布爾值),它接受一個IN參數(今天的日期)並檢查日誌表中的錯誤。如果這個函數返回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;
非常感謝你的提示 – Shades 2012-08-16 05:18:03
,我會接受你的建議,並嘗試了這一點 – Shades 2012-08-16 05:18:56