运行 SQL 在 Excel 中查询
Run SQL IN queries in Excel
Objective
我想 运行 SQL 使用 IN 语句查询到 Excel 文件并使用动态参数。
查询
首先可以是:
SELECT feature1
FROM table
WHERE feature2 IN (?)
or
SELECT feature1
FROM table
WHERE feature2 IN ?
无论参数如何,第二个都有系统误差
Syntax error or access violation
所以我专注于第一个。
参数
我在指定参数列表时遇到问题(数据 -> 请求和连接 -> 连接 -> 定义 -> 参数):
- 'a','b','c' -> returns 无
- "a","b","c" -> returns 无
- "'a','b','c'" -> returns 无
- 'a' -> returns 无
- a -> returns 东西
- a,b,c -> returns 无
最后但同样重要的是,当它是硬编码时,这个returns Something:
SELECT feature1
FROM table
WHERE feature2 IN ('a', 'b', 'c')
问题
发生了什么事?如何动态指定多个参数?有没有办法可视化这个构建的查询来检查出了什么问题?或者有什么技巧可以避免这个问题?
最好不要VBA
使用 Excel 2019 和 Microsoft SQL Server 2012(否 STRING_SPLIT
、OPENJSON
)
编辑
根据答案和这个 ,我尝试使用这个 sql 查询来避免使用 STRING_SPLIT
和 OPENJSON
:
SELECT feature1
FROM table
WHERE feature2 IN (
SELECT Split.a.value('.', 'NVARCHAR(MAX)') DATA
FROM (
SELECT CAST('<X>'+REPLACE( ? , ',', '</X><X>')+'</X>' AS XML) AS String
) AS A
CROSS APPLY String.nodes('/X') AS Split(a)
);
但是,它不理解通过 Excel 的参数,而当它在查询中被硬编码 时它可以工作。
您必须指定参数列表并相应地分配值。例如,对于 a,b,c
,您必须创建 3 个查询参数
SELECT feature1 FROM table WHERE feature2 IN (?,?,?)
参数是单个值。
您不能直接创建 IN 查询。但是,您可以将参数作为逗号分隔值或 xml 或 json 字符串发送,以便在服务器端解析为 table。这是一个简单的例子,使用 Northwind 示例数据库 + json,查询是:
SELECT * FROM [Northwind]..[Products]
WHERE ProductID IN
(
SELECT value FROM OPENJSON(@Json)
)
ENDTEXT
' A Json array of integers as parameter
Json = "[1, 3, 5, 6]"
编辑:样本 XML:
Sub test()
Dim query As String
Dim myParameters As String
query = "DECLARE @hDoc int" & vbCrLf & _
"exec sp_xml_preparedocument @hDoc OUTPUT, ?" & vbCrLf & _
"SELECT * FROM [Northwind]..[Products]" & vbCrLf & _
"WHERE ProductID IN" & vbCrLf & _
"(SELECT id FROM OPENXML(@hDoc, '/root/row', 1) WITH (id int))" & vbCrLf & _
"EXEC sp_xml_removedocument @hDoc"
myParameters = "<root>" & vbCrLf & _
"<row id=""1""/>" & vbCrLf & _
"<row id=""3""/>" & vbCrLf & _
"<row id=""5""/>" & vbCrLf & _
"<row id=""8""/>" & vbCrLf & _
"<row id=""9""/>" & vbCrLf & _
"</root>"
Dim connectionstring As String
Dim cn As ADODB.Connection
Dim cmd As ADODB.Command
Dim p As ADODB.Parameter
Dim rs As ADODB.Recordset
connectionstring = "Provider=SQLNCLI11.0;Data Source=.\SQLExpress;" & _
"Initial Catalog=Northwind;" & _
"Integrated Security=SSPI;"
Set cn = New ADODB.Connection
Set rs = New ADODB.Recordset
Set cmd = New ADODB.Command
cn.Open connectionstring
cmd.ActiveConnection = cn
cmd.CommandText = query
Set p = cmd.CreateParameter("myValues", adVarChar, adParamInput, -1)
p.Value = myParameters
cmd.Parameters.Append p
' Execute command
Set rs = cmd.Execute
Sheets(1).Range("A1").CopyFromRecordset rs
End Sub
PS:我不是 VB 也不是 VB 人,我真的会用另一种语言来做这件事,但无论如何这也行。
EDIT2:顺便说一句:
exec sp_executesql N'DECLARE @hDoc int
exec sp_xml_preparedocument @hDoc OUTPUT, @P1
SELECT * FROM [Northwind]..[Products]
WHERE ProductID IN
(SELECT id FROM OPENXML(@hDoc, ''/root/row'', 1) WITH (id int))
EXEC sp_xml_removedocument @hDoc',N'@P1 varchar(max)','<root>
<row id="1"/>
<row id="3"/>
<row id="5"/>
<row id="8"/>
<row id="9"/>
</root>'
至SQL 服务器。您也可以自己使用 sp_executesql 并创建一个更简单的 IN 查询,但是如果您不能很好地控制生成的代码,这可能很危险。
好的,根据答案和这个 post,此方法可以在 sql 查询中使用 excel 设置多个参数(和未知大小)。 没有使用IN语句但是结果是一样的
SQL :
SELECT feature1
FROM database
WHERE ?
LIKE '%,' + feature2 + ',%' ;
这里是?必须看起来像 ',a,b,c,'
Excel:
="'," & TEXJOIN(",",TRUE,A:A) & ",'"
这没有针对大量行进行优化,因此也欢迎优化解决方案
Objective
我想 运行 SQL 使用 IN 语句查询到 Excel 文件并使用动态参数。
查询
首先可以是:
SELECT feature1
FROM table
WHERE feature2 IN (?)
or
SELECT feature1
FROM table
WHERE feature2 IN ?
无论参数如何,第二个都有系统误差
Syntax error or access violation
所以我专注于第一个。
参数
我在指定参数列表时遇到问题(数据 -> 请求和连接 -> 连接 -> 定义 -> 参数):
- 'a','b','c' -> returns 无
- "a","b","c" -> returns 无
- "'a','b','c'" -> returns 无
- 'a' -> returns 无
- a -> returns 东西
- a,b,c -> returns 无
最后但同样重要的是,当它是硬编码时,这个returns Something:
SELECT feature1
FROM table
WHERE feature2 IN ('a', 'b', 'c')
问题
发生了什么事?如何动态指定多个参数?有没有办法可视化这个构建的查询来检查出了什么问题?或者有什么技巧可以避免这个问题?
最好不要VBA
使用 Excel 2019 和 Microsoft SQL Server 2012(否 STRING_SPLIT
、OPENJSON
)
编辑
根据答案和这个 STRING_SPLIT
和 OPENJSON
:
SELECT feature1
FROM table
WHERE feature2 IN (
SELECT Split.a.value('.', 'NVARCHAR(MAX)') DATA
FROM (
SELECT CAST('<X>'+REPLACE( ? , ',', '</X><X>')+'</X>' AS XML) AS String
) AS A
CROSS APPLY String.nodes('/X') AS Split(a)
);
但是,它不理解通过 Excel 的参数,而当它在查询中被硬编码 时它可以工作。
您必须指定参数列表并相应地分配值。例如,对于 a,b,c
,您必须创建 3 个查询参数
SELECT feature1 FROM table WHERE feature2 IN (?,?,?)
参数是单个值。
您不能直接创建 IN 查询。但是,您可以将参数作为逗号分隔值或 xml 或 json 字符串发送,以便在服务器端解析为 table。这是一个简单的例子,使用 Northwind 示例数据库 + json,查询是:
SELECT * FROM [Northwind]..[Products]
WHERE ProductID IN
(
SELECT value FROM OPENJSON(@Json)
)
ENDTEXT
' A Json array of integers as parameter
Json = "[1, 3, 5, 6]"
编辑:样本 XML:
Sub test()
Dim query As String
Dim myParameters As String
query = "DECLARE @hDoc int" & vbCrLf & _
"exec sp_xml_preparedocument @hDoc OUTPUT, ?" & vbCrLf & _
"SELECT * FROM [Northwind]..[Products]" & vbCrLf & _
"WHERE ProductID IN" & vbCrLf & _
"(SELECT id FROM OPENXML(@hDoc, '/root/row', 1) WITH (id int))" & vbCrLf & _
"EXEC sp_xml_removedocument @hDoc"
myParameters = "<root>" & vbCrLf & _
"<row id=""1""/>" & vbCrLf & _
"<row id=""3""/>" & vbCrLf & _
"<row id=""5""/>" & vbCrLf & _
"<row id=""8""/>" & vbCrLf & _
"<row id=""9""/>" & vbCrLf & _
"</root>"
Dim connectionstring As String
Dim cn As ADODB.Connection
Dim cmd As ADODB.Command
Dim p As ADODB.Parameter
Dim rs As ADODB.Recordset
connectionstring = "Provider=SQLNCLI11.0;Data Source=.\SQLExpress;" & _
"Initial Catalog=Northwind;" & _
"Integrated Security=SSPI;"
Set cn = New ADODB.Connection
Set rs = New ADODB.Recordset
Set cmd = New ADODB.Command
cn.Open connectionstring
cmd.ActiveConnection = cn
cmd.CommandText = query
Set p = cmd.CreateParameter("myValues", adVarChar, adParamInput, -1)
p.Value = myParameters
cmd.Parameters.Append p
' Execute command
Set rs = cmd.Execute
Sheets(1).Range("A1").CopyFromRecordset rs
End Sub
PS:我不是 VB 也不是 VB 人,我真的会用另一种语言来做这件事,但无论如何这也行。
EDIT2:顺便说一句:
exec sp_executesql N'DECLARE @hDoc int
exec sp_xml_preparedocument @hDoc OUTPUT, @P1
SELECT * FROM [Northwind]..[Products]
WHERE ProductID IN
(SELECT id FROM OPENXML(@hDoc, ''/root/row'', 1) WITH (id int))
EXEC sp_xml_removedocument @hDoc',N'@P1 varchar(max)','<root>
<row id="1"/>
<row id="3"/>
<row id="5"/>
<row id="8"/>
<row id="9"/>
</root>'
至SQL 服务器。您也可以自己使用 sp_executesql 并创建一个更简单的 IN 查询,但是如果您不能很好地控制生成的代码,这可能很危险。
好的,根据答案和这个 post,此方法可以在 sql 查询中使用 excel 设置多个参数(和未知大小)。 没有使用IN语句但是结果是一样的
SQL :
SELECT feature1
FROM database
WHERE ?
LIKE '%,' + feature2 + ',%' ;
这里是?必须看起来像 ',a,b,c,'
Excel:
="'," & TEXJOIN(",",TRUE,A:A) & ",'"
这没有针对大量行进行优化,因此也欢迎优化解决方案