PL/SQLのプロシージャでカーソルの受渡について
- PL/SQLのプロシージャ間でカーソルの受渡について教えてください。
- VBでの例を交えながら、親と子プロシージャ間でカーソルを受け渡す方法について教えてください。
- カーソルを子プロシージャで生成し、親プロシージャに戻すことは可能なのでしょうか?
- ベストアンサー
PL/SQLのプロシージャ間でカーソル?の受渡
PL/SQLのプロシージャ間でカーソル?の受渡 お世話になります。 親でループ対象とするカーソルを、子プロシージャで生成し 親に戻すということは可能でしょうか。 うまく伝わりにくいかと思いますので、下記にVBで行った例を記します。 親----------------------- Sub aaa() Dim rs As New ADODB.Recordset Call bbb(rs) Do Until rs.EOF Debug.Print rs!COLUMN1 rs.MoveNext Loop End Sub 子----------------------- Function bbb(ByRef rs As ADODB.Recordset) rs.Open "SELECT * FROM TABLE1", CurrentProject.Connection End Function 以上、お願い致します。
- forgedcode
- お礼率50% (52/102)
- その他(プログラミング・開発)
- 回答数2
- ありがとう数1
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
エラーの原因は、カーソル変数の場合はforループを利用できないためだと思います。 なので、loop内fetchするようにします。 こんな感じでしょうか --REF CUSOR宣言 CREATE OR REPLACE PACKAGE PKG_TEST_CURSOR IS --TYPE CUR_TEST IS REF CURSOR; --レコード全体を取得するなら型を指定した方が楽だと思います TYPE CUR_TEST IS REF CURSOR RETURN TEST%ROWTYPE; END; / --親プロシージャ CREATE OR REPLACE PROCEDURE PC_TEST親(PI_HIKISU1 IN TEST.TEST_COLUMN%TYPE) IS TEST_REC PKG_TEST_CURSOR.CUR_TEST; -- l_test_rec PKG_TEST_CURSOR.CUR_TEST; --CUR_TEST を型指定したのでrowtypeが使えます l_test_rec TEST_REC%ROWTYPE; BEGIN PD_TEST子(PI_HIKISU1,TEST_REC); -- FOR l_test_rec IN TEST_REC LOOP -- dbms_output.put_line(l_test_rec.TEST_COLUMN99); -- END LOOP; --ref cursorの場合はforループはできないので loop fetch TEST_REC into l_test_Rec; exit when TEST_REC%notfound; dbms_output.put_line(l_test_rec.TEST_COLUMN99); end loop; close TEST_REC; END; / --子プロシージャ CREATE OR REPLACE PROCEDURE PD_TEST子 ( PI_HIKISU1 IN TEST.TEST_COLUMN%TYPE, PI_TEST_RECIN OUT PKG_TEST_CURSOR.CUR_TEST) IS l_test_rec PKG_TEST_CURSOR.CUR_TEST; BEGIN OPEN l_test_rec FOR SELECT * FROM TEST WHERE TEST_COLUMN = PI_HIKISU1; --カーソルを返すならopenするだけでいいのでは? -- LOOP -- EXIT WHEN l_test_rec%NOTFOUND; -- FETCH lc_test_rec INTO PI_TEST_REC; -- END LOOP; END; /
その他の回答 (1)
- yamada_g
- ベストアンサー率68% (258/374)
ref cursor を使えばいいのではないかと思います。 http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/appdev.102/B19257-01/sqloperations.html#9160
補足
yamada_g様 ご回答ありがとうございます。 教えて頂いたとおりref cursorでいけそうですが 実際コーディングしたところ、うまくいきませんでした。 どこか考え方が根本的に間違ってるかもしれません。 エラーは親プロシージャで [TEST_RECがプロシージャではないか、未定義です」と出ます。 ご指摘いただければ幸いです。 --REF CUSOR宣言 CREATE OR REPLACE PACKAGE PKG_TEST_CURSOR IS TYPE CUR_TEST IS REF CURSOR; END; --親プロシージャ CREATE OR REPLACE PROCEDURE PC_TEST親(PI_HIKISU1 IN TEST.TEST_COLUMN%TYPE) IS TEST_REC PKG_TEST_CURSOR.CUR_TEST; l_test_rec PKG_TEST_CURSOR.CUR_TEST; BEGIN PD_TEST子(PI_HIKISU1,TEST_REC); FOR l_test_rec IN TEST_REC LOOP dbms_output.put_line(l_test_rec.TEST_COLUMN99); END LOOP; END; --子プロシージャ CREATE OR REPLACE PROCEDURE PD_TEST子 ( PI_HIKISU1 IN TEST.TEST_COLUMN%TYPE, PI_TEST_REC IN OUT PKG_TEST_CURSOR.CUR_TEST) IS l_test_rec PKG_TEST_CURSOR.CUR_TEST; BEGIN OPEN l_test_rec FOR SELECT * FROM TEST WHERE TEST_COLUMN = PI_HIKISU1; LOOP EXIT WHEN l_test_rec%NOTFOUND; FETCH lc_test_rec INTO PI_TEST_REC; END LOOP; END;
関連するQ&A
- ADOでレコードを閉じるタイミング。。Access2000/VB6/Win2K
レコードセットを返すFuncitonプロシージャーを作ってみたのですが。。。 下のGet_Recordsの方のレコードセットをCloseすると上の方のDisp_Dataでオブ ジェクトが閉じているといって怒られます。しかし、閉じないと下の方では開きっ ぱなしになると思うのですが。。。どのように処理すればいいのでしょうか? Public P_CN As ADODB.Connection Private Sub Disp_Date() Dim RS As ADODB.Recordset Dim SQL AS String Set RS = Get_Records(SQL) With RS If .RecordCount > 0 Then .MoveLast: .MoveFirst .Debug.Print !顧客_ID End If End With RS.Close Set RS = Nothing End Sub Public Function Get_Records(pSQL As String) As ADODB.Recordset Dim RS As ADODB.Recordset Set RS = New ADODB.Recordset RS.Open pSQL, P_CN, adOpenKeyset, adLockOptimistic Set Get_Records = RS ''' RS.Close ''' Set RS = Nothing End Function
- ベストアンサー
- その他(データベース)
- VB6の複数検索条件で連続検索が出来ないので教えて下さい
下記のごとく、ADOデーターベースの複数アンド条件で検索をしているのですが、一番最初のレコードは検索されるのですが、次の検索をしようと思い、rs.movenextを実行しても次のレコードに飛んで検索をしてくれません。たった一度のみの検索となります。 連続検索を行いたいのですが分かりません。 どなたか、詳しい方がおられましたら宜しくお願い致します。 Public Sub Multi_find(ByRef oRs As ADODB.Recordset, sCriteria As String) Dim clone_rs As ADODB.Recordset Set clone_rs = oRs.Clone clone_rs.Filter = sCriteria If clone_rs.EOF Or clone_rs.BOF Then oRs.MoveLast oRs.MoveNext Else oRs.Bookmark = clone_rs.Bookmark End If clone_rs.Close Set clone_rs = Nothing End Sub
- 締切済み
- Visual Basic
- rs.MoveFirst
アクセスvbaです。 Sub Sample() Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset Dim i As Long Set cn = CurrentProject.Connection rs.Open "Tテーブル", cn, adOpenKeyset, adLockOptimistic rs.MoveFirst '←これいらない? For i = 1 To rs.RecordCount rs.MoveNext Next rs.Close: Set rs = Nothing cn.Close: Set cn = Nothing End Sub このようなコードの場合 rs.MoveFirst はあってもなくても変わらないですか?
- ベストアンサー
- オフィス系ソフト
- 引数付のFuncitonプロシージャと引数付のSUBプロシージャの違い
親プロシージャに数値を渡すときに、引数付のFuncitonプロシージャと引数付のSUBプロシージャは、結果を見ると同じ動きをするように思います。 このような場合、両者には、どのような違いがあるのでしょうか? Sub 親プロシージャ() Cells(1,MyNOend)=123 end Sub ・子プロシージャ Function FMyRowCnt(MyNOend As Integer) MyNOend = TMYKanriBkWs1.Range("D1").CurrentRegion.Rows.Count End Function Sub FMyRowCnt(MyNOend As Integer) MyNOend = TMYKanriBkWs1.Range("D1").CurrentRegion.Rows.Count End Sub 以上 よろしくお願い致します。
- ベストアンサー
- オフィス系ソフト
- ADO 「Set」は使ったほうがいいのでしょうか?
Sub test1() Dim cn As ADODB.Connection Dim rs As ADODB.Recordset Set cn = New ADODB.Connection Set rs = New ADODB.Recordse End Sub Sub test2() Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset End Sub この二つは同じ意味ですか? 「Set」は使ったほうがいいのでしょうか? よろしくお願いします。
- ベストアンサー
- オフィス系ソフト
- SQL文の最後に「;」はいらないのでしょうか?
VBAのADOについて質問です。 SQL文の最後には「;」を付けなくちゃいけないものだと思っているのですが ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ Private Sub test_Click() Dim CN As ADODB.Connection Dim RS As ADODB.Recordset Set CN = CurrentProject.Connection Set RS = New ADODB.Recordset SQL = "SELECT * FROM Tテーブル" ・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・ でも問題なくコードが動きました。 SQL文の最後に「;」はいらないのでしょうか? ちなみに SQL = "SELECT * FROM Tテーブル;" でもエラーになりませんでした。
- 締切済み
- Visual Basic
- ADO オブジェクトの渡し方
こんにちは。ADOについてお教えください。 フォームをロード時に接続プロシージャと切断プロシージャを走らせたいと思います。 ConnectDatabaseを呼び出しは成功しますが、CloseDatabase呼び出しには失敗します。 スコープの問題で、rs、cnのオブジェクトが無い為だと思います。 ConnectDatabaseで作成されたcn、rsオブジェクトを別の関数で処理するにはどのようにコードをかけばよろしいでしょうか?宜しくお願い致します。 Private Sub Form_Load() Call ConnectDatabase Call CloseDatabase End Sub Module1 ------------------ sub ConnectDatabase() Dim cn As ADODB.Connection Dim rs As ADODB.Recordset Set cn = New ADODB.Connection Set rs = New ADODB.Recordset 処理~~~~ end sub sub CloseDatabase() rs.Close cn.Close Set rs = Nothing Set cn = Nothing end sub
- ベストアンサー
- Visual Basic
- ACCESS SQLで複数データ表示させるには?
*************************************************** Private Sub Form_Load() Dim cn As New ADODB.Connection Dim rs As New ADODB.Recordset Set cn = CurrentProject.Connection mySQL = "select * from テーブル" rs.Open mySQL, cn, adOpenForwardOnly, adLockOptimistic ’コントロールに代入 Me.No = rs![No] Me.項目 = rs![項目] ・・・ End Sub *************************************************** こんな感じで、クエリでなくSQLで フォームにテーブルの全レコードを表示させたい場合、 どのようにすればよいのでしょうか? 上の文には、何が不足しているのでしょうか? http://www.accessclub.jp/ado/09.html を見ましたが、解決できませんでした。
- ベストアンサー
- オフィス系ソフト
- Functionプロシージャの便利さがわかりません
私はVBAコードを作る時は、もっぱらsubプロシージャーを使ってしまうのですが、 http://excelvba.pc-users.net/fol5/5_4.html を参考に、 Functionプロシージャとsubプロシージャの違いを確認してみたのですが、 Functionプロシージャの便利さがわかりません。 *********************************** Sub Test() SubプロシージャとFunctionプロシージャのテスト i = 1 Call Subプロシージャ(i) i = Functionプロシージャ(i) MsgBox "Functionプロシージャ結果:" + CStr(i) End Sub Sub Subプロシージャ(ByVal i As Integer) MsgBox "Subプロシージャ結果:" + CStr(i) End Sub Function Functionプロシージャ(ByVal i As Integer) As Integer i = i + 1 Functionプロシージャ = i End Function *********************************** Functionプロシージャは、 (ByVal i As Integer) As Integer のように、、二回もデータ型(Integer)の指定をしなくてはいけないのでしょうか? リンク先の説明には、 「SubプロシージャとFunctionプロシージャの違いは Subプロシージャが引数を受け取るのみに対して Functionプロシージャは引数を受け取り、 戻り値を返すという関数としての役割を果たすことができる点です。」 と記載されてますが、 それはSubプロシージャでも出来てますよね? サンプルコードにおいてのFunctionプロシージャの便利さを教えてください。
- ベストアンサー
- オフィス系ソフト
- PL/SQL-プロシージャ
プロシージャBはテスト実行のため、プロシージャAを真似て作成しています。 --最後のIF文で、プロシージャAかBのどちらかに走らせたいと思っています。 DECLARE --プロシージャA--------------------------------------- PROCEDURE A IS fno1 utl_file.file_type; dnm1 varchar(200) :='XXX'; fnm1 varchar2(200) :='BBB.txt'; CURSOR cu1 is select XYZ as ABC from CCC; BEGIN fno1 := utl_file.fopen(dnm1,fnm1,'w'); FOR CU1_REC1 in CU1 loop utl_file_put_line(fno1,' '|| CU1_REC1.XYZ END LOOP; utl_file.fclose(fno1); end; --プロシージャB------------------------------------- プロシージャAと似たような処理 --プロシージャAかBかを判定するIF文------------------------------ BEGIN IF CCC.ABC = '0'; THEN A; ELSE B; ENDIF; END; /
- 締切済み
- Oracle
お礼
yamada_g 様 細かく教えて頂きありがとうございました。 無事に動作する事を確認できました。 ただ一部誤りがあるようでした。 --子プロシージャ CREATE OR REPLACE PROCEDURE PD_TEST子 ( PI_HIKISU1 IN TEST.TEST_COLUMN%TYPE, PI_TEST_RECIN OUT PKG_TEST_CURSOR.CUR_TEST) IS --l_test_rec PKG_TEST_CURSOR.CUR_TEST;--←直接引数に返すので必要ない BEGIN --OPEN l_test_rec FOR SELECT * FROM TEST WHERE TEST_COLUMN = PI_HIKISU1; OPEN PI_TEST_REC FOR SELECT * FROM TEST WHERE TEST_COLUMN = PI_HIKISU1; --←引数に返してあげる 以上です、本当に助かりました。