VBA等待DoCmd.RunSQL或更好的查询-Ms访问

VBA等待DoCmd.RunSQL或更好的查询-Ms访问,sql,ms-access,vba,Sql,Ms Access,Vba,我有一个查询,它使用一个表数组(存储为字符串数组)循环遍历我的表并执行一组删除/更新查询。查询与表名不同,因此使用循环将表名作为变量进行迭代 问题是,我的删除查询锁定了表,更新查询随后运行得太快;我收到一个“db已锁定”错误 我需要两件事中的任何一件: 告诉VBA“等待上一个命令”或 将这些查询连接成一个(或两个)查询的方法:一个用于删除数据库行,另一个用于导入新的行。有了这个,我就可以从一个标准的访问查询运行查询(应该分配适当的时间,完成查询等) 唯一的问题是存在父子关系,因此父表必须在其子表

我有一个查询,它使用一个表数组(存储为字符串数组)循环遍历我的表并执行一组删除/更新查询。查询与表名不同,因此使用循环将表名作为变量进行迭代

问题是,我的删除查询锁定了表,更新查询随后运行得太快;我收到一个“db已锁定”错误

我需要两件事中的任何一件:

  • 告诉VBA“等待上一个命令”或
  • 将这些查询连接成一个(或两个)查询的方法:一个用于删除数据库行,另一个用于导入新的行。有了这个,我就可以从一个标准的访问查询运行查询(应该分配适当的时间,完成查询等)
  • 唯一的问题是存在父子关系,因此父表必须在其子表之前更新(目前通过数组排序完成)

    以下是(有时)生成“DB locked/in use”消息的当前代码:

    应该澄清:查询从相同的表中获取一个后端的(
    fromDB
    )行,并将其推送到另一个后端的(
    toDB
    )行


    编辑:对于有关插入到中的
    的问题,我的问题是如果我在
    toDB
    中添加字段,如果我覆盖,它将删除这些字段。我之所以必须使用这种后门方法,是因为数据库仍在开发中,但也在与select表一起使用。每天都会进行更新和功能改进。我也不能使用简单的拆分后端,因为访问数据库的另一台计算机并不总是在网络上(当它返回网络时,我们必须手动同步它),所以我在一个后端上工作,它在另一个相同的(ish,减去我的模式更新)后端上工作。

    我不是专家,但我认为您不需要删除部分。SELECT INTO是制作表格的语法。如果该表已经存在,它将被覆盖。

    您可以使用ADO而不是DoCmd.RunSQL来同步执行SQL

     Dim cmd As ADODB.Command
     Dim cnn As New ADODB.Connection
    
     Set cnn = CurrentProject.Connection
    
     For i = 0 To UBound(tables)
         Set cmd = New ADODB.Command
         With cmd
    
            .CommandType = adCmdText
             .ActiveConnection = cnn
            .CommandText = "DELETE * FROM " & tables(i)
            .Execute
          End With
    
         Set cmd = New ADODB.Command
         With cmd
    
            .CommandType = adCmdText
             .ActiveConnection = cnn
            .CommandText = "INSERT INTO " & tables(i) & " IN """ & toDB & """ SELECT " & tables(i) & " .* FROM " & tables(i) & " IN """ & fromDB & """;"
            .Execute
          End With
    
    Next
    

    您还可以添加
    cnn.beginters
    cnn.CommitTrans
    以使这两个语句原子化。

    如果需要等待,我倾向于使用
    DoEvents
    来允许windows处理已暂停的任何其他操作。
    来自帮助:“生成执行,以便操作系统可以处理其他事件。”

    找到此:
    .begints
    然后
    .CommitTrans dbForceOSFlush

    作为一种在继续之前强制写入更新的方法,请尝试这样做(注意,我已经对您的
    DoCmd.RunSQL
    进行了注释。我使用
    db.Execute
    对其进行了更改:

    Sub DeleteInsertData(tables() As String, toDB As String, fromDB As String)
    
        Dim db As DAO.Database
        Dim i As Integer
        Dim SQL As String
        
        Set db = CurrentDb()
        For i = 0 To UBound(tables)
            'Delete all data first
            SQL = "DELETE * FROM " & tables(i)
            db.Execute SQL, dbFailOnError
            'DoCmd.RunSQL SQL
            'Update all data second
            SQL = "INSERT INTO " & tables(i) & " IN """ & toDB & """ SELECT " & tables(i) & " .* FROM " & tables(i) & " IN """ & fromDB & """;"
            db.Execute SQL, dbFailOnError
            'DoCmd.RunSQL SQL
        Next
        Set db = Nothing
    End Sub
    

    您应该使用
    CurrentDb.Execute sSQL,dbFailOnError
    而不是
    DoCmd.RunSQL
    .Works,我认为这是更好的做法,但我仍然会遇到相同的错误。也许我必须添加一个“wait-until\uuuuuuuuuuu未锁定”改为某种语句?可能是一个新手问题,但VBA无法识别ADODB对象。是否需要在某个位置设置允许此对象?您需要添加对“Microsoft ActiveX数据对象”的引用使用工具->引用。但是您可以考虑尝试<代码> CurrutDB。执行< /COD>作为HK1通配符:基本上说<代码>美国有线电视新闻网< /代码>在您的上面不是有效的OLE DB会话对象。对不起,检查我的编辑应该是“代码> SETVALID= CurrnEngest.CONTION/CODE”。我想是这样的。您的编辑可能是一个PROB。lem,但给出的错误不是问题(我最后的评论)。我认为这与引用有关,因为代码生成器没有将ADODB识别为命令;自动完成上下文菜单没有显示。我添加了引用,重新启动了Access,它发现了.command、.CommandType等。尝试了您的编辑,现在一切正常;无法使用此命令复制我的原始错误方法。似乎很好!即使在使用DoEvents时也会发生相同的错误。是否有原因导致后端被锁定的时间比需要的时间稍长?当然,根据此处建议的所有更改,查询正在完全运行。为什么后端保持锁定?似乎需要刷新缓冲区-我已将信息添加到我的答案中
    Sub DeleteInsertData(tables() As String, toDB As String, fromDB As String)
    
        Dim db As DAO.Database
        Dim i As Integer
        Dim SQL As String
        
        Set db = CurrentDb()
        For i = 0 To UBound(tables)
            'Delete all data first
            SQL = "DELETE * FROM " & tables(i)
            db.Execute SQL, dbFailOnError
            'DoCmd.RunSQL SQL
            'Update all data second
            SQL = "INSERT INTO " & tables(i) & " IN """ & toDB & """ SELECT " & tables(i) & " .* FROM " & tables(i) & " IN """ & fromDB & """;"
            db.Execute SQL, dbFailOnError
            'DoCmd.RunSQL SQL
        Next
        Set db = Nothing
    End Sub