Я много, много раз писал о своем подходе к этой проблеме на разных форумах, но я просто подведу итог основной структуре подхода, который я использую. Однако сделать это за один шаг невозможно.
обновить существующие записи из внешнего источника данных.
вставить записи, которые еще не существуют.
Это предполагает общий первичный ключ, который можно использовать для связи существующей таблицы с внешним источником данных.
Задача № 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, и вам нужно это делать только для записей, которые действительно имеют разные значения.