存储过程:光标坏了?

Posted

技术标签:

【中文标题】存储过程:光标坏了?【英文标题】:Stored Procedure: Cursor is bad? 【发布时间】:2012-06-05 21:42:12 【问题描述】:

我在某处读到 99% 的时间不需要使用光标。

但我想不出在以下情况下除了使用光标之外的任何其他方式。

Select t.flag
From Dual t; 

假设这会返回 4 行 'Y''N'。我希望该过程在找到'Y' 时触发某些东西。我通常声明一个游标并循环直到%NOTFOUND。请告诉我是否有更好的方法。

另外,如果您有任何想法,什么时候是使用光标的最佳时间?

编辑:不是插入标志,而是如果我想做 “如果 'Y' 然后触发某些东西”

【问题讨论】:

wiki.lessthandot.com/index.php/Cursors_and_How_to_Avoid_Them ***.com/questions/1479680/… 在您的查询中添加where t.flag = 'Y'? ...INSERT INTO tbl_flag (<column list>) VALUES (<values>) WHERE (SELECT COUNT(*) FROM Dual t where t.flag = 'Y') > 1 mysql、T-SQL 和dual/%NOTFOUND(暗示Oracle)? 是的,它是甲骨文。对此感到抱歉...正如我编辑过的那样,如果 Select 查询具有“Y”,我会尝试触发 【参考方案1】:

你的情况肯定落入 99%。

您可以使用insert into ... select... 轻松进行条件插入。这只是一个问题或创建一个select 来返回您想要插入的结果。

如果您想为每个 'Y' 插入一条记录,请使用带有 where flag = 'Y' 的查询。如果您只想根据是否至少有一个'Y' 插入一条记录,则可以将distinct 添加到查询中。

当您使事情变得更复杂时,光标很有用。例如,当需要在一个表中插入或更新记录时,我使用游标,并且还为每条记录插入或更新一条或多条记录到其他几张表中。

【讨论】:

触发一些东西怎么样?如果它找到“Y”,则放入一些已创建的值或执行某些操作? @sayhaha:那你可以使用if exists(select * from Dual where Flag = 'Y')【参考方案2】:

类似这样的:

INSERT INTO TBL_FLAG (col)
SELECT ID FROM Dual where flag = 'Y'

当使用基于集合而不是过程操作时,您通常会看到性能提升,因为大多数现代 DBMS 都设置为执行基于集合的操作。你可以阅读更多here。

【讨论】:

触发一些东西怎么样?如果它找到“Y”,则放入一些已创建的值或执行某些操作? 我不确定你在问什么,但在这种情况下你不需要触发器。 :p 对不起所以假设我运行 select * from dual;它返回 4 行 'Y', 'N', 'N', 'Y' 然后由于系统找到 'Y' 我想从 TABLE1 中查询一个值并将其放入 TABLE2。【参考方案3】:

这个例子不太合理..

但你总是可以写一个insert as select 声明而不是我认为你描述的内容

【讨论】:

【参考方案4】:

当来自一个表的列值将在不同表的多个查询中重复使用时,最好使用游标。

假设 id_test 列的值是使用游标 CUR_TEST 从 MY_TEST_TBL 获取的。现在这个 id_test 列是 MY_TEST_TBL 中的一个外键。如果我们想使用 id_test 来插入或更新表 A_TBL、B_TBL 和 C_TBL 中的任何行,那么在这种情况下最好使用游标而不是使用复杂的查询。

希望这可能有助于理解光标的用途

【讨论】:

以上是关于存储过程:光标坏了?的主要内容,如果未能解决你的问题,请参考以下文章

ORACLE 存储过程光标运行缓慢

存储过程中的光标完成并卡住(Oracle Linux VM 上的 Oracle 11g)

使用游标的存储过程

存储过程和函数

DB2 - 在光标中聚合大小写

oracle 存储过程调用