闪回版本查询

时间:2013-09-27 07:24:01

标签: sql oracle flashback

select语句返回两行

id || description
1        TWO
2        TWO 

我有点期待三排

id || description
1        ONE
1        TWO
2        TWO 
根据link的声明 读It returns all the committed occurrences of the rows for a query of an object, while NOT displaying the UNCOMMITTED row versions. 代码如下: -


CREATE TABLE digits
(id NUMBER(2),
description VARCHAR2(15));
INSERT INTO digits VALUES (1,'ONE');
UPDATE digits SET description ='TWO' WHERE id=1;
INSERT INTO digits VALUES (2,'TWO');
COMMIT;
DELETE FROM digits;
SELECT id,description FROM digits
VERSIONS BETWEEN TIMESTAMP MINVALUE AND MAXVALUE;

我能想到的唯一原因是,如果时间戳minvalue和maxvalue 采用DML时间戳值而不是DDL值.....请注意这一点!

1 个答案:

答案 0 :(得分:3)

您认为缺少的行将来自:

INSERT INTO digits VALUES (1,'ONE');

...但是数据永远不会在该状态下提交,因为:

UPDATE digits SET description ='TWO' WHERE id=1;

...发生在COMMIT之前。因此,与您引用的语句一致,1, ONE不是该行的已提交事件。从来没有任何一个会议可以看到这些价值观。

如果查看version data pseudocolumns,您会发现这两行都被视为具有当前数据的插入内容:

CREATE TABLE digits (id NUMBER(2), description VARCHAR2(15));
EXEC dbms_lock.sleep(10);

INSERT INTO digits VALUES (1,'ONE');
UPDATE digits SET description ='TWO' WHERE id=1;
INSERT INTO digits VALUES (2,'TWO');
COMMIT;

SELECT id, description, versions_xid, versions_operation
FROM digits
VERSIONS BETWEEN TIMESTAMP MINVALUE AND MAXVALUE;

        ID DESCRIPTION     VERSIONS_XID     V
---------- --------------- ---------------- -
         2 TWO             08001B005C0D0100 I
         1 TWO             08001B005C0D0100 I

如果您在第一个insertupdate之间提交,则可以看到这三行以及它们的修改方式:

CREATE TABLE digits (id NUMBER(2), description VARCHAR2(15));
EXEC dbms_lock.sleep(10);

INSERT INTO digits VALUES (1,'ONE');
COMMIT;
EXEC dbms_lock.sleep(10);

UPDATE digits SET description ='TWO' WHERE id=1;
INSERT INTO digits VALUES (2,'TWO');
COMMIT;

SELECT id, description, versions_xid, versions_operation
FROM digits
VERSIONS BETWEEN TIMESTAMP MINVALUE AND MAXVALUE;

        ID DESCRIPTION     VERSIONS_XID     V
---------- --------------- ---------------- -
         2 TWO             060018007C0C0100 I
         1 TWO             060018007C0C0100 U
         1 ONE             05000B00450C0100 I

我不完全确定为什么需要SLEEP调用,但没有它们就不能正常工作(伪列是空白的,只显示当前数据)。我认为我没有看到过这方面的好解释,但它不太可能成为现实世界中的问题。


来自the documentation

  

指定BETWEEN TIMESTAMP ...以检索该行的版本   存在于两个时间戳之间。两个表达式都必须评估为a   timestamp值并且无法计算为NULL。 MINVALUEMAXVALUE   解析可用的最旧和最新数据的时间戳,   分别

正常情况下,MINVALUE会受到撤消保留的限制;因为这是一个新表,它将回到创建表的点,这比撤消保留少。你不能超越它,因为它没有任何意义:如果你试图在表创建时间之前使用显式时间戳值,它会告诉你表结构已经改变。您正在进行的DML / DDL区别并不是真正相关,因为您提交数据时只会看到两行。