VBA ADO 将数组参数传递给存储过程
Posted
技术标签:
【中文标题】VBA ADO 将数组参数传递给存储过程【英文标题】:VBA ADO pass array parameter to stored procedure 【发布时间】:2021-12-29 13:01:11 【问题描述】:我在 VBA MS Excel 文件中有一个 3 列和 100K 行的数组。
我想将此数组传递给 SQL Server 存储过程并在存储过程中将其转换为 Tmp-table 并执行我的“事情..”
如何将数组传递给存储过程?
这是我的 VBA 数组的示例:
Col1 | Col2 | Col3
1 AAA XXX
2 BBB YYY
3 CCC ZZZ
VBA 代码:
......
Set Cmd = CreateObject("ADODB.Command")
Cmd.CommandType = 4
Cmd.NamedParameters = True
Cmd.ActiveConnection = DbConn
Cmd.CommandText = "My_SP_WithArrayParam"
''I dont know what parameters to use here:
Cmd.Parameters.Append Cmd.CreateParameter("@Arr", ??? , ?? , ??? , My_100K_Arr)
Cmd.Execute
在 SQL 方面:
Create or alter proc My_SP_WithArrayParam(
@Arr ???
)
as
begin
create table #Tbl_From_Excel (
ID int
,COL1 nvarchar(60)
,COL2 nvarchar(60)
)
---Need to insert the array to the tmp table, and I dont know the syntax
end
【问题讨论】:
SQL Server 没有“数组”对象类型。您要使用的是 Table Type 参数。 @Larnu ,好的,对于表类型我可以传递我的 VBA 数组? 为什么不将 json 格式的文本与数组的内容一起使用并将其作为文本传递。 Sql Server 从版本 13 开始可以处理 json。这是link 可能有用。 @AntonGrig - 将 100K * 3 值转换为 JSON 并将大量字符串发送到 SQL 会很慢,我测试了一种将数组转换为“插入”字符串的类似方法花了 7 分钟变成了一个字符串 发送 100,000 行作为表类型参数也不会有效。我闻到了 XY 问题。 【参考方案1】:对象数组可以作为结构化参数值传递,例如表值参数、XML 或 json(SQL 2016 及更高版本)。尽管较新的 SQL Server 驱动程序支持表值参数,但 ADODB(又名 ADO 经典)不支持。我建议在 XML 上使用 json 字符串,因为它的有效负载较小,并且可以被 SQL Server 高效解析。
以下是 VBA 示例代码。 SQL 调用只用了几秒钟,但在我的工作站上使用传统的字符串连接构建 json 字符串需要几分钟。在 VBA 中构建高性能字符串需要非常注意细节,但如果你想去那里,似乎有 techniques to improve it considerably。
存储过程:
CREATE OR ALTER PROC My_SP_WithArrayParam
@Arr nvarchar(MAX)
AS
SET NOCOUNT ON;
SELECT Col1, Col2, Col3
INTO #Tbl_From_Excel
FROM OPENJSON(@arr)
WITH (
Col1 int
,Col2 varchar(100)
,Col3 varchar(100)
);
GO
ArrayEntry 类:
Option Explicit
Public Col1 As Long
Public Col2 As String
Public Col3 As String
Public Function getJson()
Dim json As String
` note if double quotes may exist in values, they need to be escaped with a backslash
' TODO: string building optimization
getJson = """Col1"":""" & CStr(Col1) & """,""Col2"":""" & Col2 & """,""Col3"":""" & Col3 & """"
End Function
示例使用代码:
' load 100000 array entries
Dim arrayEntries(100000) As ArrayEntry
Dim i As Long
For i = 0 To 99999
Set entry = New ArrayEntry
Set arrayEntries(i) = entry
entry.Col1 = i
entry.Col2 = "AAA"
entry.Col3 = "XXX"
Next i
' build json from array (TODO: string building optimization)
Dim json As String
json = "["
For i = 0 To 99999
Set entry = arrayEntries(i)
If i > 0 Then json = json & ","
json = json & entry.getJson()
Next
json = json & "]"
' call proc with json parameter
con.Open "Provider=MSOLEDBSQL;Data Source=.;Initial Catalog=YourDatabase;Integrated Security=SSPI;"
cmd.ActiveConnection = con
cmd.CommandText = "My_SP_WithArrayParam"
cmd.CommandType = adCmdStoredProc
cmd.Parameters.Append cmd.CreateParameter("@json", adVarChar, adParamInput, -1, json)
cmd.Execute
con.Close
Set cmd = Nothing
Set con = Nothing
【讨论】:
以上是关于VBA ADO 将数组参数传递给存储过程的主要内容,如果未能解决你的问题,请参考以下文章
在 ASP.Net Core 项目中使用 ADO.Net 将 JSON 类型作为参数传递给 SQL Server 2016 存储过程