【问题标题】:Run SQL IN queries in Excel在 Excel 中运行 SQL IN 查询
【发布时间】:2021-10-31 03:27:38
【问题描述】:

目标

我想通过 IN 语句在 Excel 文件中运行 SQL 查询并使用动态参数。

查询

首先,可以是:

SELECT feature1 
FROM table 
WHERE feature2 IN (?) 

or

SELECT feature1 
FROM table 
WHERE feature2 IN ? 

无论参数如何,第二个都有系统误差

语法错误或访问冲突

所以我专注于第一个。

参数

我在指定参数列表时遇到问题(数据 -> 请求和连接 -> 连接 -> 定义 -> 参数):

  • 'a','b','c' -> 无返回值
  • "a","b","c" -> 无返回值
  • "'a','b','c'" -> 无返回值
  • 'a' -> 不返回任何内容
  • a -> 返回一些东西
  • a,b,c -> 无返回值

最后但同样重要的是,当它被硬编码时,这返回Something

SELECT feature1 
FROM table 
WHERE feature2 IN ('a', 'b', 'c') 

问题

发生了什么?如何动态指定多个参数?有没有办法可视化这个构建的查询来检查有什么问题?或者有什么技术可以避免这个问题?

最好不要使用 VBA

使用 Excel 2019 和 Microsoft SQL Server 2012(否 STRING_SPLITOPENJSON

编辑

根据答案和这个post,我尝试使用这个sql查询来避免使用STRING_SPLITOPENJSON

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 理解参数,而在查询中硬编码时它可以工作

【问题讨论】:

  • 你不能传递带有单个 [scalar] 参数的 IN 并期望将值视为数组;数组不是 SQL Server 中存在的数据类型。相反,一种方法是使用 Table-Type 参数和 JOIN 来代替它。否则,您可以使用分隔字符串并拆分值,但由于您使用的是 SQL Server 2012,那么您将无法访问STRING_SPLIT,因此需要使用 good 基于集合的 udf.
  • 请澄清您的具体问题或提供其他详细信息以准确突出您的需求。正如目前所写的那样,很难准确地说出你在问什么。
  • 我不明白什么是难以理解的:所有的答案都与我的帖子相关和相关,他们帮助了我。所以我认为我的问题已经很好理解了,但是如果您坚持添加详细信息,我会这样做

标签: sql sql-server excel sql-server-2012


【解决方案1】:

您不能直接创建 IN 查询。但是,您可以将参数作为逗号分隔值或 xml 或 json 字符串发送,以便在服务器端解析为表。这是一个使用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 也不是 VBA 人,我真的会用另一种语言来做这件事,但无论如何这也可以。

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 查询,但如果您无法很好地控制生成的代码,这可能会很危险。

【讨论】:

  • OPENJSON 仅适用于 SQL Server 2016 (13.x) 及更高版本doc
  • @BDouchet,正如我所说,如果您愿意,也可以使用逗号分隔值或 xml。代码虽然不同。如果您需要,我也可以给您一个 XML 示例(甚至是 csv)。
  • 请用XML解析检查我的编辑,但字符串参数不能通过Excel理解
  • 我真的不是那个意思。添加完整样本。
【解决方案2】:

您必须指定参数列表并相应地分配值。例如对于a,b,c,您必须创建查询的 3 个参数

SELECT feature1 FROM table WHERE feature2 IN (?,?,?)

参数是单个值。

【讨论】:

  • 可以,但是a,b,c只是举例,参数个数未知
  • 您可以在 EXCEL 端使用 VBA 构建查询文本。或者在 Sql Server 端解析一个 csv 字符串。
【解决方案3】:

好的,根据答案和这个post,此方法可以使用excel 在sql 查询中设置多个参数(和未知大小)。 不使用IN语句但结果是一样的。

SQL:

SELECT feature1 
FROM database
WHERE ?
LIKE '%,' + feature2 + ',%' ;

这里是?必须看起来像',a,b,c,'

Excel:

="'," & TEXJOIN(",",TRUE,A:A) & ",'"

这并未针对大量行进行优化,因此也欢迎优化解决方案

【讨论】:

  • 这不是一个好的解决方案,但在某些情况下会起作用。恕我直言,OpenXml 方法要好得多。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-07
  • 2022-08-20
  • 2016-04-09
  • 2013-09-18
  • 1970-01-01
相关资源
最近更新 更多