我正在运行看起来像这样的查询:
INSERT INTO foo (...) VALUES (...) RETURNING ROWID INTO :bind_var
SELECT ... FROM foo WHERE ROWID = :bind_var
基本上,我正在插入一行并获取其ROWID,然后针对该ROWID进行选择以从该记录中获取数据。但偶尔会发现ROWID。
忽略这样一个事实:可能有更好的方法来做我正在尝试做的事情,是否有可能ROWID快速改变,假设没有其他人使用数据库? / p>
更新涉及触发器。这是它的DDL语句:
CREATE OR REPLACE TRIGGER "LOG_ELIG_DEMOGRAPHICS_TRG"
before insert on log_elig_demographics
for each row
begin
select log_elig_demographics_seq.nextval into :new.log_idn from dual;
end;
基本上,它只是一个触发器,用于帮助我们模拟IDENTITY / AUTO INCREMENT字段。这个触发器有问题吗?
答案 0 :(得分:3)
除非:
,否则ROWID不会改变当一行在标准(HEAP)表中从一个块移动到另一个块时,因为它变得如此之大以至于无法适应其原始块,例如,它将被迁移。 Oracle将保留指向新块的指针并移动该行。该行将保留其原始的ROWID。
可以依赖ROWID,例如,它们用于复制以刷新物化视图。
答案 1 :(得分:2)
你的INSERT应该是:
INSERT INTO foo
(primary_key,
...)
VALUES
(log_elig_demographics_seq.nextval,
...)
RETURNING primary_key INTO :bind_var
不需要触发器。
答案 2 :(得分:2)
我同意沃尔特的意见
而不是
INSERT INTO foo (...) VALUES (...) RETURNING ROWID INTO :bind_var SELECT ... FROM foo WHERE ROWID = :bind_var
......为什么不这样做呢?
SELECT primaryKey_seq.nextVal INTO bind_var FROM dual; INSERT INTO foo (primaryKeyColumn,...) VALUES (bind_var,...); SELECT ... FROM foo WHERE primaryKeyColumn = bind_var;
答案 3 :(得分:2)
可能还会发生其他一些事情。 首先,INSERT可能失败。你在检查错误/例外吗?如果没有,可能变量中的值是垃圾。
其次,您可以插入可以选择的内容。虚拟专用数据库/行级安全可能是负责任的。
第三,如果在insert和select之间提交,则延迟约束可能会强制回滚插入。
第四,也许你正在做回滚。
答案 4 :(得分:1)
桌面上是否有可能正在反转插入的触发器?
答案 5 :(得分:1)
根据我的经验,发生此类错误的最可能原因是介于两者之间,发生了回滚。或者,如果有提交,则另一个用户可能已删除该记录。
答案 6 :(得分:1)
如何声明绑定变量?在SQLPlus中,您不能使用ROWID类型,因此正在进行类型转换。我想知道这是否有可能在某些时候改变了ROWID值。