一時表の代替

  EXECUTE IMMEDIATE で作成して削除する



コードがかなり煩雑になりますが、テーブルのフォーマットをプログラム側で決定するので、
自由度が格段に高くなります。

テーブル定義として固定される一時表は、管理者が管理するというコストがかかる上に、
追加や変更という対応を管理者に強いる事にもなります。
システムとしては仕方の無い事ですが、現場の急な運用に対応する事のほうが
重要である場合もあります。

元となる、一時表を使ったコードはこちら



  PL/SQLコード



  
PROCEDURE 代替一時表
AUTHID CURRENT_USER	-- 実行者権限

/**********************************************************/
/* 変数の定義 */
/**********************************************************/
AS
	WK_TEMPNO NUMBER := 0;
	WK_TBL VARCHAR2(100);
	WK_SQL VARCHAR2(1000);

	CURSOR cur_main IS
		SELECT * FROM 社員マスタ
			where 所属 != '1001'
			order by 給与+NVL(手当,0) desc;

	社員_REC cur_main%ROWTYPE;

	cur_sub SYS_REFCURSOR;

	WK_CNT NUMBER := 0; 
	WK_YEN NUMBER := 0; 
	WK_ROWID VARCHAR2(20); 

/**********************************************************/
/* 処理開始 */
/**********************************************************/
BEGIN

	/**********************************************************/
	/* ● 一時テーブル用の番号採取 */
	/**********************************************************/
	select 自動採番.NEXTVAL into WK_TEMPNO from dual;
	/**********************************************************/
	/* ● 一時テーブル名作成 */
	/**********************************************************/
	WK_TBL := '一時テーブル' || WK_TEMPNO;
	DBMS_OUTPUT.PUT_LINE('デバッグ:シーケンス番号:'||WK_TEMPNO);

	/**********************************************************/
	/* ● 一時テーブル作成 */
	/**********************************************************/
	WK_SQL := 'CREATE TABLE ' || WK_TBL ||
		' as SELECT * FROM 社員マスタ ' ||
		' where 1 = 2 ';
	EXECUTE IMMEDIATE WK_SQL;

	DBMS_OUTPUT.PUT_LINE('デバッグ:データ転送1開始');

	/**********************************************************/
	/* ● データ転送1 */
	/**********************************************************/
	OPEN cur_main;
	LOOP
		FETCH cur_main INTO 社員_REC;
		EXIT when cur_main%NOTFOUND;

		WK_CNT := WK_CNT + 1;
		if WK_CNT > 10 and 社員_REC.給与 + NVL(社員_REC.手当,0) != WK_YEN then
			EXIT;
		end if;

		WK_SQL := 'insert into ' || WK_TBL ||
		' (社員コード,氏名,フリガナ,所属,性別,作成日,更新日,給与,手当,管理者,生年月日)'||
		' values(
			:1
			,:2
			,:3
			,:4
			,:5
			,:6
			,NULL
			,:7
			,:8
			,:9
			,:10
		)';

		EXECUTE IMMEDIATE WK_SQL USING
			社員_REC.社員コード
			,社員_REC.氏名
			,社員_REC.フリガナ
			,社員_REC.所属
			,社員_REC.性別
			,社員_REC.作成日
			,社員_REC.給与 + NVL(社員_REC.手当,0)
			,社員_REC.手当
			,社員_REC.管理者
			,社員_REC.生年月日;

		WK_YEN := 社員_REC.給与 + NVL(社員_REC.手当,0);

	END LOOP;
	CLOSE cur_main;

	DBMS_OUTPUT.PUT_LINE('デバッグ:データ加工開始');

	/**********************************************************/
	/* ● データ加工 */
	/**********************************************************/
	WK_SQL := 	'SELECT 社員コード,ROWID FROM ' || WK_TBL;
	OPEN cur_sub for WK_SQL;
	LOOP
		FETCH cur_sub INTO 社員_REC.社員コード,WK_ROWID;
		EXIT when cur_sub%NOTFOUND;

		select count(*) into WK_CNT from 社員マスタ
			where 管理者 = 社員_REC.社員コード;
		if WK_CNT != 0 then
			社員_REC.社員コード :=
				'9' || substr(社員_REC.社員コード,2,3);
		else
			社員_REC.社員コード :=
				'5' || substr(社員_REC.社員コード,2,3);
		end if;

		WK_SQL := 'UPDATE ' || WK_TBL ||
			' set 社員コード = :1
			where ROWID = :2';
		EXECUTE IMMEDIATE WK_SQL using 社員_REC.社員コード,WK_ROWID;

	END LOOP;
	CLOSE cur_sub;

	WK_SQL := 'UPDATE ' || WK_TBL ||
		' set 更新日 = sysdate';
	EXECUTE IMMEDIATE WK_SQL;

	DBMS_OUTPUT.PUT_LINE('デバッグ:データ転送2開始');

	/**********************************************************/
	/* ● データ転送2 */
	/**********************************************************/
	WK_SQL := 'insert into 社員加工データ
		select * from ' || WK_TBL;
	EXECUTE IMMEDIATE WK_SQL;

	/**********************************************************/
	/* ● 一時テーブル削除 */
	/**********************************************************/
	WK_SQL := 'DROP TABLE ' || WK_TBL;
	EXECUTE IMMEDIATE WK_SQL;

/**********************************************************/
/* 一番外側のブロックの例外処理 */
/**********************************************************/
EXCEPTION
	WHEN OTHERS THEN
		DBMS_OUTPUT.PUT_LINE('例外発生:'||SQLCODE||':'||SQLERRM);
END;
  










  infoboard   管理者用   
このエントリーをはてなブックマークに追加





フリーフォントWEBサービス
SQLの窓WEBサービス

SQLの窓フリーソフト

素材

一般WEBツールリンク

SQLの窓

フリーソフト

JSライブラリ