SQL Story(十)————游标的应该与不应该 (转)
游标概观
相信很多Delphi程序员都写过这样的代码:
...
begin
MyDataSet.Open;
MyDataSet.Frist;
while not ( MyDataSet.BOF or MyDataSet.EOF) do
begin
...
end;
MyDataSet.Close;
end;
...
很久以来,我们习惯了用这样的代码对数据库返回的数据进行逐行操作。在用客户端程序的代码打开数据集之前,我们把它当做是一个无序集合。不过,在需要时,我们在服务器端就可以直接以行操作形式处理数据集,这就是游标。
游标的的使用方法类似前面的Delphi代码,通常有如下四步:
一、声明游标:Declare Cursor,这一过程在前面的代码中没有体现出来。然而我们都知道,在使用一个数据集之前,我们总要定义它的种种属性,比如数据源、sql语句、打开方式等等。在游标中,数据源一般是不用指定了(因为就在当前数据库中,MS SQL SERVER中也可以通过SQL语言来读取异构数据源)。不过我们要为它指定一个数据集,还可以为它指定各种打开方式的设置,比如是否允许写操作,是否可以随机读取等等。一般来说,数据库系统默认的游标是只读、单向、逐行读取的。
二、打开游标:Open Cursor,一个Delphi(或其它开发平台)的数据集组件,在指定了各种必要属性后,还一定要用一个打开指令(如前面的MyDataSet.Open)来打开它,才能得到我们所需要的数据集,对于游标,我们也一样需要一个Open指令来打开它,才能使用。
三、操作数据:这一步骤通常包括移动当前游标、读取当前数据、操作代码三部分。前面设置的游标属性,很大一部分是关于这里面所能进行什么样操作的。比如,对于双向游标,我们可以向前或向后一行,而随机游标,我们甚至可以以随机方式指定游标的操作位置,但最常见的游标,是单向、只读的那一种。而对于当前行数据,我们能常是通过定义一些变量来读取,或移动到适当位置再进行写操作,这一点和一般的开发工具是一样的。至于操作代码,这虽然不是SQL的强项,但一般的数据库系统也提供基本的过程化编码能力,可以让我们完成操作。
四、关闭结果集:Close Cursor 做事要有始有终,在Delphi中,如果忘了关闭自己打开的数据集,会带来很多麻烦,而在数据库系统中,如果打开一个游标没有关上(想想吧,游标操作是要对数据上锁的),如果有很多用户都在执行这段有问题的代码……所以,在游标的标准语法中,有明确的语句,用来关闭数据集,并释放所占用的各种资源。这一点更像是OO语言中的析构函数,比Delphi的数据集组件的Close方法要做的事情要多一些。
以上各个步骤,SQL标准都约定了相应的实现代码。但具体到各个dbMS平台的实现,却是大同小异。问题就在于这一点不同之处足以把人烦死。所以,我在这里不具体写出实现方法。读者完全可以查阅自己使用的系统所带的帮助文件,看看自己用的数据库是如何实现的游标,实现了哪些功能。
不合理的存在
我们可以看到,游标与SQL语言的其它部分有相当大的差别。它的实现和操作很复杂,而且由于要逐行操作,完成同样功能的情况下,它通常比集合操作要慢。差距会有多大呢?举一个极端的例子:我曾经试验用游标给一个表填充行号,结果执行了十二个小时都没有完,而同样的操作,用前面文章提到过的不等联接,只要不到三秒钟。我保证不是所有情况下差距都会有这么大,但这种情况的确存在。特别是当大量并发任务存在时,这种长时间的锁定是很危险的。复杂和低效,是游标的最大缺点,仅仅为这两点,就足以让我们对它抱有一种谨慎的态度。而且,一般来说,需要用游标进行的操作,都可以在客户端完成(能过所谓的宿主语言,Host Language)。
也许,在极端的关系模型拥护者看来,游标是一个丑恶的存在。在一个完美、优雅,以无序的集合来管理信息的体系中,我们为什么要安置一个以有序方式逐行操作信息的游标呢?然而,正如《龙枪编年史》中,伊斯塔城神圣的帕拉丁神殿,却游荡着有史以来最黑暗的黑衣法师费斯坦但提勒斯,在庞大严谨的关系数据库中,有游标这样的另类存在。这是创造关系世界的众神之旨意,自有其道理。
存在即合理
游标虽有如此的缺憾,但它也有存在的价值。首先,当需要有序操作的数据集很大时,特别是最终的运算结果相对很小时,如果还要发到前台做,对网络资源的浪费就太大了。而且,一个很大的数据集传过来,宿主语言也不一定能支持这么庞大的数据结构(比如Delphi的VCL容器在这方面就倍受指责),这一点也限制了我们用宿主语言来扩充系统功能 (比如MS SQL Server和Interbase本来可以写扩展函数和扩展存储过程)。另外,如果要大量的逐行的写操作,与前台交互通常效率更低。游标的确不是好方法,但没有更好的方法时,它就是最好的方法。再就是以我的经验,以脚本写就的游标要比宿主语言编译后的二制代码的可维护性和可调试性要强。
俗世之中,是没有绝对的黑暗和光明的。关键,在于我们是否正确的利用它。
正确使用游标
游标本身没有所谓的对错,但在使用它时,我们应先三思而后行。
很多时候,游标未必是你想像中的唯一方法。我见过太多的游标脚本,本来都可以用更简洁高效的结构化操作完成。只要简单语句可以达到同样的效果,就不要用游标。《程序员》上读到过一句话:Simple is smart。这是软件开发的真理。
游标中,显然只读、单向的游标速度最快,而且也不容易造成死锁,尽可能用它吧。
在游标使用的表上,建立适当的索引,这么做带来的效率提高会比一般的SQL语句更明显,尤其是执行写操作的游标。
游标操作的结果集,要尽可能的小。
如果游标代码中有大量的运算,那么考虑是不是把它分散开,放到其它服务器或客户端。
对游标代码要进行充分的测试和验证,再投入使用,尤其是优化程序和稳定性。这方面不能相信系统。比如你写一个游标,每读一行把一个变量累加一,系统永远也不会主动把它优化成count(*)。
有些系统可以把当前事务打开的游标保持到以后的事务中,直到显示地关闭它。不过最好不要随便使用它。这个功能当然看起来很酷,不过滥用它会给我们带来无穷无尽的麻烦。你真的需要这种功能吗?
适当的时候,把它写成扩展存储过程或扩展存储函数,以二进制代码的形式链接进数据库系统。这样做的缺点是失去了灵活性,换来的是效率的提升。
附:
以前一直不会在Interbase的ISQL中输入多条成批执行的语句,所以什么存储过程、触发器、甚至于游标,都建不起来。直到有一天,注意了一下,发现在ISQL中是这样做的:
set term^;
...
^
...
^
...
set term;^
从第一行set term^;开始,ISQL会把用^分隔开的语句成组地发至后台执行,直至set term;^为止。有点像MS SQL Server的查询分析器的“GO”。这样,我们就可以自如地用ISQL编写脚本了。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10752043/viewspace-992766/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/10752043/viewspace-992766/
SQL Story(十)————游标的应该与不应该 (转)相关推荐
- 【Oracle】PL/SQL 显式游标、隐式游标、动态游标
在PL/SQL块中执行SELECT.INSERT.DELETE和UPDATE语句时,Oracle会在内存中为其分配上下文区(Context Area),即缓冲区.游标是指向该区的一个指针,或是命名一个 ...
- SQL Server的游标
SQL中的游标,可以用在过程或者作业中. Declare @eventid varchar(50) Declare cur_name cursor for select --Selectxxxxx ...
- 【校招VIP】数据库基础之sql五十道题
考点介绍: 数据库在测试工程师的面试过程中也是常问的一项.面试有一定的层次性,如bat级别公司每个点都会深入,而有些公司则只会问到表层,所以每个领域都分为必须掌握和深入了解这两个部分. 本期分享的数据 ...
- [20161228]sql语句父子游标的堆转储2.txt
[20161228]sql语句父子游标的堆转储2.txt --以前仅仅看了父游标堆0的堆转储,链接:http://blog.itpub.net/267265/viewspace-2076605/ -- ...
- SQL Server之游标的基础知识
什么是游标: 游标是可以在结果集中上下游动的指针. 游标的作用: --允许定位到结果集中的特定行. --从结果集的当前位置检索一行或多行数据. --支持对结果集中当前位置的行进行修改. 注意:游标虽然 ...
- oracle sql developer 查看游标结果集(3.0.04
http://space.itpub.net/23065269/viewspace-714035 以前在oracle sql developer里,要查看存储过程的结果集,只能是通过写个函数来查看,这 ...
- access update语句执行_SQL Server与Access数据库sql语法十大差异
本文总结了SQL Server与Access数据库sql语法的十大差异. ACCESS结构简单容易处理,而且也能满足多数的应用程序要求,也是初学者的试牛刀. 随着时间的推移,大多数数据库应用程序都会发 ...
- 游标sql server_SQL Server游标教程
游标sql server 介绍 (Introduction) 大多数使用Microsoft SQL Server的人至少会听说过游标,而且即使人们基本了解SQL Server游标的作用,他们也不总是确 ...
- 游标sql server_SQL Server游标属性
游标sql server A SQL Server cursor is a database object that is used to process the data in a set row ...
- 游标sql server_SQL Server游标性能问题
游标sql server 介绍 (Introduction) 在上一篇文章中,我们讨论了如何设置基本游标. 我们解释了游标是基于行的操作,它采用给定的SELECT语句并将数据处理分解为循环执行. 没有 ...
最新文章
- springboot 配置多线程
- C/C++中的连续赋值
- js下拉 selenium_selenium 常见面试题以及答案(Java版)
- OrchardCore实现模块化核心原理分析
- Designing Virtual Connect for vSphere 5.x
- 用php web编程作业,用PHP进行Web编程.ppt
- 如何将原图和json融合_用 base64 进行图片和字符串互转,并保存至 json
- Spring实现多数据源配置
- 为什么接口在设计时所有的方法一般都要抛异常?
- 程序员面试金典——7.4加法运算替代
- 为什么基于接口而非实现编程?
- C/C++ 活动预处理器
- ad 4层板设计实例文件_独家数据 | 1619Fall美研传媒类专业1590+申请实例(含大众传播、新闻学、公共关系、新媒体、整合营销等)...
- Java加密方式(AES,DES,RSA,DSA,MD5)
- R语言教程(1)——基础知识
- ttest求pvalue_TTEST 在EXCEL计算出的结果是t还是p值
- 科普|2022软交换设备测试项目,交换机进网认证、CTA认证
- SAP WRITE设置列表颜色 页眉页尾输出控制
- Mercury mw150us(8188eu) debian wireless driver
- 液晶面板里面有些什么配件_液晶显示器参数和部件详细介绍