Ambas respuestas tienen posibilidades. Solo para ampliar un poco tus opciones...
Opción #1
SI mySQL admite algún tipo de hashing, por fila , podría usar una variación de la sugerencia de comodoro para evitar eliminaciones forzadas.
Identificar cambiado
Para identificar cambios, realice una combinación interna en la clave principal y verifique los valores hash. Si son diferentes, el producto fue cambiado y debe actualizarse:
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
Identificar eliminado
Use una combinación externa simple para identificar registros que no existen en la tabla temporal y márquelos como "eliminados"
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
Identificar nuevo
Finalmente, use una combinación externa similar para insertar cualquier producto "nuevo".
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
Opción #2
Si el hashing por fila no es factible, un enfoque alternativo es una variación de la sugerencia de Sharondio .
Agregue una columna de "estado" a la tabla temporal y marque todos los registros importados como "nuevos", "cambiados" o "sin cambios" a través de una serie de uniones. (El valor predeterminado debe ser "cambiado").
Identificar UN-Change
Primero use una combinación interna, en todos los campos, para identificar los productos que NO han cambiado. (Tenga en cuenta que si su tabla contiene campos que aceptan valores NULL, recuerde usar algo como coalesce
De lo contrario, los resultados pueden estar sesgados porque null
los valores no son iguales a nada.
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
...
Identificar nuevo
Como antes, use una combinación externa para identificar registros "nuevos".
UPDATE Products_Temp tmp LEFT JOIN Products p ON tmp.ProductID = p.ProductID
SET tmp.Status = 'New'
WHERE p.ProductID IS NULL
Mediante el proceso de eliminación, todos los demás registros de la tabla temporal se "cambian". Una vez que haya calculado los estados, puede actualizar la tabla Productos:
/* 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