001:テーブル内容比較のパッケージ

同じテーブル定義のテーブルのデータ内容を比較して違いを出力する

テーブルA(TEST_A)とテーブルB(TEST_B)を比較します

TEST_AとTEST_Bの定義
DROP TABLE TEST_A CASCADE CONSTRAINTS;

CREATE TABLE TEST_A
(
	FLD001		NUMBER		(10,0)		NOT NULL,
	FLD002		VARCHAR2	(32)				,
	CONSTRAINT PK_TEST_A PRIMARY KEY (FLD001) USING INDEX
);

DROP TABLE TEST_B CASCADE CONSTRAINTS;

CREATE TABLE TEST_B
(
	FLD001		NUMBER		(10,0)		NOT NULL,
	FLD002		VARCHAR2	(32)				,
	CONSTRAINT PK_TEST_B PRIMARY KEY (FLD001) USING INDEX
);

 

比較に使用するテーブルの定義
DROP TABLE INF_COMPARE_INPUT CASCADE CONSTRAINTS;

CREATE TABLE INF_COMPARE_INPUT
(
	SEQ				NUMBER		(10,0)		NOT NULL,
	USERID_A		VARCHAR2	(32)		NOT NULL,
	TABLE_A			VARCHAR2	(32)		NOT NULL,
	USERID_B		VARCHAR2	(32)		NOT NULL,
	TABLE_B			VARCHAR2	(32)		NOT NULL,
	FIELD_B			VARCHAR2	(32)		NOT NULL,
	FLG				NUMBER		(1,0)		DEFAULT 0,
	CONSTRAINT PK_INF_COMPARE_INPUT PRIMARY KEY (SEQ) USING INDEX
);

COMMENT ON TABLE	INF_COMPARE_INPUT				IS '比較テーブル';
COMMENT ON COLUMN	INF_COMPARE_INPUT.SEQ			IS '順番';
COMMENT ON COLUMN	INF_COMPARE_INPUT.USERID_A		IS '比較元ユーザー名';
COMMENT ON COLUMN	INF_COMPARE_INPUT.TABLE_A		IS '比較元テーブル名';
COMMENT ON COLUMN	INF_COMPARE_INPUT.USERID_B		IS '比較先ユーザー名';
COMMENT ON COLUMN	INF_COMPARE_INPUT.TABLE_B		IS '比較先テーブル名';
COMMENT ON COLUMN	INF_COMPARE_INPUT.FIELD_B		IS '比較フィールド';
COMMENT ON COLUMN	INF_COMPARE_INPUT.FLG			IS '比較対象フラグ(0:対象外,1:対象)';

 

サンプルデータをセット
TRUNCATE TABLE TEST_A;
INSERT INTO TEST_A VALUES(001,'001');
INSERT INTO TEST_A VALUES(002,'002');
INSERT INTO TEST_A VALUES(003,'003');
COMMIT;

TRUNCATE TABLE TEST_B;
INSERT INTO TEST_B VALUES(001,'001');
INSERT INTO TEST_B VALUES(003,'333');
INSERT INTO TEST_B VALUES(004,'004');
COMMIT;

TRUNCATE TABLE INF_COMPARE_INPUT;
INSERT INTO INF_COMPARE_INPUT VALUES(001,'USER_A','TEST_A','USER_B','TEST_B','FLD002',1);
COMMIT;

 

パッケージ
-- **************
-- Package Header
-- **************
CREATE OR REPLACE PACKAGE PK_COMPARE_TOOL

AS
	--Global変数
	gintRet			PLS_INTEGER;		--関数の戻り値の格納用
	gdteDate		DATE;				--パッケージの実行開始時刻を保持し、エラー発生時にテーブルに書き込む
	gintSeqErr		PLS_INTEGER;		--エラー情報書き込みごとに+1のインクリメントを行い、重複を防ぐ
	gstrErr			VARCHAR2(1000);		--エラー発生時の文字列情報を保持
	gcon_table_all	VARCHAR2(4) := '_ALL';
	gcon_table_del	VARCHAR2(4) := '_DEL';
	gcon_table_upd	VARCHAR2(4) := '_UPD';

PROCEDURE	PR_COMPARE_TABLE
(
	in_owner1		IN		VARCHAR2,
	in_table1		IN		VARCHAR2,
	in_owner2		IN		VARCHAR2,
	in_table2		IN		VARCHAR2
);
PROCEDURE	PR_CREATE_TEMP_TABLE
(
	in_owner		IN		VARCHAR2,
	in_table		IN		VARCHAR2
);
PROCEDURE	PR_ERR_INSERT
(
	in_err			IN		VARCHAR2
);
PROCEDURE	PR_INPUT_DATA_CHECK;
PROCEDURE	PR_TABLE_DATA_CHECK;
PROCEDURE	PR_MAIN;

END PK_COMPARE_TOOL;
/
SHOW ERRORS

-- ************
-- Package Body
-- ************
CREATE OR REPLACE PACKAGE BODY PK_COMPARE_TOOL
IS

--■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
--
--COMPARE実行
--
--■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
PROCEDURE	PR_COMPARE_TABLE
(
	in_owner1		IN		VARCHAR2,		--元OWNER
	in_table1		IN		VARCHAR2,		--元TABLE
	in_owner2		IN		VARCHAR2,		--先OWNER
	in_table2		IN		VARCHAR2		--先TABLE
)
IS
	strSQL			DBMS_SQL.VARCHAR2S;		--動的SQL発行のためのSQL文字列を格納
	intSQL			PLS_INTEGER;			--上の変数のPL/SQL表の添え字
	intCur			PLS_INTEGER;			--カーソル情報を保持
	intRet			PLS_INTEGER;			--関数の戻り値を保持
	intRecordCnt	PLS_INTEGER;			--レコード数を保持
	
	strOwner1		ALL_INDEXES.TABLE_OWNER%TYPE;
	strTable1		ALL_INDEXES.TABLE_NAME%TYPE;
	strOwner2		ALL_INDEXES.TABLE_OWNER%TYPE;
	strTable2		ALL_INDEXES.TABLE_NAME%TYPE;
	
	blnFlg			BOOLEAN;
	
	--フィールド名を格納するPL/SQL表の定義
	TYPE arr IS TABLE OF VARCHAR2(30) INDEX BY VARCHAR2(30);
	col_arr			arr;					--フィールド名を格納するPL/SQL表の実体

BEGIN
	DBMS_OUTPUT.PUT_LINE('START:[PR_COMPARE_TABLE]');

	--_DELと_UPD(更新後以外)を作成
	FOR intCnt IN 1 .. 2 LOOP
		--ループ@:元と先を比べて、元にあり、先にないレコードを取得する(DELのパターン)
			--INSERT INTO TEST_A_DEL
			--SELECT * FROM TEST_A A
			--WHERE NOT EXISTS (SELECT * FROM TEST_B B WHERE A.FLD001 = B.FLD001);
		--ループA:元と先を比べて、先にあり、元にないレコードを取得する(INSのパターン)
			--INSERT INTO TEST_A_INS
			--SELECT * FROM TEST_B B
			--WHERE NOT EXISTS (SELECT * FROM TEST_A A WHERE A.FLD001 = B.FLD001);
		
		--テーブル名とフィールド情報を生成
		IF intCnt = 1 THEN
			strOwner1 := in_owner1;
			strTable1 := in_table1;
			strOwner2 := in_owner2;
			strTable2 := in_table2;
		ELSE
			strOwner1 := in_owner2;
			strTable1 := in_table2;
			strOwner2 := in_owner1;
			strTable2 := in_table1;
		END IF;
		
		strSQL.DELETE();
		intSQL := 1;
		IF intCnt = 1 THEN
			strSQL(intSQL) := 'INSERT INTO ' || in_owner2 || '.' || in_table2 || gcon_table_del;
		ELSE
			strSQL(intSQL) := 'INSERT INTO ' || in_owner2 || '.' || in_table2 || gcon_table_upd;
		END IF;
		intSQL := intSQL + 1;
		strSQL(intSQL) := ' SELECT * FROM ' || strOwner1 || '.' || strTable1 || ' A';
		intSQL := intSQL + 1;
		strSQL(intSQL) := ' WHERE NOT EXISTS (SELECT * FROM ' || strOwner2 || '.' || strTable2 || ' B';
		intSQL := intSQL + 1;
		
		--WHERE句で使用するPrimaryKey情報を取得
		FOR rec IN
		(
			SELECT	IND.*
			FROM	ALL_IND_COLUMNS		IND,
					ALL_CONSTRAINTS		CST
			WHERE	IND.TABLE_OWNER			= strOwner2
			AND		IND.TABLE_NAME			= strTable2
			AND		IND.TABLE_OWNER			= CST.OWNER
			AND		IND.TABLE_NAME			= CST.TABLE_NAME
			AND		IND.INDEX_NAME			= CST.CONSTRAINT_NAME
			AND		CST.CONSTRAINT_TYPE		= 'P'
			ORDER BY
					IND.COLUMN_POSITION
		) LOOP
			IF rec.COLUMN_POSITION = 1 THEN
				strSQL(intSQL) := ' WHERE';
				intSQL := intSQL + 1;
			ELSE
				strSQL(intSQL) := ' AND';
				intSQL := intSQL + 1;
			END IF;
			strSQL(intSQL) := ' A.' || rec.COLUMN_NAME || ' = B.' || rec.COLUMN_NAME;
			intSQL := intSQL + 1;
		END LOOP;
		strSQL(intSQL) := ')';
		intSQL := intSQL + 1;

		BEGIN
			intCur := DBMS_SQL.OPEN_CURSOR;
			DBMS_SQL.PARSE(intCur,strSQL,strSQL.FIRST,strSQL.LAST,TRUE,DBMS_SQL.NATIVE);
			intRet := DBMS_SQL.EXECUTE(intCur);
			DBMS_SQL.CLOSE_CURSOR(intCur);
		EXCEPTION
			WHEN OTHERS THEN
				DBMS_OUTPUT.PUT_LINE('SQL文字列生成エラー(_DELと_UPD(更新後以外)を作成)');
				FOR intLoopCnt IN 1 .. intSQL - 1 LOOP
					DBMS_OUTPUT.PUT_LINE(strSQL(intLoopCnt));
				END LOOP;
				DBMS_OUTPUT.PUT_LINE('ERROR-Code:' || SQLCODE);
				DBMS_OUTPUT.PUT_LINE('ERROR-Str :' || SQLERRM);
				gintRet := 1;
				gstrErr := 'SQL文字列生成エラー(_DELと_UPD(更新後以外)を作成)[ERROR-Str :' || SQLERRM || ']';
				DBMS_OUTPUT.PUT_LINE(gstrErr);
				PR_ERR_INSERT(gstrErr);
				RETURN;
		END;
	END LOOP;

	--_DELを_ALLに入れる
	--INSERT INTO TEST_A_ALL SELECT 'DEL',A.* FROM TEST_A_DEL A
	strSQL.DELETE();
	intSQL := 1;
	strSQL(intSQL) := 'INSERT INTO ' || in_owner2 || '.' || in_table2 || gcon_table_all;
	intSQL := intSQL + 1;
	strSQL(intSQL) := ' SELECT ''DEL'',A.* FROM ' || in_owner2 || '.' || in_table2 || gcon_table_del || ' A';
	intSQL := intSQL + 1;

	BEGIN
		intCur := DBMS_SQL.OPEN_CURSOR;
		DBMS_SQL.PARSE(intCur,strSQL,strSQL.FIRST,strSQL.LAST,TRUE,DBMS_SQL.NATIVE);
		intRet := DBMS_SQL.EXECUTE(intCur);
		DBMS_SQL.CLOSE_CURSOR(intCur);
	EXCEPTION
		WHEN OTHERS THEN
			DBMS_OUTPUT.PUT_LINE('SQL文字列生成エラー(_DELを_ALLに入れる)');
			FOR intLoopCnt IN 1 .. intSQL - 1 LOOP
				DBMS_OUTPUT.PUT_LINE(strSQL(intLoopCnt));
			END LOOP;
			DBMS_OUTPUT.PUT_LINE('ERROR-Code:' || SQLCODE);
			DBMS_OUTPUT.PUT_LINE('ERROR-Str :' || SQLERRM);
			gintRet := 1;
			gstrErr := 'SQL文字列生成エラー(_DELを_ALLに入れる)[ERROR-Str :' || SQLERRM || ']';
			DBMS_OUTPUT.PUT_LINE(gstrErr);
			PR_ERR_INSERT(gstrErr);
			RETURN;
	END;
	
	--_UPDを_ALLに入れる
	--INSERT INTO TEST_A_ALL SELECT 'INS',A.* FROM TEST_A_UPD A
	strSQL.DELETE();
	intSQL := 1;
	strSQL(intSQL) := 'INSERT INTO ' || in_owner2 || '.' || in_table2 || gcon_table_all;
	intSQL := intSQL + 1;
	strSQL(intSQL) := ' SELECT ''INS'',A.* FROM ' || in_owner2 || '.' || in_table2 || gcon_table_upd || ' A';
	intSQL := intSQL + 1;

	BEGIN
		intCur := DBMS_SQL.OPEN_CURSOR;
		DBMS_SQL.PARSE(intCur,strSQL,strSQL.FIRST,strSQL.LAST,TRUE,DBMS_SQL.NATIVE);
		intRet := DBMS_SQL.EXECUTE(intCur);
		DBMS_SQL.CLOSE_CURSOR(intCur);
	EXCEPTION
		WHEN OTHERS THEN
			DBMS_OUTPUT.PUT_LINE('SQL文字列生成エラー(_UPDを_ALLに入れる)');
			FOR intLoopCnt IN 1 .. intSQL - 1 LOOP
				DBMS_OUTPUT.PUT_LINE(strSQL(intLoopCnt));
			END LOOP;
			DBMS_OUTPUT.PUT_LINE('ERROR-Code:' || SQLCODE);
			DBMS_OUTPUT.PUT_LINE('ERROR-Str :' || SQLERRM);
			gintRet := 1;
			gstrErr := 'SQL文字列生成エラー(_UPDを_ALLに入れる)[ERROR-Str :' || SQLERRM || ']';
			DBMS_OUTPUT.PUT_LINE(gstrErr);
			PR_ERR_INSERT(gstrErr);
			RETURN;
	END;

	--_ALL(UPDATEのみ)を作成
	strSQL.DELETE();
	intSQL := 1;
	FOR LOOP_CNT IN 1 .. 2 LOOP
		blnFlg := FALSE;
		IF LOOP_CNT = 1 THEN
			strSQL(intSQL) := 'INSERT INTO ' || in_owner2 || '.' || in_table2 || gcon_table_all;
			intSQL := intSQL + 1;
			strSQL(intSQL) := ' (SELECT ''UPD_1'',A.* FROM ' || in_owner1 || '.' || in_table1 || ' A,';
			intSQL := intSQL + 1;
			strSQL(intSQL) := in_owner2 || '.' || in_table2 || ' B WHERE ';
			intSQL := intSQL + 1;
		ELSE
			strSQL(intSQL) := 'UNION';
			intSQL := intSQL + 1;
			strSQL(intSQL) := 'SELECT ''UPD_2'',B.* FROM ' || in_owner1 || '.' || in_table1 || ' A,';
			intSQL := intSQL + 1;
			strSQL(intSQL) := in_owner2 || '.' || in_table2 || ' B WHERE ';
			intSQL := intSQL + 1;
		END IF;

		FOR rec IN
		(
			SELECT	IND.COLUMN_NAME
			FROM	ALL_IND_COLUMNS		IND,
					ALL_CONSTRAINTS		CST
			WHERE	IND.TABLE_OWNER			= in_owner1
			AND		IND.TABLE_NAME			= in_table1
			AND		IND.INDEX_NAME			= CST.INDEX_NAME
			AND		IND.INDEX_NAME			= CST.CONSTRAINT_NAME
			AND		CST.CONSTRAINT_TYPE		= 'P'
			ORDER BY
					IND.COLUMN_POSITION
		) LOOP
			col_arr(rec.COLUMN_NAME) := rec.COLUMN_NAME;
			IF blnFlg = TRUE THEN
				strSQL(intSQL) := ' AND ';
				intSQL := intSQL + 1;
			END IF;
			strSQL(intSQL) := 'A.' || rec.COLUMN_NAME || ' = B.' || rec.COLUMN_NAME;
			intSQL := intSQL + 1;
			blnFlg := TRUE;
		END LOOP;
		strSQL(intSQL) := ' AND (';
		intSQL := intSQL + 1;

		blnFlg := FALSE;
		FOR rec IN
		(
			SELECT	FIELD_B
			FROM	INF_COMPARE_INPUT
			WHERE	USERID_B	= in_owner2
			AND		TABLE_B		= in_table2
			AND		FLG = 1
			ORDER BY
					SEQ
		) LOOP
			IF col_arr.EXISTS(rec.FIELD_B) = FALSE THEN
				IF blnFlg = TRUE THEN
					strSQL(intSQL) := ' OR ';
					intSQL := intSQL + 1;
				END IF;
				strSQL(intSQL) := 'A.' || rec.FIELD_B || ' != B.' || rec.FIELD_B;
				intSQL := intSQL + 1;
				blnFlg := TRUE;
			END IF;
		END LOOP;
		IF LOOP_CNT = 1 THEN
			strSQL(intSQL) := ')';
		ELSE
			strSQL(intSQL) := '))';
		END IF;
		intSQL := intSQL + 1;
	END LOOP;
	
	BEGIN
		intCur := DBMS_SQL.OPEN_CURSOR;
		DBMS_SQL.PARSE(intCur,strSQL,strSQL.FIRST,strSQL.LAST,TRUE,DBMS_SQL.NATIVE);
		intRet := DBMS_SQL.EXECUTE(intCur);
		DBMS_SQL.CLOSE_CURSOR(intCur);
	EXCEPTION
		WHEN OTHERS THEN
			DBMS_OUTPUT.PUT_LINE('SQL文字列生成エラー(_ALL(UPDATEのみ)を作成)');
			FOR intLoopCnt IN 1 .. intSQL - 1 LOOP
				DBMS_OUTPUT.PUT_LINE(strSQL(intLoopCnt));
			END LOOP;
			DBMS_OUTPUT.PUT_LINE('ERROR-Code:' || SQLCODE);
			DBMS_OUTPUT.PUT_LINE('ERROR-Str :' || SQLERRM);
			gintRet := 1;
			gstrErr := 'SQL文字列生成エラー(_ALL(UPDATEのみ)を作成)[ERROR-Str :' || SQLERRM || ']';
			DBMS_OUTPUT.PUT_LINE(gstrErr);
			PR_ERR_INSERT(gstrErr);
			RETURN;
	END;

	--_ALLのUPD_2を_UPDに入れる
	--INSERT INTO TEST_A_UPD SELECT ---- FROM TEST_A_ALL A WHERE FIELD_FLG = 'UPD_2'
	strSQL.DELETE();
	intSQL := 1;
	strSQL(intSQL) := 'INSERT INTO ' || in_owner2 || '.' || in_table2 || gcon_table_upd;
	intSQL := intSQL + 1;
	strSQL(intSQL) := ' SELECT';
	intSQL := intSQL + 1;
	blnFlg := FALSE;
	FOR rec IN
	(
		SELECT	COLUMN_NAME
		FROM	ALL_TAB_COLUMNS
		WHERE	OWNER		= in_owner2
		AND		TABLE_NAME	= in_table2
		ORDER BY
				COLUMN_ID
	) LOOP
		IF rec.COLUMN_NAME != 'FIELD_FLG' THEN
			IF blnFlg = FALSE THEN
				strSQL(intSQL) := ' ' || rec.COLUMN_NAME;
				blnFlg := TRUE;
			ELSE
				strSQL(intSQL) := ',' || rec.COLUMN_NAME;
			END IF;
			intSQL := intSQL + 1;
		END IF;
	END LOOP;

	strSQL(intSQL) := ' FROM ' || in_owner2 || '.' || in_table2 || gcon_table_all;
	intSQL := intSQL + 1;
	strSQL(intSQL) := ' WHERE FIELD_FLG = ''UPD_2''';
	intSQL := intSQL + 1;

	BEGIN
		intCur := DBMS_SQL.OPEN_CURSOR;
		DBMS_SQL.PARSE(intCur,strSQL,strSQL.FIRST,strSQL.LAST,TRUE,DBMS_SQL.NATIVE);
		intRet := DBMS_SQL.EXECUTE(intCur);
		DBMS_SQL.CLOSE_CURSOR(intCur);
	EXCEPTION
		WHEN OTHERS THEN
			DBMS_OUTPUT.PUT_LINE('SQL文字列生成エラー(_ALLのUPD_2を_UPDに入れる)');
			FOR intLoopCnt IN 1 .. intSQL - 1 LOOP
				DBMS_OUTPUT.PUT_LINE(strSQL(intLoopCnt));
			END LOOP;
			DBMS_OUTPUT.PUT_LINE('ERROR-Code:' || SQLCODE);
			DBMS_OUTPUT.PUT_LINE('ERROR-Str :' || SQLERRM);
			gintRet := 1;
			gstrErr := 'SQL文字列生成エラー(_ALLのUPD_2を_UPDに入れる)[ERROR-Str :' || SQLERRM || ']';
			DBMS_OUTPUT.PUT_LINE(gstrErr);
			PR_ERR_INSERT(gstrErr);
			RETURN;
	END;
	
	COMMIT;
	
	/*
	FOR intLoopCnt IN 1 .. 3 LOOP
		CASE intLoopCnt
			WHEN 1 THEN
				strTable0 := gcon_table_all;
			WHEN 2 THEN
				strTable0 := gcon_table_del;
			WHEN 3 THEN
				strTable0 := gcon_table_upd;
		END CASE;
		
		strSQL.DELETE();
		intSQL := 1;
		strSQL(intSQL) := 'SELECT COUNT(*) FROM ' || in_owner2 || '.' || in_table2 || strTable0;
		intSQL := intSQL + 1;
		intCur := DBMS_SQL.OPEN_CURSOR;
		DBMS_SQL.PARSE(intCur,strSQL,strSQL.FIRST,strSQL.LAST,TRUE,DBMS_SQL.NATIVE);
		intRet := DBMS_SQL.EXECUTE(intCur);
		DBMS_SQL.DEFINE_COLUMN(intCur,1,intRecordCnt);
		DBMS_SQL.CLOSE_CURSOR(intCur);
		DBMS_OUTPUT.PUT_LINE(strSQL(1));
		DBMS_OUTPUT.PUT_LINE('レコード数(' || in_owner2 || '.' || in_table2 || strTable0 || '):[' || TO_CHAR(intRecordCnt,'00000') || ']');
	END LOOP;
	*/
	
	DBMS_OUTPUT.PUT_LINE('END  :[PR_COMPARE_TABLE]');

EXCEPTION
	WHEN OTHERS THEN
		DBMS_OUTPUT.PUT_LINE('ERROR-Code:' || SQLCODE);
		DBMS_OUTPUT.PUT_LINE('ERROR-Str :' || SQLERRM);

END PR_COMPARE_TABLE;

--■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
--
--格納用テーブル作成
--
--■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
PROCEDURE	PR_CREATE_TEMP_TABLE
(
	in_owner		IN		VARCHAR2,
	in_table		IN		VARCHAR2
)
IS
	strTruncTable	VARCHAR2(100);
	strSQL_ALL		DBMS_SQL.VARCHAR2S;
	intIdx_ALL		PLS_INTEGER;
	strSQL_DEL		DBMS_SQL.VARCHAR2S;
	intIdx_DEL		PLS_INTEGER;
	strSQL_UPD		DBMS_SQL.VARCHAR2S;
	intIdx_UPD		PLS_INTEGER;
	
	strTmpField		VARCHAR2(100);

	strTmpIdx_ALL	VARCHAR2(100);
	strTmpIdx_DEL	VARCHAR2(100);
	strTmpIdx_UPD	VARCHAR2(100);
	
	intCur			PLS_INTEGER;
	intRet			PLS_INTEGER;

BEGIN
	DBMS_OUTPUT.PUT_LINE('START:[PR_CREATE_TEMP_TABLE]');

	--CREATE TABLE TEST001
	--(
	--	FIELD001                       NUMBER(3,0) NOT NULL,
	--	FIELD002                       NUMBER(5,0) NOT NULL,
	--	FIELD003                       VARCHAR2(32),
	--	FIELD004                       VARCHAR2(32),
	--	FIELD005                       DATE,
	--)
	--テーブル名とフィールド情報を生成
	FOR rec IN
	(
		SELECT	*
		FROM	ALL_TAB_COLUMNS
		WHERE	OWNER		= in_owner
		AND		TABLE_NAME	= in_table
		ORDER BY
				COLUMN_ID
	) LOOP
		IF rec.COLUMN_ID = 1 THEN
			--EXECUTE IMMEDIATE 'DROP TABLE TEST001_0 CASCADE CONSTRAINTS';
			BEGIN
				strTruncTable := 'DROP TABLE ' || rec.OWNER || '.' || rec.TABLE_NAME || gcon_table_all || ' CASCADE CONSTRAINTS';
				--DBMS_OUTPUT.PUT_LINE(strTruncTable);
				EXECUTE IMMEDIATE strTruncTable;
			EXCEPTION
				WHEN OTHERS THEN
					gstrErr := '削除すべきテーブルがないが、問題なし[' || strTruncTable || ']';
					DBMS_OUTPUT.PUT_LINE(gstrErr);
					PR_ERR_INSERT(gstrErr);
			END;
			
			BEGIN
				strTruncTable := 'DROP TABLE ' || rec.OWNER || '.' || rec.TABLE_NAME || gcon_table_del || ' CASCADE CONSTRAINTS';
				--DBMS_OUTPUT.PUT_LINE(strTruncTable);
				EXECUTE IMMEDIATE strTruncTable;
			EXCEPTION
				WHEN OTHERS THEN
					gstrErr := '削除すべきテーブルがないが、問題なし[' || strTruncTable || ']';
					DBMS_OUTPUT.PUT_LINE(gstrErr);
					PR_ERR_INSERT(gstrErr);
			END;

			BEGIN
				strTruncTable := 'DROP TABLE ' || rec.OWNER || '.' || rec.TABLE_NAME || gcon_table_upd || ' CASCADE CONSTRAINTS';
				--DBMS_OUTPUT.PUT_LINE(strTruncTable);
				EXECUTE IMMEDIATE strTruncTable;
			EXCEPTION
				WHEN OTHERS THEN
					gstrErr := '削除すべきテーブルがないが、問題なし[' || strTruncTable || ']';
					DBMS_OUTPUT.PUT_LINE(gstrErr);
					PR_ERR_INSERT(gstrErr);
			END;

			strSQL_ALL.DELETE();
			strSQL_DEL.DELETE();
			strSQL_UPD.DELETE();
			intIdx_ALL := 1;
			intIdx_DEL := 1;
			intIdx_UPD := 1;
			strSQL_ALL(intIdx_ALL) := 'CREATE TABLE ' || rec.OWNER || '.' || rec.TABLE_NAME || gcon_table_all;
			intIdx_ALL := intIdx_ALL + 1;
			strSQL_ALL(intIdx_ALL) := '( ';
			intIdx_ALL := intIdx_ALL + 1;
			strSQL_ALL(intIdx_ALL) := ' FIELD_FLG VARCHAR2(10) NOT NULL,';
			intIdx_ALL := intIdx_ALL + 1;
			strSQL_DEL(intIdx_DEL) := 'CREATE TABLE ' || rec.OWNER || '.' || rec.TABLE_NAME || gcon_table_del;
			intIdx_DEL := intIdx_DEL + 1;
			strSQL_DEL(intIdx_DEL) := '( ';
			intIdx_DEL := intIdx_DEL + 1;
			strSQL_UPD(intIdx_UPD) := 'CREATE TABLE ' || rec.OWNER || '.' || rec.TABLE_NAME || gcon_table_upd;
			intIdx_UPD := intIdx_UPD + 1;
			strSQL_UPD(intIdx_UPD) := '( ';
			intIdx_UPD := intIdx_UPD + 1;
		END IF;
		strTmpField := '';
		strTmpField := strTmpField || ' ' || rec.COLUMN_NAME;
		CASE rec.DATA_TYPE
			WHEN 'NUMBER' THEN
				strTmpField := strTmpField || ' ' || rec.DATA_TYPE;
				strTmpField := strTmpField || ' (' || rec.DATA_PRECISION;
				strTmpField := strTmpField || '.' || rec.DATA_SCALE;
				strTmpField := strTmpField || ')';
			WHEN 'VARCHAR2' THEN
				strTmpField := strTmpField || ' ' || rec.DATA_TYPE;
				strTmpField := strTmpField || ' (' || rec.DATA_LENGTH;
				strTmpField := strTmpField || ')';
			WHEN 'DATE' THEN
				strTmpField := strTmpField || ' ' || rec.DATA_TYPE;
			ELSE
				gintRet := 1;
				gstrErr := 'テーブルの型情報の対応が足りていません!!型情報:[' || rec.DATA_TYPE || ']';
				DBMS_OUTPUT.PUT_LINE(gstrErr);
				PR_ERR_INSERT(gstrErr);
				RETURN;
		END CASE;
		IF rec.NULLABLE = 'N' THEN
			strTmpField := strTmpField || ' NOT NULL';
		END IF;
		strTmpField := strTmpField || ',';
		
		strSQL_ALL(intIdx_ALL) := strTmpField;
		intIdx_ALL := intIdx_ALL + 1;
		strSQL_DEL(intIdx_DEL) := strTmpField;
		intIdx_DEL := intIdx_DEL + 1;
		strSQL_UPD(intIdx_UPD) := strTmpField;
		intIdx_UPD := intIdx_UPD + 1;
	END LOOP;

	--CONSTRAINT PK_TEST001 PRIMARY KEY (FIELD001, FIELD002) USING INDEX
	--インデックス情報を生成
	FOR rec IN
	(
		SELECT	ICM.*
		FROM	ALL_IND_COLUMNS		ICM,
				ALL_INDEXES			IND
		WHERE	IND.TABLE_OWNER	=	in_owner
		AND		IND.TABLE_NAME	=	in_table
		AND		IND.UNIQUENESS	=	'UNIQUE'
		AND		IND.TABLE_OWNER	=	ICM.TABLE_OWNER
		AND		IND.TABLE_NAME	=	ICM.TABLE_NAME
		AND		IND.INDEX_NAME	=	ICM.INDEX_NAME
		ORDER BY
				ICM.COLUMN_POSITION
	) LOOP
		IF rec.COLUMN_POSITION = 1 THEN
			strTmpIdx_ALL := '';
			strTmpIdx_ALL := strTmpIdx_ALL || ' CONSTRAINT';
			strTmpIdx_ALL := strTmpIdx_ALL || ' ' || rec.INDEX_NAME || gcon_table_all;
			strTmpIdx_ALL := strTmpIdx_ALL || ' PRIMARY KEY';
			strTmpIdx_ALL := strTmpIdx_ALL || ' (';

			strTmpIdx_DEL := '';
			strTmpIdx_DEL := strTmpIdx_DEL || ' CONSTRAINT';
			strTmpIdx_DEL := strTmpIdx_DEL || ' ' || rec.INDEX_NAME || gcon_table_del;
			strTmpIdx_DEL := strTmpIdx_DEL || ' PRIMARY KEY';
			strTmpIdx_DEL := strTmpIdx_DEL || ' (';

			strTmpIdx_UPD := '';
			strTmpIdx_UPD := strTmpIdx_UPD || ' CONSTRAINT';
			strTmpIdx_UPD := strTmpIdx_UPD || ' ' || rec.INDEX_NAME || gcon_table_upd;
			strTmpIdx_UPD := strTmpIdx_UPD || ' PRIMARY KEY';
			strTmpIdx_UPD := strTmpIdx_UPD || ' (';
		ELSE
			strTmpIdx_ALL := strTmpIdx_ALL || ',';
			strTmpIdx_DEL := strTmpIdx_DEL || ',';
			strTmpIdx_UPD := strTmpIdx_UPD || ',';
		END IF;
		strTmpIdx_ALL := strTmpIdx_ALL || rec.COLUMN_NAME;
		strTmpIdx_DEL := strTmpIdx_DEL || rec.COLUMN_NAME;
		strTmpIdx_UPD := strTmpIdx_UPD || rec.COLUMN_NAME;
	END LOOP;
	strTmpIdx_ALL := strTmpIdx_ALL || ',FIELD_FLG';
	strTmpIdx_ALL := strTmpIdx_ALL || ')';
	strTmpIdx_ALL := strTmpIdx_ALL || ' USING INDEX';
	strTmpIdx_ALL := strTmpIdx_ALL || ')';

	strTmpIdx_DEL := strTmpIdx_DEL || ')';
	strTmpIdx_DEL := strTmpIdx_DEL || ' USING INDEX';
	strTmpIdx_DEL := strTmpIdx_DEL || ')';

	strTmpIdx_UPD := strTmpIdx_UPD || ')';
	strTmpIdx_UPD := strTmpIdx_UPD || ' USING INDEX';
	strTmpIdx_UPD := strTmpIdx_UPD || ')';

	strSQL_ALL(intIdx_ALL) := strTmpIdx_ALL;
	intIdx_ALL := intIdx_ALL + 1;
	strSQL_DEL(intIdx_DEL) := strTmpIdx_DEL;
	intIdx_DEL := intIdx_DEL + 1;
	strSQL_UPD(intIdx_UPD) := strTmpIdx_UPD;
	intIdx_UPD := intIdx_UPD + 1;

	--_ALL作成
	BEGIN
		intCur := DBMS_SQL.OPEN_CURSOR;
		DBMS_SQL.PARSE(intCur,strSQL_ALL,strSQL_ALL.FIRST,strSQL_ALL.LAST,TRUE,DBMS_SQL.NATIVE);
		intRet := DBMS_SQL.EXECUTE(intCur);
		DBMS_SQL.CLOSE_CURSOR(intCur);
	EXCEPTION
		WHEN OTHERS THEN
			DBMS_OUTPUT.PUT_LINE('SQL文字列生成エラー(_ALL作成)');
			FOR intLoopCnt IN 1 .. intIdx_ALL - 1 LOOP
				DBMS_OUTPUT.PUT_LINE(strSQL_ALL(intLoopCnt));
			END LOOP;
			DBMS_OUTPUT.PUT_LINE('ERROR-Code:' || SQLCODE);
			DBMS_OUTPUT.PUT_LINE('ERROR-Str :' || SQLERRM);
			gintRet := 1;
			gstrErr := 'SQL文字列生成エラー(_ALL作成)[ERROR-Str :' || SQLERRM || ']';
			DBMS_OUTPUT.PUT_LINE(gstrErr);
			PR_ERR_INSERT(gstrErr);
			RETURN;
	END;
	
	--_DEL作成
	BEGIN
		intCur := DBMS_SQL.OPEN_CURSOR;
		DBMS_SQL.PARSE(intCur,strSQL_DEL,strSQL_DEL.FIRST,strSQL_DEL.LAST,TRUE,DBMS_SQL.NATIVE);
		intRet := DBMS_SQL.EXECUTE(intCur);
		DBMS_SQL.CLOSE_CURSOR(intCur);
	EXCEPTION
		WHEN OTHERS THEN
			DBMS_OUTPUT.PUT_LINE('SQL文字列生成エラー(_DEL作成)');
			FOR intLoopCnt IN 1 .. intIdx_DEL - 1 LOOP
				DBMS_OUTPUT.PUT_LINE(strSQL_DEL(intLoopCnt));
			END LOOP;
			DBMS_OUTPUT.PUT_LINE('ERROR-Code:' || SQLCODE);
			DBMS_OUTPUT.PUT_LINE('ERROR-Str :' || SQLERRM);
			gintRet := 1;
			gstrErr := 'SQL文字列生成エラー(_DEL作成)[ERROR-Str :' || SQLERRM || ']';
			DBMS_OUTPUT.PUT_LINE(gstrErr);
			PR_ERR_INSERT(gstrErr);
			RETURN;
	END;
	
	--_UPD作成
	BEGIN
		intCur := DBMS_SQL.OPEN_CURSOR;
		DBMS_SQL.PARSE(intCur,strSQL_UPD,strSQL_UPD.FIRST,strSQL_UPD.LAST,TRUE,DBMS_SQL.NATIVE);
		intRet := DBMS_SQL.EXECUTE(intCur);
		DBMS_SQL.CLOSE_CURSOR(intCur);
	EXCEPTION
		WHEN OTHERS THEN
			DBMS_OUTPUT.PUT_LINE('SQL文字列生成エラー(_UPD作成)');
			FOR intLoopCnt IN 1 .. intIdx_UPD - 1 LOOP
				DBMS_OUTPUT.PUT_LINE(strSQL_UPD(intLoopCnt));
			END LOOP;
			DBMS_OUTPUT.PUT_LINE('ERROR-Code:' || SQLCODE);
			DBMS_OUTPUT.PUT_LINE('ERROR-Str :' || SQLERRM);
			gintRet := 1;
			gstrErr := 'SQL文字列生成エラー(_UPD作成)[ERROR-Str :' || SQLERRM || ']';
			DBMS_OUTPUT.PUT_LINE(gstrErr);
			PR_ERR_INSERT(gstrErr);
			RETURN;
	END;

	DBMS_OUTPUT.PUT_LINE('END  :[PR_CREATE_TEMP_TABLE]');

EXCEPTION
	WHEN OTHERS THEN
		DBMS_OUTPUT.PUT_LINE('ERROR-Code:' || SQLCODE);
		DBMS_OUTPUT.PUT_LINE('ERROR-Str :' || SQLERRM);

END PR_CREATE_TEMP_TABLE;

--■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
--
--テーブルデータのチェックのメインルーチン
--
--■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
PROCEDURE PR_TABLE_DATA_CHECK
IS

BEGIN
	DBMS_OUTPUT.PUT_LINE('START:[PR_TABLE_DATA_CHECK]');

	FOR rec IN
	(
		SELECT	DISTINCT USERID_A,TABLE_A,USERID_B,TABLE_B
		FROM	INF_COMPARE_INPUT
		WHERE	FLG = 1
	) LOOP
		--差分格納用テーブルを作成
		--DBMS_OUTPUT.PUT_LINE('TABLE_NAME:[' || rec.TABLE_B || ']');
		PR_CREATE_TEMP_TABLE(rec.USERID_B,rec.TABLE_B);
		IF gintRet != 0 THEN
			RETURN;
		END IF;
		
		--データを比較する
		PR_COMPARE_TABLE(rec.USERID_A,rec.TABLE_A,rec.USERID_B,rec.TABLE_B);
		IF gintRet != 0 THEN
			RETURN;
		END IF;
		
	END LOOP;

	DBMS_OUTPUT.PUT_LINE('END  :[PR_TABLE_DATA_CHECK]');

EXCEPTION
	WHEN OTHERS THEN
		DBMS_OUTPUT.PUT_LINE('ERROR-Code:' || SQLCODE);
		DBMS_OUTPUT.PUT_LINE('ERROR-Str :' || SQLERRM);

END PR_TABLE_DATA_CHECK;

--■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
--
--エラー情報書き込み
--
--■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
PROCEDURE PR_ERR_INSERT
(
	in_err			IN		VARCHAR2
)
IS

BEGIN
	gintSeqErr := gintSeqErr + 1;
	INSERT INTO INF_COMPARE_ERROR
	(
		START_DATE,
		SEQ,
		ERROR_STRING
	) VALUES 
	(
		gdteDate,
		gintSeqErr,
		in_err
	);
	COMMIT;

EXCEPTION
	WHEN OTHERS THEN
		DBMS_OUTPUT.PUT_LINE('ERROR-Code:' || SQLCODE);
		DBMS_OUTPUT.PUT_LINE('ERROR-Str :' || SQLERRM);

END PR_ERR_INSERT;

--■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
--
--入力情報として渡されるINF_COMPARE_INPUTの内容を精査
--
--■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
PROCEDURE PR_INPUT_DATA_CHECK
IS
	strOwner0		ALL_TABLES.OWNER%TYPE;
	strTable0		ALL_TABLES.TABLE_NAME%TYPE;
	rowRecord1		ALL_TAB_COLUMNS%ROWTYPE;
	rowRecord2		ALL_TAB_COLUMNS%ROWTYPE;
	
	intColCnt1		PLS_INTEGER;
	intColCnt2		PLS_INTEGER;
	
BEGIN
	DBMS_OUTPUT.PUT_LINE('START:[PR_INPUT_DATA_CHECK]');

	--テーブル名チェック
	FOR rec IN
	(
		SELECT	DISTINCT USERID_A,
				TABLE_A,
				USERID_B,
				TABLE_B
		FROM	INF_COMPARE_INPUT
		WHERE	FLG = 1
	) LOOP
		strOwner0 := '';
		strTable0 := '';
		BEGIN
			--テーブルが存在するかどうかをチェック
			SELECT	OWNER,
					TABLE_NAME
			INTO	strOwner0,
					strTable0
			FROM	ALL_TABLES
			WHERE	OWNER = rec.USERID_A
			AND		TABLE_NAME = rec.TABLE_A;
		EXCEPTION
			WHEN OTHERS THEN
				gintRet := 1;
				gstrErr := '元テーブルの指定を間違えています!!テーブル情報:[' || rec.USERID_A || '.' || rec.TABLE_A || ']';
				DBMS_OUTPUT.PUT_LINE(gstrErr);
				PR_ERR_INSERT(gstrErr);
		END;
	
		strOwner0 := '';
		strTable0 := '';
		BEGIN
			--テーブルが存在するかどうかをチェック
			SELECT	OWNER,
					TABLE_NAME
			INTO	strOwner0,
					strTable0
			FROM	ALL_TABLES
			WHERE	OWNER = rec.USERID_B
			AND		TABLE_NAME = rec.TABLE_B;
		EXCEPTION
			WHEN OTHERS THEN
				gintRet := 1;
				gstrErr := '先テーブルの指定を間違えています!!テーブル情報:[' || rec.USERID_B || '.' || rec.TABLE_B || ']';
				DBMS_OUTPUT.PUT_LINE(gstrErr);
				PR_ERR_INSERT(gstrErr);
		END;
		
		--元テーブルのカラム数を数える
		SELECT	COUNT('X')
		INTO	intColCnt1
		FROM	ALL_TAB_COLUMNS
		WHERE	OWNER = rec.USERID_A
		AND		TABLE_NAME = rec.TABLE_A;

		--先テーブルのカラム数を数える
		SELECT	COUNT('X')
		INTO	intColCnt2
		FROM	ALL_TAB_COLUMNS
		WHERE	OWNER = rec.USERID_B
		AND		TABLE_NAME = rec.TABLE_B;

		IF intColCnt1 != intColCnt2 THEN
			gintRet := 1;
			gstrErr := 'フィールド数が違います!!テーブル情報:[' || rec.USERID_A || '.' || rec.TABLE_A || ']';
			DBMS_OUTPUT.PUT_LINE(gstrErr);
			PR_ERR_INSERT(gstrErr);
		END IF;
		
	END LOOP;

	IF gintRet != 0 THEN
		RETURN;
	END IF;
	
	--フィールドチェック
	FOR rec IN
	(
		SELECT	*
		FROM	INF_COMPARE_INPUT
		WHERE	FLG = 1
	) LOOP
		BEGIN
			SELECT	*
			INTO	rowRecord1
			FROM	ALL_TAB_COLUMNS
			WHERE	OWNER = rec.USERID_A
			AND		TABLE_NAME = rec.TABLE_A
			AND		COLUMN_NAME = rec.FIELD_B;
		EXCEPTION
			WHEN OTHERS THEN
				gintRet := 1;
				gstrErr := '元テーブルのフィールド名指定が間違えています!!フィールド情報:[' || rec.USERID_A || '.' || rec.TABLE_A || '.' || rec.FIELD_B || ']';
				DBMS_OUTPUT.PUT_LINE(gstrErr);
				PR_ERR_INSERT(gstrErr);
		END;
		
		BEGIN
			SELECT	*
			INTO	rowRecord2
			FROM	ALL_TAB_COLUMNS
			WHERE	OWNER = rec.USERID_B
			AND		TABLE_NAME = rec.TABLE_B
			AND		COLUMN_NAME = rec.FIELD_B;
		EXCEPTION
			WHEN OTHERS THEN
				gintRet := 1;
				gstrErr := '先テーブルのフィールド名指定が間違えています!!フィールド情報:[' || rec.USERID_B || '.' || rec.TABLE_B || '.' || rec.FIELD_B || ']';
				DBMS_OUTPUT.PUT_LINE(gstrErr);
				PR_ERR_INSERT(gstrErr);
		END;

		IF rowRecord1.DATA_TYPE != rowRecord2.DATA_TYPE THEN
			gintRet := 1;
			gstrErr := '比較するフィールドのデータ型が違います!!フィールド情報:[' || rec.USERID_A || '.' || rec.TABLE_A || '.' || rec.FIELD_B || ']';
			DBMS_OUTPUT.PUT_LINE(gstrErr);
			PR_ERR_INSERT(gstrErr);
		END IF;
		
		IF rowRecord1.DATA_LENGTH != rowRecord2.DATA_LENGTH THEN
			gintRet := 1;
			gstrErr := '比較するフィールドのデータ長が違います!!フィールド情報:[' || rec.USERID_A || '.' || rec.TABLE_A || '.' || rec.FIELD_B || ']';
			DBMS_OUTPUT.PUT_LINE(gstrErr);
			PR_ERR_INSERT(gstrErr);
		END IF;

		IF rowRecord1.COLUMN_ID != rowRecord2.COLUMN_ID THEN
			gintRet := 1;
			gstrErr := '比較するフィールドのフィールド位置が違います!!フィールド情報:[' || rec.USERID_A || '.' || rec.TABLE_A || '.' || rec.FIELD_B || ']';
			DBMS_OUTPUT.PUT_LINE(gstrErr);
			PR_ERR_INSERT(gstrErr);
		END IF;
	END LOOP;

	DBMS_OUTPUT.PUT_LINE('END  :[PR_INPUT_DATA_CHECK]');

EXCEPTION
	WHEN OTHERS THEN
		DBMS_OUTPUT.PUT_LINE('ERROR-Code:' || SQLCODE);
		DBMS_OUTPUT.PUT_LINE('ERROR-Str :' || SQLERRM);

END PR_INPUT_DATA_CHECK;

--■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
--
--メインロジック(ここから開始)
--
--■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
PROCEDURE PR_MAIN
IS
	dteDate1		TIMESTAMP;
	dteDate2		TIMESTAMP;
	dteDate3		INTERVAL DAY TO SECOND;

BEGIN
	dteDate1 := CURRENT_TIMESTAMP;
	gdteDate:= SYSDATE;
	DBMS_OUTPUT.PUT_LINE('START:[' || TO_CHAR(dteDate1,'YYYY/MM/DD HH24:MI:SS.FF3') || ']');
	
	DBMS_OUTPUT.PUT_LINE('START:[PR_MAIN]');
	gintRet := 0;
	gintSeqErr := 0;
	
	--入力情報のチェック
	PR_INPUT_DATA_CHECK;
	IF gintRet != 0 THEN
		DBMS_OUTPUT.PUT_LINE('入力情報に誤りがあります');
	END IF;
	
	--データチェック
	IF gintRet = 0 THEN
		PR_TABLE_DATA_CHECK;
	END IF;
	
	DBMS_OUTPUT.PUT_LINE('END  :[PR_MAIN]');

	dteDate2 := CURRENT_TIMESTAMP;
	DBMS_OUTPUT.PUT_LINE('END  :[' || TO_CHAR(dteDate2,'YYYY/MM/DD HH24:MI:SS.FF3') || ']');

	dteDate3 := dteDate2 - dteDate1;
	DBMS_OUTPUT.PUT_LINE('DIFF :[' || TO_CHAR(dteDate3,'YYYY/MM/DD HH24:MI:SS.FF3') || ']');

EXCEPTION
	WHEN OTHERS THEN
		DBMS_OUTPUT.PUT_LINE('ERROR-Code:' || SQLCODE);
		DBMS_OUTPUT.PUT_LINE('ERROR-Str :' || SQLERRM);

END PR_MAIN;

END PK_COMPARE_TOOL;
/
SHOW ERRORS

 

sqlplusから実行
@PK_COMPARE_TOOL
SET SERVEROUTPUT ON SIZE 1000000
EXEC PK_COMPARE_TOOL.PR_MAIN;

実行結果

SQL> @start

パッケージが作成されました。

エラーはありません。

パッケージ本体が作成されました。

エラーはありません。
START:[2006/04/03 16:41:16.484]
START:[PR_MAIN]
START:[PR_INPUT_DATA_CHECK]
END  :[PR_INPUT_DATA_CHECK]
START:[PR_TABLE_DATA_CHECK]
START:[PR_CREATE_TEMP_TABLE]
END  :[PR_CREATE_TEMP_TABLE]
START:[PR_COMPARE_TABLE]
END  :[PR_COMPARE_TABLE]
END  :[PR_TABLE_DATA_CHECK]
END  :[PR_MAIN]
END  :[2006/04/03 16:41:17.234]
DIFF :[+000000 00:00:00.750000000]

PL/SQLプロシージャが正常に完了しました。

SQL>

 

正常終了すると[TEST_B_ALL],[TEST_B_DEL],[TEST_B_UPD]という3つのテーブルが作成されて、その中にそれぞれ値が格納されている