技術ブログ
先のエントリで記載したとおり、In-Database Archivingを有効にすると、 ORA_ARCHIVE_STATEという名前のVARCHAR2型のhidden列が追加され、ORA_ARCHIVE_STATEが'0'以外の場合は、データは論理削除されたものとして扱われ、SELECT文の結果に表示されません。
しかしこれ以外にもhidden列が追加されています。
SQL> SELECT column_name, data_type, hidden_column, virtual_column, user_generated 2 FROM USER_TAB_COLS WHERE table_name = 'EMP' ORDER BY INTERNAL_COLUMN_ID; COLUMN_NAME DATA_TYP HID VIR USE -------------------- -------- --- --- --- EMPNO NUMBER NO NO YES ENAME VARCHAR2 NO NO YES SYS_NC00003$ RAW YES NO NO <== ORA_ARCHIVE_STATE VARCHAR2 YES NO NO
SYS_??? という名前と、USER_TAB_COLS の user_generated列が'NO'であることからわかる通り、この列はシステム生成された列です。
SQL> SELECT emp.*, SYS_NC00003$, ORA_ARCHIVE_STATE FROM emp;
EMPNO ENAME SYS_NC00003$ ORA_ARCHIVE_STATE
---------- ---------- ------------ -----------------
7369 SMITH 01 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行が選択されました。
検証した限りでは、初期状態では値はNULLであり、ORA_ARCHIVE_STATEに何らかの更新を加えると01という値を持つようです。
なお、実行計画を取得すると、このシステム生成列にアクセスしていることがわかります。
SQL> SELECT * FROM table(DBMS_XPLAN.DISPLAY_CURSOR());
PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------
SQL_ID 4u5074pdutxzs, child number 0
-------------------------------------
SELECT * FROM emp
Plan hash value: 3956160932
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 3 (100)| |
|* 1 | TABLE ACCESS FULL| EMP | 1 | 20 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(DECODE(TO_CHAR(SYS_OP_VECBIT("SYS_NC00003$",0)),NULL,NVL("
EMP"."ORA_ARCHIVE_STATE",'0'),'0',NVL("EMP"."ORA_ARCHIVE_STATE",'0'),'1'
,"EMP"."ORA_ARCHIVE_STATE")='0')
20行が選択されました。
Predicate Informationに記載されたfilter条件のDECODEをわかりやすく書き換えると 以下のようになります。
DECODE(TO_CHAR(SYS_OP_VECBIT("SYS_NC00003$",0)),
NULL, NVL("EMP"."ORA_ARCHIVE_STATE",'0'),
'0', NVL("EMP"."ORA_ARCHIVE_STATE",'0'),
'1', "EMP"."ORA_ARCHIVE_STATE")
システム生成列 SYS_NCnnnnn$ が
NULL or 0 → NVL(ORA_ARCHIVE_STATE,'0')
ORA_ARCHIVE_STATEが非NULLの場合 ORA_ARCHIVE_STATE
ORA_ARCHIVE_STATEがNULLの場合 '0'
1 → ORA_ARCHIVE_STATE
このDECODEの結果を'0'と比較することで、ORA_ARCHIVE_STATEが'0'以外のデータを検索結果から除外しています。
このシステム生成列、表の作成時にROW ARCHIVALを指定すると作成されないようです。
SQL> CREATE TABLE EMP 2 ( "EMPNO" NUMBER(4,0), 3 "ENAME" VARCHAR2(10) 4 ) ROW ARCHIVAL; 表が作成されました。 SQL> col column_name format a20 SQL> col data_type format a8 SQL> SELECT column_name, data_type, hidden_column, virtual_column, user_generated 2 FROM USER_TAB_COLS WHERE table_name = 'EMP' ORDER BY INTERNAL_COLUMN_ID; COLUMN_NAME DATA_TYP HID VIR USE -------------------- -------- --- --- --- ORA_ARCHIVE_STATE VARCHAR2 YES NO NO EMPNO NUMBER NO NO YES ENAME VARCHAR2 NO NO YES
しかし、既存の表にROW ARCHIVALを指定すると作成されるようです。
SQL> ALTER TABLE emp NO ROW ARCHIVAL; 表が変更されました。 SQL> SELECT column_name, data_type, hidden_column, virtual_column, user_generated 2 FROM USER_TAB_COLS WHERE table_name = 'EMP' ORDER BY INTERNAL_COLUMN_ID; COLUMN_NAME DATA_TYP HID VIR USE -------------------- -------- --- --- --- EMPNO NUMBER NO NO YES ENAME VARCHAR2 NO NO YES SQL> ALTER TABLE emp ROW ARCHIVAL; 表が変更されました。 SQL> SELECT column_name, data_type, hidden_column, virtual_column, user_generated 2 FROM USER_TAB_COLS WHERE table_name = 'EMP' ORDER BY INTERNAL_COLUMN_ID; COLUMN_NAME DATA_TYP HID VIR USE -------------------- -------- --- --- --- EMPNO NUMBER NO NO YES ENAME VARCHAR2 NO NO YES SYS_NC00003$ RAW YES NO NO ORA_ARCHIVE_STATE VARCHAR2 YES NO NO
うーん、ちょっと謎ですね。