2015-10-15 12 views
7

奇妙なことが見つかりました。。サブクエリでFORが動作する仕組みを理解できないSELECT INTO

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リターンnullでない値私は理解しました。もちろん、

  1. Oracleはこのクエリを許可し、それは実行だ後、なぜcnt変数が変更されない理由を理解することはできませんこの場合、FORは必要ありません。 CountなしINTOは1行だけを返します。
  2. 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値を返さない理由は?

+1

私の答えを見てください。 select文の中でカラムに名前を付ける必要があります。テーブル行のように 'r'を処理します。 –

答えて

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 
4

正しい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という名前で参照することはできません。

cnt変数は無視されエラーが発生しませんので、これは、以下の例により証明できるhttp://docs.oracle.com/cd/E11882_01/appdev.112/e25519/cursor_for_loop_statement.htm#LNPLS1155

を参照してください。

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; 
+0

@RaduGheorghiu問題なくテストしました。 –

+0

私のコードは間違っています。あなたは正しい。 –

+0

うん、それは動作します。答えに+1。しかし、これはINTOで正しく動作しない理由を説明していません –

関連する問題