将DROP TABLE代码更改为APPEND / INSERT

时间:2014-03-21 12:00:54

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

此代码当前正在使用DROP TABLE将数据从Access传输到SQL Server,即用于一个人的时间。现在它将由多人使用,因此我需要将代码更改为APPEND。我试图弄清楚如何让它检查目标表以查看记录是否已经存在,如果它确实会跳过它,如果不是,它会将该员工数据写入表中。 SQL表是预构建的,它有一个ROW ID列和TIME STAMP列,访问表没有该列,以便跟踪输入的记录。

目前的代码如下:

Public Function Update()
Dim cdb As DAO.Database, qdf As DAO.QueryDef
Dim err As DAO.Error
Const DestinationTableName = "AC_CDData"
Const ConnectionString = _
    "ODBC;" & _
        "Driver={SQL Server Native Client 10.0};" & _
        "Server=SERVER;" & _
        "Database=DB;" & _
        "UID=ID;" & _
        "PWD=PW;"
Set cdb = CurrentDb
Set qdf = cdb.CreateQueryDef("")
qdf.Connect = ConnectionString
qdf.SQL = _
    "IF EXISTS " & _
        "(" & _
            "SELECT * FROM INFORMATION_SCHEMA.TABLES " & _
            "WHERE TABLE_NAME='" & DestinationTableName & " '" & _
        ") " & _
    "DROP TABLE [" & DestinationTableName & "]"
qdf.ReturnsRecords = False
On Error GoTo Update_qdfError
qdf.Execute dbFailOnError
On Error GoTo 0
Set qdf = Nothing
Set cdb = Nothing
DoCmd.TransferDatabase _
    acExport, _
    "ODBC Database", _
    ConnectionString, _
    acTable, _
    "CDData", _
    DestinationTableName, _
    False
Exit Function

Update_qdfError:
For Each err In DAO.Errors
MsgBox err.Description, vbCritical, "Error " & err.Number
Next
End Function

3 个答案:

答案 0 :(得分:2)

DoCmd.TransferDatabase将数据从Access表完全传输到SQL Server数据库。此功能无法根据现有记录进行部分插入。

然而,您可以做的是将数据导出到临时新表中(不删除现有表),然后执行SQL MERGE语句,以合并临时表的新记录,现有的表格。

您需要知道如何从VBA对SQL数据库执行SQL查询,并且您需要知道如何使用SQL MERGE语句。谷歌搜索将很快为您提供答案。

答案 1 :(得分:0)

只需在Access中为SQL服务器设置一个简单的标准链接表。

由于现有记录的列是主键(或者只是索引集=唯一),因此您只需要一行代码来附加数据。

这将有效:

CurrentDb.Execute "INSERT INTO AC_CDData SELECT * FROM CDData;"

由于密钥(或索引)违规,任何已存在的行都将被忽略。因此,只有新的非现有记录将附加上面一行代码。

编辑: 目标表是SQL链接表吗?您启动时的应用程序并不关心您是否有一些链接表。除非您使用它们,否则您的应用程序不会使用也不关心此类链接表。

这里假设你有一个本地数据表。链接表仅在您要进行导出时发挥作用。如上所述,除非连接到SQL服务器,否则无法导出。在这个问题中没有处理“代码”或测试你是否已连接,但即使它是问题的一部分,在这两种情况下你仍然需要测试连接,当你最终确定你有连接时再次你决定再次导出链接表,如上所述。

所以我真的没有理由想到为什么只有在附加到SQL表期间使用的链接表才会出现任何问题或问题。

如上所述,那么一行VBA代码就足够了。

答案 2 :(得分:0)

如果同时使用,则需要更改该过程:

  1. DestinationTableName每个会话(线程)必须是唯一的,需要更改(从常量变为变量)

  2. 需要在导出数据之前删除需要DestinationTableName neame的表格(就像在当前解决方案中一样)。

  3. DoCmd.TransferDatabase不会更改 - 数据将导出到唯一的临时表中。

  4. 为简化Merge进程,可以在源表名作为参数的SQL Server端(所有需要APSERT逻辑)上编写存储过程。需要在DoCmd.TransferDatabase完成

  5. 之后调用此SP

    在这种情况下,流程如下:

    • DestinationTableName唯一名称生成
    • 在SQL Server端(qdf.Execute ...
    • 上删除此表
    • 将数据导出到临时表(DoCmd.TransferDatabase ...
    • 合并SQL Server端的数据(使用所需的更新/插入逻辑调用创建的SP)