- - PR -
PL/SQLでOPEN CURSORとCLOSE CURSORを別々のストアドから行いたい
| 投稿者 | 投稿内容 | ||||
|---|---|---|---|---|---|
|
投稿日時: 2006-08-30 19:02
PL/SQLの質問です。
あるストアドでOPENしたCURSORを、別のストアドでCLOSEする ということができますでしょうか? 通常は、OPEN CURSOR名、CLOSE CURSOR名でCURSORをOPEN/CLOSE すると思います(少なくとも自分は) これを例えば、OPENした時にセッションごとに固有のIDを取得 して、ストアドを呼んだアプリに返し、次にアプリからIDを指 定してCLOSEするというのは可能ですか? ORCLEのバージョンは9i。ストアドをコールするアプリはC#です。 | ||||
|
投稿日時: 2006-08-30 20:11
saki1208です。 なぜ?そのようなことが必要なのかはわかりませんが... ストアド・パッケージ使用すれば可能ではないでしょうか? (実際に試した訳ではないので、間違っていたらごめんなさいですが) ストアド・パッケージの仕様部で宣言されたカーソル、変数などは 同一セッション上でその内容を保持しています。 | ||||
|
投稿日時: 2006-09-05 17:51
saki1208さん、ありがとうございます。
返答が遅れてしまいまして、申し訳ありません。 今、C#からPL/SQLをコールして、結果をOracleDataReaderで 受け取る処理を作っています。 ところ、カーソルを閉じるメソッドがわからず困っています。 ※CloseやDisposeがそれかと思ったのですが、ダメでした。 ※MSDNで見てもCloseで終わっていました。 カーソルが閉じないため、数百回同じPL/SQLをコールすると 「最大オープン・カーソル数を超えました」とエラーになり、 OracleDataReaderのインスタンスを作る処理で、 「文の処理が実行されません」とエラーになります。 それで、あのような質問をさせていただきました。 | ||||
|
投稿日時: 2006-09-05 18:32
saki1208です。 出力されているメッセージからすると... Oracleのエラーだと思います。 また、該当のエラーは、PL/SQL内でカーソルを閉じずに Openを繰り返した場合に出力されるエラーです。 ※これは、マニュアルを参照すればわかると思います。 マニュアルは、Oracleのインストール媒体に含まれて いますし、OTNからダウンロードすることも可能です。 最初の返信にて記述させていただいた通り、ストアド・ パッケージの仕様部で宣言されたカーソル、変数などは 同一セッション上でその内容を保持しています。 PL/SQL上でカーソルのクローズを行わずに、OPENのみを 繰り返し実行されているのではないでしょうか? エラーが発生しないようにするためには、結果をOracle DataReaderで受け取った後に、PL/SQL上でカーソルをク ローズしてあげる必要があるはずですが、クロースされ ていますか? | ||||
|
投稿日時: 2006-09-06 15:07
>>Openを繰り返した場合に出力されるエラーです。
そこまではわかっているのですが、Closeの仕方がわからないのです。 C#のソースは↓のような感じです。 OracleCommand oracmd = db.OpenCmd("カーソルを開くPL/SQL"); oracmd.CommandType = CommandType.StoredProcedure; oracmd.ExecuteNonQuery(); OracleDataReader oradatr = oracmd.ExecuteReader(); while(oradatr.Read()) {} oradatr.Close(); <---カーソルが閉じない PL/SQLは↓のような感じです。 ---仕様部 TYPE CUR_TYPE IS REF CURSOR; FUNCTION OpenCur(P_CUR OUT CUR_TYPE) RETURN NUMBER; ---実行部 FUNCTION OpenCur(P_CUR OUT CUR_TYPE) RETURN NUMBER IS BEGIN OPEN P_CUR FOR SELECT * FROM テーブル RETURN 0; END OpenCur; saki1208さんは、FUNCTION内部でCLOSE P_CURをやれと 言われてると思いますが、それをやるとC#側でフェッチ できないのです。 そこで、OpenCurというFunctionでOpenしたカーソルを CloseCurなど別のFunctionでCloseできないか?ということを 聞きたかったのです。説明不足ですいません。 | ||||
|
投稿日時: 2006-09-07 11:45
function の出力を、カーソルそのものじゃなくて PL/SQL 表とかに
変更したら対応できないでしょうかね。 (function の出力結果がカーソルそのものだったら、カーソルは 閉じようがないのでは、と思ってみたり) _________________ もしもし@RMAN 友の会 | ||||
|
投稿日時: 2006-09-09 09:23
OracleのODP.NETには
OracleParameterクラスにDispose()があります OUTパラメータのREFCURSORをDisposeすることで コネクションをクローズしなくてもカーソルがクローズされると思います *オラクルのサイトにサンプルがあります REFCURSORについて msdn2.microsoft.com/ja-jp/library/bw9eczdk.aspx 入力パラメータとしての REF CURSOR はサポートしていません。 とあるので カーソルをクローズするプロシージャに引数としてわたせません パッケージでREF CURSOR変数を保持する案 PLS-00994: カーソル変数をパッケージの一部として宣言できません。 のエラーになります 同一セッションで使用する変数にREF CURSORは使用できないようです なのでOracleのODP.NETをためされてはいかがでしょうか? v$open_cursorで結果(カーソルクローズの有無)を確認できます | ||||
|
投稿日時: 2006-09-09 17:20
Dispose()でカーソルクローズするのではないようです OracleRefCursorクラス経由でとりだしを行うと oracmd.ExecuteNonQuery(); OracleDataReader reader1 = ((OracleRefCursor)p1.Value).GetDataReader(); reader1.Close(); で最後に発行したSQLのみv$open_cursorに表示されました 環境は10gです | ||||
