Tôi muốn tải hàng loạt dữ liệu tệp csv lên sql server 2005 từ mã c # nhưng tôi gặp phải lỗi dưới đây -
Đã nhận được độ dài cột không hợp lệ từ máy khách bcp cho cột 6.
khi sao chép hàng loạt ghi vào máy chủ cơ sở dữ liệu
Câu trả lời:
Một trong các cột dữ liệu trong excel (Cột Id 6) có một hoặc nhiều dữ liệu ô vượt quá độ dài kiểu dữ liệu của cột dữ liệu trong cơ sở dữ liệu.
Xác minh dữ liệu trong excel. Đồng thời xác minh dữ liệu trong excel để định dạng của nó tuân thủ với lược đồ bảng cơ sở dữ liệu.
Để tránh điều này, hãy thử vượt quá độ dài dữ liệu của kiểu dữ liệu chuỗi trong bảng cơ sở dữ liệu.
Hi vọng điêu nay co ich.
Tôi biết bài đăng này đã cũ nhưng tôi đã gặp phải vấn đề tương tự này và cuối cùng đã tìm ra giải pháp để xác định cột nào đang gây ra sự cố và báo cáo lại nếu cần. Tôi đã xác định rằng colid
trả về trong SqlException không dựa trên số 0, vì vậy bạn cần trừ 1 từ nó để nhận giá trị. Sau đó, nó được sử dụng làm chỉ mục của _sortedColumnMappings
ArrayList của cá thể SqlBulkCopy chứ không phải là chỉ mục của ánh xạ cột đã được thêm vào cá thể SqlBulkCopy. Một điều cần lưu ý là SqlBulkCopy sẽ dừng ở lỗi đầu tiên nhận được nên đây có thể không phải là vấn đề duy nhất nhưng ít nhất cũng giúp tìm ra nó.
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;
}
Tôi đã gặp phải một loại vấn đề tương tự khi chuyển một chuỗi vào bảng Cơ sở dữ liệu bằng cách sử dụng tùy chọn SQL BulkCopy. Chuỗi tôi đang chuyển có 3 ký tự trong khi độ dài cột đích là varchar(20)
. Tôi đã thử cắt bớt chuỗi trước khi chèn vào DB bằng Trim()
hàm để kiểm tra xem sự cố có phải do bất kỳ khoảng trắng nào (đầu và cuối) trong chuỗi hay không. Sau khi cắt tỉa chuỗi, nó hoạt động tốt.
Bạn co thể thử text.Trim()
Kiểm tra kích thước của các cột trong bảng mà bạn đang thực hiện chèn / sao chép hàng loạt. varchar hoặc các cột chuỗi khác có thể cần được mở rộng hoặc giá trị bạn đang chèn cần được cắt bớt. Thứ tự cột cũng phải giống như trong bảng.
vd: Tăng kích thước của cột varchar 30 lên 50 =>
ALTER TABLE [dbo]. [TableName] ALTER COLUMN [ColumnName] Varchar (50)
Đoạn mã tuyệt vời, cảm ơn vì đã chia sẻ!
Tôi đã kết thúc bằng cách sử dụng phản chiếu để lấy DataMemberName thực tế để trả lại cho khách hàng do lỗi (tôi đang sử dụng lưu hàng loạt trong dịch vụ WCF). Hy vọng rằng ai đó sẽ thấy cách tôi đã làm nó hữu ích.
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;
}
Tôi nhận được thông báo lỗi này với phiên bản ssis gần đây hơn nhiều (so với phiên bản doanh nghiệp 2015, tôi nghĩ đó là ssis 2016). Tôi sẽ nhận xét ở đây vì đây là tài liệu tham khảo đầu tiên xuất hiện khi bạn google thông báo lỗi này. Tôi nghĩ rằng nó xảy ra chủ yếu với các cột ký tự khi kích thước ký tự nguồn lớn hơn kích thước ký tự đích. Tôi nhận được thông báo này khi tôi đang sử dụng đầu vào ado.net cho ms sql từ cơ sở dữ liệu teradata. Thật buồn cười vì oledb trước đó ghi vào ms sql đã xử lý tất cả quá trình chuyển đổi ký tự một cách hoàn hảo mà không có ghi đè mã hóa. Số màu và cột Đầu vào đích tương ứng # mà đôi khi bạn nhận được với thông báo có màu đều vô giá trị. Nó không phải là cột khi bạn đếm ngược từ trên cùng của ánh xạ hoặc bất cứ thứ gì tương tự. Nếu tôi là microsoft, tôi ' d bị bối rối khi đưa ra một thông báo lỗi có vẻ như nó đang chỉ vào cột sự cố khi không phải vậy. Tôi phát hiện ra sự cố bị mờ bằng cách đưa ra một phỏng đoán có học thức và sau đó thay đổi đầu vào cho ánh xạ thành "Bỏ qua" rồi chạy lại và xem thông báo có biến mất hay không. Trong trường hợp của tôi và trong môi trường của tôi, tôi đã sửa lỗi bằng substr ('nhập đầu vào Teradata vào kích thước ký tự của khai báo sql ms cho cột đầu ra. Kiểm tra và đảm bảo rằng substr đầu vào của bạn truyền qua tất cả các chuyển đổi và ánh xạ dữ liệu của bạn. Trong của tôi trong trường hợp nó không xảy ra và tôi phải xóa tất cả Bản đồ và Chuyển đổi dữ liệu của mình và bắt đầu lại từ đầu. Một lần nữa, buồn cười là OLEDB chỉ xử lý nó và ADO.net đã phát sinh lỗi và phải có tất cả sự can thiệp này để làm cho nó hoạt động. Nói chung bạn nên sử dụng OLEDB khi mục tiêu của bạn là MS Sql. s chỉ vào cột vấn đề khi nó không phải. Tôi phát hiện ra sự cố bị mờ bằng cách đưa ra một phỏng đoán có học thức và sau đó thay đổi đầu vào cho ánh xạ thành "Bỏ qua" rồi chạy lại và xem thông báo có biến mất hay không. Trong trường hợp của tôi và trong môi trường của tôi, tôi đã sửa lỗi bằng substr ('nhập đầu vào Teradata vào kích thước ký tự của khai báo sql ms cho cột đầu ra. Kiểm tra và đảm bảo rằng substr đầu vào của bạn truyền qua tất cả các chuyển đổi và ánh xạ dữ liệu của bạn. Trong của tôi trong trường hợp nó không xảy ra và tôi phải xóa tất cả Bản đồ và Chuyển đổi dữ liệu của mình và bắt đầu lại từ đầu. Một lần nữa, buồn cười là OLEDB chỉ xử lý nó và ADO.net đã phát sinh lỗi và phải có tất cả sự can thiệp này để nó hoạt động. Nói chung bạn nên sử dụng OLEDB khi mục tiêu của bạn là MS Sql. s chỉ vào cột vấn đề khi nó không phải. Tôi nhận thấy sự cố bị mờ bằng cách đưa ra một phỏng đoán có học thức và sau đó thay đổi đầu vào cho ánh xạ thành "Bỏ qua" rồi chạy lại và xem liệu thông báo có biến mất hay không. Trong trường hợp của tôi và trong môi trường của tôi, tôi đã sửa lỗi bằng substr ('nhập đầu vào Teradata vào kích thước ký tự của khai báo sql ms cho cột đầu ra. Kiểm tra và đảm bảo rằng substr đầu vào của bạn truyền qua tất cả các chuyển đổi và ánh xạ dữ liệu của bạn. Trong của tôi trong trường hợp nó không xảy ra và tôi phải xóa tất cả Bản đồ và Chuyển đổi dữ liệu của mình và bắt đầu lại từ đầu. Một lần nữa, buồn cười là OLEDB chỉ xử lý nó và ADO.net đã phát sinh lỗi và phải có tất cả sự can thiệp này để nó hoạt động. Nói chung bạn nên sử dụng OLEDB khi mục tiêu của bạn là MS Sql. Tôi nhận thấy sự cố bị mờ bằng cách đưa ra một phỏng đoán có học thức và sau đó thay đổi đầu vào cho ánh xạ thành "Bỏ qua" rồi chạy lại và xem liệu thông báo có biến mất hay không. Trong trường hợp của tôi và trong môi trường của tôi, tôi đã sửa lỗi bằng substr ('nhập đầu vào Teradata vào kích thước ký tự của khai báo sql ms cho cột đầu ra. Kiểm tra và đảm bảo rằng substr đầu vào của bạn truyền qua tất cả các chuyển đổi và ánh xạ dữ liệu của bạn. Trong của tôi trong trường hợp nó không xảy ra và tôi phải xóa tất cả Bản đồ và Chuyển đổi dữ liệu của mình và bắt đầu lại từ đầu. Một lần nữa, buồn cười là OLEDB chỉ xử lý nó và ADO.net đã phát sinh lỗi và phải có tất cả sự can thiệp này để nó hoạt động. Nói chung bạn nên sử dụng OLEDB khi mục tiêu của bạn là MS Sql. Tôi phát hiện ra sự cố bị mờ bằng cách đưa ra một phỏng đoán có học thức và sau đó thay đổi đầu vào cho ánh xạ thành "Bỏ qua" rồi chạy lại và xem thông báo có biến mất hay không. Trong trường hợp của tôi và trong môi trường của tôi, tôi đã sửa lỗi bằng substr ('nhập đầu vào Teradata vào kích thước ký tự của khai báo sql ms cho cột đầu ra. Kiểm tra và đảm bảo rằng substr đầu vào của bạn truyền qua tất cả các chuyển đổi và ánh xạ dữ liệu của bạn. Trong của tôi trong trường hợp nó không xảy ra và tôi phải xóa tất cả Bản đồ và Chuyển đổi dữ liệu của mình và bắt đầu lại từ đầu. Một lần nữa, buồn cười là OLEDB chỉ xử lý nó và ADO.net đã phát sinh lỗi và phải có tất cả sự can thiệp này để nó hoạt động. Nói chung bạn nên sử dụng OLEDB khi mục tiêu của bạn là MS Sql. s và Ánh xạ và bắt đầu lại từ đầu. Một lần nữa buồn cười là OLEDB chỉ xử lý nó và ADO.net đã phát hiện ra lỗi và phải có tất cả sự can thiệp này để làm cho nó hoạt động. Nói chung, bạn nên sử dụng OLEDB khi mục tiêu của bạn là MS Sql. s và Ánh xạ và bắt đầu lại từ đầu. Một lần nữa buồn cười là OLEDB chỉ xử lý nó và ADO.net đã phát hiện ra lỗi và phải có tất cả sự can thiệp này để làm cho nó hoạt động. Nói chung, bạn nên sử dụng OLEDB khi mục tiêu của bạn là MS Sql.
Tôi chỉ tình cờ phát hiện ra điều này và sử dụng đoạn mã của @ b_stil, tôi đã có thể tìm ra cột thủ phạm. Và trong quá trình điều tra sau này, tôi nhận ra mình cần phải cắt bớt cột giống như @Liji Chandran đã đề xuất nhưng tôi đang sử dụng IExcelDataReader và tôi không thể tìm ra cách dễ dàng để xác thực và cắt từng cột trong số 160 cột của mình.
Sau đó, tôi tình cờ gặp lớp này, lớp (ValidatingDataReader) từ CSVReader .
Điều thú vị về lớp này là nó cung cấp cho bạn độ dài dữ liệu cột nguồn và cột đích, hàng thủ phạm và thậm chí cả giá trị cột gây ra lỗi.
Tất cả những gì tôi làm chỉ là cắt bỏ tất cả các cột (nvarchar, varchar, char và nchar).
Tôi vừa thay đổi GetValue
phương pháp của mình thành:
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;
}
Hy vọng điều này sẽ giúp ai đó