使用ROWID在Oracle中查找行/记录是否安全?

时间:2012-07-20 20:06:51

标签: sql oracle oracle-sqldeveloper

我正在查看一个客户端应用程序,该应用程序检索包括ROWID在内的多个列 稍后使用ROWID来标识需要更新的行:

update some_table t set col1=value1
where t.rowid = :selected_rowid

这样做是否安全?在修改表时,行ROWID可以更改吗?

3 个答案:

答案 0 :(得分:7)

“从Oracle 8开始,ROWID格式和大小从8更改为10个字节。请注意,重组或导出/导入表时ROWID会发生更改。如果是分区表如果行在UPDATE期间从一个分区迁移到另一个分区,它也会发生变化。“

http://www.orafaq.com/wiki/ROWID

我会说不。例如,如果应用程序临时存储ROWID(例如生成可选项目列表,每个项目都标有ROWID,但列表经常重新生成而不存储),这可能是安全的。但如果以任何持久的方式使用ROWID,那就不安全了。

答案 1 :(得分:6)

假设您在ROWID之后的短时间内使用SELECT,表格是一个标准的堆组织表,并且DBA没有对table(如果应用程序在线,这是一个相当安全的假设),ROWID将是稳定的。最好使用主键,但是当主键不可用时,许多Oracle开发的工具和框架将在短时间内使用ROWID。如果您打算在ROWID之后很长一段时间内使用SELECT,那将是不安全的 - 例如,如果您允许用户在本地编辑数据然后与主数据库同步一些任意长度的时间。

ROWID只是行的物理位置,因此导致该位置发生变化的任何内容都会更改ROWID

  • 如果您使用的是索引组织表或分区表,则行的更新可能会更改行的实际位置,这将更改ROWID
  • 如果从堆组织表中删除行,则后续INSERT可能会插入具有完全不同数据的数据,这些数据碰巧使用之前已删除行的ROWID {。}}。
  • 各种管理任务可能导致ROWID发生变化。例如,导出和导入表将更改ROWID,但是会执行类似new-ish online shrink命令的操作。但是,这些管理任务通常不会在应用程序启动时完成,并且几乎肯定不会在白天完成。但是,当DBA执行此类操作或应用程序持久保存数据时,如果应用程序未关闭,则可能会导致问题。

随着时间的推移,新功能为ROWID s引入新的可能性变得越来越普遍。例如,索引组织表和在线收缩选项是相对较新的功能。将来,可能会有更多功能涉及至少ROWID更改的潜力。

当然,如果我们迂腐,依靠主键也是不安全的。完全可能的是,某些其他会话出现并在您读取后更新该行的主键,或者某个其他会话在您选择它之后删除该行并插入具有相同数据和不同主键的新行。在任何一种情况下,都有一些关于使用数据库的应用程序实际上应该做什么的本地知识是有帮助的。例如,允许更新主键或重用主键非常罕见,因此您通常可以确定使用主键是安全的。类似地,相对常见的结论是,鉴于您使用分区的方式或者您已经在索引组织表中定义索引的方式,更新实际上不会更改ROWID。例如,如果您知道该表已由LOAD_DATE分区,并且您永远不会更新LOAD_DATE,则由于更新,您实际上不会对ROWID进行更改。如果您知道该表是由索引组织的,但您没有更新属于该索引的列,则ROWID上的UPDATE不会更改。

答案 2 :(得分:4)

我不认为这样做是安全的,理论上它不会改变,当然直到有人“意外地”删除了实际数据库中的某些内容......

我只是使用PK更有意义。