web-dev-qa-db-de.com

Kann eine SELECT-Anweisung aus einem PL/SQL-Block ausgegeben werden?

Wie bekomme ich einen PL/SQL-Block, um die Ergebnisse einer SELECT-Anweisung auf dieselbe Weise auszugeben, als hätte ich eine einfache SELECT-Anweisung ausgeführt?

Zum Beispiel, wie man eine SELECT wie macht:

SELECT foo, bar FROM foobar;

Hinweis :

BEGIN
SELECT foo, bar FROM foobar;
END;

funktioniert nicht.

52
GameFreak

Es hängt davon ab, wofür Sie das Ergebnis benötigen.

Wenn Sie sicher sind, dass es nur eine Zeile geben wird, verwenden Sie den impliziten Cursor:

DECLARE
   v_foo foobar.foo%TYPE;
   v_bar foobar.bar%TYPE;
BEGIN
   SELECT foo,bar FROM foobar INTO v_foo, v_bar;
   -- Print the foo and bar values
   dbms_output.put_line('foo=' || v_foo || ', bar=' || v_bar);
EXCEPTION
   WHEN NO_DATA_FOUND THEN
     -- No rows selected, insert your exception handler here
   WHEN TOO_MANY_ROWS THEN
     -- More than 1 row seleced, insert your exception handler here
END;

Wenn Sie mehr als eine Zeile auswählen möchten, können Sie entweder einen expliziten Cursor verwenden:

DECLARE
   CURSOR cur_foobar IS
     SELECT foo, bar FROM foobar;

   v_foo foobar.foo%TYPE;
   v_bar foobar.bar%TYPE;
BEGIN
   -- Open the cursor and loop through the records
   OPEN cur_foobar;
   LOOP
      FETCH cur_foobar INTO v_foo, v_bar;
      EXIT WHEN cur_foobar%NOTFOUND;
      -- Print the foo and bar values
      dbms_output.put_line('foo=' || v_foo || ', bar=' || v_bar);
   END LOOP;
   CLOSE cur_foobar;
END;

oder einen anderen Cursor verwenden:

BEGIN
   -- Open the cursor and loop through the records
   FOR v_rec IN (SELECT foo, bar FROM foobar) LOOP       
   -- Print the foo and bar values
   dbms_output.put_line('foo=' || v_rec.foo || ', bar=' || v_rec.bar);
   END LOOP;
END;
32
Sergey Stadnik

Sie können dies in Oracle 12.1 oder höher tun:

declare
    rc sys_refcursor;
begin
    open rc for select * from dual;
    dbms_sql.return_result(rc);
end;

Ich habe keine 12.x-Datenbank oder keinen DBVisualizer zum Testen, aber das sollte wahrscheinlich Ihr Ausgangspunkt sein.

Weitere Informationen finden Sie unter Implizite Ergebnissätze im Oracle 12.1 - Handbuch zu neuen Funktionen , Blog von Tom Kyte , Oracle Base usw.

Bei früheren Versionen können Sie abhängig vom Tool möglicherweise Ref-Cursor-Bindevariablen wie in diesem Beispiel von SQL * Plus verwenden:

set autoprint on

var rc refcursor

begin
    open :rc for select count(*) from dual;
end;
/

PL/SQL procedure successfully completed.


  COUNT(*)
----------
         1

1 row selected.
30

Erstellen Sie eine Funktion in einem Paket und geben Sie ein SYS_REFCURSOR zurück:

FUNCTION Function1 return SYS_REFCURSOR IS 
       l_cursor SYS_REFCURSOR;
       BEGIN
          open l_cursor for SELECT foo,bar FROM foobar; 
          return l_cursor; 
END Function1;
7
Igor Zelaya

Aus einem anonymen Block? Ich möchte jetzt mehr über die Situation erfahren, in der Sie dies für erforderlich halten, denn mit Unterabfrage-Factoring-Klauseln und Inline-Ansichten ist es ziemlich selten, dass Sie für andere Situationen als für die komplexesten Situationen auf PL/SQL zurückgreifen müssen.

Wenn Sie eine benannte Prozedur verwenden können, verwenden Sie Pipeline-Funktionen. Hier ein Beispiel aus der Dokumentation:

CREATE PACKAGE pkg1 AS
  TYPE numset_t IS TABLE OF NUMBER;
  FUNCTION f1(x NUMBER) RETURN numset_t PIPELINED;
END pkg1;
/

CREATE PACKAGE BODY pkg1 AS
-- FUNCTION f1 returns a collection of elements (1,2,3,... x)
FUNCTION f1(x NUMBER) RETURN numset_t PIPELINED IS
  BEGIN
    FOR i IN 1..x LOOP
      PIPE ROW(i);
    END LOOP;
    RETURN;
  END;
END pkg1;
/

-- pipelined function is used in FROM clause of SELECT statement
SELECT * FROM TABLE(pkg1.f1(5));
6
David Aldridge

wenn Sie die Abfrageausgabe in pl/sql anzeigen möchten, müssen Sie einen expliziten Cursor verwenden. Der aktive Datensatz wird gespeichert, und durch Abrufen der einzelnen Zeilen wird der gesamte Datensatz aus dem aktiven Datensatz angezeigt, sofern er den Datensatz aus dem Datensatz durch Wiederholung in einer Schleife abruft. Diese Daten werden nicht in Tabellenform generiert. Dieses Ergebnis wird im Nur-Text-Format angezeigt. Hoffe das wird hilfreich sein. Für jede andere Frage können Sie fragen ....

set serveroutput on;
declare
cursor c1 is
   select foo, bar from foobar;
begin
  for i in c1 loop
    dbms_output.put_line(i.foo || ' ' || i.bar);
  end loop;
end;
4
Ahsan Habib

Der klassische Block "Hello World!" Enthält einen ausführbaren Abschnitt, in dem die Prozedur DBMS_OUTPUT.PUT_LINE aufgerufen wird, um Text auf dem Bildschirm anzuzeigen:

BEGIN
  DBMS_OUTPUT.put_line ('Hello World!');
END;

Sie können es hier überprüfen: http://www.Oracle.com/technetwork/issue-archive/2011/11-mar/o21plsql-242570.html

4
Dinesh Katwal

Für Versionen unter 12c lautet die einfache Antwort NO , zumindest nicht in der Art und Weise, wie dies mit SQL Server durchgeführt wird.
Sie können die Ergebnisse drucken, Sie können die Ergebnisse in Tabellen einfügen, Sie können die Ergebnisse als Cursor innerhalb der Funktion/Prozedur zurückgeben oder einen Zeilensatz von function - zurückgeben.
aber Sie können nicht SELECT-Anweisung ausführen, ohne etwas mit den Ergebnissen zu tun.


SQL Server

begin
    select 1+1
    select 2+2
    select 3+3
end

/ * 3 Ergebnismengen zurückgegeben * /


Orakel

SQL> begin
  2  select 1+1 from dual;
  3  end;
  4  /
select * from dual;
*
ERROR at line 2:
ORA-06550: line 2, column 1:
PLS-00428: an INTO clause is expected in this SELECT statement

verwenden Sie die Anweisung zum Ausführen des Befehls

mögen: 

declare
 var1    integer;
var2 varchar2(200)
begin
 execute immediate 'select emp_id,emp_name from emp'
   into var1,var2;
 dbms_output.put_line(var1 || var2);
end;

Sie müssen Native Dynamic SQL verwenden. Zum Ausführen des SQL-Befehls benötigen Sie auch kein BEGIN-END:

declare
  l_tabname VARCHAR2(100) := 'dual';
  l_val1    VARCHAR2(100):= '''foo''';
  l_val2    VARCHAR2(100):= '''bar''';
  l_sql     VARCHAR2(1000);  
begin
  l_sql:= 'SELECT '||l_val1||','||l_val2||' FROM '||l_tabname;
  execute immediate l_sql;
  dbms_output.put_line(l_sql);
end;
/

Output:
 SELECT 'foo','bar' FROM dual
2
Art

Auch wenn die Frage alt ist, werde ich die Lösung teilen, die die Frage perfekt beantwortet:

SET SERVEROUTPUT ON;

DECLARE
    RC SYS_REFCURSOR;
    Result1 varchar2(25);
    Result2 varchar2(25);
BEGIN
    OPEN RC FOR SELECT foo, bar into Result1, Result2 FROM foobar;
    DBMS_SQL.RETURN_RESULT(RC);
END;
0
Issam El omri