在插入Oracle后,rowid可以立即失效吗?

时间:2009-09-29 18:09:10

标签: sql oracle plsql oracle10g rowid

我正在运行看起来像这样的查询:

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字段。这个触发器有问题吗?

7 个答案:

答案 0 :(得分:3)

除非:

,否则ROWID不会改变
  • 您将表格(ALTER TABLE t MOVE)从一个表空间移动到另一个表空间,例如
  • 行从一个分区切换到另一个分区(具有ENABLE ROW MOVEMENT的分区表)
  • 您更新了INDEX ORGANIZED表的主键。

当一行在标准(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值。