ExcelVBA+OO4Oを使用してストアドのカーソルを操作する方法

このQ&Aのポイント
  • ExcelVBA+OO4Oを使用してストアドのカーソルを操作する方法を教えてください。引数としてカーソルを渡したいのですが、Oracleストアドでは値を取得することができませんでした。二次元配列以外の方法で引数を渡す必要があるのでしょうか?
  • ExcelVBA+OO4Oを使用してストアドのカーソルを操作する方法について教えてください。引数の渡し方に問題があり、値を取得できませんでした。二次元配列以外の方法で引数を渡す必要があるのでしょうか?
  • ExcelVBA+OO4Oを使用してストアドのカーソルを操作する方法を教えてください。引数としてカーソルを渡す際に問題が発生し、値を取得することができませんでした。他の方法で引数を渡す必要があるのでしょうか?
回答を見る
  • ベストアンサー

ExcelVBA+OO4O使ったストアドのカーソルの扱い

お世話になります Dim Cellsvalue(1,1) As Variant Cellsvalue(0,0) = 1: Cellsvalue(1,0) = 1 Cellsvalue(0,1) = 2: Cellsvalue(1,2) = 2 With UsroOraDB   .Parameters.Add "PARA1", Cellsvalue, ORAPARM_INPUT .Parameters("PARA1").serverType = ORATYPE_CURSOR   .BeginTrans   .ExecuteSQL("BEGIN TestPack.TestProc(":PARA1"); END;")   .CommitTrans End With 以上のように、引数としてカーソルを渡したいのですがOracleストアドでは値をひろっていませんでした。 引数の渡し方がまずいと思うのですが、この場合は二次元配列ではだめなのでしょうか? よろしくおねがいします

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

配列のパラメータを渡すにはバインド配列 ( OraParamArray ) を使用しないとダメだと思います。 ORATYPE_CURSOR は ORAPARM_OUTPUT でカーソルの内容を取得 ( 呼び出し側に戻す ) ときに使用するものだと思います。

forgedcode
質問者

お礼

tsukasa-12r様回答ありがとうございます 私はVBAの担当でストアド(PL/SQL)が分からないものでして やはりINPUTはできないのですね、ストアドの実行まで通るので問題ないとは思ってたのですが。 各項目毎(列毎)に配列を使用しないとだめですね

関連するQ&A

  • oo4oを使ったOracleへのデータ処理を高速化したい

    タブ区切りのtsvファイルの1項目目に並んでいるデータをDBのプライマリーキーとみなして、DB上に既にあればupdate、なければinsertします。 下のPGは、DBに30万件のデータが入った状態で実行すると、遅すぎて使えません。もっと速くすることはできませんでしょうか。 Public Const OraSQL_01 = "INSERT INTO CUSTOMER (COMPANY_CODE, TEST1) Values (:データ0, :データ1)" Public Const OraSQL_02 = "UPDATE CUSTOMER SET COMPANY_CODE = :データ0, TEST1 = :データ1 WHERE COMPANY_CODE = :データ0" wkFile1 = "c:\test\test.csv" Open wkFile1 For Input As #1 OraSession.BeginTrans Set rs = OraDatabase.CreateDynaset("SELECT COMPANY_CODE FROM CUSTOMER", ORADYN_DEFAULT) OraDatabase.Parameters.Add "データ0", 0, ORAPARM_INPUT OraDatabase.Parameters("データ0").ServerType = ORATYPE_NUMBER OraDatabase.Parameters.Add "データ1", 0, ORAPARM_INPUT OraDatabase.Parameters("データ1").ServerType = ORATYPE_VARCHAR2 Do Until EOF(1) Line Input #1, Text sec = Split(Text, vbTab) OraDatabase.Parameters("データ0").Value = sec(0) OraDatabase.Parameters("データ1").Value = sec(1) Dim flg As Boolean Do Until rs.EOF flg = False If rs("COMPANY_CODE") = sec(0) Then OraDatabase.ExecuteSQL OraSQL_02 flg = True Exit Do Else rs.MoveNext End If Loop If flg = False Then OraDatabase.ExecuteSQL OraSQL_01 End If rs.MoveFirst Loop OraSession.CommitTrans

  • :ストアドプロシージャ内での配列の使用:

    :ストアドプロシージャ内での配列の使用: 環境 アプリケーション側:C#.net データベース側:Oracle10g アプリケーションから文字列の配列を引数として渡し、 プロシージャ内でその配列の中身がなくなるまでループでUPDATE文を実行しようとしています。 引数例(文字列配列):para[] (para[0]='ねこ',para[1]='ねずみ',para[2]='たぬき',para[3]='人',…) While文1週目では「ねこ」を、2週目では「ねずみ」をSET句に格納したSQLを実行するのが目的です。 同じストアド内であれば、結果セットをカーソルに放り込み フェッチ&Whileで順番に取得する事ができますが、 外部から引数として渡された配列をストアド内ループで順番に取得するにはどうしたらよいのでしょうか? アプリ側で引数を特定してから渡せば配列個数文ストアドをコールするという手段が取れますが 配列数が多くなった時に遅くなりすぎるという問題があります。 どなたか詳しい方おりましたらご教授いただきたく思います。宜しくお願いします。

  • ストアドプロシージャ結果のファイル出力について

    お世話になります。 以下のようにOracleにてストアドプロシージャを作成して、 それをAccessからコールしております。 そしてそのDBMS_OUTPUTの結果をファイル出力したいのですが、 試しに「sqlstmt = "BEGIN proc_SeikyuMeisai(:yyyymm); END;"」の部分を 「sqlstmt = "spool aaa.csv BEGIN proc_SeikyuMeisai(:yyyymm); END; spool off"」 や、ストアド側でspoolしてみましたがダメでした。 UTL_FILEを使うしかないのでしょうか? ご存じの方おられたらご教示いただけますでしょうか? 宜しくお願い致します。 【Access2003側】 ' セッションの作成 Set OraSession = CreateObject("OracleInProcServer.XOraSession") 'データベースへの接続 Set OraDatabase = OraSession.OpenDatabase("Hoge", "hoge/hoge", ORADB_DEFAULT) '■ ストアド実行 ■ sqlstmt = "BEGIN proc_SeikyuMeisai(:yyyymm); END;" 'バインド変数の設定 OraDatabase.Parameters.Add "yyyymm", 0, ORAPARM_INPUT OraDatabase.Parameters("yyyymm").serverType = ORATYPE_NUMBER '引数設定 OraDatabase.Parameters("yyyymm").value = Forms!F月次データ取込.txt日付1 'SQL文の実行 OraDatabase.ExecuteSQL sqlstmt DoCmd.Hourglass False '砂時計 'バインド変数の削除 OraDatabase.Parameters.Remove "yyyymm" '■ORACLEへの切断■ OraDatabase.Close 'オブジェクトの破棄 Set OraDatabase = Nothing Set OraSession = Nothing MsgBox "正常に出力されました。" 【Oracle10g】 Create or replace procedure Proc_SeikyuMeisai ( P1_YYYYMM IN number ) IS WK_KANID varchar2(10); WK_CODE varchar2(6); WK_SUU varchar2(12); WK_TEN varchar2(9); WK_KAI varchar2(2); -- カーソルタイプの定義 TYPE typeMyCursor IS REF CURSOR; -- カーソル変数の定義 curSeikyu typeMyCursor; curID varchar2(10); curMAX number; curMEISAI varchar2(1000); curTEN number; curKAI number; vSql varchar2(1000); BEGIN vSql := 'select KANNO, MEISAI_MAX, _MEISAI, HOU_TENSUU_KEI, TOTAL_KAISUU from SEIKYUUMEISAI' || P1_YYYYMM; -- カーソルオープン open curSeikyu for vSql; loop fetch curSeikyu into curID, curMAX, curMEISAI, curTEN, curKAI; exit when curSeikyu%NOTFOUND; WK_KANID := curID; for nLpCnt IN 1..curMAX loop WK_CODE := substrb(curMEISAI, 3, 6); WK_SUU := substrb(curMEISAI, 34, 12); WK_TEN := substrb(curMEISAI, 89, 9); WK_KAI := lpad(curKAI, 2, 0); dbms_output.put_line(WK_KANID || ',' || WK_CODE || ',' || WK_SUU || ',' || WK_TEN || ',' || WK_KAI); end loop; end loop; end; /

  • ExcelVBAからOracleストアド実行

    Excel:2010 Oracle:10g 接続:ADODB Oracleで質問すべきか、VB側にすべきか迷いましたが、こちらに質問させていただきます。 ExcelVBAからOracleに接続し、ストアドを実行して複数行のデータを取得後 エクセルの各セルに取得データを設定するマクロを作成しております。 コマンドのExecuteを行った後、レコードセットが取得できていないようで 「オブジェクトが閉じている場合は、操作は許可されません」 となってしまいます。 ストアド自身は、Oracle側でエラーなく動いています。 カーソルで取得したデータをエクセル側に渡すには、それ用のOutputの変数(配列?)が必要なのでしょうか? よろしくお願いいたします。 ストアドプロシージャ(一部SELECT文は長いため、省いています) -------------------- CREATE OR REPLACE PROCEDURE A.P930 ( varCD IN VARCHAR2, varDate IN VARCHAR2 ) AS CURSOR C_SIM IS SELECT CD, NAME FROM T WHERE CD = varCD AND CNTRCT_DATE = varDate; SIM_REC C_SIM%ROWTYPE; BEGIN OPEN C_SIM; LOOP FETCH C_SIM INTO SIM_REC; EXIT WHEN C_SIM%NOTFOUND; END LOOP; CLOSE C_SIM; END; / VBA側 Connection接続はOK -------------------- Sub LIST() 変数宣言等省いています Set myCmd = New ADODB.Command With myCmd .ActiveConnection = DBADOCon .CommandType = adCmdStoredProc .CommandText = "P930" .Parameters.Append .CreateParameter("varCD", adVarChar, adParamInput, 3, strLineCd) .Parameters.Append .CreateParameter("varDate", adVarChar, adParamInput, 6, strMonth) Set myRs = New ADODB.Recordset Set myRs = .Execute End With If myRs.RecordCount = 0 Then     ←ここでエラーになります 'エラーメッセージ表示 Exit Sub End I

  • VBからoo4o接続でストアドを呼ぶ方法

    お世話になります、 VBからoo4o接続でストアドを呼ぶ方法を探しています。 <現在の状況> ■ストアドパッケージ ・次のように値を返すストアドパッケージがあるとします。これを CreatePLSQLDynaset で実行して、レコードセットを取得します。(OraDynaset) create or replace package testp is procedure GetTestm(key in number, cu out CHAR); end; / create or replace package body testp is procedure GetTestm(key in number,cu out CHAR) is begin select NAME into cu from TEMP where STATUS=key; end; end; / ■VBのボタンイベント Private Sub Command1_Click() Dim dbname Dim cnuser '** サービス、ユーザ設定 dbname = "aaa" cnuser = "bb/bb" '** oo4o 接続 Set GoORASESSION = CreateObject("OracleInProcServer.XOraSession")  Set GoORADATABASE = GoORASESSION.OpenDatabase(dbname, cnuser, &H0) '** リクエリレコードセットオープン Set Recordset = GoORADATABASE.CreatePLSQLDynaset("Begin testp.GetTestm (1,:cu); end;", "cu", &H0) End Sub これを実行したところ以下のようなエラーが出ました <エラー> ____________________________ 実行時エラー '440' SQL実行エラー,ORA-06550:行:1、列:7 PLS-00306:'GETTESTM'の呼び出しで、引数の数または型が正しくありません ORA-06550:行:1、列:7 PL/SQL:Statement ignored _______________________________ というエラーが出てしまいます、引数の数は合っていると思うのですが、どこがお菓子のでしょうか? よろしくお願いします。

  • .NETからストアドプロシージャを実行

    VB.Netからストアドプロシージャを実行するプログラムの書き方がよく分かりません。 データベースはOracleです。 PROCEDURE test(aaa IN number, bbb IN varvhar2, ccc IN OUT varchar2); といったPL/SQLをVB.NET上で実行するとします。 (略:データベースへの接続処理) strSql = "begin test(10, 'テスト', '');end;" 結果「式が割り当てられていません」とエラーが出ます。 すべての引数がINのプロシージャでは、上記の方法で実行できたので、IN OUTへの引数の渡し方に問題があると思うのですが、どうしても分かりません。 まだ使い始めたばかりで、どうしていいかまったく分からない状態です。 どうかご指導お願い致します。

  • CSVを取込むストアドプロシージャで、1件目が登録されない現象が起きています

    いつもお世話になっております 古い環境なので大変恐縮ですが、行き詰ってしまったので、 ご教示いただきたいと思います。 環境: WinXP sp2 SQLServer8.0 VB6.0 sp4 VBでCSVのデータ1行について、ストアドプロシージャにて3つのテーブルに格納しようとしています。 トランザクションの管理はVB側で行っています。 1行ごとにCommitを行えば、全行格納されるのですが、 2行以上ごとにCommitを行うと、最初の1行のみが格納されないという現象がおきています。 6800行存在する同じCSVファイルについて、1行ごとにCommitを行った場合は、6800件登録されるのに 処理の最後でCommitをきった場合、6799行しか登録されません。 1行ごとにCommitをきった場合に6800行登録されるので、キー重複は考えられません。 いろいろ試してみたことを下記に書きます 結果はこのような感じです。 CASE1・・・全件登録できます CASE2・・・2件目で重複エラーが発生します CASE3・・・全件 - 1件が登録できます CASE4・・・全件登録できます CASE5・・・全件登録できます CASE2, CASE3 で全件登録できない理由をご教示いただきたく思います。 よろしくお願いいたします。 CASE1(VBでINSERT文を記述)  localConnection.beginTrans localConnection.execute "DELETE FROM TABLE_A" localConnection.execute "DELETE FROM TABLE_B" localConnection.execute "DELETE FROM TABLE_C" FOR i = 1 to 6800 localConnection.execute "INSERT INTO TABLE_A (COL_A1, COL_A2) VALUES ('" & VAL_A1(i) & "','" & VAL_A2(i) & "')" localConnection.execute "INSERT INTO TABLE_B (COL_B1, COL_B2) VALUES ('" & VAL_A1(i) & "','" & VAL_B2(i) & "')" localConnection.execute "INSERT INTO TABLE_C (COL_C1, COL_C2) VALUES ('" & VAL_A1(i) & "','" & VAL_C2(i) & "')" NEXT  localConnection.commitTrans CASE2(ストアドプロシージャ) localConnection.beginTrans localConnection.execute "DELETE FROM TABLE_A" localConnection.execute "DELETE FROM TABLE_B" localConnection.execute "DELETE FROM TABLE_C" ' -- ストアドプロシージャのパラメータ作成 FOR i = 1 to 6800 localConnection.execute NEXT  localConnection.commitTrans CASE3(ストアドプロシージャ) localConnection.beginTrans localConnection.execute "DELETE FROM TABLE_A" localConnection.execute "DELETE FROM TABLE_B" localConnection.execute "DELETE FROM TABLE_C"  localConnection.commitTrans ' -- ストアドプロシージャのパラメータ作成 localConnection.beginTrans FOR i = 1 to 6800 localConnection.execute NEXT  localConnection.commitTrans CASE4(ストアドプロシージャ) localConnection.beginTrans localConnection.execute "DELETE FROM TABLE_A" localConnection.execute "DELETE FROM TABLE_B" localConnection.execute "DELETE FROM TABLE_C"  localConnection.commitTrans ' -- ストアドプロシージャのパラメータ作成 localConnection.beginTrans FOR i = 1 to 6800 localConnection.execute   localConnection.commitTrans   localConnection.beginTrans NEXT  localConnection.commitTrans CASE5(ストアドプロシージャ) localConnection.beginTrans localConnection.execute "DELETE FROM TABLE_A" localConnection.execute "DELETE FROM TABLE_B" localConnection.execute "DELETE FROM TABLE_C"  localConnection.commitTrans ' -- ストアドプロシージャのパラメータ作成 localConnection.beginTrans FOR i = 1 to 6800 localConnection.execute if i = 1 then   localConnection.commitTrans   localConnection.beginTrans end if NEXT  localConnection.commitTrans

  • ストアドプロシージャの戻り値が取得できない

    ストアドプロシージャの戻り値が取得できない ストアドプロシージャ内でSelectとUpdateを行い、設定した戻り値をリターンしたいのです。 ついでにSelectとした複数行の結果の読み込みもしたいのですが。 Dim cmd As New System.Data.SqlClient.SqlCommand Dim i As Integer Dim readerA As System.Data.SqlClient.SqlDataReader cmd.CommandType = Data.CommandType.StoredProcedure cmd.CommandText = "SP名" cmd.Parameters.Add("A", System.Data.SqlDbType.Int) cmd.Parameters("A").Direction = System.Data.ParameterDirection.ReturnValue readerA = cmd.ExecuteReader() i = cmd.Parameters("A").Value if (i = 0) Then 処理 End If While readerA.Read() 処理 End While 上記でSelectした結果をreaderA("カラム名") で読みこめているのですが、戻り値Aの値が取得できていません。 ウォッチ式でcmd.Parameters("A").Valueを見るとNothingになっています。 ちなみに、違うストアドを実行しているところでは戻り値は取得できています。。。 ストアドがおかしいんでしょうか。Selectの取得結果も見ようとしているのがまずいのでしょうか。 環境はvb.net、SQLServer2005です。

  • VB.NETでADOでOracleのストアドを起動

    いつも楽しく勉強させていただいております。 環境はWindows Server 2008R2 DataCenter、データベースはOracle10G、開発ツールはVB.NET2015です。 このたびWindows Server 2003のVB6.0から上記の環境に乗せ換えているところです(Oracleのバージョンは変わりなし)。 最初にVB6.0からVB.NETへの変換はかけましたが、 なるべくVBのソースは変更しないという制約があります(テストのし直しが膨大になるので)。 VBとOracleはADOを使って接続しています。 ADOを使ってテーブルの読み書きはできるのですが、ストアドプロシージャの起動がうまくいきません。 具体的には入力パラメータはストアドに渡って処理も動くのですが、出力パラメータが返ってきません。 ストアドが正しく動くことはObjectBrowserで確認済みです。 下記のソースはVB6.0で動いていたものですが、VB.NET2015では二つの出力パラメータの値がNothingとなります。 (本来ならステータスとメッセージが返ります)。 VB.NET2015でADOでストアドを使うことは無理なのでしょうか。 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Dim Cnn As New ADODB.Connection Dim cmd As New ADODB.Command Dim Prm As New ADODB.Parameter Dim strMsg As String On Error GoTo Err_cmdExec_Click With Cnn .Provider = "MSDASQL" .ConnectionString = "DSN=DB1;" & "UID=abc;" & "PWD=efg" .Open() End With 'ストアドプロシージャ呼び出し設定&呼び出し With cmd .CommandTimeout = 0 'タイムアウト設定を無制限に .ActiveConnection = Cnn 'サーバー接続設定 .CommandText = "CHECK_PROC" 'ストアド名セット .CommandType = ADODB.CommandTypeEnum.adCmdStoredProc 'ストアドなのでadCmdStoredProc Prm = .CreateParameter("p_yyyymm", ADODB.DataTypeEnum.adChar, ADODB.ParameterDirectionEnum.adParamInput, 6, "201601") cmd.Parameters.Append(Prm) Prm = .CreateParameter("p_sts", ADODB.DataTypeEnum.adChar, ADODB.ParameterDirectionEnum.adParamOutput, 1) cmd.Parameters.Append(Prm) Prm = .CreateParameter("p_msg", ADODB.DataTypeEnum.adVarChar, ADODB.ParameterDirectionEnum.adParamOutput, 512) cmd.Parameters.Append(Prm) '実行 .Execute() '戻り値の判断&表示用メッセージ生成 If .Parameters.Item("p_sts").Value = "0" Then strMsg = "正常終了しました" Else strMsg = "異常終了しました" & vbCrLf & "ErrMsg=" & .Parameters.Item("p_msg").Value End If End With Exit_cmdExec_Click: '接続解除 Cnn.Close() 'Set Cnn = Nothing 'メッセージ表示 MsgBox(strMsg) Exit Sub Err_cmdExec_Click: 'ストアド以外の場所でのエラーなので、VBのErrの情報セット strMsg = "異常終了しました" & vbCrLf & "ErrNO=" & Err.Number & " ErrMsg=" & Err.Description Resume Exit_cmdExec_Click End Sub

  • [性能改善]AccessのDBに大量のデータをUpdateする場合の性能対策について

    初めまして。 早速質問なのですが、VB(6.0)でmdb(Access2000)のDBを更新する処理を作りました。 DAOを用いて(初めて使います)以下のような構文を作ったのですが、 性能がぱっとしません。 何か下記のソースをいじることで性能が改善するような手立てはありませんでしょうか? ---------------------------------------------------------------------- Sub Main()      Dim cDaoDB    As DAO.Database      Dim cDaoWS    As Workspace      Dim cColUpdate  As Collection      Dim varColItem  As Variant      Dim lngCnt    As Long      Set cDaoWS = DBEngine.Workspaces(0)      Set cDaoDB = mDaoWS.OpenDatabase("C:\TEST.mdb")      'コレクションにデータをaddする処理は省略しています      cColUpdate.add            With cDaoDB           cDaoWS.BeginTrans           'cColUpdateコレクションには10万件ほどのSQL構文(Update構文)が格納されています           '10万回ほど繰り返し処理します           For Each varColItem In cColUpdate                lngCnt = lngCnt + 1                If lngCnt > 1000 Then                     'データ量が多いため1000件ごとにコミットしています                     cDaoWS.CommitTrans                     cDaoWS.BeginTrans                     lngCnt = 0                End If                strErrSQL = varColItem                'Update処理が繰り返し流れます。                .Execute varColItem           Next           .Close           cDaoWS.Close      End With      Set cDaoDB = Nothing      Set cDaoWS = Nothing End Sub ---------------------------------------------------------------------- よろしくお願いします。

専門家に質問してみよう