Beide Antworten haben Möglichkeiten. Nur um Ihre Optionen ein wenig zu erweitern ..
Möglichkeit Nr. 1
WENN mySQL unterstützt eine Art Hashing, auf Zeilenbasis , könnten Sie eine Variation von comodoros Vorschlag verwenden um endgültiges Löschen zu vermeiden.
Geändert identifizieren
Um Änderungen zu identifizieren, führen Sie einen Inner Join für den Primärschlüssel durch und überprüfen Sie die Hash-Werte. Wenn sie unterschiedlich sind, wurde das Produkt geändert und sollte aktualisiert werden:
UPDATE Products p INNER JOIN Products_Temp tmp ON tmp.ProductID = p.ProductID
SET p.ProductName = tmp.ProductName
, p.Stock = tmp.Stock
, ...
, p.DateLastChanged = now()
, p.IsDiscontinued = 0
WHERE tmp.TheRowHash <> p.TheRowHash
Identifizieren gelöscht
Verwenden Sie einen einfachen äußeren Join, um Datensätze zu identifizieren, die nicht in der temporären Tabelle vorhanden sind, und markieren Sie sie als "gelöscht"
UPDATE Products p LEFT JOIN Products_Temp tmp ON tmp.ProductID = p.ProductID
SET p.DateLastChanged = now()
, p.IsDiscontinued = 1
WHERE tmp.ProductID IS NULL
Neu identifizieren
Verwenden Sie schließlich einen ähnlichen äußeren Join, um alle "neuen" Produkte einzufügen.
INSERT INTO Products ( ProductName, Stock, DateLastChanged, IsDiscontinued, .. )
SELECT tmp.ProductName, tmp.Stock, now() AS DateLastChanged, 0 AS IsDiscontinued, ...
FROM Products_Temp tmp LEFT JOIN Products p ON tmp.ProductID = p.ProductID
WHERE p.ProductID IS NULL
Option Nr. 2
Wenn Hashing pro Zeile nicht möglich ist, ist ein alternativer Ansatz eine Variation von Sharondios Vorschlag .
Fügen Sie der temporären Tabelle eine „Status“-Spalte hinzu und kennzeichnen Sie alle importierten Datensätze durch eine Reihe von Verknüpfungen als „neu“, „geändert“ oder „unverändert“. (Die Voreinstellung sollte "geändert" sein).
UN-geändert identifizieren
Verwenden Sie zunächst einen Inner Join für alle Felder, um Produkte zu identifizieren, die sich NICHT geändert haben. (Beachten Sie, wenn Ihre Tabelle Nullable-Felder enthält, denken Sie daran, etwas wie coalesce
zu verwenden Andernfalls können die Ergebnisse aufgrund von null
verzerrt werden Werte sind mit nichts gleich.
UPDATE Products_Temp tmp INNER JOIN Products p ON tmp.ProductID = p.ProductID
SET tmp.Status = 'Unchanged'
WHERE p.ProductName = tmp.ProductName
AND p.Stock = tmp.Stock
...
Neu identifizieren
Verwenden Sie wie zuvor einen äußeren Join, um "neue" Datensätze zu identifizieren.
UPDATE Products_Temp tmp LEFT JOIN Products p ON tmp.ProductID = p.ProductID
SET tmp.Status = 'New'
WHERE p.ProductID IS NULL
Durch den Eliminierungsprozess werden alle anderen Datensätze in der temporären Tabelle "geändert". Nachdem Sie die Status berechnet haben, können Sie die Produkttabelle aktualisieren:
/* update changed products */
UPDATE Products p INNER JOIN Products_Temp tmp ON tmp.ProductID = p.ProductID
SET p.ProductName = tmp.ProductName
, p.Stock = tmp.Stock
, ...
, p.DateLastChanged = now()
, p.IsDiscontinued = 0
WHERE tmp.status = 'Changed'
/* insert new products */
INSERT INTO Products ( ProductName, Stock, DateLastChanged, IsDiscontinued, .. )
SELECT tmp.ProductName, tmp.Stock, now() AS DateLastChanged, 0 AS IsDiscontinued, ...
FROM Products_Temp tmp
WHERE tmp.Status = 'New'
/* flag deleted records */
UPDATE Products p LEFT JOIN Products_Temp tmp ON tmp.ProductID = p.ProductID
SET p.DateLastChanged = now()
, p.IsDiscontinued = 1
WHERE tmp.ProductID IS NULL