如何对oracle表中的数据发生修改时实现跟踪,有以下几种方法:
1. 基于触发器: 当表中数据发生变化时,通过表上的触发器来记录修改的内容。这种方法是开发人员常见使用的方法。
2. 基于日志的分析: 例如使用LogMiner或者Goldengate软件,对日志文件进行分析,提取数据变化。这种方法不增加数据库负担,但配置稍麻烦,适合于DBA使用。
3. ROWDEPENDENCIES 方法: 这是oracle10G 后引入的新特性,ORACLE 通过引入ORA_ROWSCN伪列新特性,我们可以方便地找出某个数据块或某一个行最近被修改的时间戳。这也是本文介绍的重点内容。
通过scn_to_timestamp(ora_rowscn) ,显示该行修改的时间,举例如下:
SQL> select * from v$version ;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for 64-bit Windows: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 – Production
SQL> CREATE TABLE ADT_LOG
2 (
3 WARD_CODE VARCHAR2(8 BYTE),
4 DEPT_CODE VARCHAR2(8 BYTE),
5 LOG_DATE_TIME DATE,
6 PATIENT_ID VARCHAR2(10 BYTE),
7 VISIT_ID NUMBER(2),
8 ACTION VARCHAR2(1 BYTE)
9 ) rowdependencies ;
Table created
插入第一条数据
SQL> insert into adt_log
2 (WARD_CODE, DEPT_CODE, LOG_DATE_TIME, PATIENT_ID, VISIT_ID, ACTION)
3 values
4 ('0602',
5 '030201',
6 to_date('10-05-2001 16:47:22', 'dd-mm-yyyy hh24:mi:ss'),
7 '9712277002',
8 1,
9 'F');
1 row inserted
SQL> commit;
Commit complete
SQL> select scn_to_timestamp(ora_rowscn) orscn, WARD_CODE from ADT_LOG;
ORSCN WARD_CODE
------------------------------------------------- ---------
04-MAY-15 03.13.20.000000000 PM 0602
插入第二条数据
SQL> insert into adt_log
2 (WARD_CODE, DEPT_CODE, LOG_DATE_TIME, PATIENT_ID, VISIT_ID, ACTION)
3 values
4 ('0602',
5 '030201',
6 to_date('10-05-2001 16:47:34', 'dd-mm-yyyy hh24:mi:ss'),
7 '9707089371',
8 1,
9 'F');
1 row inserted
SQL> commit;
Commit complete
SQL> select scn_to_timestamp(ora_rowscn) orscn, WARD_CODE from ADT_LOG;
ORSCN WARD_CODE
------------------------------------------------- ---------
04-MAY-15 03.13.20.000000000 PM 0602
04-MAY-15 03.14.04.000000000 PM 0602
插入第三条数据
SQL> insert into adt_log
2 (WARD_CODE, DEPT_CODE, LOG_DATE_TIME, PATIENT_ID, VISIT_ID, ACTION)
3 values
4 ('0607',
5 '030702',
6 to_date('10-05-2001 16:50:16', 'dd-mm-yyyy hh24:mi:ss'),
7 '86377',
8 1,
9 'C');
1 row inserted
SQL> commit;
Commit complete
SQL> select scn_to_timestamp(ora_rowscn) orscn, WARD_CODE from ADT_LOG;
ORSCN WARD_CODE
------------------------------------------------- ---------
04-MAY-15 03.13.20.000000000 PM 0602
04-MAY-15 03.14.04.000000000 PM 0602
04-MAY-15 03.18.35.000000000 PM 0607
修改第三条记录:
SQL> update adt_log set log_date_time = sysdate where ward_code = '0607';
1 row updated
SQL> commit;
Commit complete
SQL> select scn_to_timestamp(ora_rowscn) orscn, WARD_CODE from ADT_LOG;
ORSCN WARD_CODE
------------------------------------------------- ---------
04-MAY-15 03.13.20.000000000 PM 0602
04-MAY-15 03.14.04.000000000 PM 0602
04-MAY-15 03.21.29.000000000 PM 0607
需说明的是,如果对于DELETE 的行,恐怕不能显示出来,如果要显示出来,只能使用快照查询,例如:
SQL> delete from ADT_LOG where WARD_CODE = '0607';
1 row deleted
SQL> commit;
Commit complete
SQL> select scn_to_timestamp(ora_rowscn) orscn, WARD_CODE from ADT_LOG;
ORSCN WARD_CODE
------------------------------------------------- ---------
04-MAY-15 03.26.50.000000000 PM 0602
04-MAY-15 03.26.50.000000000 PM 0602
SQL> select scn_to_timestamp(ora_rowscn) orscn, WARD_CODE
2 from ADT_LOG AS OF TIMESTAMP(SYSTIMESTAMP - INTERVAL '1' MINUTE);
ORSCN WARD_CODE
------------------------------------------------- ---------
04-MAY-15 03.26.50.000000000 PM 0602
04-MAY-15 03.26.50.000000000 PM 0602
04-MAY-15 03.26.50.000000000 PM 0607
需要注意的是ROWDEPENDENCIES属性只有在创建表时使用才有效,对于已有的表,通过alter table 语句是无效的,因此需通过重建表的方式来解决。
SQL> RENAME ADT_LOG TO ADT_LOG_1;
Table renamed
SQL>
SQL> CREATE TABLE ADT_LOG
2 (
3 WARD_CODE VARCHAR2(8 BYTE),
4 DEPT_CODE VARCHAR2(8 BYTE),
5 LOG_DATE_TIME DATE,
6 PATIENT_ID VARCHAR2(10 BYTE),
7 VISIT_ID NUMBER(2),
8 ACTION VARCHAR2(1 BYTE)
9 ) rowdependencies ;
Table created
SQL> INSERT INTO ADT_LOG
2 select * from ADT_LOG_1;
3 rows inserted
SQL> commit;
Commit complete
SQL> drop table ADT_LOG_1 purge ;
Table dropped
SQL> select scn_to_timestamp(ora_rowscn) orscn, WARD_CODE from ADT_LOG;
ORSCN WARD_CODE
------------------------------------------------- ---------
04-MAY-15 03.26.50.000000000 PM 0602
04-MAY-15 03.26.50.000000000 PM 0602
04-MAY-15 03.26.50.000000000 PM 0607