您认为缺少的行将来自此:
INSERT INTO digits VALUES (1,'ONE');
...但数据从未在该状态下提交,因为:
UPDATE digits SET description ='TWO' WHERE id=1;
...发生在您的COMMIT
. 因此,这与您引用的语句一致,1, ONE
不是该行的承诺出现。从来没有任何时间点可以让另一个会话看到这些值。
如果您查看版本数据伪列,您可以看到这两行都被视为带有当前数据的插入:
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
如果您在第一行之间提交insert
,update
您可以看到三行以及它们是如何修改的:
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
需要调用,但没有它们就无法正常工作(伪列是空白的,只显示当前数据)。我认为我从来没有见过一个很好的解释,但在现实世界的案例中这不太可能成为问题。
从文档中:
指定BETWEEN TIMESTAMP ...
检索存在于两个时间戳之间的行的版本。两个表达式都必须计算为时间戳值,并且不能计算为 NULL。MINVALUE
并MAXVALUE
分别解析为最旧和最新可用数据的时间戳。
通常MINVALUE
会受到撤消保留的限制;因为这是一个新表,它会回到创建表的点,这比撤消保留要少。您不能再回头,因为它没有任何意义:如果您尝试在表创建时间之前使用显式时间戳值,它会告诉您表结构已更改。但是,您所做的 DML/DDL 区别并不真正相关,由于您提交数据的时间,您只会看到两行。