【问题标题】:Can a rowid be invalidated right after being inserted in Oracle?插入Oracle后可以立即使rowid失效吗?
【发布时间】:2009-09-29 18:09:10
【问题描述】:

我正在运行如下所示的查询:

INSERT INTO foo (...) VALUES (...) RETURNING ROWID INTO :bind_var

SELECT ... FROM foo WHERE ROWID = :bind_var

本质上,我插入一行并获取其 ROWID,然后对该 ROWID 进行选择以从该记录中取回数据。不过,偶尔会找不到 ROWID。

忽略可能有更好的方法来做我想做的事情这一事实,假设没有其他人使用数据库,ROWID 是否有可能快速更改?

UPDATE 涉及到一个触发器。这是它的 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 字段。这个触发器有问题吗?

【问题讨论】:

    标签: sql oracle plsql oracle10g rowid


    【解决方案1】:

    ROWID 不会改变,除非:

    • 例如,您将表从一个表空间移动到另一个表空间 (ALTER TABLE t MOVE)
    • 行从一个分区切换到另一个分区(使用 ENABLE ROW MOVEMENT 的分区表)
    • 您更新了 INDEX ORGANIZED 表的主键。

    当标准 (HEAP) 表中的一行从一个块移动到另一个块时,例如,由于它变得太大以至于无法放入其原始块中,它将被迁移。 Oracle 将留下一个指向新块的指针并移动该行。该行将保留其原始 ROWID。

    可以依赖 ROWID,例如,它们用于复制以刷新物化视图。

    【讨论】:

    • 此外,ALTER TABLE MOVE 并不是移动表的唯一方法,而且它无论如何都需要表锁。在线表重新定义更有可能表现出这种行为,因为新插入很可能会在“旧”和“新”段之间移动。
    【解决方案2】:

    您的 INSERT 应该是:

    INSERT INTO foo 
      (primary_key,
       ...) 
    VALUES 
      (log_elig_demographics_seq.nextval,
       ...) 
    RETURNING primary_key INTO :bind_var
    

    不需要触发器。

    【讨论】:

      【解决方案3】:

      我同意沃尔特的观点。

      而不是

      插入 foo (...) 值 (...) 返回 ROWID 到 :bind_var SELECT ... FROM foo WHERE ROWID = :bind_var


      ...为什么不执行以下操作?

      选择primaryKey_seq.nextVal INTO bind_var 从双; INSERT INTO foo (primaryKeyColumn,...) 值(绑定变量,...); SELECT ... FROM foo WHERE primaryKeyColumn = bind_var;

      【讨论】:

        【解决方案4】:

        可能还会发生其他一些事情。 首先,INSERT 可能失败。你在检查错误/异常吗?如果不是,可能变量中的值是垃圾。

        其次,您可以插入可以选择的内容。虚拟专用数据库/行级安全可能是负责任的。

        第三,如果您在插入和选择之间提交,延迟约束可能会强制回滚插入。

        第四,也许你正在回滚。

        【讨论】:

          【解决方案5】:

          表上是否有可能正在反转插入的触发器?

          【讨论】:

          • 有一个触发器从序列中创建主键。但它不应该反转插入。我将使用触发器的 DDL 语句更新我的问题。
          【解决方案6】:

          根据我的经验,发生此类错误的最可能原因是介于两者之间的某个地方发生了回滚。或者,如果有一个提交,另一个用户可能已经删除了该记录。

          【讨论】:

            【解决方案7】:

            绑定变量是如何声明的?在 SQLPlus 中,您不能使用 ROWID 类型,因此需要进行类型转换。我想知道这是否有可能在某些时候改变了 ROWID 值。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2013-02-16
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-01-04
              • 2015-09-07
              • 1970-01-01
              相关资源
              最近更新 更多