1
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;
4

3 に答える 3

4

宣言型と命令型のプログラミング スタイルを混在させると混乱を招くため、SQL ステートメントではプロシージャを使用できません。

SQL ステートメントは条件のリストです。これらの条件に一致する結果セットを生成する方法は、Oracle によって決定されます。PL/SQL ストアド プロシージャは、非常に予測可能な方法で物事を変更する一連の命令です。

以下の例では、何回pr実行する必要がありますか? 前または後に実行されid = 1ますか? SQL ステートメントに事前定義された順序がある場合、オプティマイザーは述語をプッシュしたり、サブクエリをマージしたりすることができず、パフォーマンスが許容できなくなります。

select *
from table1
where id = 1
    and pr;

リストで手順が使用されていたとしてもselect、意味をなさない場合があります。たとえば、selectan 内のリストexistsは常に無視されます。

select * from dual where exists (select pr from dual);

しかし実際には、SQL ステートメントは外部と対話する必要があり、手続き型ロジックが必要になる場合があります。関数は通常、何かを計算して値を返すだけなので、許可されています。関数は通常、プログラムの状態に依存せず、多くの副作用があります。関数、セッション変数を使用したり、テーブルを更新したり (に設定されている場合PRAGMA AUTONOMOUS TRANSACTION)、コンテキストを設定したりできます。Oracle はこれらのことを止めることはできませんが、SQL ステートメントでプロシージャを許可しないことで、少なくともそのようなコードを思いとどまらせることができます。

于 2013-07-10T06:08:12.317 に答える
1

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
于 2013-07-10T05:15:12.070 に答える