none
SQL の GROUP BY 句を用いて集計した照会結果を Recordset オブジェクトに LockType =adLockOptimistic で格納して参照しようとすると 「SQL0100W FETCH、UPDATE または DELETE の対象となる行がないか、または照会の結果が空の表です。 」のエラーが返される。 RRS feed

  • 質問

  • ■環境
        OS    :  Windows Server 2016 64bit (IBM DB2 ODBC DRIVERをインストール)
        開発言語 : VB.NET(Visual Studio 2017, Microsoft ActiveX Data Objects2.8 Library)
      DBMS: DB2  V11.1

    ■質問の背景
     ・VB6(Microsoft ActiveX Data Objects2.5 Library)+DB2 V7.2の環境で開発されていたプログラムを
      VB.NET+DB2 V11.1にコンバージョンするプロジェクトを実施しています。
      プログラムの作りとして、DB2への接続はODBC接続を利用しており、VB.NET 化に
      おいても同様のODBC接続でDB2に接続する仕様とします。

    ■現在発生している事象

     ■問題
     ・プログラムではデータベースにアクセスして Open メソッドを使用して SQL の実行結果を Recordset オブジェクト (ADODB.Recordset)に格納しています。
     ・SQL では GROUP BY 句を用いて集計した結果を取得していますが、 Open メソッドの LockType プロパティは adLockOptimistic(共有的ロック)に設定しています。
     ・上記の Recordset オブジェクトのレコードを MoveNext メソッドで次のレコードに移動して参照していくと、以下のエラーが返されてレコードを参照できなくなります。
     「エラー番号:-2147467259,[IBM][CLI Driver][DB2/NT64] SQL0100W  FETCH、UPDATE または DELETE の対象となる行がないか、または照会の結果が空の表です。  SQLSTATE=02000,(Microsoft OLE DB Provider for ODBC Drivers)」
     ・参照しようとしたレコードが元の表でも単一のレコードである場合は上記のエラーが発生せず正常に参照でき、複数のレコードを集計した結果である場合は上記のエラーが発生することが判明しています。

        【コード】
            'ADO RECORDSET OPENメソッド発行
            adoRsMthAtmRslt = New ADODB.Recordset
            Call adoRsMthAtmRslt.Open(strSQL, adoConnect, ADODB.CursorTypeEnum.adOpenDynamic, ADODB.LockTypeEnum.adLockOptimistic, ADODB.CommandTypeEnum.adCmdText)  

     ■調査済み回避策
      ①VB6+DB2 V7.2で実行すると正常に動作し、上記エラーは発生しない。
      ②Open メソッドの LockType プロパティを adLockReadOnly (読み取り専用)に変更すると上記のエラーは発生せず、正常に動作する。
     
    ■質問
     ・VB6 と VB.NET  とで、LockType プロパティを adLockOptimistic とした場合に Recordset オブジェクトの挙動が異なる(MoveNext メソッドでエラーが発生する)ことがあるのでしょうか。
     ・上記のエラー事象の回避策として、上述の調査済み回避策の②を想定していますが、他に方法はあるでしょうか。
    2019年11月19日 11:07

回答

  • .NET から Recordset を使うと、使用済みオブジェクトの解放処理(Marshal.ReleaseComObject)が求められたりするので、個人的にはお奨めしませんが、それはさておき。

    そもそも本当に動的カーソル(adOpenDynamic)が必要かどうかを検討した方が良いと思います。このカーソルタイプをサポートしているドライバーは非常に稀であるためです。(実装するにしても、競合時のエラー処理が煩雑になりがちですし…)

    たとえば、かわりにキーセットカーソル(adOpenKeyset)を指定するのでは駄目でしょうか? このカーソルは多くのドライバーでサポートされています。

    もしどうしてもサーバー側の動的変更にも対応したいのであれば、静的カーソル(adOpenStatic)を選択した上で、Resync メソッドで同期を取るという方法も考えられます。

    それと、サポートされる CursorType と LockType の組み合わせというものは、使用している OLE DB Driver / ODBC Driver によっても異なります。もしもサポートされない組み合わせを指定して Open した場合、Recordset のこれらのプロパティは、Open 後に別の値に補正されることがあります。CursorLocation / CursorType / LockType の 3 値の組み合わせが適切な指定であるかどうか確認するため、この 3 つのプロパティの値が変化していないか、Open 前後で比較しておいた方が良いでしょう。

    • 編集済み 魔界の仮面弁士MVP 2019年11月19日 13:22 訂正:Keyset と Static が逆になっていた
    • 回答としてマーク kogiso99 2019年11月21日 13:33
    2019年11月19日 12:38
  • DB2 はわかりませんが、メッセージで検索すると以下が引っ掛かりました。

    「DB2のクライアントを7.1から8.1に変更した時に出るエラーについて」
    https://qa.itmedia.co.jp/qa1114757.html

    を見ると ODBC に何やら設定があるらしいです。

    「DB2 and ODBC - Function sequence error」
    https://bytes.com/topic/db2/answers/647506-db2-odbc-function-sequence-error

    Patch1 CLI/ODBC の 1024 がどーのこーのというお話のようです。

    Patch1 CLI/ODBC で検索すると

    「Patch1 CLI/ODBC 構成キーワード」
    https://www.ibm.com/support/knowledgecenter/ja/SSEPGG_9.7.0/com.ibm.db2.luw.apdv.cli.doc/doc/r0008804.html

    1024 は、何やら Visual Basic に関連したパラメタのようです。

    VB6 と VB.NET は同じ DSN を使用しているのでしょうか?

    違うのであれば VB6 で使用している DSN の設定を確認してみてください。

    • 回答としてマーク kogiso99 2019年11月21日 13:33
    2019年11月19日 14:25

すべての返信

  • .NET から Recordset を使うと、使用済みオブジェクトの解放処理(Marshal.ReleaseComObject)が求められたりするので、個人的にはお奨めしませんが、それはさておき。

    そもそも本当に動的カーソル(adOpenDynamic)が必要かどうかを検討した方が良いと思います。このカーソルタイプをサポートしているドライバーは非常に稀であるためです。(実装するにしても、競合時のエラー処理が煩雑になりがちですし…)

    たとえば、かわりにキーセットカーソル(adOpenKeyset)を指定するのでは駄目でしょうか? このカーソルは多くのドライバーでサポートされています。

    もしどうしてもサーバー側の動的変更にも対応したいのであれば、静的カーソル(adOpenStatic)を選択した上で、Resync メソッドで同期を取るという方法も考えられます。

    それと、サポートされる CursorType と LockType の組み合わせというものは、使用している OLE DB Driver / ODBC Driver によっても異なります。もしもサポートされない組み合わせを指定して Open した場合、Recordset のこれらのプロパティは、Open 後に別の値に補正されることがあります。CursorLocation / CursorType / LockType の 3 値の組み合わせが適切な指定であるかどうか確認するため、この 3 つのプロパティの値が変化していないか、Open 前後で比較しておいた方が良いでしょう。

    • 編集済み 魔界の仮面弁士MVP 2019年11月19日 13:22 訂正:Keyset と Static が逆になっていた
    • 回答としてマーク kogiso99 2019年11月21日 13:33
    2019年11月19日 12:38
  • DB2 はわかりませんが、メッセージで検索すると以下が引っ掛かりました。

    「DB2のクライアントを7.1から8.1に変更した時に出るエラーについて」
    https://qa.itmedia.co.jp/qa1114757.html

    を見ると ODBC に何やら設定があるらしいです。

    「DB2 and ODBC - Function sequence error」
    https://bytes.com/topic/db2/answers/647506-db2-odbc-function-sequence-error

    Patch1 CLI/ODBC の 1024 がどーのこーのというお話のようです。

    Patch1 CLI/ODBC で検索すると

    「Patch1 CLI/ODBC 構成キーワード」
    https://www.ibm.com/support/knowledgecenter/ja/SSEPGG_9.7.0/com.ibm.db2.luw.apdv.cli.doc/doc/r0008804.html

    1024 は、何やら Visual Basic に関連したパラメタのようです。

    VB6 と VB.NET は同じ DSN を使用しているのでしょうか?

    違うのであれば VB6 で使用している DSN の設定を確認してみてください。

    • 回答としてマーク kogiso99 2019年11月21日 13:33
    2019年11月19日 14:25
  • 回答ありがとうございます。この処理は Recordset の参照しかしておらず動的カーソル(adOpenDynamic)を使用する必要はないので、LockType と合わせて CursorType も修正することを検討します。

    > サポートされる CursorType と LockType の組み合わせというものは、使用している OLE DB Driver / ODBC Driver によっても異なります。

    これは実際に動かして確認する以外には方法はないでしょうか。

    2019年11月22日 0:11