Select

如果沒有任何變化,如何僅更新?在插入之前我需要驗證幾件事

  • July 5, 2015

假設我有兩個表:runners 和 waypoint_checkins。我想添加航點簽入條目,但如果跑步者已經完成比賽,我永遠無法添加航點(請參閱下面的架構)。最後。如果航點被列為已關閉,跑步者永遠無法檢查航點。

table: runners
id | name | is_finished
---+------+------------
15 | abe  | false

table: waypoints
id  | currently_open
----+---------------
1   | true
2   | true
3   | false
... | ...

table: waypoint_checkins
runner_id | waypoint_id | time
----------+-------------+-------
15        | 1           | 5:00
15        | 2           | 5:23
15        | 4           | 5:52

所以在辦理登機手續時,我得到了(runner_name,waypoint_id,time)。首先,我需要找到跑步者並確保它們仍在執行:

SELECT id, is_finished FROM runners WHERE name = %name;

然後我需要檢查跑步者是否在開放的航點;

SELECT currently_open FROM waypoints WHERE id = %waypoint_id;

最後我需要插入一個新的航點簽到:

INSERT INTO waypoint_checkins VALUES (%runner_id, %wp_id, %time);

但是在查詢 1 和 3 之間,跑步者可能已經完成。如何執行插入語句,我可以保證之前的選擇仍然有效?

不要將這些檢查作為單獨的 SELECT 語句發出,而是將它們作為 INSERT 語句的一部分。您需要用 INSERT…SELECT 替換 INSERT…VALUES 語法才能使用 WHERE 子句:

INSERT INTO
 waypoint_checkins (runner_id, waypoint_id, time)
SELECT
 runners.id,
 %waypoint_id,
 %time
FROM
 runners
WHERE
 name = %runner_name
 AND is_finished = 'false'
 AND EXISTS (
   SELECT
     *
   FROM
     waypoints
   WHERE id = %waypoint_id
     AND currently_open = 'true'
 )
;

可以看到第一個檢查是直接集成到 INSERT 語句中的,因為應用於的參數runners是一個名字,你需要從中獲取一個 ID 作為要插入的值之一。第二個檢查採用 EXISTS 謂詞的形式。

因此,所有三個初始參數(runner_namewaypoint_idtime)都是該單個語句的參數。

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