2009-07-12 193 views
7

嘿,我只是学习如何把我的SQL语句放入VBA(或至少写出它们),但我不知道如何获取返回的数据?如何从Microsoft Access VBA中的SQL查询获取数据?

我有几个表格(图表形式)的基础上查询,我运行相当规则的参数对,只是改变时间表(像月前10点的销售情况)。然后我有程序自动将图表对象转换为PowerPoint演示文稿。因此,我已经预先建立了所有这些查询(如63),并且图表形式匹配(呃,是啊...... 63 ...我知道这很糟糕),然后所有这些事情都建立在“开放/关闭“事件触发下一个(它像我最好的尝试成为一个黑客....或多米诺骨牌;无论你喜欢)。

所以我试图学习如何在VBA中使用SQL语句,以便最终我可以在那里做所有这些(我可能仍然需要保留所有这些图表形式,但我不知道,因为我显然缺乏理解)。

所以,除了我在顶部问的问题,任何人都可以提供建议吗? 谢谢

+1

对不起,如果他们帮助它总是好了投票的好人谁帮助你了如下:) – Justin 2009-07-12 00:58:50

+0

@Justin。更安全的做不.EOF ... – 2009-07-12 07:16:48

回答

9

这是有点过时,所以你可能想要抓住book on the subject。但是,这里有大量的access resources和一些tutorials and examples。但是,基本上...

每评论:看看在recordset class。它包含一个名为Fields的集合,它是从查询中返回的列。不知道您的架构,这很难说,但像...

rs.MoveFirst 
Do While Not rs.EOF 
    'do something like rs("SomeFieldName") 
    rs.MoveNext 
Loop 

就像我说的,最好的办法就是抢在这个问题上一本书,他们有一大堆的例子。

+1

不是所有的游标类型将返回的RecordCount我总是忘了....我使用Microsoft Access 2000 – 2009-07-12 01:48:46

+0

感谢和感谢的网站! – Justin 2009-07-12 02:41:11

+0

代码示例是DAO,如果有记录,所有记录集类型返回的记录数至少为1,因此不需要检查EOF和BOF,因为检查RecordCount <> 0是否足够。如果你将你的代码移植到其他数据接口上,你的观点是相关的,但它在目前的代码示例中肯定是完全脱离基础的,这非常明显是DAO。 – 2009-07-12 20:18:27

1

尽管令人费解,但您的方式比尝试在VBA中构建SQL语句更容易。请记住,单独保存查询允许您以可视方式操作它们。此外,还有一些性能优势。

对SQL的更好的理解将帮助你巩固和简化你现有的查询(如果他们甚至需要简化,听起来他们正在做很多工作,所以你可能需要所有64个查询)。

这就是说,它是很容易在代码中执行SQL查询:

Dim strSQL as String 
strSQL = "UPDATE Table MyTable SET fieldname = 1 WHERE fieldname = 0;" 
DoCmd.RunSQL strSQL 
2

使用参数化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() 

因人而异...

2

这里,你可能会考虑重构采取功能在一个字符串中,你可以在代码中的任何地方重新使用。

所以有一个const或建立你的SQL语句的字符串,并在弹出SANITIZED,非SQL INJECTED字符串作为参数:)

strSQL = "SELECT * FROM Customer WHERE ID = " & EnsureParamIsNotSQLInjection(customerID) 

...然后调用函数/子从任何你需要得到一个记录集/数据/执行语句。考虑创建一些数据访问函数/子文件,您可以只运行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 
1

另一种方式来做到这一点似乎没有人提到是你的图形绑定到单个保存的QueryDef,然后在运行时,重写的QueryDef。现在,我不建议为大多数上下文更改已保存的QueryDef,因为它会导致前端膨胀并且通常甚至不是必需的(大多数使用已保存的QueryDef的上下文可以在某种情况下以某种方式或其他方式进行过滤被使用,例如,作为一个窗体的记录源,你只需在DoCmd.OpenForm中传递一个参数)。

图形不同,因为驱动图形的SQL在运行时不能被改变。

一些人建议参数,但打开一个图形,其上使用带参数的SQL字符串的图形将弹出默认参数对话框。避免的方法之一是使用对话的形式,收集的标准,然后设置对话框形式参数上的控制参考资料,如:

PARAMETERS [Forms]![MyForm]![ID] Long; 

如果您使用的形式引用,它是关键您可以这样做,因为从Access 2002开始,当控件为空时,Jet表达式服务并不总是正确地处理它们。将它们定义为参数可以解决该问题(在Access XP之前不存在)。

必须重写图表的QueryDef的一种情况是,如果您要允许用户在TOP N SQL语句中选择N。换句话说,如果您希望他们能够选择TOP 5或TOP 10或TOP 20,则必须更改保存的QueryDef,因为N无法被参数化。

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引擎不能很好地优化(说得客气一点),对于这种结构的。

相关问题