どちらの応答にも可能性があります。オプションを少し拡張するだけです..
オプション#1
IF 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
行ごとのハッシュが実行できない場合、別のアプローチはSharondioの提案 のバリエーションです。 。
一時テーブルに「ステータス」列を追加し、一連の結合を通じて、インポートされたすべてのレコードに「新規」、「変更」、または「変更なし」のフラグを付けます。 (デフォルトは「変更」する必要があります)。
変更されていないものを特定する
まず、すべてのフィールドで内部結合を使用して、変更されていない製品を識別します。 (テーブルに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