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

时间:2012-06-07 13:26:36

标签: sql ms-access vba

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

问题是,我的Delete查询锁定了表,之后Update查询运行得太快;我收到“db is locked”错误。

我需要两件事之一:

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

    这是当前代码(有时)产生“DB locked / in use”消息:

    For i = 0 To UBound(tables)
        'Delete all data first
        sql = "DELETE * FROM " & tables(i)
        DoCmd.RunSQL sql
        'Update all data second
        sql = "INSERT INTO " & tables(i) & " IN """ & toDB & """ SELECT " & tables(i) & " .* FROM " & tables(i) & " IN """ & fromDB & """;"
        DoCmd.RunSQL sql
    Next
    

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

    编辑:在回答有关INSERT INTO的问题时,我的问题是如果我向toDB添加字段,如果我覆盖它将删除它们。我必须做这个后门方法的原因是因为数据库仍处于开发阶段,但也与select表一起使用。每天都会进行更新和功能改进。我也不能使用简单的split-backend,因为访问数据库的其他计算机并不总是在网络上(我们必须在它返回到网络时手动同步它),所以我在一个后端工作,它适用于另一个,相同(ish,减去我的架构更新)后端。

4 个答案:

答案 0 :(得分:2)

您可以使用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.BeginTranscnn.CommitTrans来制作两个语句Atomic。

答案 1 :(得分:1)

尝试这样的操作(注意我已经评论了您的 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

答案 2 :(得分:0)

我不是专家,但我认为你不需要DELETE部分。 SELECT INTO是制作表格的语法。如果表已经存在,则会被覆盖。

答案 3 :(得分:0)

如果我需要等待某事,我倾向于使用DoEvents来允许窗口处理任何其他已被搁置的操作。
从帮助:“产生执行,以便操作系统可以处理其他事件。”

发现这个:
.BeginTrans然后 .CommitTrans dbForceOSFlush
作为在继续

之前强制更新的方法