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

时间:2019-01-26 13:21:59

标签: sql excel

我正在尝试运行一个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下方的“结果”表中

2 个答案:

答案 0 :(得分:0)

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

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

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

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

答案 1 :(得分:0)

这是一个建议:

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

用于创建给定范围的SQL“中”列表的函数:

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注入问题的威胁:始终首选参数化查询,但不适用于“在”列表中