FETCH/FOR之间的区别是在PL/SQL中循环CURSOR

Jim*_*mmy 14 sql oracle plsql cursor

我知道获取光标将允许我访问%ROWCOUNT,%ROWTYPE,%FOUND,%NOTFOUND,%ISOPEN等变量

...但我想知道是否还有其他原因可以使用

Open - Fetch - 关闭循环游标的指令

而不是

用FOR循环循环光标......(在我看来这更好,因为它很简单)

你怎么看?

Jus*_*ave 27

从性能的角度来看,差异比OMG Ponies所暗示的蒂姆霍尔提示要复杂得多.我相信这个提示是对一个较大的部分的介绍,该部分已经被网络摘录 - 我希望Tim继续在书中创造大部分(如果不是全部的话).此外,整个讨论取决于您使用的Oracle版本.我相信这对于10.2,11.1和11.2是正确的,但如果你开始回到旧版本,肯定存在差异.

首先,提示中的特定示例是不切实际的.我从未见过有人使用显式游标而不是SELECT INTO编写单行提取代码.因此,SELECT INTO更高效的事实具有非常有限的实际重要性.如果我们讨论循环,我们感兴趣的性能是获取许多行的成本是多少.这就是复杂性开始出现的地方.

Oracle引入了从游标到10.1中的PL/SQL集合进行BULK COLLECT数据收集的能力.这是一种将数据从SQL引擎传递到PL/SQL集合的更有效方法,因为它允许您通过一次获取多行来最小化上下文移位.对这些集合的后续操作更有效,因为您的代码可以保留在PL/SQL引擎中.

但是,为了最大限度地利用BULK COLLECT语法,您通常必须使用显式游标,因为这样您可以填充PL/SQL集合,然后使用FORALL语法将数据写回数据库(在合理的假设是,如果你在游标中获取一堆数据,很有可能你正在进行某种操作并在某处保存操纵数据).如果在FOR循环中使用隐式游标,正如OMG Ponies正确指出的那样,Oracle将在幕后进行BULK COLLECT以使得获取数据的成本更低.但是您的代码将逐行插入和更新,因为数据不在集合中.

通常,假设您使用的是10.2或更高版本并且您的代码正在获取数据并将其写回数据库,

最快的

  1. 显式游标将BULK COLLECT执行到本地集合(具有适当的LIMIT)并使用FORALL写回数据库.
  2. 隐式游标在幕后为您执行BULK COLLECT以及单行写回数据库.
  3. 显式游标没有进行BULK COLLECT而没有利用PL/SQL集合.

最慢

另一方面,使用隐式游标可以在重构旧代码或学习新功能时使用批量操作获得很少的前期成本.如果您的大多数PL/SQL开发都是由主要语言不同或者不一定能跟上新语言特性的开发人员完成的,那么FOR循环将比使用全部的显式游标代码更容易理解和维护.新的BULK COLLECT功能.当Oracle在未来引入新的优化时,隐式游标代码更有可能自动获得好处,而显式代码可能需要一些手动返工.

当然,当您对性能进行故障排除时,您真正关心循环代码的不同变体可能会有多快,您通常会考虑将更多逻辑转移到纯SQL中并完全抛弃循环代码.

  • +1,很好的答案.在实践中,我已经看到了第1项优于列表中第2项的好处. (6认同)
  • 虽然我很惊讶你说"我从未见过有人使用显式游标而不是SELECT INTO编写单行提取代码".我看到它很多,它让我非常烦恼.我个人责备史蒂夫·费尔斯坦(Steve Feuerstein)曾经(他已经撤回)曾经写过,出于性能原因,应该总是使用explcit游标而不是SELECT..INTO. (5认同)

OMG*_*ies 7

OPEN/FETCH/CLOSE称为显式游标语法; 后者称为隐式游标语法.

你已经注意到的一个关键区别是你不能在隐式游标中使用%FOUND /%NOTFOUND /等...另外需要注意的是隐式游标比显式游标更快 - 它们会提前读取(〜 100条记录?)除了不支持显式逻辑.

附加信息: