バッチで多くの挿入ステートメントを実行するC#コードがあります。これらのステートメントの実行中に、「文字列またはバイナリデータは切り捨てられます」エラーとトランザクションロールバックが発生しました。
どの挿入ステートメントがこれを引き起こしたかを調べるには、エラーが発生するまでSQLServerに1つずつ挿入する必要があります。
例外処理を使用して、どのステートメントとどのフィールドがこの問題の原因であるかを見つける巧妙な方法はありますか? (SqlException)
一般に、どの特定のステートメントがエラーを引き起こしたかを判断する方法はありません。複数実行している場合、プロファイラーを見て最後に完了したステートメントを見て、その後のステートメントが何であるかを確認できますが、そのアプローチがあなたにとって実行可能かどうかはわかりません。
いずれにせよ、パラメーター変数の1つ(およびその中のデータ)は、データを保存しようとしているフィールドに対して大きすぎます。パラメーターサイズを列サイズと照合し、問題のフィールドがすぐに明らかになるはずです。
このタイプのエラーは、SQL Server列のデータ型の長さが、エントリフォームに入力されたデータの長さよりも短い場合に発生します。
通常、このタイプのエラーは、そのような場合にデータベーステーブルで指定した文字または値よりも多くの文字または値を入力する必要がある場合に発生します。それがこのコードでこのタイプのエラーに直面した理由です
BEGIN TRY
INSERT INTO YourTable (col1, col2) VALUES (@val1, @val2)
END TRY
BEGIN CATCH
--print or insert into error log or return param or etc...
PRINT '@val1='+ISNULL(CONVERT(varchar,@val1),'')
PRINT '@val2='+ISNULL(CONVERT(varchar,@val2),'')
END CATCH
通常、最大許容値を超える値を挿入します。たとえば、データ列には最大200文字しか入力できませんが、201文字の文字列を挿入しています
あなたは次のようなものになるはずです
SELECT
Col1, Col2, ..., [ColN]
INTO [MyTempTable]
FROM
[Tables etc.]
WHERE 0 = 1
これにより、DBにMyTempTableというテーブルが作成され、ターゲットテーブル構造と比較できます。つまり、両方のテーブルの列を比較して、どこが違うかを確認できます。それは少しの回避策ですが、私が見つけた最も速い方法です。
呼び出しの挿入方法によって異なります。すべてを1つの呼び出しとして、またはトランザクション内の個々の呼び出しとして?個々の呼び出しの場合は、はい(呼び出しを繰り返しながら、失敗した呼び出しをキャッチします)。 1つの大規模なコールの場合、いいえ。 SQLはステートメント全体を処理しているため、コードの手に負えません。
また、null
値をデータベースに戻そうとしていることが原因の可能性もあります。そのため、トランザクションの1つにヌルが含まれている可能性があります。
ここでの回答のほとんどは、データベースで定義されている列の長さが、渡そうとしているデータよりも小さくないことを明確に確認することです。
何度か、SQL Management Studioに行って噛みつきました。
sp_help 'mytable'
問題の列がnvarcharであることに気付くまで数分間混乱します。つまり、sp_helpによって報告される長さは、ダブルバイト(ユニコード)データ型であるため、サポートされる実際の長さの2倍です。
つまり、sp_helpがnvarchar長さ40を報告する場合、最大20文字を保存できます。
Linq To SQLでは、コンテキストをログに記録してデバッグしました。 _Context.Log = Console.Out
_次に、明らかなエラーをチェックするためにSQLをスキャンしました。2つありました。
_-- @p46: Input Char (Size = -1; Prec = 0; Scale = 0) [some long text value1]
-- @p8: Input Char (Size = -1; Prec = 0; Scale = 0) [some long text value2]
_
テーブルスキーマを値に対してスキャンして見つけた最後のフィールドは、nvarchar(20)でしたが、値は22文字でした
-- @p41: Input NVarChar (Size = 4000; Prec = 0; Scale = 0) [1234567890123456789012]
私たちの場合、フロントエンドから投稿された合計文字数よりも少ないSQLテーブルの許容文字またはフィールドサイズを増やします。したがって、それは問題を解決します。