SQL: Insert über 2 Tabellen in SQLite

Bezugnehmend auf den letzten Artikel bekam ich doch gleich noch die Frage wie man denn Änderungen in die „Adressen“ Tabelle wegspeichern könnte.

Eine Änderung würde in diesem Fall so Aussehen, dass z.B. die „Jennifer Achter“ ihren Namen ändert (sowas kann schon mal passieren, wollen wir für sie aber hier nicht hoffen – Jede Kriese kann man irgendwie bewältigen 🙂 )
Also mal angenommen ihr Name ändert sich in „Jennifer Achterbahn“, aber ihre E-Mail Adresse bleibt gleich (ist in den meisten Fällen von namensänderungen vermutlich nicht der Fall, aber irgendein kriterium zum Vergleichen brauchen wir hier ja – also bleibt die E-Mail Adresse gleich).

Damit sieht der Eintrag in der Tabelle „Adressen_tmp“ jetzt so aus:

RecNo id vorname  name       email              
----- -- -------- ---------- ------------------ 
    1  4 Jennifer Achterbahn jennifer@achter.de 

Der Inahlt der Spalte „name“ hat sich nun also geändert. Und diesen wollen wir in die Tabelle „Adressen“ beim gleichen Datensatz übernehmen.
Folgender Query würde mir dann auch die Änderung anzeigen:

1
2
3
4
5
6
7
8
SELECT 
     *    
FROM 
     Adressen
INNER JOIN Adressen_tmp ON Adressen.email = Adressen_tmp.email
WHERE
     Adressen.[vorname]!=Adressen_tmp.[vorname]     
OR  Adressen.[name]!=Adressen_tmp.[name]

Das Ergebnis:

RecNo id vorname  name   email              id_1 vorname_1 name_1     email_1            
----- -- -------- ------ ------------------ ---- --------- ---------- ------------------ 
    1  8 Jennifer Achter jennifer@achter.de    4 Jennifer  Achterbahn jennifer@achter.de 

Diese Änderung müssen wir jetzt in die „Adressen“ Tabelle übernhemen.
In „normalen“ SQL Servern würde in etwa ein Insert mit einem Join wie z.B. dieser hier funktionieren:

1
2
3
4
5
6
7
8
9
UPDATE
     Adressen 
INNER JOIN Adressen_tmp ON Adressen.email = Adressen_tmp.email
WHERE
     Adressen.[vorname]!=Adressen_tmp.[vorname]     
OR   Adressen.[name]!=Adressen_tmp.[name]
SET 
    Adressen.[vorname]=Adressen_tmp.[vorname],  
    Adressen.[name]=Adressen_tmp.[name]

…funktioniert nur leider in SQLite nicht! 🙁
SQLite unterstüzuz keine JOINs im INSERT Query.
Mhm… was könnte man statt dessen benutzen?
Vielleicht ein Konstrukt mit einem Subquery drin?

Würde dann in etwa so aussehen:

1
2
3
4
5
6
7
8
9
10
SELECT * FROM Adressen_tmp
WHERE email IN (
      SELECT 
             email 
      FROM 
             Adressen 
      WHERE 
             Adressen.vorname!=Adressen_tmp.vorname
          OR Adressen.name!=Adressen_tmp.name
      )

Aber auch dies funktioniert nicht in SQLite.
Letzenlich habe ich nach 2 Stunden Suche den richtigen Query zusammen gebastelt:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
INSERT OR REPLACE INTO Adressen 
      SELECT 
             Adressen.id AS id,
             Adressen_tmp.vorname AS vorname,
             Adressen_tmp.name AS name,
             Adressen_tmp.email AS email 
      FROM 
             Adressen,Adressen_tmp 
      WHERE 
             Adressen.[email]=adressen_tmp.[email]             
          AND (
             Adressen.vorname!=Adressen_tmp.vorname
          OR Adressen.name!=Adressen_tmp.name
          )

Das Geheimnis liegt hier im „INSERT OR REPLACE“.
Es werden ALLE Datensätze aus beiden Tabellen anhand der E-Mail Adresse Verknüpft und vergleichen.
Sollte es eine Abweichung der Datensätze aus beiden Tabellen geben, wird der erste Datensatz durch einen UPDATE Befehl aktualisiert.
Sollte der Datensatz aus der 2. Tabelle nicht in der ersten Tabelle vorhanden sein, so wird er mit einem INSERT Befehl eingefügt.
Dies kann allerdings nicht passieren, weil für diesen Fall gar keine verknüpfung der Datensätze anhand der E-Mail Adresse zustande kommt.

Nun sind wir alle wieder etwas schlauer 🙂

leave your comment


*

Unterstütze den Frickelblog!