ฉันต้องการอัปโหลดข้อมูลไฟล์ csv จำนวนมากไปยังเซิร์ฟเวอร์ sql 2005 จากรหัส c # แต่ฉันพบข้อผิดพลาดด้านล่าง -
ได้รับความยาวคอลัมน์ที่ไม่ถูกต้องจากไคลเอนต์ bcp สำหรับ colid 6
เมื่อสำเนาจำนวนมากเขียนไปยังเซิร์ฟเวอร์ฐานข้อมูล
ฉันต้องการอัปโหลดข้อมูลไฟล์ csv จำนวนมากไปยังเซิร์ฟเวอร์ sql 2005 จากรหัส c # แต่ฉันพบข้อผิดพลาดด้านล่าง -
ได้รับความยาวคอลัมน์ที่ไม่ถูกต้องจากไคลเอนต์ bcp สำหรับ colid 6
เมื่อสำเนาจำนวนมากเขียนไปยังเซิร์ฟเวอร์ฐานข้อมูล
คำตอบ:
คอลัมน์ข้อมูลหนึ่งใน excel (Column Id 6) มีข้อมูลเซลล์อย่างน้อยหนึ่งคอลัมน์ที่เกินความยาวประเภทข้อมูลคอลัมน์ข้อมูลในฐานข้อมูล
ตรวจสอบข้อมูลใน excel ตรวจสอบข้อมูลใน excel ด้วยว่ารูปแบบเป็นไปตามสคีมาตารางฐานข้อมูล
เพื่อหลีกเลี่ยงปัญหานี้ให้ลองเกินความยาวข้อมูลของประเภทข้อมูลสตริงในตารางฐานข้อมูล
หวังว่านี่จะช่วยได้
ฉันรู้ว่าโพสต์นี้เก่า แต่ฉันพบปัญหาเดียวกันนี้และในที่สุดก็หาวิธีแก้ไขเพื่อระบุว่าคอลัมน์ใดเป็นสาเหตุของปัญหาและรายงานกลับตามต้องการ ฉันพิจารณาแล้วว่าสิ่งที่colid
ส่งคืนใน SqlException ไม่ใช่ศูนย์ดังนั้นคุณต้องลบ 1 ออกเพื่อให้ได้ค่า หลังจากนั้นจะใช้เป็นดัชนีของ_sortedColumnMappings
ArrayList ของอินสแตนซ์ SqlBulkCopy ไม่ใช่ดัชนีของการแมปคอลัมน์ที่ถูกเพิ่มลงในอินสแตนซ์ 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;
}
ฉันประสบปัญหาคล้าย ๆ กันขณะส่งสตริงไปยังตารางฐานข้อมูลโดยใช้ตัวเลือก SQL BulkCopy สตริงฉันถูกส่งผ่านเป็น 3 varchar(20)
ตัวอักษรในขณะที่ระยะเวลาในคอลัมน์ปลายทางคือ ฉันลองตัดแต่งสตริงก่อนที่จะแทรกลงในฐานข้อมูลโดยใช้Trim()
ฟังก์ชันเพื่อตรวจสอบว่าปัญหาเกิดจากการเว้นวรรค (นำหน้าและต่อท้าย) ในสตริงหรือไม่ หลังจากตัดแต่งสตริงแล้วก็ใช้งานได้ดี
คุณสามารถลอง text.Trim()
ตรวจสอบขนาดของคอลัมน์ในตารางที่คุณกำลังทำการแทรก / คัดลอกจำนวนมาก อาจต้องขยาย varchar หรือคอลัมน์สตริงอื่น ๆ หรือค่าที่คุณกำลังแทรกจะต้องถูกตัดแต่ง ลำดับคอลัมน์ควรจะเหมือนกับในตาราง
เช่นเพิ่มขนาดของคอลัมน์ varchar 30 ถึง 50 =>
แก้ไขตาราง [dbo] [TableName] แก้ไขคอลัมน์ [ColumnName] Varchar (50)
รหัสชิ้นเยี่ยมขอบคุณสำหรับการแบ่งปัน!
ฉันลงเอยด้วยการใช้การสะท้อนกลับเพื่อรับ 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;
}
ฉันได้รับข้อความแสดงข้อผิดพลาดนี้พร้อมเวอร์ชัน ssis ที่ใหม่กว่ามาก (เทียบกับองค์กรปี 2015 ฉันคิดว่าเป็น ssis 2016) ฉันจะแสดงความคิดเห็นที่นี่เพราะนี่เป็นการอ้างอิงครั้งแรกที่เกิดขึ้นเมื่อคุณ Google ข้อความแสดงข้อผิดพลาดนี้ ฉันคิดว่าส่วนใหญ่เกิดขึ้นกับคอลัมน์อักขระเมื่อขนาดอักขระต้นทางใหญ่กว่าขนาดอักขระเป้าหมาย ฉันได้รับข้อความนี้เมื่อฉันใช้การป้อนข้อมูล adm.net ไปยัง ms sql จากฐานข้อมูล teradata ตลกเพราะ oledb ก่อนหน้านี้เขียนถึง ms sql จัดการการแปลงอักขระทั้งหมดได้อย่างสมบูรณ์แบบโดยไม่มีการแทนที่การเข้ารหัส หมายเลข colid และคอลัมน์การป้อนข้อมูลปลายทางที่เกี่ยวข้อง # บางครั้งคุณได้รับพร้อมกับข้อความ colid นั้นไร้ค่า ไม่ใช่คอลัมน์เมื่อคุณนับถอยหลังจากด้านบนของการทำแผนที่หรืออะไรทำนองนั้น ถ้าฉันเป็นไมโครซอฟท์ฉัน ' d ต้องอายที่จะให้ข้อความแสดงข้อผิดพลาดที่ดูเหมือนว่ากำลังชี้ไปที่คอลัมน์ปัญหาเมื่อไม่เป็นเช่นนั้น ฉันพบปัญหา colid โดยทำการเดาอย่างมีความรู้จากนั้นเปลี่ยนอินพุตเป็นการแมปเป็น "ละเว้น" จากนั้นเรียกใช้ใหม่และดูว่าข้อความหายไปหรือไม่ ในกรณีของฉันและในสภาพแวดล้อมของฉันฉันแก้ไขโดยใช้ substr ('ในการป้อนข้อมูล Teradata กับขนาดอักขระของการประกาศ ms sql สำหรับคอลัมน์เอาต์พุตตรวจสอบและตรวจสอบให้แน่ใจว่าอินพุตย่อยของคุณแพร่กระจายผ่านการแปลงข้อมูลและการแมปข้อมูลทั้งหมดของคุณใน ในกรณีที่มันไม่ได้และฉันต้องลบการแปลงข้อมูลและการแม็ปของฉันทั้งหมดและเริ่มต้นใหม่อีกครั้งตลกอีกครั้งที่ OLEDB เพิ่งจัดการมันและ ADO.net ก็โยนข้อผิดพลาดและต้องมีการแทรกแซงทั้งหมดนี้เพื่อให้มันทำงานได้โดยทั่วไปคุณ ควรใช้ OLEDB เมื่อเป้าหมายของคุณคือ MS Sql ชี้ไปที่คอลัมน์ปัญหาเมื่อมันไม่ได้ ฉันพบปัญหา colid โดยการเดาอย่างมีความรู้จากนั้นเปลี่ยนอินพุตเป็นการแมปเป็น "ละเว้น" จากนั้นเรียกใช้ใหม่และดูว่าข้อความหายไปหรือไม่ ในกรณีของฉันและในสภาพแวดล้อมของฉันฉันแก้ไขโดยใช้ substr ('ในการป้อนข้อมูล Teradata กับขนาดอักขระของการประกาศ ms sql สำหรับคอลัมน์เอาต์พุตตรวจสอบและตรวจสอบให้แน่ใจว่าอินพุตย่อยของคุณแพร่กระจายผ่านการแปลงข้อมูลและการแมปข้อมูลทั้งหมดของคุณใน ในกรณีที่มันไม่ได้และฉันต้องลบการแปลงข้อมูลและการแม็ปของฉันทั้งหมดและเริ่มต้นใหม่อีกครั้งตลกอีกครั้งที่ OLEDB เพิ่งจัดการมันและ ADO.net ก็โยนข้อผิดพลาดและต้องมีการแทรกแซงทั้งหมดนี้เพื่อให้มันทำงานได้โดยทั่วไปคุณ ควรใช้ OLEDB เมื่อเป้าหมายของคุณคือ MS Sql ชี้ไปที่คอลัมน์ปัญหาเมื่อมันไม่ได้ ฉันพบปัญหา colid โดยการเดาอย่างมีความรู้จากนั้นเปลี่ยนอินพุตเป็นการแมปเป็น "ละเว้น" จากนั้นเรียกใช้ใหม่และดูว่าข้อความหายไปหรือไม่ ในกรณีของฉันและในสภาพแวดล้อมของฉันฉันแก้ไขโดยใช้ substr ('ในการป้อนข้อมูล Teradata กับขนาดอักขระของการประกาศ ms sql สำหรับคอลัมน์เอาต์พุตตรวจสอบและตรวจสอบให้แน่ใจว่าอินพุตย่อยของคุณแพร่กระจายผ่านการแปลงข้อมูลและการแมปข้อมูลทั้งหมดของคุณใน ในกรณีที่มันไม่ได้และฉันต้องลบการแปลงข้อมูลและการแม็ปของฉันทั้งหมดและเริ่มต้นใหม่อีกครั้งตลกอีกครั้งที่ OLEDB เพิ่งจัดการมันและ ADO.net ก็โยนข้อผิดพลาดและต้องมีการแทรกแซงทั้งหมดนี้เพื่อให้มันทำงานได้โดยทั่วไปคุณ ควรใช้ OLEDB เมื่อเป้าหมายของคุณคือ MS Sql ฉันพบปัญหา colid โดยทำการเดาอย่างมีความรู้จากนั้นเปลี่ยนอินพุตเป็นการแมปเป็น "ละเว้น" จากนั้นรันใหม่และดูว่าข้อความหายไปหรือไม่ ในกรณีของฉันและในสภาพแวดล้อมของฉันฉันแก้ไขโดยใช้ substr ('ในการป้อนข้อมูล Teradata กับขนาดอักขระของการประกาศ ms sql สำหรับคอลัมน์เอาต์พุตตรวจสอบและตรวจสอบให้แน่ใจว่าอินพุตย่อยของคุณแพร่กระจายผ่านการแปลงข้อมูลและการแมปข้อมูลทั้งหมดของคุณใน ในกรณีที่มันไม่ได้และฉันต้องลบการแปลงข้อมูลและการแม็ปของฉันทั้งหมดและเริ่มต้นใหม่อีกครั้งตลกอีกครั้งที่ OLEDB เพิ่งจัดการมันและ ADO.net ก็โยนข้อผิดพลาดและต้องมีการแทรกแซงทั้งหมดนี้เพื่อให้มันทำงานได้โดยทั่วไปคุณ ควรใช้ OLEDB เมื่อเป้าหมายของคุณคือ MS Sql ฉันพบปัญหา colid โดยทำการเดาอย่างมีความรู้จากนั้นเปลี่ยนอินพุตเป็นการแมปเป็น "ละเว้น" จากนั้นรันใหม่และดูว่าข้อความหายไปหรือไม่ ในกรณีของฉันและในสภาพแวดล้อมของฉันฉันแก้ไขโดยใช้ substr ('ในการป้อนข้อมูล Teradata กับขนาดอักขระของการประกาศ ms sql สำหรับคอลัมน์เอาต์พุตตรวจสอบและตรวจสอบให้แน่ใจว่าอินพุตย่อยของคุณแพร่กระจายผ่านการแปลงข้อมูลและการแมปข้อมูลทั้งหมดของคุณใน ในกรณีที่มันไม่ได้และฉันต้องลบการแปลงข้อมูลและการแม็ปของฉันทั้งหมดและเริ่มต้นใหม่อีกครั้งตลกอีกครั้งที่ OLEDB เพิ่งจัดการมันและ ADO.net ก็โยนข้อผิดพลาดและต้องมีการแทรกแซงทั้งหมดนี้เพื่อให้มันทำงานได้โดยทั่วไปคุณ ควรใช้ OLEDB เมื่อเป้าหมายของคุณคือ MS Sql s และการแมปและเริ่มต้นใหม่อีกครั้ง ตลกอีกครั้งที่ OLEDB เพิ่งจัดการมันและ ADO.net ก็โยนข้อผิดพลาดและต้องมีการแทรกแซงทั้งหมดนี้เพื่อให้มันใช้งานได้ โดยทั่วไปคุณควรใช้ OLEDB เมื่อเป้าหมายของคุณคือ MS Sql s และการแมปและเริ่มต้นใหม่อีกครั้ง ตลกอีกครั้งที่ OLEDB เพิ่งจัดการและ ADO.net ก็โยนข้อผิดพลาดและต้องมีการแทรกแซงทั้งหมดนี้เพื่อให้มันใช้งานได้ โดยทั่วไปคุณควรใช้ OLEDB เมื่อเป้าหมายของคุณคือ MS Sql
ฉันเพิ่งสะดุดกับสิ่งนี้และใช้ตัวอย่างข้อมูลของ @ b_stil ฉันสามารถหาคอลัมน์ผู้ร้ายได้ และในการตรวจสอบเพิ่มเติมฉันคิดว่าฉันจำเป็นต้องตัดแต่งคอลัมน์เหมือนที่ @Liji Chandran แนะนำ แต่ฉันใช้ IExcelDataReader และฉันไม่สามารถหาวิธีง่ายๆในการตรวจสอบและตัดแต่ละคอลัมน์ 160 คอลัมน์ของฉันได้
จากนั้นฉันก็เจอคลาสนี้ (ValidatingDataReader)จากCSVReader CSVReader
สิ่งที่น่าสนใจเกี่ยวกับคลาสนี้คือให้ความยาวข้อมูลคอลัมน์ต้นทางและปลายทางแถวผู้ร้ายและแม้แต่ค่าคอลัมน์ที่ทำให้เกิดข้อผิดพลาด
สิ่งที่ฉันทำมีเพียงแค่ตัดคอลัมน์ (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;
}
หวังว่านี่จะช่วยใครบางคนได้