除了在某些情况下,sql Server开发人员认为游标是一种不好的做法.他们认为,游标不会最佳地使用sql引擎,因为它是一个程序性的构造,并且击败了基于Set的RDBMS概念.
但是,Oracle开发人员似乎并不推荐使用光标. Oracle的DML语句本身是隐式游标.
为什么这种差异的方法?是因为这两种产品的制造方式,还是这种建议适用于这两种产品?
解决方法
游标出现的问题是在Oracle和MS sql中都经常被滥用.
光标用于保持稳定的结果集,您可以逐行检索.当您的查询运行时,它们是隐式创建的,并在完成查询后关闭.
当然,保留这样的结果集需要一些资源:锁,锁存器,内存,甚至磁盘空间.
这些资源越快越好.
保持光标打开就像保持冰箱门打开
你不要在几个小时没有必要,但这并不意味着你不应该打开你的冰箱.
这意味着:
>你不会逐行得到结果,并且总结出来:你调用sql的SUM.
>您不执行整个查询并从游标获取第一个结果:您将rownum< = 10条件附加到查询中
等等
对于Oracle,在一个过程中处理你的游标需要臭名昭着的sql / PLsql上下文切换,每当你从游标中得到SQL查询的结果时,它就会发生.
它涉及在线程之间传递大量数据并同步线程.
这是Oracle中最令人激动的事情之一.
这种行为的不太明显的后果之一是如果可能,应该避免Oracle中的触发器.
创建触发器并调用DML函数等于打开游标,选择更新的行并为该游标的每一行调用触发器代码.
触发器的存在(甚至是空触发器)可能会减慢DML操作10次或更多次.
10g上的测试脚本:
- sql> CREATE TABLE trigger_test (id INT NOT NULL)
- 2 /
- Table created
- Executed in 0,031 seconds
- sql> INSERT
- 2 INTO trigger_test
- 3 SELECT level
- 4 FROM dual
- 5 CONNECT BY
- 6 level <= 1000000
- 7 /
- 1000000 rows inserted
- Executed in 1,469 seconds
- sql> COMMIT
- 2 /
- Commit complete
- Executed in 0 seconds
- sql> TRUNCATE TABLE trigger_test
- 2 /
- Table truncated
- Executed in 3 seconds
- sql> CREATE TRIGGER trg_test_ai
- 2 AFTER INSERT
- 3 ON trigger_test
- 4 FOR EACH ROW
- 5 BEGIN
- 6 NULL;
- 7 END;
- 8 /
- Trigger created
- Executed in 0,094 seconds
- sql> INSERT
- 2 INTO trigger_test
- 3 SELECT level
- 4 FROM dual
- 5 CONNECT BY
- 6 level <= 1000000
- 7 /
- 1000000 rows inserted
- Executed in 17,578 seconds
1.47秒没有触发,17.57秒用空触发器什么也没做.