Menerima panjang kolom yang tidak valid dari klien bcp untuk colid 6

87

Saya ingin mengunggah data file csv secara massal ke sql server 2005 dari kode c # tetapi saya mengalami kesalahan di bawah ini -

Menerima panjang kolom yang tidak valid dari klien bcp untuk colid 6.

ketika copy massal menulis ke server database

Sana Sana
sumber

Jawaban:

69

Salah satu kolom data di excel (Column Id 6) memiliki satu atau lebih data sel yang melebihi panjang tipe data kolom data dalam database.

Verifikasi data di excel. Juga verifikasi data di excel agar formatnya sesuai dengan skema tabel database.

Untuk menghindari ini, coba melebihi panjang data dari tipe data string dalam tabel database.

Semoga ini membantu.

Dinesh
sumber
1
Secara khusus, jika Anda memiliki kolom yang VARCHAR lebih kecil dari 4, hati-hati terhadap NULL dalam data Anda yang salah ditafsirkan sebagai string 4char "NULL"
CrazyPyro
196

Saya tahu posting ini sudah lama tetapi saya mengalami masalah yang sama ini dan akhirnya menemukan solusi untuk menentukan kolom mana yang menyebabkan masalah dan melaporkannya kembali sesuai kebutuhan. Saya memutuskan bahwa yang coliddikembalikan di SqlException tidak berbasis nol sehingga Anda perlu mengurangi 1 darinya untuk mendapatkan nilainya. Setelah itu digunakan sebagai indeks _sortedColumnMappingsArrayList contoh SqlBulkCopy bukan indeks pemetaan kolom yang ditambahkan ke contoh SqlBulkCopy. Satu hal yang perlu diperhatikan adalah bahwa SqlBulkCopy akan berhenti pada kesalahan pertama yang diterima sehingga ini mungkin bukan satu-satunya masalah tetapi setidaknya membantu untuk mengetahuinya.

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;
}
b_stil
sumber
4
Ini bekerja dengan sangat baik, terima kasih telah mengirimkan.
Steven
1
Apakah Anda tahu apakah mungkin juga mendapatkan baris nr?
Gerhard Powell
2
DataFormatException adalah pengecualian khusus sehingga saya dapat melaporkan kembali masalah tersebut karena panjang kolom tidak valid. Saya belum bisa menemukan cara mendapatkan nomor baris.
m_stil
1
Solusi hebat, satu-satunya hal yang hilang adalah tangkapan sqlTran.RollBack ();
pqsk
8
Mungkin terlihat sangat jelas bagi sebagian besar orang, tetapi "kolom yang dikembalikan di SqlException tidak berbasis nol" membantu saya memadamkannya.
panhandel
4

Saya menghadapi masalah serupa saat mengirimkan string ke tabel Database menggunakan opsi SQL BulkCopy. String yang saya lewati terdiri dari 3 karakter sedangkan panjang kolom tujuan adalah varchar(20). Saya mencoba memangkas string sebelum memasukkan ke DB menggunakan Trim()fungsi untuk memeriksa apakah masalahnya disebabkan oleh spasi (di depan dan di belakang) dalam string. Setelah memotong senar, itu bekerja dengan baik.

Anda dapat mencoba text.Trim()

Liji Chandran
sumber
Bagus sekali, terima kasih banyak! Itu adalah alasan yang tepat dalam kasus saya juga - spasi kosong dan akibatnya panjang kolom terlampaui.
aleor
Jika string mungkin nol, gunakan teks? .Trim ()
Charles Plager
1

Periksa ukuran kolom di tabel yang Anda lakukan penyisipan / penyalinan massal. varchar atau kolom string lainnya mungkin perlu diperpanjang atau nilai yang Anda sisipkan perlu dipotong. Urutan kolom juga harus sama seperti pada tabel.

misalnya, Tingkatkan ukuran kolom varchar 30 menjadi 50 =>

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

Nalan Madheswaran
sumber
0

Sepotong kode yang bagus, terima kasih telah berbagi!

Saya akhirnya menggunakan refleksi untuk mendapatkan DataMemberName yang sebenarnya untuk melempar kembali ke klien pada kesalahan (Saya menggunakan penyimpanan massal dalam layanan WCF). Mudah-mudahan orang lain akan merasakan manfaat dari cara saya melakukannya.

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

infocyde.dll
sumber
Bagaimana ini bisa diterapkan?
Apollo
0

Saya mendapat pesan kesalahan ini dengan versi ssis yang jauh lebih baru (vs perusahaan 2015, saya pikir ini ssis 2016). Saya akan berkomentar di sini karena ini adalah referensi pertama yang muncul ketika Anda google pesan kesalahan ini. Saya pikir itu terjadi sebagian besar dengan kolom karakter ketika ukuran karakter sumber lebih besar dari ukuran karakter target. Saya mendapat pesan ini ketika saya menggunakan input ado.net ke ms sql dari database teradata. Lucu karena oledb sebelumnya menulis ke ms sql menangani semua konversi karakter dengan sempurna tanpa penggantian pengkodean. Nomor kolom dan kolom Input Tujuan yang sesuai # yang terkadang Anda dapatkan dengan pesan kolom tidak ada gunanya. Ini bukan kolom saat Anda menghitung mundur dari atas pemetaan atau semacamnya. Jika saya microsoft, saya ' d akan dipermalukan untuk memberikan pesan kesalahan yang sepertinya menunjuk ke kolom masalah padahal sebenarnya tidak. Saya menemukan kolom masalah dengan membuat tebakan terpelajar dan kemudian mengubah masukan ke pemetaan menjadi "Abaikan" dan kemudian menjalankan kembali dan melihat apakah pesan tersebut hilang. Dalam kasus saya dan di lingkungan saya, saya memperbaikinya dengan substr (memasukkan input Teradata ke ukuran karakter deklarasi ms sql untuk kolom output. Periksa dan pastikan substrat input Anda menyebar melalui semua konversi dan pemetaan data Anda. jika tidak dan saya harus menghapus semua Konversi Data dan Pemetaan saya dan memulai lagi. Lagi-lagi lucu bahwa OLEDB baru saja menanganinya dan ADO.net melakukan kesalahan dan harus melakukan semua intervensi ini untuk membuatnya bekerja. Secara umum Anda harus menggunakan OLEDB bila target Anda adalah MS Sql. s menunjuk ke kolom masalah padahal sebenarnya tidak. Saya menemukan kolom masalah dengan membuat tebakan terpelajar dan kemudian mengubah masukan ke pemetaan menjadi "Abaikan" dan kemudian menjalankan kembali dan melihat apakah pesan tersebut hilang. Dalam kasus saya dan di lingkungan saya, saya memperbaikinya dengan substr (memasukkan input Teradata ke ukuran karakter deklarasi ms sql untuk kolom output. Periksa dan pastikan substrat input Anda menyebar melalui semua konversi dan pemetaan data Anda. jika tidak dan saya harus menghapus semua Pemetaan dan Konversi Data saya dan memulai lagi. Lagi-lagi lucu bahwa OLEDB baru saja menanganinya dan ADO.net melakukan kesalahan dan harus melakukan semua intervensi ini untuk membuatnya bekerja. Secara umum Anda harus menggunakan OLEDB bila target Anda adalah MS Sql. s menunjuk ke kolom masalah padahal sebenarnya tidak. Saya menemukan kolom masalah dengan membuat tebakan terpelajar dan kemudian mengubah masukan ke pemetaan menjadi "Abaikan" dan kemudian menjalankan kembali dan melihat apakah pesan tersebut hilang. Dalam kasus saya dan di lingkungan saya, saya memperbaikinya dengan substr (memasukkan input Teradata ke ukuran karakter deklarasi ms sql untuk kolom output. Periksa dan pastikan substrat input Anda menyebar melalui semua konversi dan pemetaan data Anda. jika tidak dan saya harus menghapus semua Pemetaan dan Konversi Data saya dan memulai lagi. Lagi-lagi lucu bahwa OLEDB baru saja menanganinya dan ADO.net melakukan kesalahan dan harus melakukan semua intervensi ini untuk membuatnya bekerja. Secara umum Anda harus menggunakan OLEDB bila target Anda adalah MS Sql. Saya menemukan kolom masalah dengan membuat tebakan terpelajar dan kemudian mengubah masukan ke pemetaan menjadi "Abaikan" dan kemudian menjalankan kembali dan melihat apakah pesan tersebut hilang. Dalam kasus saya dan di lingkungan saya, saya memperbaikinya dengan substr (memasukkan input Teradata ke ukuran karakter deklarasi ms sql untuk kolom output. Periksa dan pastikan substrat input Anda menyebar melalui semua konversi dan pemetaan data Anda. jika tidak dan saya harus menghapus semua Pemetaan dan Konversi Data saya dan memulai lagi. Lagi-lagi lucu bahwa OLEDB baru saja menanganinya dan ADO.net melakukan kesalahan dan harus melakukan semua intervensi ini untuk membuatnya bekerja. Secara umum Anda harus menggunakan OLEDB bila target Anda adalah MS Sql. Saya menemukan kolom masalah dengan membuat tebakan terpelajar dan kemudian mengubah input ke pemetaan menjadi "Abaikan" dan kemudian menjalankan kembali dan melihat apakah pesan itu hilang. Dalam kasus saya dan di lingkungan saya, saya memperbaikinya dengan substr (memasukkan input Teradata ke ukuran karakter deklarasi ms sql untuk kolom output. Periksa dan pastikan substrat input Anda menyebar melalui semua konversi dan pemetaan data Anda. jika tidak dan saya harus menghapus semua Pemetaan dan Konversi Data saya dan memulai lagi. Lagi-lagi lucu bahwa OLEDB baru saja menanganinya dan ADO.net melakukan kesalahan dan harus melakukan semua intervensi ini untuk membuatnya bekerja. Secara umum Anda harus menggunakan OLEDB bila target Anda adalah MS Sql. s dan Pemetaan dan mulai lagi. Sekali lagi lucu bahwa OLEDB hanya menanganinya dan ADO.net melakukan kesalahan dan harus melakukan semua intervensi ini untuk membuatnya bekerja. Secara umum, Anda harus menggunakan OLEDB jika target Anda adalah MS Sql. s dan Pemetaan dan mulai lagi. Sekali lagi lucu bahwa OLEDB hanya menanganinya dan ADO.net melakukan kesalahan dan harus melakukan semua intervensi ini untuk membuatnya bekerja. Secara umum, Anda harus menggunakan OLEDB jika target Anda adalah MS Sql.

renaissanceMan
sumber
0

Saya baru saja menemukan ini dan menggunakan cuplikan @ b_stil, saya dapat mengetahui kolom pelakunya. Dan pada penyelidikan lebih lanjut, saya pikir saya perlu memangkas kolom seperti yang disarankan @Liji Chandran tetapi saya menggunakan IExcelDataReader dan saya tidak dapat menemukan cara mudah untuk memvalidasi dan memangkas masing-masing dari 160 kolom saya.

Kemudian saya menemukan kelas ini, kelas (ValidatingDataReader) dari CSVReader .

Hal yang menarik tentang kelas ini adalah ia memberi Anda panjang data kolom sumber dan tujuan, baris pelakunya, dan bahkan nilai kolom yang menyebabkan kesalahan.

Yang saya lakukan hanyalah memangkas semua kolom (nvarchar, varchar, char dan nchar).

Saya baru saja mengubah GetValuemetode saya menjadi ini:

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

Semoga ini bisa membantu seseorang

Ahmad Tijani
sumber