2

LOBとOCI8PHP拡張機能に関して読んだドキュメントから、$lob->close()を使用したので、以下のコードを呼び出す必要があるよう$lob->writeTemporary()です。$lob->close()INパラメーターを受け入れるストアード・プロシージャーにLOBを渡す場合は正常に機能しますが、IN OUTパラメーターを受け入れるストアード・プロシージャーにLOBを渡す場合は機能しません。

明らかに$lob->close()、IN OUTパラメーターの呼び出しを省略できますが、なぜそうする必要があるのか​​知りたいです。誰かが次のエラーを生成する原因となる以下のコードで何が起こっているのか説明してもらえますか?どんな洞察も大歓迎です。

OCI-Lob :: close()[oci-lob.close]:ORA-22289:開いていないファイルまたはLOBに対して%s操作を実行できません

$my_clob = 'Lorem ipsum dolor sit amet...';

$connection = oci_connect('user', 'pass', 'connection string');
$statement  = oci_parse($connection, 'begin p_clob_in_out(:p_my_clob); end;');
$lob        = oci_new_descriptor($connection, OCI_D_LOB);

$lob->writeTemporary($my_clob, OCI_TEMP_CLOB);

oci_bind_by_name($statement, ':p_my_clob', $lob, -1, OCI_B_CLOB);

oci_execute($statement, OCI_DEFAULT);

if (is_object($lob))
{
  $data = $lob->load();

  $lob->close();
  $lob->free();
}

echo $data;

手順は次のp_clob_in_outようになります。

procedure p_clob_in_out(
    p_my_clob in out clob
)
is
begin
    p_my_clob := 'ABC123... ' || p_my_clob;
end p_clob_in_out;

Vincent Malgratの回答のおかげでさらに読むと、これが起こっていると思います...私のPHPコードでは、$lob変数は渡される一時LOBです。その一時LOBは、プロシージャによって変更され、そのコピーが作成されます。 。次に、コピーが渡され、$lob変数が置き換えられます。このwriteTemporaryメソッドはLOBのコピーで呼び出されなかったため、呼び出す$lob->close()と失敗します。最初に作成された(私が呼び出すことができる$lob->close())元のLOBには、PHPスクリプトからアクセスできなくなりました。

このページの「NOCOPYの制限」では、「サブプログラムがデータベースリンクを介して、または外部プロシージャとして呼び出された場合」、NOCOPYは無視されると記載されているため、NOCOPYヒントはここでは当てはまらないと思います。このページによると、ストアドプロシージャを呼び出しているPHPスクリプトの匿名ブロックは、外部プロシージャと見なされるようです。

4

1 に答える 1

0

一時LOBで同様の不可解な問題に遭遇しました(純粋なPl/SQLなので、PHPでも似ている可能性があります)。永続的な LOB で正常に動作していた一部のコードが、一時的な LOB では動作しませんでした。いくつか検索した後、ドキュメントでこのメモを見つけました:

別のロケータもそれを指しているときにユーザーが一時LOBを変更すると、一時LOBのコピーが作成されます。変更が実行されたロケータは、一時LOBの新しいコピーを指しています。他のロケーターには、変更が行われたロケーターと同じデータが表示されなくなります。

プロシージャでNOCOPYを指定した場合に同じ問題が発生するかどうかを知りたいと思いますprocedure p_clob_in_out(p_my_clob in out NOCOPY clob)'ABC123... 'また、プロシージャ呼び出しの後にロブに含まれていることを確認できますか?

私の推論は次のとおりです。INパラメーターは参照として渡されるため、LOB を IN パラメーターとして渡すと変更されます。IN OUTパラメータは値によって渡されるため、実際にはプロシージャを一時LOBのコピーに適用します(永続LOBはディープ・コピーされません)。

于 2011-12-20T16:54:49.663 に答える