web-dev-qa-db-ja.com

「クエリ内でDML操作を実行できない」という解決策はありますか?

私はデータ分析ツールを使用しており、ユーザーからの値を受け入れ、それをパラメーターとして渡し、テーブルに保存するという要件がありました。かなり簡単なので、私はこれを書いて座った

create or replace
procedure complex(datainput in VARCHAR2)
is
begin
insert into dumtab values (datainput);
end complex;

私はこれをSQL Developerで次のステートメントを使用して実行しました

begin
complex('SomeValue');  
end;

正常に機能し、値がテーブルに挿入されました。ただし、上記のステートメントはデータ分析ツールではサポートされていないため、代わりに関数を使用しました。以下は、コンパイルする関数のコードです。

create or replace
function supercomplex(datainput in VARCHAR2)
return varchar2
is
begin
insert into dumtab values (datainput);
return 'done';
end supercomplex;   

もう一度SQL Developerで実行しようとしましたが、次のコードを実行するとクエリ内でDML操作を実行できませんになりました

select supercomplex('somevalue') from dual;

私の質問は-前述の関数をSQL Developerで実行できるステートメントが必要です-または-selectステートメントで実行できる、探しているものを実行できる関数です。 -求めていることを実行できない場合は、PL/SQLに非常に新しい(1週間前など)のでマネージャーに通知できるように、理由を知りたいので、ルールと構文。

追伸私がこれがC++であること、あるいはJava :(

[〜#〜] edit [〜#〜]

関数が有効かどうかをテストするために、DMine(ツール)で実行する前に、SQL Developerで関数を実行する必要があります。 SQLで無効なものはすべてDMineでも無効ですが、その逆ではありません。

助けてくれて、状況とそれが違法である/推奨されない理由を理解しました

25
Joshua1729

ディレクティブpragma autonomous_transactionを使用できます。これにより、ORA-14551を発生させることなくDMLを実行できる独立したトランザクションで関数が実行されます。

自律トランザクション は独立しているため、DMLの結果は親トランザクションのスコープ外でコミットされることに注意してください。ほとんどの場合、これは許容できる回避策ではありません。

SQL> CREATE OR REPLACE FUNCTION supercomplex(datainput IN VARCHAR2)
  2     RETURN VARCHAR2 IS
  3     PRAGMA AUTONOMOUS_TRANSACTION;
  4  BEGIN
  5     INSERT INTO dumtab VALUES (datainput);
  6     COMMIT;
  7     RETURN 'done';
  8  END supercomplex;
  9  /

Function created

SQL> SELECT supercomplex('somevalue') FROM dual;

SUPERCOMPLEX('SOMEVALUE')
--------------------------------------------------------------------------------
done

SQL> select * from dumtab;

A
--------------------------------------------------------------------------------
somevalue

Tom Kyte いい説明があります そもそもエラーが発生する理由について。行が処理される順序に依存する可能性があるため、安全ではありません。さらに、Oracleは、関数が行ごとに少なくとも1回、最大で1回実行されることを保証しません。

43
Vincent Malgrat

戻り値を受け入れる変数を宣言するだけです。次に例を示します。

declare
    retvar varchar2(4);
begin
    retvar := supercomplex('somevalue');
end;

関数は挿入を実行しているため、選択は機能しません。値を返すだけであれば機能します。

12
John Doyle