甲骨文。无法理解 FOR 如何与子查询 SELECT INTO 一起使用

Posted

技术标签:

【中文标题】甲骨文。无法理解 FOR 如何与子查询 SELECT INTO 一起使用【英文标题】:Oracle. Can't understand how FOR works with subquery SELECT INTO 【发布时间】:2015-10-15 08:21:12 【问题描述】:

发现奇怪的东西。无法理解为什么 Oracle 允许此查询以及为什么 cnt 变量在执行后不会改变:

declare cnt number;
begin
 for r in (Select count(1) into cnt from  v$session) loop
   dbms_output.put_line(cnt);
 END LOOP; 
end;

Select count(1) from v$session 返回非空值

我当然明白:

    FOR 在这种情况下不需要。 Count 没有 INTO 只返回一行。 我可以在没有INTO 的情况下使用它,它会起作用。

只是好奇它在上面的查询中是如何以及为什么起作用的。

为什么Oracle允许使用SELECT INTO进行子查询很奇怪,因为通常情况下Oracle会返回编译错误ORA-06550

declare cnt number;
 begin
        select count(1) from  (Select count(1) into cnt from  v$session)
 end;
or 

如果第一个查询有效 - 为什么它不能正确返回 cnt 值?

【问题讨论】:

请看我的回答。您应该在 for select 语句中命名您的列。像处理表格行一样处理r 【参考方案1】:

正确的sql语句

试试这个

declare cnt number;
begin
 for r in (Select count(1) as cnt from  v$session) loop
   dbms_output.put_line(r.cnt);
 END LOOP; 
end;

说明

select_statement

SQL SELECT 语句(不是 PL/SQL SELECT INTO 语句)。对于 select_statement,PL/SQL 声明、打开、获取和关闭隐式游标。但是,因为 select_statement 不是独立语句,所以隐式游标是内部的——您不能使用名称 SQL 来引用它。

见http://docs.oracle.com/cd/E11882_01/appdev.112/e25519/cursor_for_loop_statement.htm#LNPLS1155

cnt 变量被忽略,这可以通过下面的例子来证明,因为没有引发错误:

declare
  cnt       number;
  a_varchar varchar2(1);
begin
  for r in (Select 'AA' into a_varchar from v$session) loop
    dbms_output.put_line(a_varchar);
  end loop;
end;

【讨论】:

@RaduGheorghiu 我已经测试过了,没有问题。 我的错,我的代码出错了。你是对的。 是的,它有效。 +1回答。但这并不能解释为什么它与 INTO 一起工作不正确 @ViktorBardakov 没错,这还不清楚。我已对您的问题投了赞成票以引起更多关注 @sstan 你说得对,我已将第二个答案与第一个答案合并。【参考方案2】:

非常有趣,我会说这是一个错误,但它是一个良性的。 INTO cnt 位是有效的 PL/SQL 但在此上下文中被忽略,这可以通过一个简单的测试用例来证明:

declare cnt number;
begin
 for r in (select count(1) into cnt from dual) loop
   dbms_output.put_line('cnt=' || cnt);
   dbms_output.put_line('r=' || r."COUNT(1)");
 end loop;
end;

如您所见,INTO 子句被忽略,正如预期的那样,r 记录已正确填充。我的 11gR2 实例上的输出:

cnt=
r=1

【讨论】:

以上是关于甲骨文。无法理解 FOR 如何与子查询 SELECT INTO 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

SELECT FOR UPDATE 与子查询导致死锁

如何将查询与子查询连接起来?

MySQL 索引优化与子查询与左连接

为啥当我的子查询无效时,此 SQL 查询会起作用? - 甲骨文 [重复]

MSSQL之五 连接查询与子查询

如何处理 for 循环中的异常以使用存储过程插入行?甲骨文 PLSQL