使用SSIS脚本任务(VB)将Excel数据导入现有SQL Server表时遇到问题

时间:2019-02-12 21:49:19

标签: sql-server excel vb.net ssis script-task

我已经使用Excel文件中表中的数据成功加载了datatable对象。如何在UPDATE查询中使用此数据表对象更新现有的SQL Server表?

我遇到此错误:

  

调用的目标已引发异常。

     在System.RuntimeMethodHandle.InvokeMethod中的

(对象目标,对象[]参数,签名sig,布尔值构造函数)      在System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj,Object []参数,Object []参数)      在System.Reflection.RuntimeMethodInfo.Invoke处(对象obj,BindingFlags invokeAttr,活页夹活页夹,Object []参数,CultureInfo文化)      在System.RuntimeType.InvokeMember处(字符串名称,BindingFlags bindingFlags,活页夹绑定程序,对象目标,Object []提供的Args,ParameterModifier []修饰符,CultureInfo文化,String [] namedParams)      在Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTATaskScriptingEngine.ExecuteScript()

Public Sub Main()

    Dim fileToTest As String
    Dim SheetName As String
    Dim connectionString As String
    Dim excelConnection As OleDbConnection
    Dim excelCommand As OleDbCommand
    Dim ODA As OleDbDataAdapter
    Dim dtExcel As New DataTable()
    Dim SQLConn As SqlClient.SqlConnection
    Dim SQLCmd As SqlClient.SqlCommand
    Dim SQLPara As SqlClient.SqlParameter

    'open a connection to the excel file
    fileToTest = "C:\Users\testuser\Documents\test\mytestfile.xls"
    connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & "Data Source=" &
    fileToTest & ";Extended Properties=""Excel 8.0;HDR=YES;IMEX=1"""
    excelConnection = New OleDbConnection(connectionString)
    excelConnection.Open()

    'open a SQL connection to the LRPSF_Source_DB SQL Server DB
    connectionString = "Data Source=mysqlserver.net\sqlentdb1d;Trusted_Connection=True;DATABASE=LRPSF_Source_DB;CONNECTION RESET=FALSE"
    SQLConn = New SqlClient.SqlConnection(connectionString)
    SQLConn.Open()

    'fetch the data from TEST table in Excel file using a command query and store in datatable object
    SheetName = "TEST$"
    excelCommand = excelConnection.CreateCommand()
    excelCommand.CommandText = "SELECT * FROM [" & SheetName & "]"
    excelCommand.CommandType = CommandType.Text
    ODA = New OleDbDataAdapter(excelCommand)
    ODA.Fill(dtExcel) '<- this datatable object is filled with the data successfully

    'using the dtExcel datatable as a table input, update the existing dbo.TEST_INPUT_SIMPLE SQL Server table
    SQLCmd = SQLConn.CreateCommand()
    SQLCmd.CommandText = "UPDATE TIS SET TIS.MY_COLUMN = TISX.MY_COLUMN " &
                         "FROM dbo.TEST_INPUT_SIMPLE TIS INNER JOIN @source AS TISX " &
                         "ON TIS.UPDATE_ID = TISX.UPDATE_ID"
    SQLCmd.CommandType = CommandType.Text
    SQLCmd.Parameters.AddWithValue("@source", dtExcel).SqlDbType = SqlDbType.Structured
    SQLCmd.ExecuteNonQuery() '<-- the program errors on this line

    Dts.TaskResult = ScriptResults.Success

End Sub

2 个答案:

答案 0 :(得分:2)

更新1

我认为问题是您没有在SQL Server中声明表结构。而不是使用SqlDbType.Structured而不指定类型名称:

SQLCmd.Parameters.AddWithValue("@source", dtExcel).SqlDbType = SqlDbType.Structured

有关如何将数据表作为参数传递给SQL Server的更多信息,请检查以下SO问题:

此外,他们在link you have mentioned in your comments中使用dbo.tStudent作为类型名称:

param.SqlDbType = SqlDbType.Structured;
param.TypeName = "dbo.tStudent";

初始答案

如果要通过加入Excel文件来更新SQL表,则这不是正确的方法。您可以通过这种方式将表作为参数传递。将Excel表与SQL表联接的方法有很多:

在SQL Server中

在SSIS中

在VB / C#中

在这个答案中我没有提供太多细节,但是我试图给出一些比您可以更好地使用脚本任务来实现目标的方法的见解。每个链接都包含您需要的信息以及更多

答案 1 :(得分:1)

我通过执行以下步骤解决了这个问题:

1)在数据库中创建用户定义的TableType:

CREATE TYPE [dbo].[MyTableType] AS TABLE(
    [UPDATE_ID] NVARCHAR(255),
    [MY_COLUMN] NVARCHAR(255)
)

2)创建一个包含先前创建的表类型的存储过程并更新查询:

CREATE procedure UpdateDB
    @myTableType MyTableType readonly
AS
BEGIN
    UPDATE TIS SET TIS.MY_COLUMN = TISX.MY_COLUMN 
    FROM dbo.TEST_INPUT_SIMPLE TIS INNER JOIN @myTableType AS TISX 
    ON TIS.UPDATE_ID = TISX.UPDATE_ID
END

3)使用VB脚本任务,获取Excel数据并运行存储过程:

Public Sub Main()

    Dim fileToTest As String
    Dim SheetName As String
    Dim connectionString As String
    Dim excelConnection As OleDbConnection
    Dim excelCommand As OleDbCommand
    Dim ODA As OleDbDataAdapter
    Dim dtExcel As New DataTable()
    Dim SQLConn As SqlClient.SqlConnection
    Dim SQLCmd As SqlClient.SqlCommand

    'open a connection to the excel file'
    fileToTest = "C:\Users\testuser\Documents\test\mytestfile.xls"
    connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" & "Data Source=" &
    fileToTest & ";Extended Properties=""Excel 8.0;HDR=YES;IMEX=1"""
    excelConnection = New OleDbConnection(connectionString)
    excelConnection.Open()

    'open a SQL connection to the LRPSF_Source_DB SQL Server DB'
    connectionString = "Data Source=mysqlserver.net\sqlentdb1d;Trusted_Connection=True;DATABASE=LRPSF_Source_DB;CONNECTION RESET=FALSE"
    SQLConn = New SqlClient.SqlConnection(connectionString)
    SQLConn.Open()

    'fetch the data from TEST table in Excel file using a command query and store in datatable object'
    SheetName = "TEST$"
    excelCommand = excelConnection.CreateCommand()
    excelCommand.CommandText = "SELECT * FROM [" & SheetName & "]"
    excelCommand.CommandType = CommandType.Text
    ODA = New OleDbDataAdapter(excelCommand)
    ODA.Fill(dtExcel) 'object is filled with Excel data'

    'load the dtExcel object into @myTableType object and run the stored procedure'
    SQLCmd = SQLConn.CreateCommand() 
    SQLCmd.CommandText = "[dbo].[UpdateDB]"
    SQLCmd.CommandType = CommandType.StoredProcedure
    SQLCmd.Parameters.AddWithValue("@myTableType", dtExcel) 
    SQLCmd.ExecuteNonQuery() 'run the stored procedure containing the update query'

    Dts.TaskResult = ScriptResults.Success

End Sub

感谢您的帮助!