如何将参数传递给SQL(Excel)中的查询

Posted

技术标签:

【中文标题】如何将参数传递给SQL(Excel)中的查询【英文标题】:how to pass parameters to query in SQL (Excel) 【发布时间】:2011-07-23 00:42:05 【问题描述】:

我将 Excel“链接”到 Sql,它运行良好 - 我编写了一些 SQL 脚本,运行良好。我要做的就是将参数传递给查询。就像每次刷新一样,我希望能够将参数(过滤条件)传递给 Sql Query。 在“连接属性”参数按钮被禁用。所以我不能进行参数查询。 谁能帮帮我?

【问题讨论】:

你需要更精确,例如我们在谈论什么样的SQL? (MS SQL Server、Oracle 等)。但是,您可以在任何情况下阅读存储过程,这是您在 SQL 中传递参数的方式,除非您准备一个字符串,您可以动态更新,然后执行它。 【参考方案1】:

这篇文章已经足够老了,这个答案对 OP 来说可能没什么用,但我花了很长时间试图回答同样的问题,所以我想我会用我的发现来更新它。

此答案假定您的 Excel 文档中已经有一个有效的 SQL 查询。有很多教程向您展示如何在 Web 上完成此操作,并且有很多教程解释了如何向其中添加参数化查询,但似乎没有一个适用于 现有的 OLE DB 查询。

因此,如果您像我一样收到了一个带有有效查询的旧版 Excel 文档,但用户希望能够根据其中一个数据库字段过滤结果,而如果您像我一样都不是Excel 或 SQL 大师,或许能帮到你。

对此问题的大多数网络回复似乎都说您应该添加“?”在您的查询中让 Excel 提示您输入自定义参数,或者将提示或单元格引用放在参数应该位于的 [括号] 中。这可能适用于 ODBC 查询,但它似乎不适用于 OLE DB,在前一种情况下返回“没有为一个或多个必需参数提供值”和“无效的列名 'xxxx'”或“未知对象” 'xxxx'”在后两个中。同样,使用神话般的“参数...”或“编辑查询...”按钮也不是一个选项,因为在这种情况下它们似乎永久变灰。 (作为参考,我使用的是 Excel 2010,但使用的是 Excel 97-2003 工作簿 (*.xls))

然而,我们可以做的是添加一个参数单元格和一个带有简单例程的按钮,以便以编程方式更新我们的查询文本。

首先,在外部数据表(或任何地方)上方添加一行,您可以在其中将参数提示放在空单元格和按钮旁边(开发人员->插入->按钮(表单控件)-您可能需要启用开发人员选项卡,但您可以在其他地方了解如何执行此操作),如下所示:

接下来,在外部数据(蓝色)区域中选择一个单元格,然后打开数据->全部刷新(下拉菜单)->连接属性...查看您的查询。下一节中的代码假定您的查询中已经有一个参数(连接属性->定义->命令文本),格式为“WHERE (DB_TABLE_NAME.Field_Name = ‘Default Query Parameter’)”(包括括号)。显然,“DB_TABLE_NAME.Field_Name”和“默认查询参数”在您的代码中需要有所不同,这取决于数据库表名称、数据库值字段(列)名称以及打开文档时要搜索的一些默认值(如果你有自动刷新设置)。记下“DB_TABLE_NAME.Field_Name”值,因为您将在下一部分中需要它,以及查询的“连接名称”,可以在对话框顶部找到。

关闭连接属性,然后按 Alt+F11 打开 VBA 编辑器。如果您还没有,请在“项目”窗口中右键单击包含您的按钮的工作表名称,然后选择“查看代码”。将以下代码粘贴到代码窗口中(建议复制,因为单引号/双引号很冒险且必要)。

Sub RefreshQuery()
 Dim queryPreText As String
 Dim queryPostText As String
 Dim valueToFilter As String
 Dim paramPosition As Integer
 valueToFilter = "DB_TABLE_NAME.Field_Name ="

 With ActiveWorkbook.Connections("Connection name").OLEDBConnection
     queryPreText = .CommandText
     paramPosition = InStr(queryPreText, valueToFilter) + Len(valueToFilter) - 1
     queryPreText = Left(queryPreText, paramPosition)
     queryPostText = .CommandText
     queryPostText = Right(queryPostText, Len(queryPostText) - paramPosition)
     queryPostText = Right(queryPostText, Len(queryPostText) - InStr(queryPostText, ")") + 1)
     .CommandText = queryPreText & " '" & Range("Cell reference").Value & "'" & queryPostText
 End With
 ActiveWorkbook.Connections("Connection name").Refresh
End Sub

将“DB_TABLE_NAME.Field_Name”和“连接名称”(在两个位置)替换为您的值(需要包含双引号以及空格和等号)。

将“单元格引用”替换为您的参数所在的单元格(从头开始的空单元格) - 我的是第一行中的第二个单元格,所以我输入了“B1”(再次,双引号是必要的) .

保存并关闭 VBA 编辑器。

在适当的单元格中输入您的参数。

右键单击您的按钮以将 RefreshQuery 子分配为宏,然后单击您的按钮。查询应该更新并显示正确的数据!

注意事项: 仅当您的查询中有连接或其他出现等号时,才需要使用整个过滤器参数名称(“DB_TABLE_NAME.Field_Name =”),否则只需一个等号就足够了,Len() 计算将是多余的。 如果您的参数包含在也用于连接表的字段中,则需要将代码中的“paramPosition = InStr(queryPreText, valueToFilter) + Len(valueToFilter) - 1”行更改为“paramPosition = InStr( Right(.CommandText, Len(.CommandText) - InStrRev(.CommandText, "WHERE")), valueToFilter) + Len(valueToFilter) - 1 + InStr(.CommandText, "WHERE")" 以便它只查找 valueToFilter 在“WHERE”之后

这个答案是在 datapig 的“BaconBits”的帮助下创建的,我在其中找到了查询更新的基本代码。

【讨论】:

另外请注意,如果您的参数中包含括号,则更新代码将无法正常工作。 (它依靠括号来确定它在查询字符串中的位置)。您可以重新编码 queryPostText 字符串以根据 second (等)关闭括号找到它的长度以使其工作。 这太棒了 :) 谢谢,帮了我很多。 嗨,我正在通过 OLE DB 连接阅读,我的查询总共有 3 个表和 2 个连接,我认为这对我不起作用吗? @Mowgli 是的,它可以工作,但正如我在最后一段中指出的那样,如果您尝试基于用于连接的相同字段进行过滤(参数化),您将拥有更改 paramPosition 设置。 从有效的外部数据源形成表格后,参数按钮“ungreys”本身...因此,如果您填充了表格(没有参数),然后返回连接属性,您应该会看到可供您设置的参数按钮。 (别忘了在你的 SQL 查询中使用fieldname=?【参考方案2】:

这取决于您尝试连接的数据库、创建连接的方法以及您使用的 Excel 版本。 (也很可能是您计算机上相关 ODBC 驱动程序的版本。)

以下示例在我的本地计算机上使用 SQL Server 2008 和 Excel 2007。

当我使用数据连接向导(在功能区的“数据”选项卡上的“获取外部数据”部分的“来自其他来源”下)时,我看到了与您所做的相同的事情:“参数”按钮被禁用,并添加了一个查询的参数,例如 select field from table where field2 = ?,导致 Excel 抱怨未指定参数的值,并且未保存更改。

当我使用 Microsoft Query(与数据连接向导相同的位置)时,我能够创建参数,为它们指定显示名称,并在每次运行查询时输入值。调出该连接的连接属性,启用“参数...”按钮,并且可以根据需要修改和使用参数。

我也可以使用 Access 数据库来做到这一点。 Microsoft Query 可用于创建针对其他类型数据库的参数化查询似乎是合理的,但我现在无法轻松测试。

【讨论】:

以上是关于如何将参数传递给SQL(Excel)中的查询的主要内容,如果未能解决你的问题,请参考以下文章

如何将参数传递给节点js中的sql查询

如何将参数传递给`pymssql`中的`cursor.execute`?

将函数参数传递给 sql 查询

Delphi:如何将列表作为参数传递给SQL查询?

如何将参数传递给 sql 'in' 语句?

如何将两个参数传递给来自 IBM Bluemix 的 Node-Red 的 dashDB 查询元素