プレーンなSELECT
を実行した場合と同じ方法でSELECT
ステートメントの結果を出力するPL/SQLブロックを取得するにはどうすればよいですか?
たとえば、次のようなSELECT
の実行方法:
SELECT foo, bar FROM foobar;
ヒント:
BEGIN
SELECT foo, bar FROM foobar;
END;
動作しません。
結果が必要なものに依存します。
行が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;
これは、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 などの暗黙的な結果セットを参照してください。
以前のバージョンでは、ツールによっては、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.
匿名ブロックから?サブクエリファクタリング句とインラインビューでは、最も複雑な状況以外で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));
パッケージに関数を作成し、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;
pl/sqlで選択クエリ出力を表示するには、明示カーソルを使用する必要があります。アクティブデータセットを保持し、一度に各行をフェッチすることにより、ループで反復してデータセットからレコードをフェッチする限り、アクティブデータセットからすべてのレコードを表示します。このデータは表形式では生成されず、この結果はプレーンテキスト形式になります。これが役に立てば幸いです。その他のクエリについては、尋ねることができます。
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;
古典的な「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
12c未満のバージョンの場合、単純な答えは[〜#〜] no [〜#〜]です。少なくとも、SQL Serverの場合はそうではありません。
結果を印刷したり、結果を表に挿入したり、関数/プロシージャ内からカーソルとして結果を返したり、関数から行セットを返したりできます-
しかし、あなたはできません結果で何もせずにSELECT文を実行します。
begin
select 1+1
select 2+2
select 3+3
end
/ * 3つの結果セットが返されました* /
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
即時ステートメントの実行を使用
好む:
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;
ネイティブ動的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
質問は古いですが、質問に完全に答える解決策を共有します:
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;