,今天開發人員問我如何快速並方便的查出一張表最近被更改的記錄,這個需求很簡單,由於是查最近被更改的數據,查回滾段就可以,下面是我做的小實驗。
SQL> create table test(id number,name varchar2(10),gender varchar2(5));
表已創建。
SQL> insert into test values(1,'宋春風','男');
已創建 1 行。
SQL> insert into test values(2,'葉民','男');
已創建 1 行。
SQL> insert into test values(3,'白冰','男');
已創建 1 行。
SQL> insert into test values(4,'方巍森','男');
已創建 1 行。
SQL> insert into test values(5,'孫書禎','男');
已創建 1 行。
SQL> insert into test values(6,'史波','男');
已創建 1 行。
SQL> commit;
提交完成。
利用下面的SQL就可以查處最近更改的數據。
SQL> SELECT ID,NAME,VERSIONS_STARTTIME,VERSIONS_ENDTIME,VERSIONS_OPERATION
FROM TEST VERSIONS BETWEEN TIMESTAMP MINVALUE AND MAXVALUE WHERE
VERSIONS_STARTTIME IS NOT NULL ORDER BY VERSIONS_STARTTIME DESC;
ID NAME GENDE VERSIONS_STARTTIME VERSIONS_ENDTIME V
---------- ------ ----- ------------------------- ------------------------- -
6 史波 男 30-11月-11 04.02.28 下午 I
5 孫書禎 男 30-11月-11 04.02.28 下午 I
1 宋春風 男 30-11月-11 04.02.28 下午 I
3 白冰 男 30-11月-11 04.02.28 下午 I
2 葉民 男 30-11月-11 04.02.28 下午 I
4 方巍森 男 30-11月-11 04.02.28 下午 I
已選擇6行。
修改幾條數據和接下來的查詢做對比。
SQL> UPDATE TEST SET GENDER='女' WHERE NAME='孫書禎';
已更新 1 行。
SQL> COMMIT;
提交完成。
SQL> UPDATE TEST SET GENDER='女' WHERE NAME='史波';
已更新 1 行。
SQL> COMMIT;
提交完成。
再次查詢,被修改的數據就可以看到被修改和修改前的數據。
SQL> SELECT ID,NAME,GENDER,VERSIONS_STARTTIME,VERSIONS_ENDTIME,
VERSIONS_OPERATION FROM TEST VERSIONS BETWEEN TIMESTAMP MINVALUE AND
MAXVALUE WHERE VERSIONS_STARTTIME IS NOT NULL ORDER BY
VERSIONS_STARTTIME DESC;
ID NAME GENDE VERSIONS_STARTTIME VERSIONS_ENDTIME V
---------- ------ ----- ------------------------- ------------------------- -
6 史波 女 30-11月-11 04.15.07 下午 U
5 孫書禎 女 30-11月-11 04.14.31 下午 U
4 方巍森 男 30-11月-11 04.02.28 下午 I
3 白冰 男 30-11月-11 04.02.28 下午 I
2 葉民 男 30-11月-11 04.02.28 下午 I
1 宋春風 男 30-11月-11 04.02.28 下午 I
6 史波 男 30-11月-11 04.02.28 下午 30-11月-11 04.15.07 下午 I
5 孫書禎 男 30-11月-11 04.02.28 下午 30-11月-11 04.14.31 下午 I
已選擇8行。
再修改幾條數據后后查詢。
SQL> delete from test WHERE NAME='史波';
已刪除 1 行。
SQL> delete from test WHERE NAME='孫書禎';
已刪除 1 行。
SQL> commit;
提交完成。
SQL> SELECT ID,NAME,GENDER,VERSIONS_STARTTIME,VERSIONS_ENDTIME,
VERSIONS_OPERATION FROM TEST VERSIONS BETWEEN TIMESTAMP MINVALUE AND
MAXVALUE WHERE VERSIONS_STARTTIME IS NOT NULL ORDER BY
VERSIONS_STARTTIME DESC;
ID NAME GENDE VERSIONS_STARTTIME VERSIONS_ENDTIME V
---------- ------ ----- ------------------------- ------------------------- -
5 孫書禎 男 30-11月-11 04.26.02 下午 D
6 史波 男 30-11月-11 04.26.02 下午 D
6 史波 女 30-11月-11 04.15.07 下午 30-11月-11 04.19.08 下午 U
5 孫書禎 女 30-11月-11 04.14.31 下午 30-11月-11 04.19.08 下午 U
2 葉民 男 30-11月-11 04.02.28 下午 I
3 白冰 男 30-11月-11 04.02.28 下午 I
4 方巍森 男 30-11月-11 04.02.28 下午 I
5 孫書禎 男 30-11月-11 04.02.28 下午 30-11月-11 04.14.31 下午 I
1 宋春風 男 30-11月-11 04.02.28 下午 I
6 史波 男 30-11月-11 04.02.28 下午 30-11月-11 04.15.07 下午 I
已選擇10行。
通過以上小實驗可以看出,VERSIONS_STARTTIME是數據被修改的起始時間,VERSIONS_ENDTIME是數據被修改后新數據的有效時間,也就是VERSIONS_STARTTIME和VERSIONS_ENDTIME時間段內,這條數據再沒被修改過,如果VERSIONS_ENDTIME為空,就說明這天記錄從VERSIONS_STARTTIME時間起再沒被修改過。VERSIONS_OPERATION是修改狀態,I代表INSERT,U代表UPDATE,D代表DELETE。此時如果想回滾INSERT的數據,只需要DELETE反向操作即可,如果想回滾UPDATE操作,將數據反向UPDATE回去即可,比如本實驗已經可以看到進行UPDATE操作的是NAME為史波和孫書禎的兩條記錄,而且也可以看到進行UPDATE之前的數據他們的性別是男,所以只需要在做個反向UPDATE,將性別該為男即可實現回退,如果要回滾DELETE操作,同樣做個INSERT操作,將刪除的數據在插回去即可。
注:此SQL只能查詢到回滾段內的信息,超出回滾段范圍這個SQL就無能為力了,需要借助LOGMGR工具挖掘日志了(詳見http://www.dbdream.org/?p=149)。