使用单元格值范围内的条件运行 SQL 查询列表

Posted

技术标签:

【中文标题】使用单元格值范围内的条件运行 SQL 查询列表【英文标题】:Run list of SQL queries using conditions from range of cell values 【发布时间】:2019-01-26 13:21:58 【问题描述】:

我正在尝试运行 SQL 查询列表,其中存在“代码”条件并且值位于另一个工作表上的一系列单元格中(从单元格 A2 到 A385)。

我有下面的代码,但是,我得到一个无效的 SQLQueries 对象名称!$A2:A385

所以,我知道语法不正确,但无论阅读大量文章,我都在努力找到正确的语法。

Sub RunSQLQueries()

'Select SQLQueries sheet
    Sheets("SQLQueries").Activate

'Initializes variables
    Dim cnn As New ADODB.Connection
    Dim rst As New ADODB.Recordset
    Dim ConnectionString As String
    Dim StrQuery As String

'Setup the connection string for accessing MS SQL database
    ConnectionString = "Provider=SQLOLEDB; Data Source=HOSTNAME; Initial Catalog=DBNAME; UID=domain\user; Integrated Security=SSPI"

'Opens connection to the database
    cnn.Open ConnectionString

'Timeout
    cnn.CommandTimeout = 900

'Build SQK queries
    StrQuery = "SELECT * FROM table WHERE code IN (SELECT * FROM [SQLQueries!$A2:A385])"

'Performs the queries
    rst.Open StrQuery, cnn

'Select Results sheet
    Sheets("Results").Activate

'Dumps all the results from the StrQuery into cell A2 of the active sheet
    Range("A2").CopyFromRecordset rst

End Sub

我期望的结果是使用值范围中的每个条件运行 SQL 查询,结果从单元格 A2 向下填充到“结果”表中

【问题讨论】:

【参考方案1】:

查询字符串按字面意思发送到数据库服务器,并且由于您的 sql 尝试引用服务器无法访问的 excel 列表,因此会返回错误。服务器正在查找名为 [SQLQueries!$A2:A385] 的表

要坚持您当前的计划,您需要按字面意思传递 IN () 子句或通过格式如下的 vba 变量传递: IN ('item1', 'item2' ...)

注意:如果项目是数字,您可以删除单引号

我建议通过以下方式重新考虑计划 1)如果可以在数据库端进行调整:您可以创建一个新的引用表来连接到实际表或创建一个只返回所需行的视图吗?然后,您需要在运行查询之前调整过滤视图/表的工作。这个想法是你不需要每次都调整查询 bc 一个常量 sql 字符串会返回你需要的行 或者 2)如果源表有 100k 行或更少,并且数据不是太宽,只需在新工作表中将所有行选择到 excel 中,然后过滤该工作表(在 excel 中添加一个新列,使用 vlookup 对您的参考表)或在参考表上使用 vlookup 来拉出所需的列

【讨论】:

【参考方案2】:

这里有一个建议:

StrQuery = "SELECT * FROM table WHERE code IN (" & _
             InList(Sheets("SQLQueries").Range("A2:A385"),True) & ")"

在给定范围内创建 SQL“in”列表的函数:

Function InList(rng As Range, quoted As Boolean)
    Dim qt, a, r As Long, c As Long, rv As String, v, sep As String
    a = rng.Value
    qt = IIf(quoted, "'", "")
    For r = 1 To UBound(a, 1)
    For c = 1 To UBound(a, 2)
        v = Trim(a(r, c))
        If Len(v) > 0 Then
            rv = rv & sep & qt & v & qt
            sep = ","
        End If
    Next c
    Next r
    InList = rv
End Function

注意事项:

如果您有数值,则将 False 作为第二个参数传递 我不会将它用于非常大的列表 请确保您不会面临可能的 SQL 注入问题:参数化查询始终是可取的,但不适用于“in”列表

【讨论】:

以上是关于使用单元格值范围内的条件运行 SQL 查询列表的主要内容,如果未能解决你的问题,请参考以下文章

根据单元格值合并范围内的单元格,但最后一个单元格没有被合并

如何从 SQL 表中动态获取单元格值?

VBA 突出显示边界条件外范围内的单元格

如果条件为真,如何循环 LibreOffice Calc 电子表格中的行范围、比较单元格值、设置单元格值和删除行

Excel:使用单元格值作为 SQL 查询的参数

使用 VBA 进行颜色填充,以单元格值为条件