78

PL/SQL ブロックを取得して、SELECT文の結果を平文を実行した場合と同じ方法で出力するにはどうすればよいSELECTですか?

たとえば、SELECT好きなことをする方法:

SELECT foo, bar FROM foobar;

ヒント:

BEGIN
SELECT foo, bar FROM foobar;
END;

動作しません。

4

11 に答える 11

58

これは、Oracle 12.1 以降で実行できます。

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

テストする DBVisualizer はありませんが、おそらくそれが出発点になるはずです。

詳細については、Oracle 12.1 新機能ガイドOracle Baseなどの Implicit Result Sets を参照してください。

以前のバージョンでは、ツールによっては、次の SQL*Plus の例のように ref カーソル バインド変数を使用できる場合があります。

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.
于 2016-11-01T12:53:34.047 に答える
47

それはあなたが結果を必要とするものに依存します。

行が1つだけになることが確実な場合は、暗黙カーソルを使用します。

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;

複数の行を選択する場合は、明示カーソルを使用できます。

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;

または別のタイプのカーソルを使用します。

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;
于 2008-12-09T04:09:39.827 に答える
9

パッケージに関数を作成し、SYS_REFCURSOR を返します。

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;
于 2008-12-09T05:26:54.177 に答える
8

匿名ブロックから?サブクエリのファクタリング句とインラインビューでは、最も複雑な状況以外でPL/SQLに頼る必要があることはめったにないため、それが必要だと思われる状況について詳しく説明したいと思います。

名前付きプロシージャを使用できる場合は、パイプライン関数を使用してください。ドキュメントから抜粋した例を次に示します。

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));
于 2008-12-09T17:54:02.563 に答える
5

pl/sql で select クエリの出力を見たい場合は、明示カーソルを使用する必要があります。これはアクティブなデータセットを保持し、一度に各行をフェッチすることで、ループを繰り返してデータセットからレコードをフェッチする限り、アクティブなデータセットからすべてのレコードを表示します。このデータは表形式では生成されず、結果はプレーン テキスト形式になります。これが役立つことを願っています。あなたが尋ねることができる他のクエリについては....

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;
于 2016-11-05T13:34:14.323 に答える
4

古典的な「Hello World!」ブロックにはDBMS_OUTPUT.PUT_LINE、画面にテキストを表示するプロシージャを呼び出す実行可能セクションが含まれています。

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

ここでチェックアウトできます: http://www.oracle.com/technetwork/issue-archive/2011/11-mar/o21plsql-242570.html

于 2016-11-04T05:55:31.407 に答える
4

12c より前のバージョンの場合、単純な答えはNOです。少なくとも、SQL Server で行われている方法ではありません。
結果を印刷したり、結果をテーブルに挿入したり、関数/プロシージャ内から結果をカーソルとして返したり、関数から行セットを返したりでき
ますが、結果に対して何かを行わずに SELECT ステートメントを実行することはできません。


SQLサーバー

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

/* 3 つの結果セットが返されました */


オラクル

SQL> begin
  2  select * 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
于 2016-11-01T04:58:19.540 に答える
2

ネイティブ動的 SQL を使用する必要があります。また、SQL コマンドを実行するために 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
于 2016-11-02T19:00:52.340 に答える
1

即時実行ステートメントを使用する

お気に入り:

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;
于 2016-11-03T17:02:02.113 に答える
0

質問が古い場合でも、質問に完全に答えるソリューションを共有します:

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;
于 2018-06-26T12:44:25.727 に答える