2015-10-15 8 views
7

Znaleziono dziwną rzecz. Nie mogę zrozumieć, dlaczego Oracle pozwalają tej kwerendy i dlaczego cnt zmienna nie zmienia się po to wykonanie:Oracle. Nie można zrozumieć, jak działa FOR z podzapytaniem 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 powraca not null wartość

Oczywiście ja rozumiem:

  1. Ten FOR nie potrzebuje w tej sytuacji. Count bez INTO retunuje tylko jeden wiersz.
  2. Że można go używać bez INTO i będzie działać.

Po prostu ciekawy jak i dlaczego działa w powyższym zapytaniu.

To dziwne, dlaczego Oracle pozwalają podzapytanie z SELECT INTO, ponieważ w sytuacji wspólnego Oracle zwraca błąd kompilacji ORA-06550

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

A jeśli pierwszy kwerenda działa - dlaczego nie poprawnie powrócić wartość CNT?

+1

proszę spojrzeć na moją odpowiedź. Powinieneś nazwać swoje kolumny w instrukcji select. Uchwyć 'r' jak rząd tabeli. –

Odpowiedz

2

Bardzo ciekawy, powiedziałbym, że jest to błąd, z wyjątkiem to jest łagodne. INTO cnt bit jest ważny PL/SQL, ale jest ignorowany w tym kontekście, który może być sprawdzony za pomocą prostego testu:

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; 

Jak widać, klauzula INTO jest ignorowany, a zgodnie z oczekiwaniami rekord r jest poprawnie wypełnione. Wynik na mojej instancji 11gR2:

cnt= 
r=1 
4

Prawidłowe zestawienie SQL

spróbować tej

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; 

wyjaśnienie

select_statement

SQL SELECT (nie PL/SQL SELECT INTO). Dla select_statement, PL/SQL deklaruje, otwiera, pobiera i zamyka niejawny kursor. Jednak ponieważ select_statement nie jest niezależną instrukcją, niejawny kursor jest wewnętrzny - nie można odwoływać się do niego z nazwą SQL.

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

zmienna cnt jest ignorowany, to można udowodnić za pomocą następującego przykładu, ponieważ błąd nie jest podniesione:

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 Przetestowałem to bez problemów. –

+0

Mój zły, popełniłem błąd w moim kodzie. Masz rację. –

+0

Tak, działa. +1 do odpowiedzi.Ale to nie wyjaśnia, dlaczego działa nieprawidłowo z INTO –