Ambas as respostas têm possibilidades. Apenas para expandir suas opções um pouco ..
Opção nº 1
SE mySQL suporta algum tipo de hash, por linha , você pode usar uma variação da sugestão de comodoro para evitar exclusões difíceis.
Identificar alterado
Para identificar as alterações, faça uma junção interna na chave primária e verifique os valores de hash. Se forem diferentes, o produto foi alterado e deve ser atualizado:
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 excluído
Use uma junção externa simples para identificar registros que não existem na tabela temporária e sinalize-os como "excluídos"
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 novo
Por fim, use uma junção externa semelhante para inserir quaisquer produtos "novos".
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
Opção nº 2
Se o hash por linha não for viável, uma abordagem alternativa é uma variação da sugestão de Sharondio .
Adicione uma coluna "status" à tabela temporária e marque todos os registros importados como "novos", "alterados" ou "inalterados" por meio de uma série de junções. (O padrão deve ser "alterado").
Identificar UN-Changed
Primeiro, use uma junção interna, em todos os campos, para identificar produtos que NÃO foram alterados. (Observe que, se sua tabela contiver campos anuláveis, lembre-se de usar algo como
coalesce
Caso contrário, os resultados podem ser distorcidos porque null
os valores não são iguais 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 novo
Como antes, use uma junção externa para identificar registros "novos".
UPDATE Products_Temp tmp LEFT JOIN Products p ON tmp.ProductID = p.ProductID
SET tmp.Status = 'New'
WHERE p.ProductID IS NULL
Por processo de eliminação, todos os outros registros na tabela temporária são "alterados". Depois de calcular os status, você pode atualizar a tabela Produtos:
/* 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