どちらの応答にも可能性があります。オプションを少し拡張するだけです..
オプション1
mySQLが行ごとに何らかのハッシュをサポートしている 場合、 comodoro の提案のバリエーションを使用してハード削除を回避できます。
変更の識別
変更を識別するには、主キーで内部結合を実行し、ハッシュ値を確認します。それらが異なる場合、製品は変更されており、更新する必要があります。
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
削除された識別
単純な外部結合を使用して、一時テーブルに存在しないレコードを特定し、それらに「削除済み」のフラグを立てます
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
新規識別
最後に、同様の外部結合を使用して、「新しい」製品を挿入します。
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
オプション #2
行ごとのハッシュが実行できない場合、代替アプローチはシャロンディオの提案のバリエーションです。
一時テーブルに「ステータス」列を追加し、一連の結合を通じて、インポートされたすべてのレコードに「新規」、「変更済み」、または「未変更」のフラグを立てます。(デフォルトは「変更」する必要があります)。
UN-Change の特定
まず、すべてのフィールドで内部結合を使用して、変更されていない製品を識別します。(テーブルに null 許容フィールドが含まれているcoalesce
場合は、次のようなものを使用することを忘れnull
ないでください。
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
...
新規識別
以前と同様に、外部結合を使用して「新しい」レコードを識別します。
UPDATE Products_Temp tmp LEFT JOIN Products p ON tmp.ProductID = p.ProductID
SET tmp.Status = 'New'
WHERE p.ProductID IS NULL
削除のプロセスにより、一時テーブル内の他のすべてのレコードが「変更」されます。ステータスを計算したら、Products テーブルを更新できます。
/* 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