J'ai posté au sujet de mon approche de ce problème de nombreuses fois dans de nombreux forums différents, mais je vais récapituler la structure de base de l'approche que je l'utilise. Cependant, il n'y a aucun moyen de le faire en une seule étape.
de mettre à jour les enregistrements existants à partir de la source de données externe.
Insérer des enregistrements qui n'existent pas déjà.
Ceci suppose une clé primaire commune pouvant être utilisée pour lier la table existante à la source de données externe.
La tâche n ° 2 est plutôt triviale, juste une jointure externe pour les enregistrements qui n'existent pas déjà.
On peut utiliser la force brute pour # 1, en écrivant une instruction UPDATE avec un SET pour chaque champ autre que la clé primaire, mais je considère que cela est désordonné et inutile. De plus, comme j'ai beaucoup d'applications répliquées, je ne peux pas le faire, car cela entraînerait de faux conflits (quand un champ est mis à jour avec la même valeur que celle avec laquelle il a commencé). Donc, à cette fin, j'utilise DAO et j'écris une instruction SQL à la volée pour mettre à jour COLUMN-BY-COLUMN. La structure de base est quelque chose comme ceci:
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
Maintenant, la partie compliquée est la manipulation numérique par rapport à la date par rapport à des champs de chaîne, de sorte que vous devez avoir une certaine logique pour écrire les clauses WHERE d'utiliser des citations appropriées et d'autres délimiteurs selon le type de champ. Plutôt que de tester le type de champ, j'utiliser généralement un cas comme celui-ci SELECT, lutherie champs par défaut:
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 & ")"
je pouvais avoir les détails il y a mal, mais vous avez l'idée, je pense.Cela signifie que vous exécuterez uniquement autant de mises à jour SQL que de champs pouvant être mis à jour et que vous ne mettrez à jour que les enregistrements à mettre à jour. Si vous tamponnez également vos enregistrements avec une date de "dernière mise à jour", vous le feriez dans le SQL UPDATE et vous ne voudriez faire cela que sur les enregistrements qui avaient vraiment des valeurs différentes.
Cela peut aider votre recherche à savoir que cela est souvent appelé "upsert". – DOK