Home > OS >  Dynamically Binding parameters to push to SQL Server
Dynamically Binding parameters to push to SQL Server

Time:05-25

I have a lot of historical data I'm pushing to SQL. As a stop gap I'm coding this in VBA first. I open the .xlsx file, put the headers into an array to determine what SQL table the data goes into. Then I'm using solution #3 from INSERT INTO statement from Excel to SQL Server Table using VBA to base my SQL string on. I'm throwing an automation error at the .parameters.append line. Is there another way to dynamically append the parameters? Or is this just incorrect syntax? I appreciate any help!

Code:

'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

UPDATED: Based on @joel-coehoorn's answer, I updated the command and deleted the wbk.close. I'm throwing a "Item cannot be found in the collection corresponding to the requested name or ordinal." on the line 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

CodePudding user response:

My VBA is more than a little rusty, so there's likely a mistake in the above, but I do believe this will get you to a better place.

That disclaimer out of the way, a . is just another binary operator, and so I think the space in

.Parameters.Append .CreateParameter

is not doing all the work you think it is, in that it's not equivalent to

cmd.Parameters.Append cmd.CreateParameter

but rather

cmd.Parameters.Append.CreateParameter

which of course is not a thing.

You probably need to do something like this instead:

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

Note we don't call .Execute until we finish creating all the parameters.

Additionally, this code is itself inside a loop. You really don't need to recreate cmd or all those parameters again on every loop iteration. Rather, you should create the command and parameters once, and then only update the parameters' .Value properties inside the loop.

' ...

sys.Close
wbk.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).Value = wks.Cells(i, j)
    Next j
    
    'RUN THE SQL COMMAND
    cmd.Execute
Next i
Set cmd = Nothing
  • Related