【问题标题】:How can I improve my Classic VBA coding using SQL? I'm making a mess with loops如何使用 SQL 改进我的 Classic VBA 编码?我把循环弄得一团糟
【发布时间】:2011-11-29 18:06:41
【问题描述】:

嗯...我是一个n00b,我知道。这是非常直接的。

基本上这是我一直在写的代码。

rstSwift.MoveFirst
Do While Not rstSwift.EOF
    If Left(rstSwift!Date, 2) & Mid(rstSwift!Date, 4, 2) & Right(rstSwift!Date, 4) = fromdate Then
        INSERTFUNCTIONHERE
    Else
    End If
    rstSwift.MoveNext
Loop

我最近提出了一个关于 SQL 的问题,似乎它确实为我的问题提供了很多解决方案......你看,我当前的数据库大约有 +15000 个条目 - 每次我需要查询所有的与一天相关的条目需要一段时间 - 毕竟,我要求它在整个数据库中执行循环。

现在,我注意到这样做可能有点愚蠢 - 嗯,这是我能想到的唯一方法 - 我的主要问题是:

我可以用“do while not”代替 SQL 查询吗?喜欢

NEWTABLEVARIABLE = SELECT * from rstSwift WHERE rstSwift.Date = '20/11/2011';
NEWTABLEVARIABLE.MoveFirst
Do While Not NEWTABLEVARIABLE.EOF
INSERTFUNCTIONHERE
NEWTABLEVARIABLE.MoveNext
Loop

然后根据这个查询的结果,运行代码?它会比我当前的代码更快吗?即使它不是更快 - 它是否更慢?因为编写单个选择参数似乎比处理 While-Loop 情况要容易得多......

【问题讨论】:

    标签: sql vba ms-access while-loop vb5


    【解决方案1】:

    目标应该是完全消除循环。

    假设你 INSERTFUNCTIONHERE 将列 data_col 增加 1:而不是:

    rstSwift.MoveFirst
    Do While Not rstSwift.EOF
        If Left(rstSwift!swift_date, 2) & _
              Mid(rstSwift!swift_date, 4, 2) & _
              Right(rstSwift!swift_date, 4) = fromdate Then
            rstSwift!data_col = rstSwift!data_col + 1
            rstSwift.Update
        End If
        rstSwift.MoveNext
    Loop
    

    相反,用 SQL 重写整个操作,例如

    CREATE PROCEDURE IncrementSwifts
    (
     :fromdate DATETIME
    )
    AS
    UPDATE Swifts
       SET data_col = data_col + 1
     WHERE swift_date = :fromdate;
    

    然后在VBA中,使用Command对象执行proc,使用Parameter对象传入fromdate值。

    【讨论】:

    • +1 基于 Viva 集的操作。这绝对比循环好得多。我的 Access fu 很弱,甚至不知道它有 procs。
    【解决方案2】:

    是的,您可以在数据库端完成过滤。当您打开记录集时,您将传递您指定的查询。像这样的:

    set rstSwift = connMyDbConnection.Execute("SELECT * from rstSwift WHERE rstSwift.Date = #20/11/2011#")
    Do While Not rstSwift.EOF
       INSERTFUNCTIONHERE
       rstSwift.MoveNext
    Loop
    

    编辑:
    使用 Database.OpenRecordset() 方法时,请使用此语法而不是上述语法:

    set rstSwift = mdb.OpenRecordset("SELECT * from rstSwift WHERE rstSwift.Date = #20/11/2011#")
    Do While Not rstSwift.EOF
       INSERTFUNCTIONHERE
       rstSwift.MoveNext
    Loop
    

    它可能会比您当前使用的更快,具体取决于有多少记录与过滤器匹配。

    注意事项:
    如果您修改要根据某种输入动态创建的查询,我提供的示例可能容易受到 SQL 注入攻击。始终确保在运行 SQL 之前对其进行清理。

    【讨论】:

    • SQL 注入?就像这里描述的一样:en.wikipedia.org/wiki/SQL_injection?
    • #失败!我正在使用 MS Access 95 - connMyDbConnection 命令不起作用 =(
    • 对不起,习惯的力量(我是 SQL Server 人)。修复了 SELECT 以对 Access 使用格式正确的日期过滤器。我假设那是错误。如果它仍然不起作用,您可以发布错误吗?
    • 它为表达式“connMyDbConnection”提供了一个“未定义变量”
    • 好吧,您需要使用您已经在代码中使用的连接变量。您必须在某处建立连接(ADODB.CONNECTION 对象)。我的例子中的一个就是这样。它向您展示了您需要在连接对象上调用 Execute() 方法。在您的代码中的某处,您会出现set [somevariablename] = CreateObject("ADODB.CONNECTION") 之类的行。 [somevariablename] 是您要替换 connMyDbConnection 的内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-06
    • 2017-02-25
    • 1970-01-01
    • 2021-10-10
    • 1970-01-01
    • 1970-01-01
    • 2010-10-26
    相关资源
    最近更新 更多