使用IN子句从Excel中进行参数化查询

时间:2019-05-24 00:41:59

标签: sql excel db2 parameterized-query

我有一个从.jpg工作表到MS Query数据库的Excel 2016连接。我使用参数化查询并将参数值链接到Excel单元格。虽然IBM DB2这样的“奇异值”子句可以工作,但我无法让= < > like子句在多个值中使用 ,但在其他情况下却是超级简单的查询。

这是我生成参数值的简单演示数据集:

enter image description here

D列的公式为IN,它检查C列的值是否大于5,如果=IF(C2>5,A2&",",""),则在D列中填充ID。我希望使用一个辅助单元格来合并/合并我想用于TRUE子句的D列中的所有值(尚未完成)。

如何在单元格中使用IN来运行"value1, value2, value3, ..."子句查询? 有可能吗? IN子句在链接单元格的值为IN时工作正常,但是1会产生错误消息: 1, 3

从技术上讲,为每个单元格使用单独的参数和"Bad parameter type. Microsoft Excel is expecting a different kind of value than what was provided"子句看起来很有效,但是实际上,数据集可以轻松达到50-100个值,这意味着疯狂的参数设置。

查询本身很简单:

OR

或作为Excel MS Query替代:

select * from PRODUCTS a
where a.prod_ID in (1,3)

2 个答案:

答案 0 :(得分:0)

此:

select * from PRODUCTS a
where a.prod_ID in ?

永远不会工作。

可行的方法是将字符串传递到可以返回一组行的函数中。

select * 
from PRODUCTS a
where a.prod_ID in (select int(column_value)
                    from table ( split(?,',')) tbl
                   )

split()是用户定义的表函数,摘自IBM开发人员的文章:How to split a string into a set of rows (anti-LISTAGG)

CREATE OR REPLACE FUNCTION SPLIT(text VARCHAR(32000), split VARCHAR(10))
RETURNS TABLE(column_values VARCHAR(60))
RETURN WITH rec(rn, column_value, pos) AS
        (VALUES (1, VARCHAR(SUBSTR(text, 1, 
                                   DECODE(INSTR(text, split, 1), 
                                          0, 
                                          LENGTH(text), 
                                          INSTR(text, split, 1) - 1)),
                            255),  
                    INSTR(text, split, 1) + LENGTH(split))
         UNION ALL
         SELECT rn + 1, VARCHAR(SUBSTR(text, pos, 
                                       DECODE(INSTR(text, split, pos), 
                                              0, 
                                              LENGTH(text) - pos + 1,  
                                              INSTR(text, split, pos) - pos)), 
                                255),  
                        INSTR(text, split, pos) + LENGTH(split)
          FROM rec WHERE rn < 30000 AND pos > LENGTH(split))
      SELECT column_value FROM rec;

取决于您的平台和Db2版本,可能会有一些内置选项。

例如,在最新版本中,您可以传入带有值的XML或JSON字符串,然后使用XMLTABLE()或JSON_TABLE()将字符串拆分为行。

答案 1 :(得分:0)

将其发布在此处供将来的Google员工使用。因此,对于我来说,该解决方案有点开箱即用-尽管仍然需要增强。

它检查M1:M4范围内的工作表更改事件,然后根据B1中准备好的语法填充子句中的查询命令文本。对我来说真是开箱即用!

不幸的是,尽管我有多个应该接受相同的处理,但是这里只处理一个ListObject(1),尽管如此,它还是很棒的东西。

Private Sub Worksheet_Change(ByVal Target As Range)

    Dim INvaluesCell As Range
    Dim SQLin As String, parts As Variant
    Dim i As Long, p1 As Long, p2 As Long
    Dim qt As QueryTable

    Set INvaluesCell = Range("B1")

    If Not Intersect(Target, Range(INvaluesCell, "M1:M4")) Is Nothing Then

        SQLin = ""
        parts = Split(INvaluesCell.Value, ",")
        For i = 0 To UBound(parts)
            SQLin = SQLin & "'" & parts(i) & "',"
        Next
        SQLin = " IN (" & Left(SQLin, Len(SQLin) - 1) & ")"

        Set qt = Me.ListObjects(1).QueryTable

        p1 = InStr(1, qt.CommandText, " IN (", vbTextCompare)
        If p1 > 0 Then
            p2 = InStr(p1, qt.CommandText, ")") + 1
            qt.CommandText = Left(qt.CommandText, p1 - 1) & SQLin & Mid(qt.CommandText, p2)
        End If

    End If

End Sub