1. ----------------------------------------TEMPORAL VALIDITY Testing
---------------------------------------The Temporal Validity feature is relate to valid time dimension for a table via PERIOD FOR
clause which adds a time dimension to each row in the table consisting of two date-time
columns to indicate validity of data. By this feature we can hidden data that is no longer
valid or (inactive) or old from queries. This is an addition over timestamp columns in table
for potential future requirements base on time range.
SQL> connect monowar/password
Connected.
SQL> select table_name from user_tables;
TABLE_NAME
-------------------------------------------------------------------------------TEST_ARCH
CP_TEST_ARCH
TV_EMP
TEST_TV
SQL> desc TEST_TV
Name
Null? Type
----------------------------------------- -------- ---------------------------EMPNO
NUMBER(4)
ENAME
VARCHAR2(10)
JOB
VARCHAR2(9)
MGR
NUMBER(4)
HIREDATE
DATE
SAL
NUMBER(7,2)
COMM
NUMBER(7,2)
DEPTNO
NUMBER(2)
SQL> select count (*) from TEST_TV;
COUNT(*)
---------14
SQL> alter table TEST_TV add period for recoder_time;
Table altered.
SQL> desc TEST_TV
Name
Null? Type
----------------------------------------- -------- ---------------------------EMPNO
NUMBER(4)
ENAME
VARCHAR2(10)
JOB
VARCHAR2(9)
MGR
NUMBER(4)
HIREDATE
DATE
SAL
NUMBER(7,2)
COMM
NUMBER(7,2)
DEPTNO
NUMBER(2)
SQL> select table_name, column_name
2 from dba_tab_cols
3 where owner='MONOWAR' and table_name='TEST_TV';
TABLE_NAME
COLUMN_NAME
-------------------------------------------------------------------------------TEST_TV
EMPNO
TEST_TV
ENAME
TEST_TV
JOB
TEST_TV
TEST_TV
TEST_TV
TEST_TV
TEST_TV
TEST_TV
TEST_TV
TEST_TV
MGR
HIREDATE
SAL
COMM
DEPTNO
RECODER_TIME_START
RECODER_TIME_END
RECODER_TIME
2. 11 rows selected.
SQL> select column_name,data_type from user_tab_cols where table_name='TEST_TV' and hidden_column='YES';
COLUMN_NAME
DATA_TYPE
-------------------------------------------------------------------------------RECODER_TIME_START
TIMESTAMP(6) WITH TIME ZONE
RECODER_TIME_END
TIMESTAMP(6) WITH TIME ZONE
RECODER_TIME
NUMBER
We can use PERIOD FOR clause or use the DBMS_FLASHBACK_ARCHIVE procedure with
the SELECT statement to filter on valid-time columns .
Testing with PERIOD FOR
+++++++++++++++++++++++
SQL> connect monowar/password
Connected.
SQL> show user;
USER is "MONOWAR"
SQL> create table TV_EMP (
2 EMPNO NUMBER(7),
3 FULLNAME VARCHAR2(80),
4 USER_TIME_START DATE,
5 USER_TIME_END DATE,
6 PERIOD FOR USER_TIME (USER_TIME_START,USER_TIME_END));
Table created.
Check that implicit constraint has been created with valid-time dimension
------------------------------------------------------------------------SQL> select CONSTRAINT_NAME CN, CONSTRAINT_TYPE CT,GENERATED, VALIDATED
from dba_constraints
where table_name='TV_EMP';
CN
CT GENERATED
VALIDATED
- -------------- --------------------------USER_TIME34EC4D C USER NAME
VALIDATED
SQL> insert into tv_emp
2 values (301,'EAMMON',to_date('27-JAN-2011','dd-mon-yyyy'),
3 to_date('31-JUL-2013','dd-mon-yyyy'));
1 row created.
SQL> commit;
Commit complete.
SQL> select table_name, column_name
from dba_tab_cols
where owner='MONOWAR' and table_name='TV_EMP';
TABLE_NAME
COLUMN_NAME
-----------------------------------TV_EMP
USER_TIME
TV_EMP
EMPNO
TV_EMP
FULLNAME
TV_EMP
USER_TIME_START
TV_EMP
USER_TIME_END
Diassociate the columns of valid-time dimension
-------------------------------------------------------------SQL> alter table TV_EMP DROP (period for user_time);
Table altered.
SQL> select table_name, column_name
2 from dba_tab_cols
3 where owner='MONOWAR' and table_name='TV_EMP';
3. TABLE_NAME
COLUMN_NAME
-------------------------------------------------------------------------------TV_EMP
EMPNO
TV_EMP
FULLNAME
TV_EMP
USER_TIME_START
TV_EMP
USER_TIME_END
Constraint Check
----------------SQL> select CONSTRAINT_NAME CN, CONSTRAINT_TYPE CT,GENERATED, VALIDATED
from dba_constraints
where table_name='TV_EMP';
no rows selected
Create a new valid-time diemnsion without column names
(USER_TIME_START,USER_TIME_END)
SQL> alter table TV_EMP add period for valid_time;
Table altered.
SQL> desc TV_EMP
Name
Null? Type
----------------------------------------- -------- ---------------------------EMPNO
NUMBER(7)
FULLNAME
VARCHAR2(80)
USER_TIME_START
DATE
USER_TIME_END
DATE
Note: USER_TIME_START,USER_TIME_END are still there as part of user's definition of the
table.
Check the table columns
-------------------------------SQL> select table_name, column_name
2 from dba_tab_cols
3 where owner='MONOWAR' and table_name='TV_EMP';
TABLE_NAME
COLUMN_NAME
-------------------------------------------------------------------------------TV_EMP
VALID_TIME_START
TV_EMP
EMPNO
TV_EMP
FULLNAME
TV_EMP
USER_TIME_START
TV_EMP
USER_TIME_END
TV_EMP
VALID_TIME_END
TV_EMP
VALID_TIME
7 rows selected.
Testing with DBMS_FLASHBACK_ARCHIVE
+++++++++++++++++++++++++++++++++++++
The DBMS_FLASHBACK_ARCHIVE package to set the time visibility of the data for a given
period of time or data which is currently valid within the valid time period at the session
level.
For testing with very minimum data, I have created a TEST_TV based on SCOTT.emp table.
SQL> update TEST_TV set RECODER_TIME_START=SYSDATE;
14 rows updated.
SQL> update TEST_TV set RECODER_TIME_END=SYSDATE where HIREDATE >'23-JAN-82';
2 rows updated.
SQL> EXECUTE DBMS_FLASHBACK_ARCHIVE.enable_at_valid_time('CURRENT');
PL/SQL procedure successfully completed.
4. So now when we do a count(*) from the table TEST_TV, it only returns the rows which we
have deemed to be active or current and not all the rows (here 12/14).
SQL> select count(*) from TEST_TV;
COUNT(*)
---------12
I am going to extent the time period for more rows
NOTE:
SQL> update TEST_TV set RECODER_TIME_END=SYSDATE where HIREDATE <'23-JAN-82';
update TEST_TV set RECODER_TIME_END=SYSDATE where HIREDATE <'23-JAN-82'
*
ERROR at line 1:
ORA-00904: "RECODER_TIME_END": invalid identifier
SQL> EXECUTE DBMS_FLASHBACK_ARCHIVE.enable_at_valid_time('CURRENT');
PL/SQL procedure successfully completed.
SQL> update TEST_TV set RECODER_TIME_END=SYSDATE where HIREDATE >'28-SEP-81';
update TEST_TV set RECODER_TIME_END=SYSDATE where HIREDATE >'28-SEP-81'
*
ERROR at line 1:
ORA-00904: "RECODER_TIME_END": invalid identifier
Now set the visibility of the temporal data to the full table and update:
SQL> EXECUTE DBMS_FLASHBACK_ARCHIVE.enable_at_valid_time('ALL');
PL/SQL procedure successfully completed.
SQL> update TEST_TV set RECODER_TIME_END=SYSDATE where HIREDATE >'28-SEP-81';
6 rows updated.
SQL> EXECUTE DBMS_FLASHBACK_ARCHIVE.enable_at_valid_time('CURRENT');
PL/SQL procedure successfully completed.
SQL> select count(*) from TEST_TV;
COUNT(*)
---------8
This time select statement is getting less number (8) of rows than last time (12).
Put it back normal state
-----------------------------SQL> EXECUTE DBMS_FLASHBACK_ARCHIVE.enable_at_valid_time('ALL');
PL/SQL procedure successfully completed.
SQL> select count(*) from TEST_TV;
COUNT(*)
---------14
++++++++++++++++++++++++++
FLASHBACK ARCHIVE
++++++++++++++++++++++++++
SQL> alter database datafile '/BPELAIT2/MONDB01/MONDB01/test_arch01.dbf' resize 500M;
Database altered.
SQL> connect monowar/password
Connected.
5. SQL> create table FA_sales as select * from sh.sales;
Table created.
SQL> create Flashback Archive test_nfaopt tablespace TEST_ARCH RETENTION 10 DAY NO OPTIMIZE DATA;
Flashback archive created.
[Ref: http://docs.oracle.com/cd/E16655_01/server.121/e17209/statements_5011.htm]
SQL> alter table FA_sales flashback archive test_nfaopt;
Table altered.
Set the context level collection for FA_sales table
-----------------------------------------------SQL> exec dbms_flashback_archive.set_context_level('TYPICAL');
PL/SQL procedure successfully completed.
Make some update on Flashback table from other schema
----------------------------------------------------SQL> conn sh/sh
Connected.
SQL> update monowar.FA_sales set CUST_ID=3333 where CUST_ID=8865;
243 rows updated.
SQL> commit;
Commit complete.
Check the flashback table status
---------------------------------------SQL> select * from dba_flashback_archive_tables;
TABLE_NAME
-------------------------------------------------------------------------------OWNER_NAME
-------------------------------------------------------------------------------FLASHBACK_ARCHIVE_NAME
-------------------------------------------------------------------------------ARCHIVE_TABLE_NAME
STATUS
----------------------------------------------------- ------------FA_SALES
MONOWAR
TEST_NFAOPT
SYS_FBA_HIST_110567
ENABLED
--- NOTE: DBA_FLASHBACK_ARCHIVE_TABLES for NO OPTIMIZE DATA
Truncate the table
SQL> truncate table MONOWAR.FA_SALES;
Table truncated.
SQL> select count (*) from MONOWAR.FA_SALES;
COUNT(*)
---------0
Check data on flashback archive
-------------------------------SQL> select count (*) from MONOWAR.SYS_FBA_HIST_110567;
COUNT(*)
6. ---------919086
Retrieve the Transaction ID from flashback archive table
------------------------------------------------------SQL> select distinct XID from monowar.SYS_FBA_HIST_110567;
XID
---------------0004001500000A16
select DBMS_flashback_archive.Get_sys_context
('0004001500000A16','USERENV','SESSION_USER') as SUSPECTUSR
From MONOWAR.FA_SALES
versions between scn minvalue and maxvalue
where num=1;
SQL> select DBMS_flashback_archive.Get_sys_context
2 ('0004001500000A16','USERENV','SESSION_USER') as SUSPECTUSR
3 ,versions_XID,VERSIONS_starttime,versions_endtime
4 From MONOWAR.FA_SALES
5 versions between scn minvalue and maxvalue
SUSPECTUSR VERSIONS_XID VERSIONS_STARTTIME VERSIONS_ENDTIME
--------------------------------------------------------------------------SH
01-NOV-13 04.05.56.000000000 PM
CLEAN UP
--------------SQL> alter table MONOWAR.FA_SALES NO flashback archive;
Table altered.
SQL> drop flashback archive test_nfaopt;
Flashback archive dropped.