SqlBulkCopy 没有复制列中的所有数据
SqlBulkCopy is not copying all the data in a column over
我遇到一个问题,SqlBulkCopy
没有将列中的所有数据复制到目标 table。我已验证源数据(这是一个 .CSV
文件)在所有行的列中都有值,但只有该列中的前 40 行左右被复制。
目标 table 的列设置为 NVARCHAR(255)
并且所有列都可以为空。
这是我执行批量复制的函数:
Private Sub loadDataFromCSV(ByVal pathToFile As String, ByVal connString As String, ByVal file As String, ByVal colCount As Integer)
Dim fileLocation As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & pathToFile & ";Extended Properties='text;HDR=NO;FMT=Delimited(,)';"
Dim qry As String = "select * from " & file
Dim CompData As OleDbDataReader
Using destConnection As SqlConnection = _
New SqlConnection(connString)
destConnection.Open()
Using sourceConnection As New OleDbConnection(fileLocation)
Dim cmdSourceData As New OleDbCommand(qry, sourceConnection)
sourceConnection.Open()
CompData = cmdSourceData.ExecuteReader()
Using bulkCopy As SqlClient.SqlBulkCopy = New SqlClient.SqlBulkCopy(connString)
bulkCopy.DestinationTableName = "dbo.Records"
bulkCopy.BatchSize = 10000
bulkCopy.BulkCopyTimeout = 90
Try
bulkCopy.WriteToServer(CompData)
Catch ex As Exception
Console.WriteLine(ex.Message)
Finally
CompData.Close()
End Try
End Using
End Using
End Using
End Sub
据我所知,table 中的所有数据都进入了正确的列,第 7 列除外。在第 7 列中,我获得了前 40 行左右的数据,然后该列的其余值为 NULL。
我 运行 不知道可能出了什么问题,所以非常感谢您的帮助。
谢谢。
我猜是覆盖错误。 OLEDB 将根据前 8 行(我认为)推断列的数据类型,所以如果您的第一行是:
SomeColumn
----------
1
2
3
4
5
6
7
8
9
apple
这最初看起来像一个整数列,所以这就是它映射到的内容,但是当它到达 "apple" 时它无法将它转换为整数,所以 returns DbNull .
解决方案是将 IMEX=1
添加到您的连接字符串,这意味着不会进行任何隐式转换,OleDbReader 只会准确读取 csv 中的内容。
这样做的缺点是您在尝试调用 SqlBulkCopy.WriteToServer(DataReader)
方法时可能会遇到转换错误。您可能需要创建一个与数据库格式相同的 DataTable table,并在必要时遍历 OleDbReader 进行显式转换,然后使用 SqlBulkCopy 将此 DataTable 写入数据库。
作为一个 hacky 解决方法,我只是将一个字符串放入我的 csv 文件前 8 行的每一列中。它欺骗 sqlbulkcopy 将所有字段都视为字符串。然后在sql中删除包含该字符串的记录。
我遇到一个问题,SqlBulkCopy
没有将列中的所有数据复制到目标 table。我已验证源数据(这是一个 .CSV
文件)在所有行的列中都有值,但只有该列中的前 40 行左右被复制。
目标 table 的列设置为 NVARCHAR(255)
并且所有列都可以为空。
这是我执行批量复制的函数:
Private Sub loadDataFromCSV(ByVal pathToFile As String, ByVal connString As String, ByVal file As String, ByVal colCount As Integer)
Dim fileLocation As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & pathToFile & ";Extended Properties='text;HDR=NO;FMT=Delimited(,)';"
Dim qry As String = "select * from " & file
Dim CompData As OleDbDataReader
Using destConnection As SqlConnection = _
New SqlConnection(connString)
destConnection.Open()
Using sourceConnection As New OleDbConnection(fileLocation)
Dim cmdSourceData As New OleDbCommand(qry, sourceConnection)
sourceConnection.Open()
CompData = cmdSourceData.ExecuteReader()
Using bulkCopy As SqlClient.SqlBulkCopy = New SqlClient.SqlBulkCopy(connString)
bulkCopy.DestinationTableName = "dbo.Records"
bulkCopy.BatchSize = 10000
bulkCopy.BulkCopyTimeout = 90
Try
bulkCopy.WriteToServer(CompData)
Catch ex As Exception
Console.WriteLine(ex.Message)
Finally
CompData.Close()
End Try
End Using
End Using
End Using
End Sub
据我所知,table 中的所有数据都进入了正确的列,第 7 列除外。在第 7 列中,我获得了前 40 行左右的数据,然后该列的其余值为 NULL。
我 运行 不知道可能出了什么问题,所以非常感谢您的帮助。
谢谢。
我猜是覆盖错误。 OLEDB 将根据前 8 行(我认为)推断列的数据类型,所以如果您的第一行是:
SomeColumn
----------
1
2
3
4
5
6
7
8
9
apple
这最初看起来像一个整数列,所以这就是它映射到的内容,但是当它到达 "apple" 时它无法将它转换为整数,所以 returns DbNull .
解决方案是将 IMEX=1
添加到您的连接字符串,这意味着不会进行任何隐式转换,OleDbReader 只会准确读取 csv 中的内容。
这样做的缺点是您在尝试调用 SqlBulkCopy.WriteToServer(DataReader)
方法时可能会遇到转换错误。您可能需要创建一个与数据库格式相同的 DataTable table,并在必要时遍历 OleDbReader 进行显式转换,然后使用 SqlBulkCopy 将此 DataTable 写入数据库。
作为一个 hacky 解决方法,我只是将一个字符串放入我的 csv 文件前 8 行的每一列中。它欺骗 sqlbulkcopy 将所有字段都视为字符串。然后在sql中删除包含该字符串的记录。