只听别人说使用游标不好,但不知道为什么不好,请大家帮助解答,谢谢~~

解决方案 »

  1.   

    --用游标的好处是:用SQL语句无法满足其业务规则出其相应数据的情况下,
    --此时:只能用游标或者循环了(其实简单理解:游标就是循环......)
      

  2.   


    一、声明游标: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(*)。有些系统可以把当前事务打开的游标保持到以后的事务中,直到显示地关闭它。不过最好不要随便使用它。这个功能当然看起来很酷,不过滥用它会给我们带来无穷无尽的麻烦。你真的需要这种功能吗?适当的时候,把它写成扩展存储过程或扩展存储函数,以二进制代码的形式链接进数据库系统。这样做的缺点是失去了灵活性,换来的是效率的提升。
      

  3.   

    --呵呵:具体问题,具体对待,我就喜欢用游标,
    --现在“无语”还好,哪天老板问你要速度的时候,复杂的子查询只会令你更“无语”!http://topic.csdn.net/u/20091005/16/00ea7542-d5b3-46f6-9d34-81aa2d831643.html
      

  4.   


    大家探讨一下也挺好的,其实这个帖子当时也看到了,不过直接的想法就是干吗不在外部应用里面实现呢?
    .net或者java链接一下数据库直接循环几次hashmap也就做到了觉得探讨sql的终极用法挺好,但是也不要所有东西都放在sql语句里了,毕竟sql只是一个脚本类语言,和外部的编程语言还是有差距的
      

  5.   

    --没有“攻击”的意思,
    --在具体问题面前,你就会知道,看似“简单”的几行SQL语句,在“效率”面前,竟是如此的不堪一击!
      

  6.   

    --问题一出来,第一次想到的就是:能用SQL语句的就尽量用SQL语句,从来不去考虑有没有其他的办法,让其效率更高,这不是固执是什么?
      

  7.   

    游标对于拼一些特殊的报表还是很方便的,有时候不管你的sql如何嵌套都查不出想要的结果这个时候就要考虑游标了
      

  8.   

    ----------楼主:请去看看:到底是游标的速度低,还是嵌套子查询的速度低!
    http://topic.csdn.net/u/20091017/21/dbe5ac2a-a006-46a3-811e-1b4f6798e897.html?17537
      

  9.   

    引用llj0209013贴内容二、不要使用游标 
    让我再重复一遍:不要使用游标。如果你想破坏整个系统的性能的话,它们倒是你最有效的首选办法。大多数的初学者都使用游标,而没有意识到它们对性能造成的影响。它们占用内存,还用它们那些不可思议的方式锁定表,另外,它们简直就像蜗牛。而最糟糕的是,它们可以使你的DBA所能做的一切性能优化等于没做。不知你是否知道每执行一次FETCH就等于执行一次SELECT命令?这意味着如果你的游标有10000条记录,它将执行10000次SELECT!如果你使用一组SELECT、UPDATE或者DELETE来完成相应的工作,那将有效率的多。 
    初学者一般认为使用游标是一种比较熟悉和舒适的编程方式,可很不幸,这会导致糟糕的性能。显然,SQL的总体目的是你要实现什么,而不是怎样实现。 
    我曾经用T-SQL重写了一个基于游标的存储过程,那个表只有100,000条记录,原来的存储过程用了40分钟才执行完毕,而新的存储过程只用了10秒钟。在这里,我想你应该可以看到一个不称职的程序员究竟在干了什么!!! 
    我们可以写一个小程序来取得和处理数据并且更新数据库,这样做有时会更有效。记住:对于循环,T-SQL无能为力。 
    我再重新提醒一下:使用游标没有好处。除了DBA的工作外,我从来没有看到过使用游标可以有效的完成任何工作。 
      

  10.   


    http://topic.csdn.net/u/20091017/21/dbe5ac2a-a006-46a3-811e-1b4f6798e897.html