在表定义和删除中循环。一种方法有效,另一种无效。为什么?

时间:2018-10-08 20:54:34

标签: sql excel vba excel-vba ms-access

我有一个子例程,可以处理数据库的本地副本和网络存储的主副本(该副本始终是最新的,并且数据是实时处理的)。为了允许用户脱机运行我的excel加载项,我创建了一个本地“副本”,该表具有与主副本相同的表名,但只包含相关字段。我第一次编写时,子程序未按预期工作。它似乎正常工作(没有给出任何错误),但是当我查看本地数据库以确保确实删除并重新创建了表时,仅删除了4个表中的2个。我开发了一种变通方法,但是我想知道是否遗漏了一些东西或做错了什么,或者这仅仅是通过DAO使用访问数据库的怪癖

第一个Sub(无法正常工作,只会删除2个表而不是全部4个表):

Sub gUpdateDBTables()
    Dim DBPath As String
    Dim sSQL_Table1 As String
    Dim sSQL_Table2 As String
    Dim sSQL_Table3 As String
    Dim sSQL_Table4 As String
    Dim DB As DAO.Database
    Dim DB2 As DAO.Database
    Dim tblDef As DAO.TableDef
        'Get DB File Locations From Registry
        LocalDBPath = Interaction.GetSetting("Tools", "Settings\FileInfo", "Local_DB_Location")
        DBPath = Interaction.GetSetting("Tools", "Settings\FileInfo", "DB_Location")
        'Set SQL statements
        sSQL_Table1 = "SELECT Table1.Field1, Table1.Field2, Table1.Field3, Table1.Field4, Table1.Field INTO Table1 IN '" & LocalDBPath & "' FROM Table1 WHERE (((Table1.Field1)='1') AND ((Table1.Field4)='A' Or (Table1.Field4)='T')) OR (((Table1.Field1)='1' Or (Table1.Field1)='20'));"
        sSQL_Table2 = "SELECT Table2.Field1, Table2.Field2, Table2.Field3, Table2.Field4, Table2.Field5, Table2.Field6, Table2.Field7, Table2.Field8 INTO Table2 IN '" & LocalDBPath & "' FROM Table2 WHERE (((Table2.Field4)=99999) AND ((Table2.Field6)='1' Or (Table2.Field6)='20'));"
        sSQL_Table3 = "SELECT Table3.Field1, Table3.Field2, Table3.Field3, Table3.Field4, Table3.Field5, Table3.Field6, Table3.Field7, Table3.Field8, Table3.Field9, Table3.Field10, Table3.Field11, Table3.Field12 INTO Table3 IN '" & LocalDBPath & "' FROM Table3 WHERE (((Table3.Field1)='1' Or (Table3.Field1)='20') AND ((Table3.Field12)=0 Or (Table3.Field12)=99999));"
        sSQL_Table4 = "SELECT Table4.Field1, Table4.Field2, Table4.Field3, Table4.Field4, Table4.Field5, Table4.Field6, Table4.Field7, Table4.Field8 INTO Table4 IN '" & LocalDBPath & "' FROM Table4 WHERE (((Table4.Field8)='1' Or (Table4.Field8)='20'));"
        'Open Local DB and Cycle Through Table Definitions and Delete as Needed
        Set DB = OpenDatabase(LocalDBPath, False, False)
        For Each tblDef In DB.TableDefs
            Select Case tblDef.Name
                Case "Table1`"
                    DB.TableDefs.Delete ("Table1")
                Case "Table2"
                    DB.TableDefs.Delete ("Table2")
                Case "Table3"
                    DB.TableDefs.Delete ("Table3")
                Case "Table4"
                    DB.TableDefs.Delete ("Table4")
            End Select
        Next tblDef
        DB.Close
        'Open Networked Database and Process SQL Statements To Refresh Table Data in Local DB File
        Set DB2 = OpenDatabase(DBPath, True, False)
        With DB2
            .Execute sSQL_Table1
            .Execute sSQL_Table2
            .Execute sSQL_Table3
            .Execute sSQL_Table4
        End With
        DB2.Close
        Set DB = Nothing
        Set DB2 = Nothing
End Sub

第二个次级(解决方法):

Sub gUpdateDBTables()
    Dim DBPath As String
    Dim sSQL_Table1 As String
    Dim sSQL_Table2 As String
    Dim sSQL_Table3 As String
    Dim sSQL_Table4 As String
    Dim delTbl1 As Boolean
    Dim delTbl2 As Boolean
    Dim delTbl3 As Boolean
    Dim delTbl4 As Boolean
    Dim DB As DAO.Database
    Dim DB2 As DAO.Database
    Dim tblDef As DAO.TableDef
        'Get DB File Locations From Registry
        LocalDBPath = Interaction.GetSetting("Tools", "Settings\FileInfo", "Local_DB_Location")
        DBPath = Interaction.GetSetting("Tools", "Settings\FileInfo", "DB_Location")
        'Set SQL statements
        sSQL_Table1 = "SELECT Table1.Field1, Table1.Field2, Table1.Field3, Table1.Field4, Table1.Field INTO Table1 IN '" & LocalDBPath & "' FROM Table1 WHERE (((Table1.Field1)='1') AND ((Table1.Field4)='A' Or (Table1.Field4)='T')) OR (((Table1.Field1)='1' Or (Table1.Field1)='20'));"
        sSQL_Table2 = "SELECT Table2.Field1, Table2.Field2, Table2.Field3, Table2.Field4, Table2.Field5, Table2.Field6, Table2.Field7, Table2.Field8 INTO Table2 IN '" & LocalDBPath & "' FROM Table2 WHERE (((Table2.Field4)=99999) AND ((Table2.Field6)='1' Or (Table2.Field6)='20'));"
        sSQL_Table3 = "SELECT Table3.Field1, Table3.Field2, Table3.Field3, Table3.Field4, Table3.Field5, Table3.Field6, Table3.Field7, Table3.Field8, Table3.Field9, Table3.Field10, Table3.Field11, Table3.Field12 INTO Table3 IN '" & LocalDBPath & "' FROM Table3 WHERE (((Table3.Field1)='1' Or (Table3.Field1)='20') AND ((Table3.Field12)=0 Or (Table3.Field12)=99999));"
        sSQL_Table4 = "SELECT Table4.Field1, Table4.Field2, Table4.Field3, Table4.Field4, Table4.Field5, Table4.Field6, Table4.Field7, Table4.Field8 INTO Table4 IN '" & LocalDBPath & "' FROM Table4 WHERE (((Table4.Field8)='1' Or (Table4.Field8)='20'));"
        'Open Local DB and Cycle Through Table Definitions and Delete as Needed
        Set DB = OpenDatabase(LocalDBPath, False, False)
        For Each tblDef In DB.TableDefs
            If tblDef.Name = "Table1" Then delTbl1 = True
            If tblDef.Name = "Table2" Then delTbl2 = True
            If tblDef.Name = "Table3" Then delTbl3 = True
            If tblDef.Name = "Table4" Then delTbl4 = True
        Next tblDef
        If delTbl1 = True Then DB.TableDefs.Delete ("Table1")
        If delTbl2 = True Then DB.TableDefs.Delete ("Table2")
        If delTbl3 = True Then DB.TableDefs.Delete ("Table3")
        If delTbl4 = True Then DB.TableDefs.Delete ("Table4")
        DB.Close
        'Open Networked Database and Process SQL Statements To Refresh Table Data in Local DB File
        Set DB2 = OpenDatabase(DBPath, True, False)
        With DB2
            .Execute sSQL_Table1
            .Execute sSQL_Table2
            .Execute sSQL_Table3
            .Execute sSQL_Table4
        End With
        DB2.Close
        Set DB = Nothing
        Set DB2 = Nothing
End Sub

1 个答案:

答案 0 :(得分:1)

当您遍历一个集合并删除/添加项目时,通常会得到奇怪的结果。您的第二种方法避免了这种情况,因为会在数值上循环回退整个集合,例如

For x = DB.TableDefs.Count to 1 Step -1
    'Check DB.TableDefs(x)
Next x

或者只是尝试删除每个定义并忽略任何错误:

Dim arrTD, td
arrTD = Array("Table1","Table2","Table3","Table4")
For Each td in arrTD
    On Error Resume Next
    DB.TableDefs.Delete td
    On Error Goto 0
Next td