如何编写SQL命令将所有旧数据从访问表移动到另一个数据库/表?

时间:2014-11-16 11:02:22

标签: database vba ms-access ms-access-2003

我在MS Access 2003中有一个表,我想在其中存档所有旧数据。

标准是创建数据应小于特定日期。

我可以编写一个SQL语句来选择它们,但我不知道如何将它们移动到另一个数据库/表中?假设已经创建了存档数据库/表,并且数据结构与当前表匹配。

另外,我如何确保从当前表中删除所有移动到存档表的数据?

我想编写VBA代码来运行命令检查数据是否正确存档。

2 个答案:

答案 0 :(得分:1)

没有MOVE命令,但您可以将记录复制到目标,然后在确定没有粘贴错误时使用类似的查询将其从源中删除

INSERT INTO MyArchive (fld1, fld2, fld3, fld4) SELECT fld1, fld2, fld3, fld4 FROM MyTable WHERE fld4 < DATEADD("y", -5, Date())

复制超过5年的所有内容。确认转移后,

DELETE * FROM MyTable WHERE fld4 < DATEADD("y", -5, Date())

这是我的头脑,我在T-SQL和MS Access之间转换了一点点,但我认为这是非常可靠的Access查询代码。您自己的字段列表会相应变化。

答案 1 :(得分:1)

您希望1)将符合特定条件的数据从一个表移动到另一个表,具有相同格式的现有表。 2)您希望“确保从当前表中删除所有移动到存档表的数据”。 3)你“想编写VBA代码来运行命令检查数据是否正确存档。”

与流行的观点相反,Access确实支持transactions(声称Access SQL不支持事务是正确的,但我们仍然可以在VBA代码中使用事务)。因此,修改this post中的代码以在工作空间中使用事务,我相信这样做(使用DAO在Access 2010中测试)。

锁定,获取计数和解锁的代码并不是必需的,并且可能会增加实现存档的难度,因为它会要求在您更新表时没有人写入表。如果它确实发现问题,Access会支持事务日志记录,因此您将有一个非常短的选项列表来确定如何解决它。但听起来你想要绝对确定计数是正确的,所以这增加了另一个级别,可以说是不必要的。检查。

Option Compare Database
Option Explicit

Sub ArchiveOldRecords()

Dim nSourceCount As Long, nMoveCount As Long, nDestCount As Long
Dim strSQL As String, sMsg As String
Dim rsLock As DAO.Recordset
Dim rsBefore As DAO.Recordset, rsAfter As DAO.Recordset
Dim wrk As Workspace, db As DAO.Database

Const strcTableSource As String = "t_TestWithDate"  ' Move records FROM table
Const strcTableArch As String = "t_ArchiveTestWithDate" ' Move records TO table
Const strcWHERE As String = " WHERE field2 < " _
    & "DATEADD(""yyyy"", -1, Date())"   ' Select date field and DATEADD params
Const strcCount As String = "SELECT COUNT(*) As "

On Error GoTo TrapError
    Set db = CurrentDb
    Set wrk = DBEngine.Workspaces(0)
' Lock table - so no one can add/delete records until count is verified
    Set rsLock = db.OpenRecordset(strcTableSource, dbOpenTable, dbDenyWrite)
' Get initial table counts
    Set rsBefore = db.OpenRecordset( _
        strcCount & "SourceCount, " _
        & "(SELECT COUNT(*) FROM " & strcTableSource _
            & strcWHERE & ") As MoveCount, " _
        & "(SELECT COUNT(*) FROM " & strcTableArch & ") As DestCount " _
        & "FROM " & strcTableSource & ";", dbOpenForwardOnly)
    nSourceCount = rsBefore!SourceCount
    nMoveCount = rsBefore!MoveCount
    nDestCount = rsBefore!DestCount
    rsBefore.Close

    wrk.BeginTrans
    ' Copy records
        strSQL = "INSERT INTO " & strcTableArch _
            & " SELECT * FROM " & strcTableSource & " " & strcWHERE & ";"
        db.Execute strSQL, dbFailOnError
    ' Unlock table - only needed for counts
        rsLock.Close
        Set rsLock = Nothing
    ' Delete copied records
        strSQL = "DELETE * FROM " & strcTableSource & " " & strcWHERE & ";"
        db.Execute strSQL, dbDenyWrite + dbFailOnError
    ' Lock table - only needed for counts
        Set rsLock = db.OpenRecordset(strcTableSource, dbOpenTable, dbDenyWrite)
    wrk.CommitTrans

    ' Get final table counts
    Set rsAfter = db.OpenRecordset( _
        strcCount & "SourceCount, " _
        & "(SELECT COUNT(*) FROM " & strcTableSource _
            & strcWHERE & ") As MoveCount, " _
        & "(SELECT COUNT(*) FROM " & strcTableArch & ") As DestCount " _
        & "FROM " & strcTableSource & ";", dbOpenForwardOnly)

    ' Double-check counts
    If (rsAfter!SourceCount <> nSourceCount - nMoveCount) _
        Or (rsAfter!DestCount <> nDestCount + nMoveCount) _
        Or (rsAfter!MoveCount > 0) Then
        sMsg = vbNewLine
        sMsg = sMsg & "Records in " & strcTableSource & " before:            "
        sMsg = sMsg & nSourceCount
        sMsg = sMsg & vbTab & "after: "
        sMsg = sMsg & rsAfter!SourceCount
        sMsg = sMsg & vbNewLine
        sMsg = sMsg & "Records to archive from " & strcTableSource & ": "
        sMsg = sMsg & nMoveCount
        sMsg = sMsg & vbTab & "after: "
        sMsg = sMsg & rsAfter!MoveCount
        sMsg = sMsg & vbNewLine
        sMsg = sMsg & "Records in " & strcTableArch & " before:       "
        sMsg = sMsg & nDestCount
        sMsg = sMsg & vbTab & "after: "
        sMsg = sMsg & rsAfter!DestCount
        MsgBox "Count double-check failed" & sMsg
    End If

Exit_Sub:
    On Error Resume Next
    ' Unlock table and close recordsets
    rsLock.Close
    rsBefore.Close
    rsAfter.Close
    Set rsBefore = Nothing
    Set rsAfter = Nothing
    Set rsLock = Nothing
    Set db = Nothing
    Set wrk = Nothing
    Exit Sub

TrapError:
    MsgBox "Failed: " & Err.Description
    wrk.Rollback
    Err.Clear
    Resume Exit_Sub

End Sub