Transaction

是否可以在數據庫事務中分離語句的應用?

  • November 14, 2016

這是我最近遇到的一個簡單場景。

我將製造一個最小的場景來說明這個問題。

我們有一個數據庫表,其中有一列 ID 用作某物的外鍵(但未指定為外鍵;它被用來臨時保存一個臨時映射索引,這種方式非常危險,依賴於外部狀態)。每行都有一個在這裡填充的值。隨後必須使用新映射更新此數據列。

有效映射的範例:

0 -> 1
1 -> 4
2 -> 0

一個範例數據集:

2
1
0
2

明顯的預期結果:

0
4
1
0

實現(虛擬碼):

for (mapping in map) {
   sql("update table set value = " + mapping.to + " where value = " + mapping.from + ";")
}

非常簡單但幾乎同樣明顯的是,這是完全錯誤的,因為我們看到的結果是

0
4
4
0

第三行應用了兩次映射。

我在想,如果 N(其中 N 是映射的數量)語句在事務中執行,它可能會解決問題。但我不太確定,我真的不明白為什麼會這樣。該事務將僅保證第 3 行的任一映射為零或兩個映射都應用,但我只需要一個映射。基本上看起來我需要一個全新的專欄來以一種直接的方式完成這樣一個簡單的操作。

這種情況一般是怎麼處理的?我覺得我錯過了一些微不足道的東西。

你需要類似的東西

UPDATE tab1 set value = 
  CASE value
    WHEN 0 THEN 1 
    WHEN 1 THEN 4
    WHEN 2 THEN 0 
  END;

如果您需要以不同的方式處理未列出的值,CASE說不要更改它,您需要添加ELSECASEypercubeᵀᴹ 指出的:

UPDATE tab1 set value = 
      CASE value
        WHEN 0 THEN 1 
        WHEN 1 THEN 4
        WHEN 2 THEN 0 
        ELSE value
      END;

或者您可以創建一個新表,在其中插入所有映射,然後(假設映射是唯一的)

UPDATE  tab1 t SET value = 
(SELECT new_val from mapping_table t2 WHERE t2.old_val = t.value)  

引用自:https://dba.stackexchange.com/questions/154745