【问题标题】:Do database cursors pick up changes to the underlying data?数据库游标是否会拾取对基础数据的更改?
【发布时间】:2009-11-06 22:09:41
【问题描述】:

关于游标(尤其是 Oracle 游标)的快速问题。

假设我有一个名为“my_table”的表,它有两列,一个 ID 和一个名称。有数百万行,但名称列始终是字符串'test'。

然后我运行这个 PL/SQL 脚本:

declare
 cursor cur is
  select t.id, t.name
    from my_table t
   order by 1;
 begin
   for cur_row in cur loop
     if (cur_row.name = 'test') then
        dbms_output.put_line('everything is fine!');
     else
        dbms_output.put_line('error error error!!!!!');
        exit;
     end if;
   end loop;
 end; 
 /

如果我在运行时运行此 SQL:

 update my_table 
   set name = 'error'
  where id = <max id>;
commit;

PL/SQL 块中的光标会拾取该更改并打印出“error error error”并退出吗?或者它根本不会接受更改......或者它甚至会允许更新到 my_table?

谢谢!

【问题讨论】:

  • 你有一些代码,你为什么不运行它看看?

标签: database oracle cursors


【解决方案1】:

游标有效地运行 SELECT,然后让您遍历结果集,该结果集保存在数据库状态的快照中。因为您的结果集已经被提取,它不会受到 UPDATE 语句的影响。 (否则,您每次移动光标时都需要重新运行查询!)

见:

http://www.techonthenet.com/oracle/cursors/declare.php

【讨论】:

  • 虽然游标确实不会受到更新语句的影响,但并非所有游标将访问的数据都已预取到内存中。如果是这种情况,通常需要很长时间才能从游标中获取第一行。会发生什么情况是光标选择“在”打开时当前 SCN 的数据。这就是为什么长时间运行的查询有时会因“快照太旧”错误而失败。
  • 很好的说明,托尼。谢谢你。我会相应地更新我的答案。
  • 对于 SYBASE ASE,从 15.7 开始,您可以声明游标 INSENSITIVE,其中:“指定独立于游标所做的数据更改对游标结果集不可见。如果不指定此参数,默认为 semi_sensitive。不能更新不敏感游标。"