动态绑定参数以推送到 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
我有很多历史数据要推送到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