Я отправил о моем подходе к этой проблеме много, много раз в самых разных форумах, но я просто резюмировать основную структуру подхода, который я использую. Однако нет способа сделать это за один шаг.
обновить существующие записи из внешнего источника данных.
Вставьте записи, которые еще не существуют.
Это предполагает общий первичный ключ, который может использоваться для связывания существующей таблицы с внешним источником данных.
Задача № 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
Теперь сложная часть обработки числовой против даты против строковых полей, так что вы должны иметь определенную логику, чтобы написать пункты, где использовать правильные кавычки и другие разделители в зависимости от типа поля. Вместо того, чтобы проверить тип поля, я обычно просто использовать СЛУЧАЙ ВЫБРАТЬ, как это, делает строку поля по умолчанию:
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, и вы только захотите сделать это в записях, которые действительно имели разные значения.
Это может помочь вам найти, что это часто называют «upsert». – DOK