oracle存储过程中循环for in是如何使用的
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了oracle存储过程中循环for in是如何使用的相关的知识,希望对你有一定的参考价值。
参考技术A 这样使用的:for
xx
in
(select
语句)
这是隐式游标,这个结构中不能带参数,或者说普通的游标,隐式或显式的都不能带参数,使用参数游标或引用(动态)游标。
例如:
declare
cursor cur(C_value number) is select col_A,col_B from tableA where col_C=C_value
;
begin
for xx in cur loop
--处理
end loop;
end
扩展资料:
注意事项
使用for循环实现
declare
cursor
cur
is
select
*
from
tablename;
aw_row
tablename%rowtype;
begin
for
raw_row
in
cur
loop
dbms_output.put_line('test');
end
loop;
end;
for语句直接帮做了游标的打开关闭,以及判断工作,所以比较常用。 参考技术B 1、首先需要在oracle中根据下图的代码编写存储过程的整体结构。
2、之后需要进行定义游标代码编写,根据下图的代码继续在第一步的下方输入。
3、之后继续根据下图代码编写for循环。
4、最后进行测试运行:直接点击【DBMS
Output】标签进行结果的查看。 参考技术C
这样使用的:
for xx in (select 语句) 这是隐式游标,这个结构中不能带参数,或者说普通的游标,隐式或显式的都不能带参数,使用参数游标或引用(动态)游标。
例如:
declare
cursor cur(C_value number) is select col_A,col_B from tableA where col_C=C_value
;
begin
for xx in cur loop
--处理
end loop;
end
扩展资料:
注意事项
使用for循环实现
declare
cursor cur is
select * from tablename;
aw_row tablename%rowtype;
begin
for raw_row in cur
loop
dbms_output.put_line('test');
end loop;
end;
for语句直接帮做了游标的打开关闭,以及判断工作,所以比较常用。
参考技术D 1、定义带参数的游标:cursor
cur(v_codetype
ldcode.Codetype%TYPE)
is
select
*
from
ldcode
where
codetype
=
v_codetype;
--定义游标
定义游标格式:
cursor
游标名称(变量定义)
is
查询语句;
2、编写for循环部分:
--游标for循环开始
for
temp
in
cur('llmedfeetype')
loop
--temp为临时变量名,自己任意起
--cur('llmedfeetype')为"游标名称(传入的变量)"
Dbms_Output.put_line(temp.Code);
--输出某个字段,使用"变量名.列名"即可。
end
loop;
--游标for循环结束
3、最后,点击DBMS
Output标签页查看结果,如图所示,这样就可以解决问题了。
存储过程中的 Oracle For 循环不循环
【中文标题】存储过程中的 Oracle For 循环不循环【英文标题】:Oracle For Loop in Stored Procedure Not Looping 【发布时间】:2012-11-29 18:00:38 【问题描述】:在尝试在我们的一个系统中提高 SP 的可维护性时,我决定使用循环比硬编码一组值(在本例中为表名)更好,并尝试相应地重构代码这样在系统中添加或删除表不需要编辑数组。暂且不说循环的原因和原因(我非常清楚反对它们的论点),谁能解释发生了什么?
想象两个用户 SourceUser 和 DestUser 都在同一个数据库中,每个用户的表都在同一个表空间中。 SourceUser 中的一堆存储过程将 SourceUser 中的数据填充到 DestUser 中以用于报告目的。作为其中的一部分,要运行的第一个过程会删除 DestUser 中的所有表并重新创建它们。同样,这里不讨论这样做的相对优点。
SourceUser 对 DestUser 具有删除任何表和创建任何表的权限。我们要保留 DestUser 中的一张表。所以,我在过程中构造的 SQL 如下所示:
Begin
For T In (SELECT TABLE_NAME FROM all_tables WHERE TABLE_NAME != 'MIDBLOG' AND OWNER = sTarget_DB) Loop
Begin
Execute Immediate('Drop Table ' || sTarget_DB || '.' || T.TABLE_NAME);
Exception
When Others Then
--Don't care if we get an exception here as most likely the table wasn't there to be dropped in the first place.
NULL;
End;
End Loop;
End;
在这种情况下,sTarget_DB 设置为 DestUser,并且此代码正在针对 SourceUser 运行。
当程序运行时,我发现没有表被删除(我确认有几十个表,包括一个在开始之前名为 MIDBLOG 的表)。我在 SQL Developer 调试模式下运行它,执行甚至从未进入循环内部,因为它似乎认为它没有要处理的行,但我确定 select 语句将返回几十个表名。
接下来我将其修改为:
Begin
For T In (SELECT TABLE_NAME FROM all_tables WHERE OWNER = sTarget_DB) Loop
Begin
If T.TABLE_NAME != 'MIDBLOG' THEN
Execute Immediate('Drop Table ' || sTarget_DB || '.' || T.TABLE_NAME);
End If;
Exception
When Others Then
--Don't care if we get an exception here as most likely the table wasn't there to be dropped in the first place.
NULL;
End;
End Loop;
End;
运行此之后,WAS 删除的唯一表就是我不想删除的那个!更奇怪的是循环只执行了一次,就好像选择查询只返回一行一样。如果我在 SQL Developer 3.2 的调试中运行该过程,我可以看到它正在发生。我们在同事的 PC 上的 SQL Developer(可能是 3.1)上做了同样的事情,循环只执行了一次,但这次它正确地决定不删除表 MIDBLOG 并再次留下其他所有内容。
如果我在 SQL Developer 中将上述示例中的任何一个作为匿名块运行,它就会完全按照我的预期运行。我尝试了更详细的显式游标声明,结果与以前相同。我从来没有得到任何例外。
所有这些都在 Oracle 10g 企业版版本 10.2.0.4.0(64 位)上。只要在 Oracle 11g Enterprise Edition Release 11.2.0.1.0 (64bit) 上尝试过,它就可以正常工作。为什么这样一个基本要求会在两个版本中表现出如此截然不同的行为?它可以在两个版本中使用相同的代码按我想要的方式工作吗?
【问题讨论】:
关于others
异常及其附带的注释 - 除了表不存在之外,drop table
命令命令可能失败的原因有很多。最好明确处理 -942 异常,让其他异常正常失败。
确实如此,但据我所知,实际的例外情况对手头的场景并不感兴趣 - 现在是 3 1/2 年前!
【参考方案1】:
我的猜测是问题与权限有关,而不是 Oracle 的版本。 DestUser
的权限是否通过一个数据库中的角色和另一个数据库中的直接授予授予SrcUser
?
在运行匿名 PL/SQL 块之前,如果先禁用角色会发生什么?
set role none;
<<run the anonymous PL/SQL block>>
如果您在代码中添加检测,针对all_tables
的查询是否会返回您期望的表集?我的猜测是,当代码失败时,它位于定义者权限存储过程中,其中过程的所有者可以通过角色访问DestUser
表。由于通过角色授予的权限在定义者的权限存储过程中不可见,这将导致循环中的 SELECT
语句返回 0 行(尽管以交互方式运行相同的查询将返回您期望的行)。另一方面,如果直接授予DestUser
表上的权限,则相同的定义者权限存储过程将成功运行。它可以在匿名 PL/SQL 块中工作。
【讨论】:
我会检查任何角色等,但在所有情况下,授权都是直接的,而不是按角色。令我困惑的是为什么一个人在 10g 服务器上获得 0 行而另一个人获得 1 行。两者都使用相同的登录名,因此具有相同的权限。我会尝试禁用角色并报告。针对 all_tables 的查询完全返回了我孤立地期望的结果,这就是为什么我不明白它在计算机和服务器之间的差异。 好的,正如你所建议的,我已经尝试在两台服务器上运行匿名块之前禁用所有角色,果然结果也是你所建议的:set roles none =>匿名块什么都不做,自行运行选择不会产生任何结果。我不得不得出结论,我们在两台服务器之间的设置存在不一致,所以如果我想坚持这一点,我需要调查我们的角色如何在我们的(和我们的客户)服务器上工作。耻辱,比一组表名更简洁的解决方案! 由于开发计划的压力,这将不得不继续作为学术撇开,但令人担忧的是,我们的用户(SourceUser 和 DestUser)被授予 DBA 角色,我认为这已经足够了,但也许 SP 是在其他系统用户的权限下执行。我不是 Oracle DBA,此时我有点不知所措,但会继续阅读它。非常感谢您的帮助。 @StevePettifer - 从安全角度来看,授予任何用户DBA
角色是一个坏主意。但是,由于 所有 角色在定义者权限存储过程中是不可见的,因此定义者权限存储过程不能使用授予DBA
角色或任何其他角色的权限。它只能使用直接授予用户的权限。
我完全同意 - 当我发现我很惊讶并且有点担心时。作为附录,我发现通过在 SP 声明中添加 authid current_user
可以对问题进行排序并确保存储过程确实继承了正确的权限以实现我想要的。这里很好地解释了这样做的目的和理论:docs.oracle.com/cd/B19306_01/appdev.102/b14261/…以上是关于oracle存储过程中循环for in是如何使用的的主要内容,如果未能解决你的问题,请参考以下文章