MySql Tabellenreparatur mit IF

Sprint

Erfahrenes Mitglied
Hallo zusammen,

ich habe hier eine Kundentabelle aus einem Online Shop, bei der durch ein Update Daten verstümmelt wurden. Und zwar wurden Daten mit einem Umlaut vor dem Umlaut abgeschnitten. Aus Jürgen wurde z.B. J. Ich habe die alte Tabelle noch, nur wäre ein manueller Abgleich bei 15000 Datensätzen zu aufwendig.

Gibt es eine Möglichkeit, in einer Abfrage zwei Tabellen abzugleichen und Daten bei der neuen zu ergänzen, wenn in einem Feld der neuen Tabelle ein Substring des entsprechenden Felds in der alten Tabelle ist? In Pseudocode also
Code:
UPDATE neue_tabelle SET neu.nachname = alt.nachname IF (neu.nachname = SUBSTR(alt.nachname,1,x))
 
Lösung
Hast du keine Primär-Schlüssel? bzw. anstatt eines expliziten Primär-Schlüssels ein Attribut/Spalte, welche pro Satz eindeutig ist
Wenn die Tabelle (und somit auch das "Backup") Primär-Schlüssel (bzw. so eine UNIQUE-Spalte) haben ist das käse-einfach.

btw: Habt ihr schon den Grund herausgefunden, warum abgeschnitten wurde?
Klingt für mich nach falschem Encoding der "neuen" Tabelle/Spalte (Latin1 vs. UTF8 vs. irgendwas)

ungetestet
SQL:
UPDATE neue_tabelle
SET neue_tabelle.nachname=(SELECT nachname FROM alte_tabelle WHERE alte_tabelle.ID=neue_tabelle.ID)

//bzw. in MySQL kann man auch ein UPDATE mit impizitem JOIN machen
UPDATE neue_tabelle AS neu, alte_tabelle AS alt
SET neu.nachname=alt.nachname
WHERE neu.id = alt.id

....und dein...
Hast du keine Primär-Schlüssel? bzw. anstatt eines expliziten Primär-Schlüssels ein Attribut/Spalte, welche pro Satz eindeutig ist
Wenn die Tabelle (und somit auch das "Backup") Primär-Schlüssel (bzw. so eine UNIQUE-Spalte) haben ist das käse-einfach.

btw: Habt ihr schon den Grund herausgefunden, warum abgeschnitten wurde?
Klingt für mich nach falschem Encoding der "neuen" Tabelle/Spalte (Latin1 vs. UTF8 vs. irgendwas)

ungetestet
SQL:
UPDATE neue_tabelle
SET neue_tabelle.nachname=(SELECT nachname FROM alte_tabelle WHERE alte_tabelle.ID=neue_tabelle.ID)

//bzw. in MySQL kann man auch ein UPDATE mit impizitem JOIN machen
UPDATE neue_tabelle AS neu, alte_tabelle AS alt
SET neu.nachname=alt.nachname
WHERE neu.id = alt.id

....und dein Pseudocode ist "brandgefährlich" wie er da steht, auch wenn man das IF nur durch ein WHERE ersetzen müsste....
"Müller" wurde beim "M" abgeschnitten, bei deinem Pseudocode findet er aber als erstes einen "Maier"
Rate mal wie "Müller" nach der "Reparatur" dann mit Nachnamen heisst....
 
Zuletzt bearbeitet:
Lösung
Warum die Daten verstümmelt wurden, ist mir selbst ein Rätsel. Schuld war ein fertiges Script, das Latin1 Tabellen in UTF-8 umwandeln sollte. Verstümmelt wurden aber nur die Daten, die bereits in UTF-8 Tabellen standen.

Mein Pseudocode war sicher unvollständig. Ein Primärschlüssel ist vorhanden und ich wollte den auch verwenden. Nur hatte ich gedacht, daß ich das über ein IF machen müßte. Auf eine so "einfache" Lösung bin ich gar nicht gekommen. Werde die gleich mal testen.
 
Mal für die „Kuhzunft“: Solche Sachen in eine Transaktion packen
1) starte Transaktion
2) führe “update“ aus
3) Ergebnis anschauen
4) falls ok >> COMMIT, sonst ROLLBACK

EDIT: Für Schritt 3 kann man ein SELECT schreiben, welches die korrespondierenden Felder vergleicht. Falls du Hilfe dabei bräuchtest gib laut
 
Mal für die „Kuhzunft“: Solche Sachen in eine Transaktion packen
1) starte Transaktion
2) führe “update“ aus
3) Ergebnis anschauen
4) falls ok >> COMMIT, sonst ROLLBACK
Da gebe ich dir im Prinzip Recht, nur hätte ich nicht gedacht, daß ein Script, das auf der Webseite des Shop Herstellers veröffentlicht wurde, so merkwürdig agiert.
 
Nach ein paar lokalen Tests habe ich jetzt die originalen Daten bearbeitet und es hat funktioniert. Allerdings mußte ich das ganze in eine kleine PHP Routine umbauen, da sich ein Wert mit einem Fehler #1048 hartnäckig geweigert hat, sich überschreiben zu lassen. Aber am Ende hat alles funktioniert.

Vielen Dank für deine Hilfe, Zvoni!
 
Hier mal der Ansatz für den check in Schritt 3:
SQL:
SELECT a.ID, SUM(a.Wert1, a.Wert2, ....., a.WertX) As Result
FROM
    (SELECT neu.ID,
        IF(neu.Feld1=alt.Feld1, 0 ,1) As Wert1,
        IF(neu.Feld2=alt.Feld2, 0 ,1) As Wert2,
        .
        .
        .
        IF(neu.FeldX=alt.FeldX, 0 ,1) As WertX
    FROM tabelle_neu AS neu INNER JOIN tabelle_alt As alt ON neu.ID=alt.ID) As a
HAVING SUM(a.Wert1, a.Wert2, ....., a.WertX)>0
Gibt dir alle Sätze in der neuen Tabelle, welche "fehlerhaft" sind, wobei ich mir gerade nicht sicher bin, ob es HAVING oder WHERE sein muss in der letzten Zeile bzw. ob da noch ein GROUP BY a.ID rein muss

Fehler 1048 bei MySQL ist "Column cannot be NULL"
Leicht mit einem COALESCE im SQL selbst zu lösen
 
Zuletzt bearbeitet:
Vielen Dank für die Prüfroutine. Ich habe inzwischen die Daten aktualisiert. Zum Glück sind in den betroffenen Tabellen ein Datum der Eintragung und der letzten Änderung eingetragen. So konnte ich feststellen, daß seit dem Shopupdate keine Änderungen an den Namen und Adressdaten vorgenommen worden waren und ich konnte die Daten einfach übertragen.
 
Und hier sogar als "Einzelaufstellung"
DB Fiddle - SQL Database Playground
SQL:
CREATE TABLE neu(ID int, Feld1 int, Feld2 varchar(10), Feld3 varchar(20), Feld4 int);
INSERT INTO neu(ID, Feld1, Feld2, Feld3, Feld4)
VALUES (1, 100, 'Test1', 'Grosser Test1', 3),(2, 200, 'Test2', 'Grosser Test2', 5),(3, 300, 'Test3', 'Grosser Test3', 1);

CREATE TABLE alt(ID int, Feld1 int, Feld2 varchar(10), Feld3 varchar(20), Feld4 int);
INSERT INTO alt (ID, Feld1, Feld2, Feld3, Feld4)
VALUES (1, 150, 'Test1', 'Grosser Test1', 3), (2, 200, 'Test2', 'Grosser Test2', 50),(3, 300, 'Test3', 'Großer Test3', 1);
SQL:
select a.ID, a.MyCheck,a.Feld, a.NeuValue, a.AltValue
from
    (select srcneu.ID,
     srcneu.Feld as Feld,
     srcneu.Value as NeuValue,
     srcalt.Value As AltValue,
     if(srcneu.Value=srcalt.Value,0, 1) As MyCheck
    from
         (select ID, Feld1 As value, 'Feld1' As Feld
          from neu union all
          select ID, Feld2 As value, 'Feld2' As Feld
          from neu union all
          select ID, Feld3 As value, 'Feld3' As Feld
          from neu union all
          select ID, Feld4 As value, 'Feld4' As Feld
          from neu) As srcneu
    inner join
         (select ID, Feld1 As value, 'Feld1' As Feld
          from alt union all
          select ID, Feld2 As value, 'Feld2' As Feld
          from alt union all
          select ID, Feld3 As value, 'Feld3' As Feld
          from alt union all
          select ID, Feld4 As value, 'Feld4' As Feld
          from alt) As srcalt
    ON srcneu.ID=srcalt.ID and srcneu.Feld=srcalt.Feld) As a
where a.MyCheck=1
 
Zurück