For each row, ORA_ROWSCN returns the conservative upper bound system change number (SCN) of the most recent change to the row. This pseudocolumn is useful for determining approximately when a row was last updated. It is not absolutely precise, because Oracle tracks SCNs by transaction committed for the block in which the row resides. You can obtain a more fine-grained approximation of the SCN by creating your tables with row-level dependency tracking. In this note we will try to see how ORA_ROWSCN works with Rowdependencies and Norowdependecies with examples:
SOLUTION
- For rows to have unique ora_rowscn ( when using row dependencies), there should be commit after every single dml. If there are multiple row manipulated in one transaction , then all these rows will have same ORA_ROWSCN. See the test case below.
select ename, ora_rowscn from temp;
ENAME ORA_ROWSCN
SMITH 1472829
ALLEN 1472832
WARD 1472835
JONES 1472838
MARTIN 1472841
BLAKE 1472850
CLARK 1472853
SCOTT 1472698
KING 1472856
TURNER 1472859
ADAMS 1472862
ENAME ORA_ROWSCN
JAMES 1472865
FORD 1472868
MILLER 1472871
SQL> insert into temp select * from emp where empno = 7788;
SQL> select ename, ora_rowscn from temp;
ENAME ORA_ROWSCN
SMITH 1472829
ALLEN 1472832
WARD 1472835
JONES 1472838
MARTIN 1472841
BLAKE 1472850
CLARK 1472853
SCOTT 1472698
KING 1472856
TURNER 1472859
ADAMS 1472862
ENAME ORA_ROWSCN
JAMES 1472865
FORD 1472868
MILLER 1472871
SCOTT 1473294 <<< new ora_rowscn
SQL> insert into temp select * from emp where empno = 7788;
1 row created.
SQL> insert into temp select * from emp where empno = 7788;
1 row created.
SQL> insert into temp select * from emp where empno = 7788;
1 row created.
SQL> commit;
Commit complete.
SQL> select ename, ora_rowscn from temp;
ENAME ORA_ROWSCN
SMITH 1472829
ALLEN 1472832
WARD 1472835
JONES 1472838
MARTIN 1472841
BLAKE 1472850
CLARK 1472853
SCOTT 1472698
KING 1472856
TURNER 1472859
ADAMS 1472862
ENAME ORA_ROWSCN
JAMES 1472865
FORD 1472868
MILLER 1472871
SCOTT 1473294
SCOTT 1473314 <<
SCOTT 1473314 << same ora_rowscn for three rows
SCOTT 1473314 <<
*** So the only reason of having rows with duplicate ORA_ROWSCN is that a single transaction is commiting/changing number of rows together.
- When using NOROWDEPENDENCIES all the rows in a BLOCK will have the same ORA_ROWSCN.
SQL> select ename, ora_rowscn,rowid from test;
ENAME ORA_ROWSCN ROWID
SMITH 17445533 AAASMWAAEAAAAA8AAA
ALLEN 17445533 AAASMWAAEAAAAA8AAB
WARD 17445533 AAASMWAAEAAAAA8AAC
JONES 17445533 AAASMWAAEAAAAA8AAD
MARTIN 17445533 AAASMWAAEAAAAA8AAE
BLAKE 17445533 AAASMWAAEAAAAA8AAF
CLARK 17445533 AAASMWAAEAAAAA8AAG
SCOTT 17445533 AAASMWAAEAAAAA8AAH
KING 17445533 AAASMWAAEAAAAA8AAI
TURNER 17445533 AAASMWAAEAAAAA8AAJ
ADAMS 17445533 AAASMWAAEAAAAA8AAK
JAMES 17445533 AAASMWAAEAAAAA8AAL
FORD 17445533 AAASMWAAEAAAAA8AAM
MILLER 17445533 AAASMWAAEAAAAA8AAN
SCOTT 17445627 AAASMWAAEAAAAA+AAA
SCOTT 17445627 AAASMWAAEAAAAA+AAB
SCOTT 17445627 AAASMWAAEAAAAA+AAC
SCOTT 17445627 AAASMWAAEAAAAA+AAD
SCOTT 17445627 AAASMWAAEAAAAA+AAE
19 rows selected.
SQL> update test set sal=5000 where ename='WARD';
1 row updated.
SQL> select ename, ora_rowscn,rowid from test;
ENAME ORA_ROWSCN ROWID
SMITH 17445533 AAASMWAAEAAAAA8AAA
ALLEN 17445533 AAASMWAAEAAAAA8AAB
WARD 17445533 AAASMWAAEAAAAA8AAC
JONES 17445533 AAASMWAAEAAAAA8AAD
MARTIN 17445533 AAASMWAAEAAAAA8AAE
BLAKE 17445533 AAASMWAAEAAAAA8AAF
CLARK 17445533 AAASMWAAEAAAAA8AAG
SCOTT 17445533 AAASMWAAEAAAAA8AAH
KING 17445533 AAASMWAAEAAAAA8AAI
TURNER 17445533 AAASMWAAEAAAAA8AAJ
ADAMS 17445533 AAASMWAAEAAAAA8AAK
ENAME ORA_ROWSCN ROWID
JAMES 17445533 AAASMWAAEAAAAA8AAL
FORD 17445533 AAASMWAAEAAAAA8AAM
MILLER 17445533 AAASMWAAEAAAAA8AAN
SCOTT 17445627 AAASMWAAEAAAAA+AAA
SCOTT 17445627 AAASMWAAEAAAAA+AAB
SCOTT 17445627 AAASMWAAEAAAAA+AAC
SCOTT 17445627 AAASMWAAEAAAAA+AAD
SCOTT 17445627 AAASMWAAEAAAAA+AAE
19 rows selected.
SQL> commit;
Commit complete.
SQL> select ename, ora_rowscn,rowid from test;
ENAME ORA_ROWSCN ROWID
SMITH 17445699 AAASMWAAEAAAAA8AAA
ALLEN 17445699 AAASMWAAEAAAAA8AAB
WARD 17445699 AAASMWAAEAAAAA8AAC
JONES 17445699 AAASMWAAEAAAAA8AAD
MARTIN 17445699 AAASMWAAEAAAAA8AAE
BLAKE 17445699 AAASMWAAEAAAAA8AAF
CLARK 17445699 AAASMWAAEAAAAA8AAG
SCOTT 17445699 AAASMWAAEAAAAA8AAH
KING 17445699 AAASMWAAEAAAAA8AAI
TURNER 17445699 AAASMWAAEAAAAA8AAJ
ADAMS 17445699 AAASMWAAEAAAAA8AAK
JAMES 17445699 AAASMWAAEAAAAA8AAL
FORD 17445699 AAASMWAAEAAAAA8AAM
MILLER 17445699 AAASMWAAEAAAAA8AAN
SCOTT 17445627 AAASMWAAEAAAAA+AAA }
SCOTT 17445627 AAASMWAAEAAAAA+AAB }
SCOTT 17445627 AAASMWAAEAAAAA+AAC } second block
SCOTT 17445627 AAASMWAAEAAAAA+AAD }
SCOTT 17445627 AAASMWAAEAAAAA+AAE }
19 rows selected.
ORA_ROWSCN for all rows in first block got updated.
-----------------还能检查是否提交-----------
How to determine in a transaction (TX) if a row has already been committed or not?
SOLUTION
The pseudo column ORA_ROWSCN will show if the row has been committed, a thing to keep in mind is that ORA_ROWSCN will only provide correct information if the SCN is stored inline with the row (ROWDEPENDENCIES) otherwise it will return the SCN of the block the row is located in (NOROWDEPENDENCIES).
The following examples will show the difference:
NOROWDEPENDENCIES
SQL> set numwidth 20
SQL> drop table test
SQL> create table test (c varchar2(10));
SQL> insert into test values ('one');
SQL> commit;
SQL> insert into test values ('two');
SQL> select ora_rowscn,c from test;
ORA_ROWSCN C
2238860 one
2238860 two <<no commit yet so SCN should be NULL but SCN not stored in row
<<thus SCN of block returned
ROWDEPENDENCIES
SQL> set numwidth 20
SQL> drop table test;
SQL> create table test (c varchar2(10)) rowdependencies;
SQL> insert into test values ('one');
SQL> commit;
SQL> insert into test values ('two');
SQL> select ora_rowscn,c from test;
ORA_ROWSCN C
2238937 one
two << no commit yet SCN as stored with row is NULL
SQL> rollback;
Same is of course true in case of update:
SQL> update test set c='three' where c='one';
ORA_ROWSCN C
three
Is there a method to extract the changes from a table, for example all the entries inserted starting from a certain date to now?
SOLUTION
ORA_ROWSCN pseudo-column that reflects the system change-number (SCN) of the most recent change to a row and the query parameter can be used to unload the last changes from a table with DataPump.
The example below shows how to use ORA_ROWSCN in a query to generate a dump file with the last changes from a table:
1. Create a table and populate it
create table test (c varchar2(10));
begin
for i in 1..10000 loop
insert into test select rownum from dual connect by level <=10;
end loop;
commit;
end;
/
- Query the table as follows
select scn_to_timestamp (ora_rowscn), ora_rowscn, count(*) from test group by ora_rowscn order by scn_to_timestamp (ora_rowscn);
SCN_TO_TIMESTAMP(ORA_ROWSCN) ORA_ROWSCN COUNT(*)
10-FEB-15 12.14.05.000000000 PM 1222415 100000
3. Insert a new set of rows
begin
for i in 1..10000 loop
insert into test select rownum from dual connect by level <= 10;
end loop;
commit;
end;
/
4. Query the table to group the records by the system change-number (SCN) of the changes
select scn_to_timestamp(ora_rowscn),ora_rowscn, count(*) from test group by ora_rowscn order by scn_to_timestamp(ora_rowscn);
SCN_TO_TIMESTAMP(ORA_ROWSCN) ORA_ROWSCN COUNT(*)
10-FEB-15 12.14.05.000000000 PM 1222415 99999
10-FEB-15 12.15.04.000000000 PM 1222807 100001
5. Run the DataPump export with the parameter file below to unload the last changes from the table
exp_rowscn.parfile
tables=test
directory=data_pump_dir
dumpfile=orascn_test.dmp
logfile=orascn_test.log
query="where scn_to_timestamp(ora_rowscn)>cast('10-FEB-15 12:15:00' as timestamp)"
#> expdp user/<PASSWORD> parfile=exp_rowscn.parfile
Export: Release 11.2.0.4.0 - Production on Tue Feb 10 12:16:36 2015
Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
Starting "TEST"."SYS_EXPORT_TABLE_02": test/******** parfile=exp_rowscn.parfile
Estimate in progress using BLOCKS method...
Processing object type TABLE_EXPORT/TABLE/TABLE_DATA
Total estimation using BLOCKS method: 3.441 GB
(...)
Processing object type TABLE_EXPORT/TABLE/TABLE
(...)
. . exported "TEST"."TEST" 191.6 MB 100001 rows
Master table "TEST"."SYS_EXPORT_TABLE_01" successfully loaded/unloaded
******************************************************************************
Dump file set for TEST.SYS_EXPORT_TABLE_01 is:
/u01/app/oracle/admin/oradb11g/dpdump/orascn_test.dmp
Job "TEST"."SYS_EXPORT_TABLE_01" successfully completed at Tue Feb 10 12:16:49 2015 elapsed 0 00:00:12
Note: ORA_ROWSCN will only provide correct information if the SCN is stored inline with the row (ROWDEPENDENCIES) otherwise it will return the SCN of the block the row is located in (NOROWDEPENDENCIES). The difference between ROWDEPENDENCIES and NOROWDEPENDENCIES can be found in Note 748675.1 How To Identify Committed And Uncommitted Data From Table(s) in transaction.
------------how to find when record insert today---------------
You may be able to get this even if you do not have an appropriate column using ORA_ROWSCN and SCN_TO_TIMESTAMP
This query will give you the rows amended in the last 5 days
select t1.*, ora_rowscn, scn_to_timestamp(ora_rowscn) from t1
where ora_rowscn > (select min(first_change#) from v$log_history where first_time > sysdate -5);
Unfortunately, you can't go back beyond 5 days with the SCN_TO_TIMESTAMP feature, but you can still go back as far as your log history goes with
select t1.*, t1.ora_rowscn, lh.first_time from t1, v$log_history lh
where t1.ora_rowscn between lh.first_change# and lh.next_change#;
With this second query, the time is when the particular log started, rather than the row time. Also, you need to switch logs to get the most recent data.
Similarly, if you are running in archivelog mode, you can get a time range with
select t1.*, t1.ora_rowscn, lh.first_time, lh.next_time from t1, v$archived_log lh
where t1.ora_rowscn between lh.first_change# and lh.next_change#;
Hope this helps
BobB
EDIT: Unless the table has been created with rowdependencies, these queries will give all the rows in a block that has had one or more rows inserted/amended in the timeframe. With rowdependencies it gives the rows amended.
Flashback query - retrieves data from a past point in time
Example:-
Flashback Table using TIMESTAMP
This statement brings a table 'employees' back to a certain timestamp:
SQL> FLASHBACK TABLE employees
TO TIMESTAMP
TO_TIMESTAMP('03-12-2007 08:00:00','MM/DD/YY HH:MI:SS');
Reterive Data Example:-
1)select * from employees as of timestamp
to_timestamp('03-12-2007 08:00:00', 'DD-MM-YYYY HH:MI:SS')
where last_name = ahmed;
2)select employee_id, name from hr.employee as of timestamp (systimestamp - interval '15' minute);
Hopefully now can easliy do your task.