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
c#
.net
sql-server
database
sql-server-2005
Sana Sana
sumber
sumber
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
colid
dikembalikan di SqlException tidak berbasis nol sehingga Anda perlu mengurangi 1 darinya untuk mendapatkan nilainya. Setelah itu digunakan sebagai indeks_sortedColumnMappings
ArrayList 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; }
sumber
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 menggunakanTrim()
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()
sumber
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)
sumber
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; }
sumber
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.
sumber
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
GetValue
metode 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
sumber