Båda svaren har möjligheter. Bara för att utöka dina alternativ lite ..
Alternativ #1
OM mySQL stöder någon form av hash, per rad , du kan använda en variant av comodoros förslag för att undvika hårda raderingar.
Identifiera ändrad
För att identifiera ändringar, gör en inre koppling på primärnyckeln och kontrollera hash-värdena. Om de är olika har produkten ändrats och bör uppdateras:
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
Identifiera borttaget
Använd en enkel yttre koppling för att identifiera poster som inte finns i temptabellen och flagga dem som "raderade"
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
Identifiera ny
Använd slutligen en liknande yttre skarv för att infoga eventuella "nya" produkter.
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
Alternativ #2
Om hashing per rad inte är genomförbart är en alternativ metod en variant av Sharondios förslag .
Lägg till en "status"-kolumn i temptabellen och flagga alla importerade poster som "nya", "ändrade" eller "oförändrade" genom en serie kopplingar. (Standardinställningen bör "ändras").
Identifiera UN-Changed
Använd först en inre koppling, på alla fält, för att identifiera produkter som INTE har ändrats. (Obs, om din tabell innehåller några nollbara fält, kom ihåg att använda något som coalesce
Annars kan resultaten bli skeva eftersom null
värden är inte lika med någonting.
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
...
Identifiera ny
Som tidigare, använd en yttre koppling för att identifiera "nya" poster.
UPDATE Products_Temp tmp LEFT JOIN Products p ON tmp.ProductID = p.ProductID
SET tmp.Status = 'New'
WHERE p.ProductID IS NULL
Genom elimineringsprocessen "ändras" alla andra poster i temptabellen. När du har beräknat statusen kan du uppdatera produkttabellen:
/* 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