これは答えを得るのが難しい質問になるでしょう。そのため、私がこのパッケージ(これまでの私の最初のパッケージ)に取り組んできた3日間、私は尋ねることを躊躇していました。
以下は私のパッケージのスペックとボディのレイアウトです。あなたがそれを見る前に、ここに私が達成しようとしていることがあります。私はもうすぐ終わりますので、この質問があなたの時間の価値がないことを恐れる必要はありません。
コード内にも、私の個人的なメモがいくつか表示される場合があります。
私のコードは不完全で、現在コンパイルされていませんが、コンパイルが停止する前に、どちらも機能しなかったと言えます。DROPおよびCREATEプロシージャは機能します。それらに触れる必要はありません。私の主な問題は、LOG_PROC、EXCEPTIONS、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プロシージャは、終了時にこのログテーブルをチェックして、テーブルが適切にアーカイブされていないかどうかを判断する必要があります。1つのINパラメーター(今日の日付)を受け取り、ログテーブルでエラーをチェックする関数ERRORS_FOUND(ブール値を返す)を作成しました。この関数がtrueを返す場合、ARCHIVE_ALL_TABLESプロシージャはこれを考慮し、「管理者に通知する」必要があります(今のところ、これはそのままにしておきますが、最終的には、管理者に通知してNULLを配置することを示すコメントでこれを説明します。 if then終了ブロック。)
要約すると、私のパッケージ構造には、(少なくとも)次の手順が含まれている必要があります。
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;