colid6のbcpクライアントから無効な列長を受け取りました


87

csvファイルデータをc#コードからSQL Server 2005に一括アップロードしたいのですが、以下のエラーが発生します-

colid6のbcpクライアントから無効な列長を受け取りました。

データベースサーバーへの一括コピー書き込み時

回答:


69

Excelのデータ列の1つ(列ID 6)に、データベースのデータ列データ型の長さを超える1つ以上のセルデータがあります。

Excelでデータを確認します。また、Excelのデータの形式がデータベーステーブルスキーマに準拠していることを確認します。

これを回避するには、データベーステーブルの文字列データ型のデータ長を超えてみてください。

お役に立てれば。


1
具体的には、VARCHARが4より小さい列がある場合、データ内のNULLが4char文字列「NULL」として誤って解釈されることに注意してください
CrazyPyro 2010

196

この投稿が古いことは知っていますが、同じ問題が発生し、最終的に問題の原因となっている列を特定し、必要に応じて報告するための解決策を見つけました。colidSqlExceptionで返される値はゼロベースではないと判断したため、値を取得するには、そこから1を引く必要があります。その後_sortedColumnMappings、SqlBulkCopyインスタンスに追加された列マッピングのインデックスではなく、SqlBulkCopyインスタンスのArrayListのインデックスとして使用されます。注意すべき点の1つは、SqlBulkCopyは最初に受信したエラーで停止するため、これが唯一の問題ではない可能性がありますが、少なくともそれを理解するのに役立ちます。

try
{
    bulkCopy.WriteToServer(importTable);
    sqlTran.Commit();
}    
catch (SqlException ex)
{
    if (ex.Message.Contains("Received an invalid column length from the bcp client for colid"))
    {
        string pattern = @"\d+";
        Match match = Regex.Match(ex.Message.ToString(), pattern);
        var index = Convert.ToInt32(match.Value) -1;

        FieldInfo fi = typeof(SqlBulkCopy).GetField("_sortedColumnMappings", BindingFlags.NonPublic | BindingFlags.Instance);
        var sortedColumns = fi.GetValue(bulkCopy);
        var items = (Object[])sortedColumns.GetType().GetField("_items", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(sortedColumns);

        FieldInfo itemdata = items[index].GetType().GetField("_metadata", BindingFlags.NonPublic | BindingFlags.Instance);
        var metadata = itemdata.GetValue(items[index]);

        var column = metadata.GetType().GetField("column", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).GetValue(metadata);
        var length = metadata.GetType().GetField("length", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).GetValue(metadata);
        throw new DataFormatException(String.Format("Column: {0} contains data with a length greater than: {1}", column, length));
    }

    throw;
}

4
これは非常にうまく機能します、提出していただきありがとうございます。
スティーブン

1
行nrも取得できるかどうか知っていますか?
Gerhard Powell

2
DataFormatExceptionはカスタム例外であるため、無効な列の長さとして問題を報告できます。行番号を取得する方法をまだ理解できていません。
b_stil 2014年

1
素晴らしい解決策です。欠けているのはcatchsqlTran.RollBack();だけです。
pqsk 2015年

8
ほとんどの人にとって明白なことかもしれませんが、「SqlExceptionで返されるcolidはゼロベースではありません」と私はこれを嗅ぎ分けるのに役立ちました。
パンハンデル2015年

4

SQL BulkCopyオプションを使用してデータベーステーブルに文字列を渡すときに、同様の問題に直面しました。渡した文字列は3文字でしたが、宛先列の長さはでしたvarchar(20)Trim()関数を使用してDBに挿入する前に文字列をトリミングして、問題の原因が文字列のスペース(先頭と末尾)にあるかどうかを確認してみました。文字列をトリミングした後、それはうまくいきました。

あなたが試すことができます text.Trim()


それは素晴らしいです、どうもありがとう!それが私の場合も正確な理由でした。末尾の空白が原因で、列の長さが超過しました。
aleor

文字列がnullの可能性がある場合、使用テキスト.Trim()?
チャールズPlager

1

一括挿入/コピーを実行しているテーブルの列のサイズを確認してください。varcharまたはその他の文字列列を拡張するか、挿入する値をトリミングする必要がある場合があります。列の順序も表と同じである必要があります。

例:varchar列のサイズを30から50に増やします=>

ALTER TABLE [dbo]。[TableName] ALTER COLUMN [ColumnName] Varchar(50)


0

素晴らしいコード、共有してくれてありがとう!

最終的にリフレクションを使用して、エラー時に実際のDataMemberNameをクライアントにスローバックしました(WCFサービスで一括保存を使用しています)。うまくいけば、他の誰かが私がそれをどのようにしたかが役に立つとわかるでしょう。

static string GetDataMemberName(string colName, object t) {
  foreach(PropertyInfo propertyInfo in t.GetType().GetProperties()) {
    if (propertyInfo.CanRead) {
      if (propertyInfo.Name == colName) {
        var attributes = propertyInfo.GetCustomAttributes(typeof(DataMemberAttribute), false).FirstOrDefault() as DataMemberAttribute;
        if (attributes != null && !string.IsNullOrEmpty(attributes.Name))
          return attributes.Name;
        return colName;
      }
    }
  }
  return colName;
}


これはどのように実装できますか?
アポロ

0

このエラーメッセージは、はるかに新しいssisバージョンで表示されます(2015エンタープライズと比較して、ssis 2016だと思います)。これは、このエラーメッセージをグーグルで検索したときに最初に表示される参照であるため、ここでコメントします。ソース文字サイズがターゲット文字サイズよりも大きい場合、ほとんどの場合、文字列で発生すると思います。このメッセージは、teradataデータベースからmssqlへのado.net入力を使用しているときに表示されました。以前のoledbがmssqlに書き込むと、コーディングのオーバーライドなしですべての文字変換が完全に処理されたため、おかしいです。コリッド番号と、コリッドメッセージで時々表示される対応する宛先入力列#は価値がありません。マッピングの上からカウントダウンするときの列ではありません。私がマイクロソフトだったら、dそうでないのに、問題の列を指しているように見えるエラーメッセージを表示するのは恥ずかしいことです。知識に基づいた推測を行い、マッピングへの入力を「無視」に変更してから再実行して、メッセージが消えたかどうかを確認することで、問題が解決したことを発見しました。私の場合と私の環境では、substr( 'Teradata入力を出力列のmssql宣言の文字サイズに変更することで修正しました。入力substrがすべてのデータ変換とマッピングに伝播することを確認してください。そうではなく、すべてのデータ変換とマッピングを削除して最初からやり直す必要がありました。OLEDBがそれを処理し、ADO.netがエラーをスローし、それを機能させるためにこのすべての介入が必要だったのはおかしいです。ターゲットがMSSqlの場合は、OLEDBを使用する必要があります。s問題のない列を指している。知識に基づいた推測を行い、マッピングへの入力を「無視」に変更してから再実行して、メッセージが消えたかどうかを確認することで、問題が解決したことを発見しました。私の場合と私の環境では、substr( 'Teradata入力を出力列のmssql宣言の文字サイズに変更することで修正しました。入力substrがすべてのデータ変換とマッピングに伝播することを確認してください。そうでない場合は、すべてのデータ変換とマッピングを削除して、最初からやり直す必要がありました。OLEDBがそれを処理し、ADO.netがエラーをスローし、それを機能させるためにこのすべての介入が必要だったのは、やはりおかしいです。ターゲットがMSSqlの場合は、OLEDBを使用する必要があります。s問題のない列を指している。知識に基づいた推測を行い、マッピングへの入力を「無視」に変更してから再実行して、メッセージが消えたかどうかを確認することで、問題が解決したことを発見しました。私の場合と私の環境では、substr( 'Teradata入力を出力列のmssql宣言の文字サイズに変更することで修正しました。入力substrがすべてのデータ変換とマッピングに伝播することを確認してください。そうでない場合は、すべてのデータ変換とマッピングを削除して、最初からやり直す必要がありました。OLEDBがそれを処理し、ADO.netがエラーをスローし、それを機能させるためにこのすべての介入が必要だったのは、やはりおかしいです。ターゲットがMSSqlの場合は、OLEDBを使用する必要があります。知識に基づいた推測を行い、マッピングへの入力を「無視」に変更してから再実行して、メッセージが消えたかどうかを確認することで、問題が解決したことを発見しました。私の場合と私の環境では、substr( 'Teradata入力を出力列のmssql宣言の文字サイズに変更することで修正しました。入力substrがすべてのデータ変換とマッピングに伝播することを確認してください。そうでない場合は、すべてのデータ変換とマッピングを削除して、最初からやり直す必要がありました。OLEDBがそれを処理し、ADO.netがエラーをスローし、それを機能させるためにこのすべての介入が必要だったのは、やはりおかしいです。ターゲットがMSSqlの場合は、OLEDBを使用する必要があります。知識に基づいた推測を行い、マッピングへの入力を「無視」に変更してから再実行して、メッセージが消えたかどうかを確認することで、問題が解決したことを発見しました。私の場合と私の環境では、substr( 'Teradata入力を出力列のmssql宣言の文字サイズに変更することで修正しました。入力substrがすべてのデータ変換とマッピングに伝播することを確認してください。そうではなく、すべてのデータ変換とマッピングを削除して最初からやり直す必要がありました。OLEDBがそれを処理し、ADO.netがエラーをスローし、それを機能させるためにこのすべての介入が必要だったのはおかしいです。ターゲットがMSSqlの場合は、OLEDBを使用する必要があります。とマッピングを実行し、最初からやり直します。OLEDBがそれを処理し、ADO.netがエラーをスローし、それを機能させるためにこのすべての介入が必要だったこともおかしいです。一般に、ターゲットがMS Sqlの場合は、OLEDBを使用する必要があります。sとマッピングを実行し、最初からやり直します。OLEDBがそれを処理し、ADO.netがエラーをスローし、それを機能させるためにこのすべての介入が必要だったこともおかしいです。一般に、ターゲットがMS Sqlの場合は、OLEDBを使用する必要があります。


0

私はこれに偶然出くわし、@ b_stilのスニペットを使用して、原因の列を特定することができました。さらに調査したところ、@ Liji Chandranが提案したように列をトリミングする必要があると思いましたが、IExcelDataReaderを使用していたため、160列のそれぞれを検証してトリミングする簡単な方法がわかりませんでした。

次に、CSVReaderのこのクラス(ValidatingDataReader)クラスに出くわしました

このクラスの興味深い点は、ソース列と宛先列のデータ長、原因の行、さらにはエラーの原因となっている列の値を提供することです。

私がしたのは、すべての(nvarchar、varchar、char、およびnchar)列をトリミングすることだけでした。

GetValueメソッドを次のように変更しました。

 object IDataRecord.GetValue(int i)
    {
        object columnValue = reader.GetValue(i);

        if (i > -1 && i < lookup.Length)
        {
            DataRow columnDef = lookup[i];
            if
            (
                (
                    (string)columnDef["DataTypeName"] == "varchar" ||
                    (string)columnDef["DataTypeName"] == "nvarchar" ||
                    (string)columnDef["DataTypeName"] == "char" ||
                    (string)columnDef["DataTypeName"] == "nchar"
                ) &&
                (
                    columnValue != null &&
                    columnValue != DBNull.Value
                )
            )
            {
                string stringValue = columnValue.ToString().Trim();

                columnValue = stringValue;


                if (stringValue.Length > (int)columnDef["ColumnSize"])
                {
                    string message =
                        "Column value \"" + stringValue.Replace("\"", "\\\"") + "\"" +
                        " with length " + stringValue.Length.ToString("###,##0") +
                        " from source column " + (this as IDataRecord).GetName(i) +
                        " in record " + currentRecord.ToString("###,##0") +
                        " does not fit in destination column " + columnDef["ColumnName"] +
                        " with length " + ((int)columnDef["ColumnSize"]).ToString("###,##0") +
                        " in table " + tableName +
                        " in database " + databaseName +
                        " on server " + serverName + ".";

                    if (ColumnException == null)
                    {
                        throw new Exception(message);
                    }
                    else
                    {
                        ColumnExceptionEventArgs args = new ColumnExceptionEventArgs();

                        args.DataTypeName = (string)columnDef["DataTypeName"];
                        args.DataType = Type.GetType((string)columnDef["DataType"]);
                        args.Value = columnValue;
                        args.SourceIndex = i;
                        args.SourceColumn = reader.GetName(i);
                        args.DestIndex = (int)columnDef["ColumnOrdinal"];
                        args.DestColumn = (string)columnDef["ColumnName"];
                        args.ColumnSize = (int)columnDef["ColumnSize"];
                        args.RecordIndex = currentRecord;
                        args.TableName = tableName;
                        args.DatabaseName = databaseName;
                        args.ServerName = serverName;
                        args.Message = message;

                        ColumnException(args);

                        columnValue = args.Value;
                    }
                }



            }
        }

        return columnValue;
    }

これが誰かを助けることを願っています

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.