从bcp客户端收到了针对colid 6的无效列长度


87

我想将cv文件数据从c#代码批量上传到sql server 2005,但是遇到以下错误-

从bcp客户端收到针对colid 6的无效列长度。

批量复制写入数据库服务器时

Answers:


69

Excel中的数据列之一(列ID 6)具有一个或多个单元格数据,这些数据超出了数据库中datacolumn数据类型的长度。

在excel中验证数据。还请验证excel中的数据的格式是否符合数据库表架构。

为避免这种情况,请尝试超过数据库表中字符串数据类型的数据长度。

希望这可以帮助。


1
具体来说,如果您有VARCHAR小于4的任何列,请注意数据中的NULL会被误解为4char字符串“ NULL”
CrazyPyro

195

我知道这篇文章很老,但是我遇到了同样的问题,最后想出了一个解决方案来确定引起问题的列并根据需要进行报告。我确定colidSqlException中返回的值不是基于零的,因此您需要从中减去1以获得值。之后,它将用作_sortedColumnMappingsSqlBulkCopy实例的ArrayList的索引,而不是添加到SqlBulkCopy实例的列映射的索引。需要注意的一件事是,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
效果非常好,谢谢您的提交。
Steven

1
您知道是否也可以获取nr行吗?
Gerhard Powell,

2
DataFormatException是一个自定义异常,因此我可以将问题报告为无效的列长。我还无法弄清楚如何获取行号。
b_stil 2014年

1
很好的解决方案,唯一缺少的是捕获sqlTran.RollBack();
pqsk

8
对于大多数人来说,这可能是显而易见的,但是“在SqlException中返回的大肠菌不是基于零的”帮助我解决了这一问题。
panhandel 2015年

4

使用SQL BulkCopy选项将字符串传递到数据库表时,我遇到了类似的问题。我传递的字符串为3个字符,而目标列的长度为varchar(20)。我尝试在使用Trim()函数插入数据库之前修剪字符串,以检查问题是否归因于字符串中的任何空格(开头和结尾)。修剪字符串后,它可以正常工作。

你可以试试 text.Trim()


太好了,非常感谢!这也是我的确切原因-尾随空格,结果超出了列长度。
aleor

如果字符串可能为null,请使用text?.Trim()
Charles 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

我收到了一个错误的错误消息,并带有一个较新的sis版本(相对于2015 Enterprise,我认为是sis 2016)。我将在这里发表评论,因为这是您在搜索此错误消息时出现的第一个参考。我认为当源字符的大小大于目标字符的大小时,字符列通常会发生这种情况。我从Teradata数据库使用ado.net输入到ms sql时收到了此消息。很有趣,因为先前的oledb写入ms sql可以完美地处理所有字符转换,而没有任何编码覆盖。大肠菌编号和有时通过大肠菌消息获得的相应“目标输入”列号是毫无价值的。从映射顶部或类似位置向下计数时,它不是该列。如果我是微软,我 d不好意思给出一条错误消息,看起来好像是指向问题列的错误消息。通过进行有根据的猜测,然后将对映射的输入更改为“忽略”,然后重新运行以查看消息是否消失,我发现了大肠杆菌病。就我而言,在我的环境中,我通过将Teradata输入替换为输出列的ms sql声明的字符大小来修复它。检查并确保您的输入substr在所有数据转换和映射中传播。如果没有,我必须删除所有的“数据转换”和“映射”,然后重新开始。再次有趣的是,OLEDB刚刚处理了它,而ADO.net抛出了错误,必须进行所有这些干预才能使其正常工作。您的目标是MS Sql时应使用OLEDB。指向不是的问题列。通过进行有根据的猜测,然后将输入的映射更改为“忽略”,然后重新运行并查看消息是否消失,我发现了大肠杆菌病。就我而言,在我的环境中,我通过将Teradata输入替换为输出列的ms sql声明的字符大小来修复它。检查并确保您的输入substr在所有数据转换和映射中传播。如果没有,那么我必须删除所有的“数据转换”和“映射”,然后重新开始。再次有趣的是,OLEDB刚刚处理了它,而ADO.net抛出了错误,必须进行所有这些干预才能使其正常工作。您的目标是MS Sql时应使用OLEDB。指向不是的问题列。通过进行有根据的猜测,然后将输入的映射更改为“忽略”,然后重新运行以查看消息是否消失,我发现了大肠杆菌病。就我而言,在我的环境中,我通过将Teradata输入替换为输出列的ms sql声明的字符大小来修复它。检查并确保您的输入substr在所有数据转换和映射中传播。如果没有,那么我必须删除所有的“数据转换”和“映射”,然后重新开始。再次有趣的是,OLEDB刚刚处理了它,而ADO.net抛出了错误,必须进行所有这些干预才能使其正常工作。您的目标是MS Sql时应使用OLEDB。通过进行有根据的猜测,然后将对映射的输入更改为“忽略”,然后重新运行并查看消息是否消失,我发现了大肠杆菌病。就我而言,在我的环境中,我通过将Teradata输入替换为输出列的ms sql声明的字符大小来修复它。检查并确保您的输入substr在所有数据转换和映射中传播。如果没有,那么我必须删除所有的“数据转换”和“映射”,然后重新开始。再次有趣的是,OLEDB刚刚处理了它,而ADO.net抛出了错误,必须进行所有这些干预才能使其正常工作。您的目标是MS Sql时应使用OLEDB。通过进行有根据的猜测,然后将输入的映射更改为“忽略”,然后重新运行并查看消息是否消失,我发现了大肠杆菌病。就我而言,在我的环境中,我通过将Teradata输入替换为输出列的ms sql声明的字符大小来修复它。检查并确保您的输入substr在所有数据转换和映射中传播。如果没有,那么我必须删除所有的“数据转换”和“映射”,然后重新开始。再次有趣的是,OLEDB刚刚处理了它,而ADO.net抛出了错误,必须进行所有这些干预才能使其正常工作。您的目标是MS Sql时应使用OLEDB。s和Mappings,然后重新开始。再次有趣的是,OLEDB刚刚处理了它,而ADO.net抛出了错误,必须进行所有这些干预才能使其工作。通常,当目标是MS Sql时,应使用OLEDB。s和Mappings,然后重新开始。再次有趣的是,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;
    }

希望这可以帮助某人

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.