我目前正在编写基于VBA的Excel加载项,该加载项主要基于Jet数据库后端(我使用的是Office 2003套件 - 问题与最新版本的Office无关)。
在我的应用程序初始化期间,我创建了在文本文件中定义的存储过程。这些程序在需要时由我的应用程序调用。
让我举一个简单的例子来描述我的问题:假设我的应用允许最终用户选择他们想要详细信息的订单的标识符。这是表格定义:
表tblOrders:OrderID LONG,OrderDate DATE,(其他字段)
最终用户可以选择一个或多个订单ID,以表格形式显示 - 他/她只需勾选相关订单ID的复选框,其中包含他/她喜欢的详细信息(OrderDate等)。
因为我事先并不知道他/她将选择多少OrderID,所以我可以根据表单上的选择级联WHERE子句,在VBA代码中动态创建SQL查询:
SELECT * FROM tblOrders WHERE OrderID = 1 OR OrderID = 2 OR OrderID = 3
或更简单,使用IN关键字:
SELECT * FROM tblOrders WHERE OrderID IN (1,2,3)
现在,如果我将这个简单的查询转换为存储过程,以便我可以动态传递我想要显示的OrderID列表,我该怎么办?我已经尝试过这样的事情:
CREATE PROCEDURE spTest (@OrderList varchar) AS
SELECT * FROM tblOrders WHERE OrderID IN (@OrderList)
但这不起作用(我期待那样),因为@OrderList
被解释为字符串(例如“1,2,3”)而不是长值列表。 (我改编自这里的代码:Passing a list/array to SQL Server stored procedure)
我希望尽可能避免通过纯VBA代码处理此问题(即动态地将值列表分配给我的应用程序中硬编码的查询)。我知道如果这是不可能的。
有任何线索吗?
答案 0 :(得分:1)
您可以动态创建查询语句字符串。在SQL Server中,您可以拥有一个返回值为TABLE的函数,并将该函数内联调用,就像它是一个表一样。或者在JET中,您还可以创建一个kludge - 一个临时表(或提供临时表功能的持久表),它包含列表中的值,每行一个,并在该表上连接。因此,查询将分为两步:1)使用INLIST值填充临时表,然后2)执行临时表上的查询连接。
MYTEMPTABLE
autoincrementing id
QueryID [some value to identify the current query, perhaps a GUID]
myvalue one of the values in your in-list, string
select * from foo
inner join MYTEMPTABLE on foo.column = MYTEMPTABLE.myvalue and MYTEMPTABLE.QueryId = ?
[cannot recall if JET allows ANDs in INNER JOIN as SQL Server does --
if not, adjust syntax accordingly]
而不是
select * from foo where foo.column IN (... )
通过这种方式,您可以使同一个表同时处理多个查询,因为每个查询都有一个唯一的标识符。您可以在完成后删除列表中的行:
DELETE FROM MYTEMPTABLE where QueryID = ?
P.S。有几种方法可以处理连接的数据类型问题。您可以根据需要在MYTEMPTABLE中转换字符串值,或者您可以在MYTEMPTABLE中有多个不同数据类型的列,插入并连接到正确的列:
MYTEMPTABLE
id
queryid
mytextvalue
myintvalue
mymoneyvalue
etc