CodeGym /課程 /SQL SELF /從 SQL 查詢呼叫函式

從 SQL 查詢呼叫函式

SQL SELF
等級 50 , 課堂 2
開放

想像一下,你有個用來做複雜計算或資料處理的函式。如果不能把函式整合進 SQL 查詢,你大概會這樣搞:

  1. 從某個程式語言(像是 Python 或 JavaScript)呼叫函式。
  2. 把結果傳給 SQL 查詢。

這樣超麻煩!在 PostgreSQL 裡,你可以直接把函式塞進 SQL 查詢,這樣程式碼更精簡、操作更快、減少伺服器呼叫次數。這對於:

  • 自動化計算。
  • 插入前資料驗證。
  • 修改現有資料。

都超有用!

SELECT 裡呼叫函式

先從基本的開始,來看看怎麼在一般 SELECT 查詢裡用函式。假設我們有個 students 表格,裡面有學生資訊。我們想寫個函式,根據生日算出學生的現在年齡。

步驟 1:寫函式

來寫個 calculate_age 函式,傳入生日,回傳年齡:

CREATE OR REPLACE FUNCTION calculate_age(birth_date DATE) RETURNS INT AS $$
BEGIN
    RETURN DATE_PART('year', AGE(NOW(), birth_date))::INT;
END;
$$ LANGUAGE plpgsql;

步驟 2:在 SELECT 查詢裡用函式

現在我們可以對每一筆資料呼叫這個函式:

SELECT id, name, calculate_age(birth_date) AS age FROM students;

發生了什麼事?

  • students 表格的每一行,calculate_age 都會算出年齡。
  • 回傳的值會顯示在 age 欄位。

結果範例:

id name age
1 奧托 21
2 安娜 25
3 阿列克斯 22

你看,超簡單,結果又美又專業!

INSERT 裡呼叫函式

插入資料時,函式也很有用。比如說,我們有個 logs 表格,記錄使用者的動作。我們想用函式自動產生訊息內容來插入 log。

步驟 1:寫函式

寫個 generate_log_message 函式,傳入使用者名稱和動作,回傳訊息文字:

CREATE OR REPLACE FUNCTION generate_log_message(username TEXT, action TEXT) RETURNS TEXT AS $$
BEGIN
    RETURN username || ' performed action: ' || action || ' at ' || NOW();
END;
$$ LANGUAGE plpgsql;

步驟 2:在 INSERT 裡用函式

現在插入 log 時直接呼叫函式:

INSERT INTO logs (message)
VALUES (generate_log_message('奧托', '登入網站'));

結果:

id message
1 奧托 performed action: 登入網站 at 2023-10-26 12:00:00

函式幫我們搞定格式化和加上時間戳,超方便!這就是函式自動化日常操作的好例子。

UPDATE 裡呼叫函式

函式也可以用來修改表格資料。假設我們有 students 表格,想用函式把學生的 group 名稱升級到新學年。

步驟 1:寫函式

寫個 promote_student 函式,傳入舊 group(像 101),回傳新 group(像 201):

CREATE OR REPLACE FUNCTION promote_student(old_group TEXT) RETURNS TEXT AS $$
BEGIN
    RETURN '2' || RIGHT(old_group, LENGTH(old_group) - 1);
END;
$$ LANGUAGE plpgsql;

步驟 2:在 UPDATE 裡用函式

把所有學生的 group 都更新:

UPDATE students
SET group_name = promote_student(group_name);

結果:

id name group_name
1 奧托 201
2 安娜 202
3 阿列克斯 203

你看,呼叫函式就像魔法一樣,舊 group 直接變成新 group!

WHERE 條件裡呼叫函式

函式也可以用在過濾條件裡。來擴充一下剛剛學生年齡的例子。

步驟 1:用年齡過濾

用剛剛寫的 calculate_age 函式,選出年齡大於 20 歲的學生:

SELECT id, name, birth_date
FROM students
WHERE calculate_age(birth_date) > 20;

結果:

id name birth_date
2 安娜 1998-05-15
3 阿列克斯 1999-11-09

這裡主要就是函式在幫我們即時算每個學生的年齡。

跟聚合函式一起用

來點進階的。我們要算出 22 歲以下學生的總數。函式可以跟聚合函式(像 COUNT())一起用,超方便!

SELECT COUNT(*)
FROM students
WHERE calculate_age(birth_date) < 22;

發生了什麼事?

  • calculate_age 函式用來過濾。
  • COUNT(*) 算出符合條件的行數。

實戰應用範例

自動化資料驗證。 假設你想檢查所有學生的年齡都在正常範圍(像 18 到 30 歲)。寫個檢查函式,然後在 WHERE 條件裡用它。

SELECT id, name
FROM students
WHERE NOT (calculate_age(birth_date) BETWEEN 18 AND 30);

優化資料插入。 假設你在網路商店工作。與其在前端算訂單總價,不如寫個函式,直接在 orders 表格插入時計算:

INSERT INTO orders (user_id, total_price)
VALUES (1, calculate_total_price(ARRAY[5, 10, 15]));

呼叫函式時常見錯誤

當你開始大量在查詢裡用函式時,可能會遇到一些錯誤。這裡有幾個常見情況跟解法:

權限不足。 如果你不是函式或表格的擁有者,PostgreSQL 可能不讓你呼叫。記得確認你有執行函式的權限。

型別不符。 傳參數給函式時要注意型別。例如函式要 DATE,你卻給字串,就會出錯。用明確型別轉換:

SELECT calculate_age('2000-01-01'::DATE);

函式內部語法錯誤。 如果函式回傳錯誤,整個查詢都會失敗。記得先好好測試你的函式!

留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION