如何使用 SQL 改进我的经典 VBA 编码?我把循环搞得一团糟

发布于 2024-12-18 18:11:56 字数 808 浏览 2 评论 0原文

嗯...我是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 个条目 - 每次我需要查询与一天需要一段时间 - 毕竟,我要求它在整个数据库中执行循环。

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

我可以用“做而不做”代替SQL 查询?就像

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

在这个查询的结果上运行代码?它会比我当前的代码更快吗?即使它没有更快 - 它会更慢吗?因为编写单个选择参数似乎比处理 While-Loop 情况容易得多......

Well... I am a n00b, I know that. And this is pretty straight foward.

Basically this is the code I've been writing.

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

I recently made a question about SQL and it seems that it does have a lot of solutions to my problems... you see, my current database has around +15000 entries - and everytime I need to do a query about all the entries related to a single day it takes a while - after all, I'm asking it to do a LOOP across the entire database.

Now, It has come to my attention that I might be a little dumb to be doing so - well, that was the only way I could figure out to do it - my main question is:

Can I substitute that 'do while not' for a SQL query? Like

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

And on the results of this query, run the code? Would it be faster than my current code? Even if it's not faster - is it slower? Cause it seems much easier to write that single select argument than having to deal with the While-Loop situation...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

街角卖回忆 2024-12-25 18:11:57

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

假设您 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 值。

The aim should be to remove the looping entirely.

Say you INSERTFUNCTIONHERE increments the column data_col by 1: instead of:

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

Instead, re-write the entire operation in SQL e.g.

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

Then in VBA, use a Command object to execute the proc, using a Parameter object to pass in the fromdate value.

没有心的人 2024-12-25 18:11:57

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

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 之前清理它。

Yes, you can get the filtering done on the database side. You would pass the query you specified in when you open the recordset. Something like this:

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

EDIT:
When using the Database.OpenRecordset() method use this syntax instead of the above:

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

It would potentially be faster than what you are currently using, depending on how many records match the filter.

A WORD OF CAUTION:
The example I provide can be prone to SQL Injection attacks if you modify the query to be created dynamically based on some kind of input. ALWAYS make sure you're cleansing your SQL before running it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文