在 Oracle 上使用 rownum 更新具有递增 ID 的表是不是安全?

Posted

技术标签:

【中文标题】在 Oracle 上使用 rownum 更新具有递增 ID 的表是不是安全?【英文标题】:Is the use of rownum safe to update a table with incremented IDs on Oracle?在 Oracle 上使用 rownum 更新具有递增 ID 的表是否安全? 【发布时间】:2013-02-27 20:53:13 【问题描述】:

类似于mysql 我想用增量值更新(填充)一个空列——使用Oracle。 IE。之后

ALTER TABLE data ADD
(
  id  number
);

我希望ID 列的所有记录都接收唯一值。之后,我将启用 Not Nullunique 约束,使其成为主键

我很快想到了

UPDATE TABLE data SET id = rownum;

但我对此有不好的预感。它在我的测试中按预期工作,但一个例子不能证明:-)

update 语句中以这种方式使用rownum 是否安全?

【问题讨论】:

@knagaev 这是一个不同的问题,与此无关。无论如何,我必须填充现有行的数据单元格。 为什么不同?您可以使用“UPDATE TABLE data SET id = seq.nextval”获得所需的唯一值。这将是交易安全的解决方案。 @knagaev 哦,感谢您的解释,我必须尝试一下(我目前不在数据库附近)。我假设seq.nextval 只会被评估一次。 请仔细查看 Oracle 中的序列 - 这是重要的事情之一。它们的工作速度非常快,可以让您避免潜在的事务隔离问题。 @knagaev 是的,我也不喜欢max(id)+1 :-) 我试过了,它有效。 【参考方案1】:

不,这不安全,因为 ROWNUM 是伪列。意味着它不保证顺序,尤其是与 ORDER BY 一起使用时。如果必须,请使用 ROW_NUMBER() OVER (ORDER BY your_field) 而不是 ROWNUM。您也可以在循环中使用 PL/SQL 更新您的表。

【讨论】:

对于预期目的是安全的。 我认为如果“your_field”和主键值之间存在某种隐含的相关性,那么它就不会是一个非常好的“无意义”主键。 至少你的回答表明我的担忧并非完全没有根据。 @a_horse_with_no_name - 如果您可以在伪列与序列和函数(如 row_number())之间进行选择,那么使用伪列是绝对不安全和可取的。如果您有 row_number(),使用 rownum 有什么意义?固执?不考虑未来的影响?任何人都可以确定未来的影响吗?这是/是我的观点和观点。 由于需要排序,row_number() 函数可能更昂贵(=更慢)。 rownum 可以“即时”评估,无需任何额外开销。在这种情况下,它可以安全使用的。【参考方案2】:

是的,我从来没有遇到过这种方法的问题,但是启用非空和唯一约束不会使其成为主键——添加主键约束使其成为主键;)

【讨论】:

【参考方案3】:

很可能,您的方法是安全的。如果没有,如果唯一约束失败,您会收到通知:-)。

防弹方法如下:

lock table data in exclusive mode;

merge into data t
using (select t.rowid rid, t.rownum id from data t) s
on (t.rowid = s.rid)
when matched then update set
  t.id = s.id;

commit;

【讨论】:

merge 不是必需的,简单的更新会做同样的事情。 第一个问题中的update。这完全没问题(你的merge 会做同样的事情——只是稍微复杂一点)。 你用什么防弹? 反对另一个会话同时修改同一个表(这可能导致id列中的空值)。唯一约束也应该在提交之前(或代替)设置。 好吧,从这个意义上说,锁使它更健壮,但我认为不是 MERGE。

以上是关于在 Oracle 上使用 rownum 更新具有递增 ID 的表是不是安全?的主要内容,如果未能解决你的问题,请参考以下文章

oracle 分页 有无order by情况不同吗

gp里用啥代替oracle里rownum,用啥代替rowid???

#SQL #QUERY #ROWNUM #ORACLE

Oracle中rownum的说明及使用技巧

Oracle 分页查询rownum的用法

在oracle数据库表中没有添加rowid字段为啥会出现