技術ブログ
In-Database Archivingとは、いわゆる「データの論理削除」をOracle Databaseの機能として 実現する機能です。表に対して In-Database Archiving を有効にするとORA_ARCHIVE_STATEという名前のVARCHAR2型のhidden列が追加され、ORA_ARCHIVE_STATEが'0'以外の場合は、データは論理削除されたものとして扱われ、 SELECT文の結果に表示されません。
SQL> create table emp as select empno, ename from scott.emp; 表が作成されました。 SQL> desc emp 名前 NULL? 型 ------------ -------- -------------- 1 EMPNO NUMBER(4) 2 ENAME VARCHAR2(10) SQL> ALTER TABLE emp ROW ARCHIVAL; 表が変更されました。 SQL> SELECT * FROM emp; EMPNO ENAME ---------- ---------- 7369 SMITH 7499 ALLEN 7521 WARD 7566 JONES 7654 MARTIN 7698 BLAKE 7782 CLARK 7839 KING 7844 TURNER 7900 JAMES 7902 FORD 7934 MILLER 12行が選択されました。 SQL> UPDATE emp SET ORA_ARCHIVE_STATE = '1' WHERE empno = 7369; 1行が更新されました。 SQL> commit; コミットが完了しました。 SQL> SELECT * FROM emp; EMPNO ENAME ---------- ---------- 7499 ALLEN 7521 WARD 7566 JONES 7654 MARTIN 7698 BLAKE 7782 CLARK 7839 KING 7844 TURNER 7900 JAMES 7902 FORD 7934 MILLER 11行が選択されました。
論理削除されたデータ、すなわちORA_ARCHIVE_STATEに'0'以外の値が設定されたデータを表示したい場合は、 セッションの ROW ARCHIVAL VISIBILITY 属性を ALLに設定します。
SQL> ALTER SESSION SET ROW ARCHIVAL VISIBILITY = ALL; セッションが変更されました。 SQL> SELECT * FROM emp; EMPNO ENAME ---------- ---------- 7369 SMITH 7499 ALLEN 7521 WARD 7566 JONES 7654 MARTIN 7698 BLAKE 7782 CLARK 7839 KING 7844 TURNER 7900 JAMES 7902 FORD 7934 MILLER 12行が選択されました。
SELECTの列リストに明示的に ORA_ARCHIVE_STATE を指定すると、 ORA_ARCHIVE_STATEの値を確認できます。
SQL> ALTER SESSION SET ROW ARCHIVAL VISIBILITY = ALL; セッションが変更されました。 SQL> SELECT emp.*, ORA_ARCHIVE_STATE FROM emp; EMPNO ENAME ORA_ARCHIVE_STATE ---------- ---------- ----------------- 7369 SMITH 1 7499 ALLEN 0 7521 WARD 0 7566 JONES 0 7654 MARTIN 0 7698 BLAKE 0 7782 CLARK 0 7839 KING 0 7844 TURNER 0 7900 JAMES 0 7902 FORD 0 7934 MILLER 0 12行が選択されました。
なお、デフォルトの状態、すなわち、論理削除されたデータは見えない状態は、 ALTER SESSION SET ROW ARCHIVAL VISIBILITY = ACTIVE; を実行した状態に相当します。 どうやら、現行のセッションの ROW ARCHIVAL VISIBILITYがALLかACTIVEを確認する簡単な手段は無いようです。
ALTER SESSION SET ROW ARCHIVAL VISIBILITY = ACTIVE; を実行した状態で、 何故 ORA_ARCHIVE_STATEに'0'以外の値が設定されたデータが表示されないかが気になったので オプティマイザのトレースを取得してみました。
----- Current SQL Statement for this session (sql_id=4u5074pdutxzs) ----- SELECT * FROM emp : ===================================== SPD: BEGIN context at statement level ===================================== Stmt: ******* UNPARSED QUERY IS ******* SELECT "EMP"."EMPNO" "EMPNO","EMP"."ENAME" "ENAME","EMP"."JOB" "JOB" FROM "RYWATABE"."EMP" "EMP" WHERE "EMP"."ORA_ARCHIVE_STATE"='0' Objects referenced in the statement EMP[EMP] 92186, type = 1 Objects in the hash table Hash table Object 92186, type = 1, ownerid = 13711635127085985731: Dynamic Sampling Directives at location 1: dirid = 13742094096570570831, state = 3, flags = 1, loc = 1 {EC(92186)[5]} Return code in qosdInitDirCtx: ENBLD =================================== SPD: END context at statement level =================================== Final query after transformations:******* UNPARSED QUERY IS ******* SELECT "EMP"."EMPNO" "EMPNO","EMP"."ENAME" "ENAME","EMP"."JOB" "JOB" FROM "RYWATABE"."EMP" "EMP" WHERE "EMP"."ORA_ARCHIVE_STATE"='0' kkoqbc: optimizing query block SEL$1 (#0) : call(in-use=1296, alloc=16344), compile(in-use=71208, alloc=74720), execution(in-use=2752, alloc=4032) kkoqbc-subheap (create addr=0x7f6e0544fb60) **************** QUERY BLOCK TEXT **************** SELECT * FROM emp
"UNPARSED QUERY IS"の箇所からわかる通り、WHERE句に "EMP"."ORA_ARCHIVE_STATE"='0' が追加されていました。
では、どのような仕組みでWHERE句に条件が追加されたのかという話になりますが、ちょっとわかりませんでした。Oracle DatabaseでWHERE句に条件を追加する仕組みとしてよく知られるのは Virtual Private Database (VPD)です。この機能を活用しているのかと思い、VPDのポシリーを確認しましたが、該当するものは確認できませんでした。