2022年5月5日 星期四

MySQL(MariaDB) INSERT INTO ... ON DUPLICATE KEY UPDATE,只更新符合條件的資料

INSERT INTO ... ON DUPLICATE KEY UPDATE 沒辦法用 WHERE 條件過濾出要更新的資料,
但要更新的值,可以用 IF 條件來控制。
讓不欲更新的資料,用原值更新,效果便猶如沒更新過,而只更新其他資料。

[範例]
一資料表test,三個欄位 id(主鍵)、aa(int)、bb(int)。
新增(INSERT INTO)資料時,若資料(id)已存在,則更新 aa、bb 兩欄位資料,
但若原本的 bb 資料小於 100,則不更新 bb:
INSERT INTO test (id, aa, bb)
  VALUES (8, 123, 456)
ON DUPLICATE KEY UPDATE
  aa = VALUES(aa),
  bb = IF(bb<100, bb, VALUES(bb));


[注意]
如果有一筆資料(id, aa, bb) => (10, 1, 2)
INSERT INTO test (id, aa, bb)
  VALUES (10, 100, 200)
ON DUPLICATE KEY UPDATE
  aa = VALUES(aa),
  bb = aa;
得到的結果是 (id, aa, bb) => (10, 100, 100)

將最後兩行順序調換:
INSERT INTO test (id, aa, bb)
  VALUES (10, 100, 200)
ON DUPLICATE KEY UPDATE
  bb = aa,
  aa = VALUES(aa);
得到的結果是 (id, aa, bb) => (10, 100, 1)

可發現,順序不同,結果不同
=> ON DUPLICATE KEY UPDATE 若要取其他欄位的原值,須排在其他欄位修改之前。



所以最初的例子「若原本的 bb 資料小於 100,則不更新 bb」,
如果改成「若原本的 bb 資料小於 原本aa,則不更新 bb」,
則須注意 aa、bb 修改的順序,避免比較到 aa 修改後的值:
INSERT INTO test (id, aa, bb)
  VALUES (8, 123, 456)
ON DUPLICATE KEY UPDATE
  bb = IF(bb<aa, bb, VALUES(bb)),
  aa = VALUES(aa);



參考:



沒有留言:

張貼留言