none
ユーザー定義テーブル型パラメータを使用するとエラーが発生する RRS feed

  • 質問

  • はじめまして。
    いつも参考にさせて頂いております。

    SQL Server 2008にて、ユーザー定義テーブル型をREADONLYパラメータとして受け取る、ストアドプロシージャを作成しております。
    これをVBで作成したクラスから呼び出して処理しているのですが、以下のエラーが発生して困っています。

    System.Data.SqlClient.SqlException.Message
     現在のコマンドで重大なエラーが発生しました。結果は破棄しなければなりません。
     現在のコマンドで重大なエラーが発生しました。結果は破棄しなければなりません。
     ※同じ文言が2行のメッセージです

    System.Data.SqlClient.SqlException.StackTrace
       場所 System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
       場所 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
       場所 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
       場所 System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
       場所 System.Data.SqlClient.SqlDataReader.ConsumeMetaData()
       場所 System.Data.SqlClient.SqlDataReader.get_MetaData()
       場所 System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
       場所 System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
       場所 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
       場所 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
       場所 System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
       場所 System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
       場所 System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior)
       場所 System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior)
       場所 System.Data.Common.DbDataAdapter.Fill(DataTable[] dataTables, Int32 startRecord, Int32 maxRecords, IDbCommand command, CommandBehavior behavior)
       場所 System.Data.Common.DbDataAdapter.Fill(DataTable dataTable)
       場所 WindowsApplication1.Form1.Button1_Click(Object sender, EventArgs e) 場所 C:\Visual Studio 2008\Projects\WindowsApplication1\WindowsApplication1\Form1.vb:行 75


    思い違いも多くあるとは思うのですが、このユーザー定義テーブル型を使用した実装を行うにあたり、簡単な検証は行い、正常に処理できることを確認したつもりでした。
    それが先日、ユーザー定義テーブル型のパラメータをそのまま、INSERT INTO SELECT で一括登録する処理で、前述の例外が発生。
    同様にテーブル型パラメータをJOIN結合して更新する、UPDATE、DELETEは正常に動作・・・という状況に陥りました。
    その時点で自力で調べた限りではどうにもできず、とりあえずINSERTについてはテーブル型の使用を諦め、その対応を済ませました。

    が、本日、UPDATEとDELETEでも同様のエラーが発生しました。
    プロシージャだけではなく、トリガーやオプションなども含めて、特に何も変更していません。
    トリガーの有無が影響するか否かは分かりませんが、トリガーを削除しても、現象は変わりませんでした。

    再現テスト用として、末尾に記載しているソースを書いて実行してみたら・・・
    正常に動作してしまいました。
    エラーが発生している既存のものと全く同じ構成なのですけど。。

    出来ていたことが突如できなくなり、原因不明のまま納期も迫っていて途方に暮れております。
    有識者の皆さんにお力添え頂ければと投稿した次第です。
    何かご存知の方がいらっしゃいましたら、よろしくお願い致します。


    環境:
     SQL Server 2008 Express Edition
     Visual Studio 2008 9.0.30729.1 SP Professional
     .NET Framework 3.5 SP1
     Windows XP SP3 ※SQLServerインスタンス、VBアプリケーションともに

    ソース(SQL Server):
        CREATE TABLE [dbo].TestTable
        (
            TestCd NUMERIC(2, 0) NOT NULL,
            TestName NVARCHAR(64),
            Test INT
        ) ON [PRIMARY]
        GO

        CREATE TYPE [dbo].udtTestTable
        AS TABLE
        (
            TestCd NUMERIC(2, 0),
            TestName NVARCHAR(64),
            Test INT
        )
        GO

        CREATE PROCEDURE [dbo].TestTableProcedure(
            @InDataTable udtTestTable READONLY
        )
        AS
            UPDATE [dbo].TestTable
            SET TestName = C.TestName,
                Test     = C.Test
            FROM [dbo].TestTable T  INNER JOIN @InDataTable C
            ON T.TestCd = C.TestCd
        GO


    ソース(VB):
        Try
            Using cn As New SqlConnection(My.Settings.DbConnectionString)
                cn.Open()

                Dim adapter As New SqlDataAdapter("TestTableProcedure", cn)
                Dim reslt As New DataTable

                With adapter.SelectCommand
                    .CommandType = CommandType.StoredProcedure
                    With .Parameters.Add("@InDataTable", SqlDbType.Structured)
                        .TypeName = "udtTestTable"
                        .Value = DataGridView1.DataSource
                    End With
                    'reslt.Load(.ExecuteReader())
                End With

                adapter.Fill(reslt)

                DataGridView1.DataSource = reslt
                cn.Close()
            End Using
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try

    2010年4月6日 7:42

回答

  • こんにちは、nagino です。

    ちょっと現状の情報では難しい問題のような気がします。
    確かに .NET Framework 側の問題で SqlException が発生するケースもありますので、原因の切り分けから必要かもしれません。
    (例えばこちら http://support.microsoft.com/kb/927105)

    エラーが出るパターンに傾向はありませんか?
    ある特定のデータで出るかどうか、エラーが出るようになったときに他のデータではどうか、そのデータに対し SQL Server Management Studio から同等のクエリを実行した際にエラーが出るかどうか、といったあたりはいかがでしょうか。

    また、エラーは「adapter.Fill(reslt)」の行で出ていると思いますが、そこで reslt の内容は想定どおりの内容が格納されているかも確認してみて下さい。

    あと、エラーが出た際に SQL Server のエラーログには何か関連する情報が出ていませんでしょうか。
    http://technet.microsoft.com/ja-jp/library/ms187885.aspx

     


    MCITP(Database Developer/Database Administrator)
    • 回答としてマーク 菊地俊介 2010年4月27日 1:52
    2010年4月7日 10:44

すべての返信

  • 現象が合致しているかどうかは分かりませんが、以下のような現象が、SQL Server 2008 SP1 CU6 で改修されているみたいです。

    まずは、最新の修正モジュールを適用されてみてはどうでしょう。

    978504 FIX: An insert operation fails when you insert data from one database into another database when the destination database contains a user-defined data type in SQL Server 2008

    http://support.microsoft.com/kb/978504/en-us

    ※日本語訳は、若干怪しそうだったので、英語にしました。

    2010年4月6日 8:12
  • 返信ありがとうございます。

    早速環境をバックアップしてインストール中です。
    今のところ15分くらいプログレスバーがピクリとも動きませんが・・・適用完了次第再テストを行い、報告させて頂きます。

     

    ------------------------------

    (編集)

    残念ながら現象変わらずでありました。

    • 編集済み どみにか 2010年4月6日 9:10 結果報告
    2010年4月6日 8:45
  • 追記です。

    末尾の形でT-SQLを発行したところ、問題のプロシージャも正常に動作しました。
    現象とエラーメッセージからSQL Server側の問題と思ってましたが、スタックトレースで見ても『FinishExecuteReader』が呼ばれていますし、.NET Framework側かもしれませんね。。


    DECLARE @InTable udtTestTable

    INSERT INTO @InTable VALUES(5,'TEST', 128)
      
    EXEC TestTableProcedure @InTable

    SELECT * FROM TestTable

    2010年4月6日 9:28
  • こんにちは、nagino です。

    ちょっと現状の情報では難しい問題のような気がします。
    確かに .NET Framework 側の問題で SqlException が発生するケースもありますので、原因の切り分けから必要かもしれません。
    (例えばこちら http://support.microsoft.com/kb/927105)

    エラーが出るパターンに傾向はありませんか?
    ある特定のデータで出るかどうか、エラーが出るようになったときに他のデータではどうか、そのデータに対し SQL Server Management Studio から同等のクエリを実行した際にエラーが出るかどうか、といったあたりはいかがでしょうか。

    また、エラーは「adapter.Fill(reslt)」の行で出ていると思いますが、そこで reslt の内容は想定どおりの内容が格納されているかも確認してみて下さい。

    あと、エラーが出た際に SQL Server のエラーログには何か関連する情報が出ていませんでしょうか。
    http://technet.microsoft.com/ja-jp/library/ms187885.aspx

     


    MCITP(Database Developer/Database Administrator)
    • 回答としてマーク 菊地俊介 2010年4月27日 1:52
    2010年4月7日 10:44