web-dev-qa-db-fra.com

A reçu une longueur de colonne non valide du client bcp pour la colonne 6

Je veux charger en bloc des données de fichier csv sur SQL Server 2005 à partir de code c # mais je rencontre l'erreur ci-dessous -

A reçu une longueur de colonne non valide du client bcp pour la colonne 6.

lorsque la copie en bloc écrit sur le serveur de base de données

70
Sana Sana

Une des colonnes de données dans Excel (Column Id 6) contient une ou plusieurs données de cellule dépassant la longueur du type de données de colonne de données dans la base de données.

Vérifiez les données dans Excel. Vérifiez également que les données dans Excel sont conformes au schéma de la table de la base de données.

Pour éviter cela, essayez de dépasser la longueur de données du type de données chaîne dans la table de base de données.

J'espère que cela t'aides.

57
Dinesh

Je sais que cet article est vieux, mais j'ai rencontré le même problème et j'ai finalement trouvé une solution pour déterminer quelle colonne était à l'origine du problème et le signaler si nécessaire. J'ai déterminé que colid retourné dans SqlException n’est pas basé sur zéro, vous devez donc en soustraire 1 pour obtenir la valeur. Après cela, il est utilisé comme index du _sortedColumnMappings ArrayList de l’instance SqlBulkCopy et non l’index des mappages de colonnes ajoutés à l’instance SqlBulkCopy. Une chose à noter est que SqlBulkCopy s'arrêtera à la première erreur reçue. Ce n'est peut-être pas le seul problème, mais au moins, cela aide à le résoudre.

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;
}
157
b_stil

Vérifiez la taille des colonnes dans la table que vous effectuez une insertion/copie en bloc. les colonnes varchar ou autres chaînes doivent éventuellement être étendues ou la valeur que vous insérez doit être rognée. L'ordre des colonnes doit également être identique à celui du tableau.

par exemple, augmenter la taille de la colonne varchar 30 à 50 =>

ALTER TABLE [dbo]. [Nom de la table] ALTER COLUMN [Nom de la colonne] Varchar (50)

1
Nalan Madheswaran

J'ai rencontré un problème similaire en passant une chaîne à la table Database à l'aide de l'option SQL BulkCopy. La chaîne que je passais avait 3 caractères alors que la longueur de la colonne de destination était varchar(20). J'ai essayé de rogner la chaîne avant de l'insérer dans DB en utilisant la fonction Trim() pour vérifier si le problème était dû à un espace (début et fin) dans la chaîne. Après avoir coupé la chaîne, cela a bien fonctionné.

Vous pouvez essayer text.Trim()

1
Liji Chandran

Excellent morceau de code, merci pour le partage!

J'ai fini par utiliser réflexion pour que le DataMemberName réel soit renvoyé à un client en cas d'erreur (j'utilise la sauvegarde en bloc dans un service WCF). J'espère que quelqu'un d'autre trouvera comment je l'ai fait utile.

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
infocyde