如果存在,则更新,否则插入新记录

时间:2010-06-07 18:53:56

标签: sql ms-access vba

我正在将值插入表格

如果记录存在已经替换它,如果它不存在则添加一个新记录。

到目前为止,我有这段代码:

INSERT INTO table_name
VALUES (value1, value2, value3,...) where pk="some_id";

但我需要这样的东西

if not pk="some_id" exists then  INSERT INTO table_name
    VALUES (value1, value2, value3,...) where pk="some_id"; else update table_name where pk="some_id"

这是什么样的SQL语法?

请注意我正在使用sql访问,我猜它可以是vba和sql的组合

3 个答案:

答案 0 :(得分:2)

首先更新导入表和主表之间匹配的行。

UPDATE table_name AS m
    INNER JOIN tblImport AS i
    ON m.pk = i.pk
SET
    m.field2 = i.field2,
    m.field3 = i.field3,
    m.field4 = i.field4;

然后添加主表中不存在的任何导入记录。

INSERT INTO table_name (
    pk,
    field2,
    field3,
    field4)
SELECT
    i.pk,
    i.field2,
    i.field3,
    i.field4
FROM
    tblImport AS i
    LEFT JOIN table_name AS m
    ON i.pk = m.pk
WHERE
    (((m.pk) Is Null));

答案 1 :(得分:1)

这可以通过记录集轻松完成。然后代码看起来像(对于ADODB记录集):

myRecordset.find ....
if myRecordset.EOF then
    myRecordset.addNew
endif
....
myRecordset.fields(...) = ...
....
myRecordset.update

答案 2 :(得分:0)

我已经在许多不同的论坛上发布了很多次这个问题的方法,但我只是概括了我使用的方法的基本结构。但是,没有办法一步到位。

  1. 从外部数据源更新现有记录。

  2. 插入尚不存在的记录。

  3. 这假设一个公共主键,可用于将现有表与外部数据源链接。

    任务#2非常简单,只是一个尚未存在的记录的外部联接。

    可以对#1使用暴力,为主键以外的每个字段用SET写UPDATE语句,但我认为这是杂乱无用的。此外,由于我有很多复制的应用程序,我不能这样做,因为它会导致错误的冲突(当一个字段更新为与它开始时相同的值)。

    因此,为此目的,我使用DAO并编写一个动态SQL语句来更新COLUMN-BY-COLUMN。基本结构是这样的:

      Dim db As DAO.Database
      Dim rs As DAO.Recordset
      Dim fld As DAO.Field
      Dim strField As String
      Dim strSet As String
      Dim strWhere As String
      Dim strSQL As String
    
      Set db = CurrentDB
      Set rs = db.OpenRecordset("DestinationTable")
      For Each fld in rs.Fields
        strField = fld.Name
        If strField <> "PKField" Then
           strSet = "DestinationTable." & strField & " = ExternalTable." & strField
           strWhere = "Nz(DestinationTable." & strField & ",'') = Nz(ExternalTable." & strField & ", '')"
           strSQL = "UPDATE DestinationTable "
           strSQL = strSQL & " SET " & strSet
           strSQL = strSQL & " WHERE " & strWhere
           db.Execute strSQL, dbFailOnError
           Debug.Print strField & ": " & db.RecordsAffected
        End If
      Next fld
    

    现在,复杂的部分是处理数字与日期与字符串字段,因此您必须有一些逻辑来根据字段类型编写WHERE子句以使用正确的引号和其他分隔符。我通常只使用这样的CASE SELECT,而不是测试字段类型,使字符串字段成为默认值:

      Dim strValueIfNull As String
      Select Case strField
        Case "DateField1", "DateField2", "NumericField2", "NumericField2", "NumericField3"
          strValueIfNull = "0"
        Case Else
          strValueIfNull = "''"
          strWhere = "Nz(DestinationTable." & strField & ", '') = Nz(ExternalTable." & strField & ", '')"
      End Select
      strWhere = "Nz(DestinationTable." & strField & ", " & strValueIfNull & ") = Nz(ExternalTable." & strField & ", " & strValueIfNull & ")"
    

    我可能有错误的细节,但我认为你明白了。

    这意味着您将只运行与可更新字段一样多的SQL更新,并且您只会更新需要更新的记录。如果您还使用“上次更新”日期标记记录,则可以在UPDATE SQL中执行此操作,并且您只想对实际具有不同值的记录执行此操作。