这听起来像一个愚蠢的问题,但我希望我会让自己不够清晰。
- 在谈到面条代码 ,它的基础是GOTO语句的使用。 我不得不说是用来说,如果我把一个断点在代码的结尾,并没有达到这个断点,每次,什么是错的同行。
- 然而,是一种常见的(和我说,规则)使用
EXIT WHEN
Oracle包内的结构(通常后跟一个%NOTFOUND
测试)。
理所当然,使用EXIT
打破了编程流程,是不是不1和2之间的匹配吗?
下面是一个不好的做法,大家编程PL / SQL? 难道PL / SQL不遵循这个条件句特定的模式?
是否有下Oracle的引擎盖任何性能之所以用这样的言论?
道歉,如果这个问题已经被问,我不在身边找到类似的事情。
是的,很多人关注的一个不好的做法。
不良作风
我@Osy同意OPEN / FETCH / CLOSE增加了完全不必要的代码。 我会走得更远,并说,你应该几乎从来不使用CURSOR
。
首先,通常要做到尽可能在普通的SQL。 如果您需要使用PL / SQL,使用隐式游标。 它将为您节省了一行代码,将有助于你保持相关的逻辑关系更加紧密。
我在保持代码的个别单位尽可能小坚信。 乍一看,这似乎是一个CURSOR
可以帮助你做到这一点。 您可以顶部定义SQL起来在一个地方,然后执行PL / SQL后循环。
但在现实中,间接的额外层几乎没有值得的。 有时,大量的逻辑是在SQL,有时大量的逻辑是在PL / SQL。 但在实践中,它很少有意义的放了很多复杂的逻辑的两个。 您的代码通常结束看起来像其中之一:
for records in (<simple SQL>) loop
<complex PL/SQL>
end loop;
要么:
for records in
(
<complex SQL>
) loop
<simple PL/SQL>;
end loop;
无论哪种方式,你的代码段之一将是非常小的。 的那些两个部分分离的代码的复杂性比的代码较大,单个部件的复杂性更大。 (但是,这显然是我的意见。)
糟糕的表现
有使用OPEN /读取/关闭显著的性能影响。 这方法比使用for循环的光标或隐式游标慢得多 。
编译器可以自动使用散装收集一些for循环。 但是,从Oracle演示引述“PL / SQL性能-揭穿神话” ,第122页:
不要使用开放让这个机会溜走,取环,靠近形式
这里有一个简单的例子:
--Sample data
create table t(a number, b number);
insert into t select level, level from dual connect by level <= 100000;
commit;
--OPEN/FETCH/CLOSE
--1.5 seconds
declare
cursor test_cur is
select a, b from t;
test_rec test_cur%rowtype;
counter number;
begin
open test_cur;
loop
fetch test_cur into test_rec;
exit when test_cur%notfound;
counter := counter + 1;
end loop;
close test_cur;
end;
/
--Implicit cursor
--0.2 seconds
declare
counter number;
begin
for test_rec in (select a, b from t) loop
counter := counter + 1;
end loop;
end;
/
IT'IS非常值得推荐,以保持它的简单代码,所以我可以告诉你的PL / SQL大师说一下吧:
注:在某些情况下,并不推荐使用游标for循环的。 你可以收集根据您的需要考虑选择单一的SELECT INTO或BULK一个更智能的方式。
资料来源:for循环,Oracle杂志光标通过史蒂芬福伊尔施泰因
(参考: 斯坦,前二十PL / SQL的技巧和技术 ):
循环
12.采取游标FOR循环的优点。
FOR循环光标是我最喜欢的PL / SQL的结构之一。 它充分利用了与SQL数据库语言的力量语言的程序方面的紧密和有效整合。 它减少了你需要写从游标提取数据的代码量。 它大大减轻您的编程引入循环错误的机会 - 和循环是一个程序的更容易出错的部分之一。 这是否循环用声音太好了,是真的吗? 那么,它是不是 - 这一切都成真!
假设我需要更新账单所有的宠物留在我的宠物酒店,分享-A-DIN-Din的酒店。 下面的例子包含使用光标,occupancy_cur,以选择用于在旅馆所有乘员的房间号和宠物ID号码的匿名块。 该程序update_bill添加到宠物的房费什么新的变化。
DECLARE CURSOR occupancy_cur IS SELECT pet_id, room_number FROM occupancy WHERE occupied_dt = SYSDATE; occupancy_rec occupancy_cur%ROWTYPE; BEGIN OPEN occupancy_cur; LOOP FETCH occupancy_cur INTO occupancy_rec; EXIT WHEN occupancy_cur%NOTFOUND; update_bill (occupancy_rec.pet_id, occupancy_rec.room_number); END LOOP; CLOSE occupancy_cur; END;
此代码留下任何想象力。 除了定义光标(2号线),你必须明确地声明游标(5号线),打开游标(7号线)的记录,启动了一个无限循环,从光标设定到记录读取行(第9行),检查是否与光标属性(线10)的端ofdata条件,最后执行更新。 当你完成所有的工作,你必须记住要关闭游标(第14行)。 如果我转换这个PL / SQL块使用游标FOR循环,那么我所有的我已经是:
DECLARE CURSOR occupancy_cur IS SELECT pet_id, room_number FROM occupancy WHERE occupied_dt = SYSDATE; BEGIN FOR occupancy_rec IN occupancy_cur LOOP update_bill (occupancy_rec.pet_id, occupancy_rec.room_number); END LOOP; END;
在这里,你看到光标的美丽简单FOR循环! 逝去的是记录的声明。 飘的OPEN,FETCH和CLOSE语句。 飘是需要检查%FOUND属性。 飘得到的一切都是正确的后顾之忧。 取而代之的是,你说的PL / SQL,实际上::ÒYou和我都知道,我想每一行,我想转储行插入光标匹配的记录。 照顾,对我来说,你愿意吗?”和PL / SQL确实照顾它,只是方式与SQL应该集成任何现代编程语言。
文章来源: Is it a bad practice to use EXIT WHEN instruction when looping through CURSORs in Oracle?