フラッシュバッククエリーに関する検証 その4
~フラッシュバッククエリーに関する検証 その4 ~
ペンネーム ちゃむ
前回は、フラッシュバッククエリーで実際に1時間前のデータを取得できる様子
を示した。但し、データをテーブルなどに格納しようとすると、以下のように、
SQL*PLUSより実行してORA-08182が発生してしまった。
SQL> alter session set NLS_TIMESTAMP_FORMAT = 'yyyy/mm/dd hh24:mi:ss'; Session altered. SQL> execute dbms_flashback.enable_at_time('2001/12/26 12:54:44'); PL/SQL procedure successfully completed. SQL> insert into b select * from a; ORA-08182: operation not supported while in Flashback mode
今回は、このフラッシュバッククエリーで検索したデータをテーブル
などに格納する方法を説明する。また、オブジェクトの定義が変わってしまっ
たときには、どうなるのかも検証してみる。
それを実現するために使用するのは、超定番のPL/SQLである。
ポイントは、DBMS_FLASHBACK.enable_at_timeで時間してした後、カーソルに
そのデータを事前に格納しておくことと、更新処理(今回はINSERT文)を実行する前に
DBMS_FLASHBACK.DISABLE;でフラッシュバッククエリーを無効にすることである。
<PL/SQLで実現!!>
1.既にテーブルAという14行のデータが存在することを確認し、事前に空のテ
ーブルBを作成しておく。
SQL> SELECT COUNT(*) FROM A; COUNT(*) ---------- 14 SQL> CREATE TABLE B AS SELECT * FROM A WHERE 1=2; Table created. SQL> SELECT COUNT(*) FROM B; COUNT(*) ---------- 0
2.以下のPL/SQLブロックをそのまま、SQL*PLUSにコピー&ペーストで実行してみる。
------------------------ PL/SQLブロック ------------------------ DECLARE cursor A_CUR is SELECT * FROM A; A_DATA A_CUR%rowtype; BEGIN DBMS_FLASHBACK.enable_at_time(to_timestamp('2001/12/26 12:54:44', 'YYYY-MM-DD HH24:MI:SS')); /* DBMS_FLASHBACK.DISABLEをする前にカーソルをオープンしておくこと*/ OPEN A_CUR; /*INSERT 処理を行なう前に、フラッシュバッククエリーを無効にする*/ DBMS_FLASHBACK.DISABLE; LOOP FETCH A_CUR INTO A_DATA; EXIT WHEN A_CUR%NOTFOUND; INSERT INTO B VALUES(A_DATA.EMPNO,A_DATA.ENAME,A_DATA.JOB,A_DATA.MGR, A_DATA.HIREDATE,A_DATA.SAL,A_DATA.COMM,A_DATA.DEPTNO); END LOOP; COMMIT; END; / ------------------------ PL/SQLブロック ------------------------ PL/SQL procedure successfully completed.
3.テーブルBのデータの中身を確認
SQL> SELECT COUNT(*) FROM B; COUNT(*) ---------- 14
フラッシュバッククエリーの結果を別テーブルに格納できた!!
この機能を使えば、同じテーブルの現在のデータと過去のデータの
比較などもできることが想像つくであろう。
<オブジェクトの定義が変わってしまったとき>
さて、話は変わるが、テーブルが存在しないときや定義を変更してしまった場合は、
どうなるのであろうか?結果から言うとエラーが発生する。つまり、DROP TABLEして
しまった場合、フラッシュバッククエリーでは、残念ながらデータを取得できない。
ログマイナーであればORACLE9iのサプリメンタル・ロギングの機能を使用していれば、
DROP TABLEしたテーブルでも復旧できる。詳しくは、ログマイナに関する検証
その六をご覧いただきたい。
<テーブルが既にドロップされてしまった場合>
SQL> drop table a; SQL> create table a as select * from emp where 1=2; SQL> alter session set NLS_TIMESTAMP_FORMAT = 'yyyy/mm/dd hh24:mi:ss'; Session altered. SQL> execute dbms_flashback.enable_at_time('2001/12/26 12:54:44'); PL/SQL procedure successfully completed. SQL> select count(*) from a; ORA-00942: table or view does not exist
<テーブルの定義が変更された場合>
SQL> alter session set NLS_TIMESTAMP_FORMAT = 'yyyy/mm/dd hh24:mi:ss'; Session altered. SQL> execute dbms_flashback.enable_at_time('2001/12/26 12:54:44'); PL/SQL procedure successfully completed. SQL> select count(*) from a; ORA-01466: unable to read data - table definition has changed
以上 苦しいときも、悲しいときも 茅ケ崎にて