2010-06-07 5 views
0

je suis insérer des valeurs dans une tablesi elle existe, mise à jour, insérer autre nouveau record

si l'enregistrement existe déjà remplacer, et si elle n'existe pas, ajouter un nouveau.

Jusqu'à présent, j'ai ce code:

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

mais je dois quelque chose comme ça

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" 

quelle serait la syntaxe SQL correcte pour cela?

s'il vous plaît noter que je suis en utilisant l'accès sql et que je pense que ce peut être une combinaison de l'ABV et sql

+3

Cela peut aider votre recherche à savoir que cela est souvent appelé "upsert". – DOK

Répondre

1

Première mise à jour des lignes qui correspondent entre votre table d'importation et la table principale.

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; 

Ajoutez ensuite les enregistrements importés qui n'existent pas dans la table principale.

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)); 
+0

hey êtes-vous sûr (((m.pk) est Null)); est la syntaxe d'accès? Je pensais que vous deviez faire isnull (quelque chose) " –

+2

Vous pouvez utiliser la fonction IsNull.Mais le moteur de base de données Access prend en charge IS NULL et n'est pas NULL dans les instructions SQL Essayez-le! (Cela a fonctionné pour moi.) – HansUp

1

Cela pourrait se faire facilement avec recordsets. Le code ressemblerait alors à cela (pour un jeu d'enregistrements ADODB):

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

cela semble trop complexe d'une solution –

+0

En fait, il semble assez simple, car il est assez programmable. Mais je pense que ce serait très inefficace avec des lots de disques de n'importe quelle taille. –

0

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.

  1. de mettre à jour les enregistrements existants à partir de la source de données externe.

  2. 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.

+0

Si vous voulez passer en revue tous les champs, pourquoi ne pas simplement définir la valeur de chaque champ, puis simplement utiliser une instruction de mise à jour sur le jeu d'enregistrements au lieu d'exécuter plusieurs instructions sql update sql? – JeffO

+1

Euh, j'ai expliqué que deux fois: d'abord j'utilise fréquemment la réplication Jet et cela provoquerait de faux conflits Deuxièmement, si vous devez tamponner les enregistrements avec une date/heure DERNIÈRE MISE À JOUR, vous ne voulez le faire que pour les enregistrements qui ont besoin d'une mise à jour . –

Questions connexes