если существует, обновите, иначе вставьте новую запись - PullRequest
1 голос
/ 07 июня 2010

я вставляю значения в таблицу

если запись уже существует, замените ее, а если она не существует, добавьте новую.

пока у меня есть этот код:

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 * 1013

Ответы [ 3 ]

2 голосов
/ 07 июня 2010

Первые строки обновления, которые соответствуют между вашей таблицей импорта и основной таблицей.

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 голос
/ 07 июня 2010

Это можно легко сделать с помощью наборов записей. Код будет выглядеть так (для набора записей ADODB):

myRecordset.find ....
if myRecordset.EOF then
    myRecordset.addNew
endif
....
myRecordset.fields(...) = ...
....
myRecordset.update
0 голосов
/ 07 июня 2010

Я много, много раз писал о своем подходе к этой проблеме на разных форумах, но я просто подведу итог основной структуре подхода, который я использую. Однако сделать это за один шаг невозможно.

  1. обновить существующие записи из внешнего источника данных.

  2. вставить записи, которые еще не существуют.

Это предполагает общий первичный ключ, который можно использовать для связи существующей таблицы с внешним источником данных.

Задача № 2 довольно тривиальна, просто внешнее объединение для записей, которые еще не существуют.

Можно использовать грубую силу для # 1, написав инструкцию UPDATE с SET для каждого поля, отличного от первичного ключа, но я считаю, что это грязно и не нужно. Кроме того, поскольку у меня много реплицированных приложений, я не могу этого сделать, поскольку это может привести к ложным конфликтам (когда поле обновляется до того же значения, с которого оно начиналось).

Итак, для этой цели я использую 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, и вам нужно это делать только для записей, которые действительно имеют разные значения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...