您认为缺少的行将来自此:
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
如果您在第一个 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 调用,但没有它们就无法正常工作(伪列是空白的,只显示当前数据)。我认为我从未见过对此的良好解释,但在实际案例中这不太可能成为问题。
来自the documentation:
指定 BETWEEN TIMESTAMP ... 以检索该行的版本
存在于两个时间戳之间。两个表达式都必须计算为
时间戳值,不能评估为 NULL。 MINVALUE 和 MAXVALUE
解析最旧和最新可用数据的时间戳,
分别。
通常MINVALUE 会受到撤销保留的限制;因为这是一个新表,它会回到创建表的点,这比撤消保留要少。您不能再回头,因为它没有任何意义:如果您尝试在表创建时间之前使用显式时间戳值,它会告诉您表结构已更改。但是,您所做的 DML/DDL 区别并不真正相关,由于您提交数据的时间,您只会看到两行。