动态绑定参数以推送到 SQL 服务器

Dynamically Binding parameters to push to SQL Server

我有很多历史数据要推送到SQL。作为权宜之计,我首先在 VBA 中对此进行编码。我打开 .xlsx 文件,将 headers 放入一个数组中以确定 SQL table 数据进入的内容。然后我使用 INSERT INTO statement from Excel to SQL Server Table using VBA 中的解决方案 #3 作为我的 SQL 字符串的基础。我在 .parameters.append 行抛出一个自动化错误。还有另一种动态附加参数的方法吗?或者这只是不正确的语法?感谢您的帮助!

代码:

'creates db connection
Set conn = CreateObject("ADODB.Connection")
With conn
    .Provider = "Microsoft.ACE.OLEDB.12.0;"
    .ConnectionString = "Data Source=" & wbk.FullName & ";" & "Excel 8.0;HDR=Yes;IMEX=0;Mode=ReadWrite;"
    .Open
End With

sqlStr = "INSERT INTO DB_Name." & tblname & " ("

For i = 1 To UBound(hdrary)
    If i <> UBound(hdrary) Then
        sqlStr = sqlStr & hdrary(i, 1) & ", "
    Else
        sqlStr = sqlStr & hdrary(i, 1) & ") VALUES ("
    End If
Next i

For i = 1 To UBound(hdrary)
    If i <> UBound(hdrary) Then
        sqlStr = sqlStr & "?, "
    Else
        sqlStr = sqlStr & "?)"
    End If
Next i

'Statement follows this example:
'strSQL = "INSERT INTO " & Database_Name & ".[dbo]." & Table_Name & _
'         "    ([Audit], [Audit Type], [Claim Received Date], [Date Assigned], [Date Completed]," & _
'         "     [Analyst], [Customer], [ID], [Affiliate], [Facility], [DEA], [Acct Number], [Wholesaler]," & _
'         "     [Vendor], [Product], [NDC], [Ref], [Claimed Contract], [Claimed Contract Cost]," & _
'         "     [Contract Price Start Date], [Contract Price End Date], [Catalog Number], [Invoice Number], [Invoice Date]," & _
'         "     [Chargeback ID], [Contract Indicator], [Unit Cost],[WAC], [Potential Credit Due]," & _
'         "     [Qty], [Spend],[IP-DSH indicator Y/N], [DSH and/or HRSA Number], [Unique GPO Code]," & _
'         "     [Comment],[ResCode],[Correct Cost],[CRRB CM],[CRRB Rebill],[CRRB Date])" & _
'         " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?," _
'         "         ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"

lastrow = wks.Cells(Rows.count, "a").End(xlUp).Row

sys.Close

For i = 2 To lastrow
    Set cmd = CreateObject("ADODB.Command")

    With cmd
      .ActiveConnection = conn   ' CONNECTION OBJECT
      .CommandText = sqlStr        ' SQL STRING
      .CommandType = adCmdText

      ' BINDING PARAMETERS
        For j = 1 To UBound(hdrary)
            .Parameters.Append .CreateParameter("s" & hdrary(j, 1), adVarChar, adParamInput, 255, wks.Cells(i, j))
            .Execute
        Next j
    End With

    Set cmd = Nothing
Next i

更新:根据@joel-coehoorn的回答,我更新了命令并删除了wbk.close。我正在抛出“无法在 collection 中找到对应于请求的名称或序号的项目。”在 cmd.Parameters(j).Value = wks.Cells(i, j).Value

线上
'create command object
Set cmd = CreateObject("ADODB.Command")

With cmd
    .ActiveConnection = conn   ' CONNECTION OBJECT
    .CommandText = sqlStr        ' SQL STRING
    .CommandType = adCmdText
End With

'pre-binds parameters
For j = 1 To UBound(hdrary)
    Set k = cmd.CreateParameter(Chr(34) & hdrary(j, 1) & Chr(34), adVarChar, adParamInput, 255)
    cmd.Parameters.Append k
Next j

'loops through mm worksheet by row
For i = 2 To lastrow

    'SET PARAMETER VALUES
    For j = 1 To UBound(hdrary)
        cmd.Parameters(j).Value = wks.Cells(i, j).Value
    Next j
    
    'RUN THE SQL COMMAND
    cmd.Execute
Next i

Set cmd = Nothing

我的 VBA 有点生疏,所以这里可能有错误,但我相信这会让你到达一个更好的地方。

免责声明,. 只是另一个二元运算符,所以我认为 space 在

.Parameters.Append .CreateParameter

并没有完成您认为的所有工作,因为它不等同于

cmd.Parameters.Append cmd.CreateParameter

而是

cmd.Parameters.Append.CreateParameter

这当然不是事。

您可能需要改为执行以下操作:

Dim p
For j = 1 To UBound(hdrary)
    Set p = .CreateParameter("s" & hdrary(j, 1), adVarChar, adParamInput, 255, wks.Cells(i, j))
    .Parameters.Append p
Next j
.Execute

请注意,在我们完成所有参数的创建之前,我们不会调用 .Execute

此外,这段代码本身就是一个循环。您真的不需要在每次循环迭代时重新创建 cmd 或所有这些参数。相反,您应该创建一次命令和参数 ,然后仅在循环内更新参数的 .Value 属性。

' ...

sys.Close

Set cmd = CreateObject("ADODB.Command")
cmd.ActiveConnection = conn   ' CONNECTION OBJECT
cmd.CommandText = sqlStr        ' SQL STRING
cmd.CommandType = adCmdText

' PRE-BINDING PARAMETERS
Dim p
For j = 1 To UBound(hdrary)
    Set p = cmd.CreateParameter("s" & hdrary(j, 1), adVarChar, adParamInput, 255)
    cmd.Parameters.Append p
Next j

' LOOP THROUGH EACH ROW
For i = 2 To lastrow

    'SET PARAMETER VALUES
    For j = 1 To UBound(hdrary)   
        cmd.Parameters(j-1).Value = wks.Cells(i, j)
    Next j
    
    'RUN THE SQL COMMAND
    cmd.Execute
Next i
Set cmd = Nothing

感谢@Joel-Coehoorn 这是最终代码!

'creates db connection
Set conn = CreateObject("ADODB.Connection")
With conn
    .Provider = "Microsoft.ACE.OLEDB.12.0;"
    .ConnectionString = "Data Source=" & wbk.FullName & ";" & "Excel 8.0;HDR=Yes;IMEX=0;Mode=ReadWrite;"
    .Open
End With

sqlStr = "INSERT INTO DB_Name." & tblname & " ("

'puts in columns
For i = 1 To UBound(hdrary)
    If i <> UBound(hdrary) Then
        sqlStr = sqlStr & hdrary(i, 1) & ", "
    Else
        sqlStr = sqlStr & hdrary(i, 1) & ") VALUES ("
    End If
Next i

'placeholders for VALUES
For i = 1 To UBound(hdrary)
    If i <> UBound(hdrary) Then
        sqlStr = sqlStr & "?, "
    Else
        sqlStr = sqlStr & "?)"
    End If
Next i

'Statement follows this example:
'strSQL = "INSERT INTO " & Database_Name & ".[dbo]." & Table_Name & _
'         "    ([Audit], [Audit Type], [Claim Received Date], [Date Assigned], [Date Completed]," & _
'         "     [Analyst], [Customer], [ID], [Affiliate], [Facility], [DEA], [Acct Number], [Wholesaler]," & _
'         "     [Vendor], [Product], [NDC], [Ref], [Claimed Contract], [Claimed Contract Cost]," & _
'         "     [Contract Price Start Date], [Contract Price End Date], [Catalog Number], [Invoice Number], [Invoice Date]," & _
'         "     [Chargeback ID], [Contract Indicator], [Unit Cost],[WAC], [Potential Credit Due]," & _
'         "     [Qty], [Spend],[IP-DSH indicator Y/N], [DSH and/or HRSA Number], [Unique GPO Code]," & _
'         "     [Comment],[ResCode],[Correct Cost],[CRRB CM],[CRRB Rebill],[CRRB Date])" & _
'         " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?," _
'         "         ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"

lastrow = wks.Cells(Rows.count, "a").End(xlUp).Row
Debug.Print sqlStr

sys.Close

'create command object
Set cmd = CreateObject("ADODB.Command")

With cmd
    .ActiveConnection = conn   ' CONNECTION OBJECT
    .CommandText = sqlStr        ' SQL STRING
    .CommandType = adCmdText
End With

'pre-binds parameters
For j = 1 To UBound(hdrary)
    Set k = cmd.CreateParameter(Chr(34) & hdrary(j, 1) & Chr(34), adVarChar, adParamInput, 255)
    cmd.Parameters.Append k
Next j

'loops through worksheet by row
For i = 2 To lastrow

    'sets parameter values and accounts for 0 based array
    For j = 0 To cmd.Parameters.count - 1
        cmd.Parameters(j).Value = wks.Cells(i, j + 1).Value
    Next j
    
    'RUN THE SQL COMMAND
    cmd.Execute
Next i

Set cmd = Nothing