嘿,我刚刚学会了如何将我的SQL语句放入VBA(或至少写出来),但我不知道如何返回数据?
我有几种形式(图表形式)基于我运行相当常规参数的查询,只是改变时间范围(就像月份的前十名销售一样)。然后我有自动将图表对象传输到powerpoint演示文稿的过程。所以我预先建立了所有这些查询(如63),并且图表形式匹配(呃,是啊...... 63 ......我知道这很糟糕),然后所有这些事情都建立在“开放/关闭“触发下一个事件的事件(就像我最好的成为黑客......或多米诺的尝试;无论你喜欢哪个)。
所以我试图学习如何在VBA中使用SQL语句,这样我最终可以在那里完成所有这些(我可能仍然需要保留所有这些图表形式,但我不知道,因为我显然缺乏理解)
除了我在顶部提出的问题之外,有人可以提供建议吗? 感谢
答案 0 :(得分:9)
有点过时,所以你可能想要抓住book on the subject。但是,这里有大量的access resources和一些tutorials and examples。但是,基本上......
Dim dbs As Database
Dim rs As Recordset
Dim strSQL As String
Set dbs = CurrentDb
strSQL = 'your query here
Set rs = dbs.OpenRecordset(strSQL)
If Not (rs.EOF And rs.BOF) Then
rs.MoveFirst
'get results using rs.Fields()
Else
'Use results
每条评论:看看recordset class。它包含一个名为Fields的集合,它是从查询返回的列。在不了解您的架构的情况下,很难说,但有点像......
rs.MoveFirst
Do While Not rs.EOF
'do something like rs("SomeFieldName")
rs.MoveNext
Loop
就像我说的那样,你最好的办法是拿一本关于这个主题的书,他们有很多例子。
答案 1 :(得分:3)
使用参数化的querydef并从vba中调用它 查询更容易设计......易于测试......并且可以从VBA或表单轻松访问。
dim qd as querydef
set qd = currentdb.querydefs!myquerydef
qd.parameters!parm1=val1
...
任一 qd.execute
或
dim rs as recordset
set rs = qd.openrecordset()
YMMV ......
答案 2 :(得分:2)
这是一个函数,您可以考虑重构以接收字符串,并且您将能够在代码中的任何位置重复使用。
所以有一个CONST或为你的SQL语句构建一个字符串,并以你的SANITIZED,NON SQL INJECTED字符串作为参数弹出:)
即。
strSQL = "SELECT * FROM Customer WHERE ID = " & EnsureParamIsNotSQLInjection(customerID)
...然后从需要获取记录集/数据/执行语句的任何地方调用函数/ sub。考虑创建一些数据访问函数/ subs,您可以在其中运行UPDATE语句,或检索单个值,或者检索完整的记录集。
这里的关键是让这些功能都存在于一个地方,并在整个地方重复使用。以下是 VBScript 中的示例。
Sub DoStuff(strSQL)
Set adoCon = Server.CreateObject("ADODB.Connection")
strConnString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Server.MapPath("db\Database.mdb")
'strConnString = "DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=" & Server.MapPath("db\Database.mdb")
adoCon.Open strConnString
Set rsMain = Server.CreateObject("ADODB.Recordset")
rsMain.Open strSQL, adoCon
Do While NOT rsMain.EOF
customerName = rsMain("CustomerName") 'silly example
RsMain.MoveNext
Loop
rsMain.Close
Set adoCon = Nothing
End Sub
答案 3 :(得分:1)
虽然复杂,但比尝试在VBA中构建SQL语句更容易。请记住,单独保存查询允许您直观地操作它们。此外,还有一些性能优势。
更好地理解SQL可以帮助您整合和简化现有的查询(如果它们甚至需要简化。听起来他们正在做很多工作,所以无论如何你可能需要所有64个查询。)
也就是说,在代码中执行SQL查询非常容易:
Dim strSQL as String
strSQL = "UPDATE Table MyTable SET fieldname = 1 WHERE fieldname = 0;"
DoCmd.RunSQL strSQL
答案 4 :(得分:1)
执行此操作的另一种方法似乎没有人提到过将图形绑定到单个保存的QueryDef,然后在运行时重写QueryDef。现在,我不建议为大多数上下文更改已保存的QueryDef,因为它会导致前端膨胀并且通常甚至不需要(大多数使用已保存的QueryDef的上下文可以在它们的上下文中以某种方式过滤例如,作为表单的Recordsource使用,你只需在DoCmd.OpenForm中传递一个参数。
图形不同,因为驱动图形的SQL不能在运行时更改。
有些人建议使用参数,但打开一个带有图表的表单,该表单使用带参数的SQL字符串将弹出默认参数对话框。避免这种情况的一种方法是使用对话框表单来收集条件,然后将对话框表单上控件的引用设置为参数,例如:
PARAMETERS [Forms]![MyForm]![ID] Long;
如果您正在使用表单引用,那么执行此操作至关重要,因为从Access 2002开始,Jet Expression Service并不总是在控件为空时正确处理这些。将它们定义为参数可以解决该问题(在Access XP之前不存在)。
如果您希望允许用户在TOP N SQL语句中选择N,那么必须重写图形的QueryDef的一种情况。换句话说,如果您希望它们能够选择TOP 5或TOP 10或TOP 20,则必须更改已保存的QueryDef,因为N无法参数化。
答案 5 :(得分:1)
“如果你想让用户在TOP N SQL语句中选择N”,那么你可以使用相关的子查询(而不是动态SQL),例如: (ANSI-92查询模式语法):
CREATE PROCEDURE GetOrdersTopN
(
:N INTEGER
)
AS
SELECT O1.OrderDate, O1.CustomerID
FROM Orders AS O1
WHERE :N >= (SELECT COUNT(*) + 1
FROM Orders AS O2
WHERE O1.OrderDate < O2.OrderDate);
...但是上次我检查Access引擎没有很好地优化(温和地说)这种构造。