web-dev-qa-db-ja.com

Oracle PL / SQLでの単純なSELECTストアドプロシージャの記述

これは、以下のSQL Serverストアドプロシージャです。

CREATE PROCEDURE passenger_details
AS
BEGIN
SELECT Full_Name, Age, Nationality, Category, Airline_Name, Class_Type
FROM Passenger, Ticket, Airline, Class
WHERE Passenger.Passenger_No=Ticket.Passenger_No AND Airline.Airline_No=Ticket.Airline_No AND Class.Class_No=Ticket.Class_No
END

EXECUTE passenger_details

上記のSQL Serverのストアドプロシージャは正常に動作します。

次に、以下に示すOracle PL/SQLで同じストアドプロシージャを実行しようとしました。

CREATE OR REPLACE PROCEDURE passenger_details
(p_passenger_details OUT SYS_REFCURSOR) 
AS 
BEGIN 
OPEN p_passenger_details FOR
SELECT Full_Name, Age, Nationality, Category, Airline_Name, Class_Type
FROM Passenger, Ticket, Airline, Class
WHERE Passenger.Passenger_No=Ticket.Passenger_No AND Airline.Airline_No=Ticket.Airline_No AND Class.Class_No=Ticket.Class_No;
END passenger_details;

上記のOracle PL/SQLのストアドプロシージャは正常にコンパイルされます。

次に、以下に示すようにそれを実行しようとしました:

SET SERVEROUTPUT ON;
EXECUTE passenger_details;

ストアドプロシージャを実行しようとすると、次のエラーメッセージが表示されます。

Error starting at line : 12 in command -
BEGIN passenger_details; END;
Error report -
ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'PASSENGER_DETAILS'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
06550. 00000 -  "line %s, column %s:\n%s"
*Cause:    Usually a PL/SQL compilation error.
*Action:
5
stranger

dbms_sqlを使用して、暗黙の結果を返すことができます。これは、SQL Serverからの移行を容易にするためにOracle 12に追加された機能です。

CREATE PROCEDURE passenger_details
AS
  c1 SYS_REFCURSOR;  
BEGIN

  open c1 for
  SELECT Full_Name, Age, Nationality, Category, Airline_Name, Class_Type
  FROM Passenger
    JOIN Ticket on Passenger.Passenger_No = Ticket.Passenger_No
    JOIN Airline ON Airline.Airline_No = Ticket.Airline_No
    JOIN Class ON Class.Class_No = Ticket.Class_No;

  DBMS_SQL.RETURN_RESULT(c1);
END;
/

I replaced 明示的なJOIN演算子を使用した古くて時代遅れの暗黙の結合に注意してください。

プロシージャを出力(REFCURSOR)パラメータとして使用するには、OUTを渡す必要があります。

テストする簡単な手順:

CREATE OR REPLACE PROCEDURE passenger_details
(p_passenger_details OUT SYS_REFCURSOR) 
AS 
BEGIN 
OPEN p_passenger_details FOR
SELECT 'test test' as Full_Name, 10 as Age, 'alien' as Nationality, 'foo' as Category, 
'Name' as Airline_Name, 'wobble' as Class_Type
FROM dual;
END passenger_details;
/

SQL * Plusでテストします。

 SQL> 変数mycursor refcursor;
 SQL> exec passenger_details(:mycursor);
 
 PL/SQLプロシージャが正常に完了しました。
 
 SQL> mycursorを印刷します。
 
 FULL_NAME AGE NATIO CAT AIRL CLASS _ 
 --------- ---------- ----- ---- ------- 
 test test 10 alien foo Name wobble 
 
 SQL> 
5
Philᵀᴹ