create or replace procedure pr
is
v_date date;
begin
select sysdate into v_date from dual;
DBMS_output.put_line(v_date);
end pr;
3 に答える
宣言型と命令型のプログラミング スタイルを混在させると混乱を招くため、SQL ステートメントではプロシージャを使用できません。
SQL ステートメントは条件のリストです。これらの条件に一致する結果セットを生成する方法は、Oracle によって決定されます。PL/SQL ストアド プロシージャは、非常に予測可能な方法で物事を変更する一連の命令です。
以下の例では、何回pr
実行する必要がありますか? 前または後に実行されid = 1
ますか? SQL ステートメントに事前定義された順序がある場合、オプティマイザーは述語をプッシュしたり、サブクエリをマージしたりすることができず、パフォーマンスが許容できなくなります。
select *
from table1
where id = 1
and pr;
リストで手順が使用されていたとしてもselect
、意味をなさない場合があります。たとえば、select
an 内のリストexists
は常に無視されます。
select * from dual where exists (select pr from dual);
しかし実際には、SQL ステートメントは外部と対話する必要があり、手続き型ロジックが必要になる場合があります。関数は通常、何かを計算して値を返すだけなので、許可されています。関数は通常、プログラムの状態に依存せず、多くの副作用があります。関数は、セッション変数を使用したり、テーブルを更新したり (に設定されている場合PRAGMA AUTONOMOUS TRANSACTION
)、コンテキストを設定したりできます。Oracle はこれらのことを止めることはできませんが、SQL ステートメントでプロシージャを許可しないことで、少なくともそのようなコードを思いとどまらせることができます。
select ステートメントを使用してプロシージャを実行することはできません。select ステートメントを使用して実行する場合は、関数を使用できます。
selectステートメントを使用してプロシージャを実行する場合、1つのアプローチは、プロシージャを関数でラップし、selectステートメントを使用して関数を呼び出すことです。
CREATE OR REPLACE PROCEDURE pr (o_param OUT DATE)
IS
v_date DATE;
BEGIN
SELECT SYSDATE
INTO v_date
FROM DUAL;
o_param := v_date;
END pr;
プロシージャを関数でラップします
CREATE OR REPLACE FUNCTION my_funct
RETURN DATE
AS
o_param DATE;
BEGIN
pr (o_param);
RETURN o_param;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
DBMS_OUTPUT.put_line (
DBMS_UTILITY.format_error_backtrace || ' ' || SQLERRM
);
-- raise exception
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (
DBMS_UTILITY.format_error_backtrace || ' ' || SQLERRM
);
-- raise exception
END my_funct;
/
そして、selectステートメントを使用して関数を呼び出します
SELECT my_funct FROM DUAL