CodeGym /課程 /SQL SELF /建立簡單的觸發器來自動更新資料:AFTER INSERT

建立簡單的觸發器來自動更新資料:AFTER INSERT

SQL SELF
等級 57, 課堂 3
開放

想像一下,我們有一個存放學生資料的資料表。這個表裡面我們需要每次新增學生時自動更新 last_modified(紀錄最後一次修改的時間)。這個欄位很重要,因為可以追蹤資料變動跟管理資料。

流程大概是這樣:

  1. 每當有新資料加進表格,last_modified 欄位會自動設成現在的日期和時間。
  2. 我們會用 AFTER INSERT 這個觸發器,讓它在資料插入成功後自動執行。

寫一個給觸發器用的 function

首先要先寫一個 PL/pgSQL 的 function。這個 function 會幫我們更新 last_modified 欄位。function 是觸發器一定要有的,因為觸發器本身只是指示要做什麼,實際邏輯都在 function 裡面。

我們先來建立資料表:

-- 建立 students 資料表
CREATE TABLE students (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    age INT NOT NULL,
    last_modified TIMESTAMP
);

接下來寫一個 function 來更新 last_modified:

-- 更新 last_modified 的 function
CREATE OR REPLACE FUNCTION update_last_modified()
RETURNS TRIGGER AS $$
BEGIN
    -- 把現在時間設到 last_modified 欄位
    NEW.last_modified := NOW();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

來看看這個 function 到底在幹嘛:

  • CREATE OR REPLACE FUNCTION update_last_modified() — 建立一個叫 update_last_modified 的 function。如果已經有同名的會直接覆蓋。
  • RETURNS TRIGGER — 這個 function 是給觸發器用的。
  • NEW.last_modified := NOW(); — 用 NOW() function 把現在的日期時間寫進 last_modified。
  • RETURN NEW; — 回傳更新後的資料。這是 AFTER 觸發器一定要做的。

建立觸發器

寫好 function 之後,我們就可以把觸發器綁到 students 這個表。做法如下:

-- 新增資料後自動執行的觸發器
CREATE TRIGGER set_last_modified
AFTER INSERT ON students
FOR EACH ROW
EXECUTE FUNCTION update_last_modified();

這裡做了什麼:

  • CREATE TRIGGER set_last_modified — 建立一個叫 set_last_modified 的觸發器。
  • AFTER INSERT — 這個觸發器會在資料插入成功後執行。
  • ON students — 綁定在 students 這個表。
  • FOR EACH ROW — 每加一筆資料就執行一次。
  • EXECUTE FUNCTION update_last_modified(); — 執行我們剛剛寫的 function。

小提醒:觸發器(set_last_modified)跟 function(update_last_modified)的名字你可以自己取,不過建議還是照慣例命名,這樣以後看程式碼比較不會亂。

測試觸發器

來測試一下我們的觸發器。先加幾筆資料到 students 表:

-- 插入資料到表格
INSERT INTO students (name, age) VALUES ('伊凡 伊凡諾夫', 20);
INSERT INTO students (name, age) VALUES ('安娜 彼得羅娃', 22);

現在來看看表格裡的資料:

-- 查詢表格資料
SELECT * FROM students;

預期結果大概會長這樣:

id name age last_modified
1 奧托 明 20 2023-10-10 14:30:45
2 安娜 松 22 2023-10-10 14:31:12

你會發現 last_modified 欄位已經自動填上每筆資料新增時的日期和時間了。

可能遇到的錯誤

  1. 錯誤:"relation does not exist" 建立觸發器時出現。這通常是因為 students 表還沒建立。記得先建立表格再建觸發器。
  2. 權限錯誤。如果你的資料庫使用者沒有建立 function 或觸發器的權限,觸發器就建不起來。檢查一下權限設定。
  3. 觸發器沒呼叫 function。如果你忘了寫 EXECUTE FUNCTION update_last_modified(),觸發器就不會做事。

進階:加條件的觸發器

實務上有時候會想讓觸發器只在特定情況下執行。比如說,如果 age 小於 18,我們就不想更新 last_modified。這時可以用 WHEN 條件:

-- 有條件的觸發器
CREATE TRIGGER set_last_modified
AFTER INSERT ON students
FOR EACH ROW
WHEN (NEW.age >= 18)
EXECUTE FUNCTION update_last_modified();

這樣 last_modified 只會在學生年齡 >= 18 的時候才會被更新。

實際應用

像這種觸發器在專案裡超常見。舉幾個例子:

  • 自動更新資料最後修改時間(就像我們現在做的)。
  • 追蹤資料異動,把變動紀錄寫進 log 表。
  • 確保資料正確性,比如在執行操作前檢查關聯表。
  • 做資料稽核,符合法規或公司規定。

這些技巧對你以後做銀行系統、庫存管理、CRM 這種很重視資料正確性的系統都超有幫助。

2
任務
SQL SELF, 等級 57, 課堂 3
上鎖
建立自動填寫修改時間的函數與觸發器
建立自動填寫修改時間的函數與觸發器
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION