CodeGym /課程 /SQL SELF /建立簡單函式:CREATE FUNCTION

建立簡單函式:CREATE FUNCTION

SQL SELF
等級 50 , 課堂 0
開放

在 PostgreSQL 裡,函式是一個超強大的工具,可以自動化工作、寫 business logic,還能讓 server 更聰明。你可以把函式想像成在資料庫裡跑的小程式。它們很適合:

  • 重複利用程式碼。 如果你常常寫一樣的查詢,把它包成函式,想用就 call 一下。
  • 自動化任務。 比方說你要根據員工工時算薪水,用函式就超方便。
  • 封裝邏輯。 把複雜的計算丟給 server 處理,client 端不用煩 SQL 查詢。

CREATE FUNCTION 的基本語法

建立函式的基本結構長這樣:

CREATE FUNCTION function_name(parameters) RETURNS return_type AS $$
BEGIN
    -- 函式主體(邏輯)
    RETURN 結果;
END;
$$ LANGUAGE plpgsql;

來拆解一下重點:

CREATE FUNCTION function_name(parameters)

這行是設定函式名稱 function_name,還有參數(如果有的話)。

參數可以有名字跟型別:my_param INTEGERanother_param TEXT

RETURNS return_type

這裡要指定函式會回傳什麼:單一值(INTEGERTEXT 等等)或資料集(TABLERECORD)。

BEGIN ... END

這兩個關鍵字包住的就是「主體」,所有魔法都在這裡發生。

RETURN 結果

回傳函式執行的結果。要注意:回傳型別要跟 RETURNS 指定的一樣。

LANGUAGE plpgsql

這裡指定用 PL/pgSQL 語言。PostgreSQL 也支援其他語言,但我們現在就用這個。

簡單範例:兩個數字相加

來寫一個回傳兩個整數和的函式。

CREATE FUNCTION add_numbers(a INT, b INT) RETURNS INT AS $$
BEGIN
    RETURN a + b;
END;
$$ LANGUAGE plpgsql;

現在來呼叫它:

SELECT add_numbers(5, 7); -- 結果:12

這裡發生什麼事?

  • 函式接收兩個參數 ab,型別都是 INT
  • 函式裡直接把它們加起來(a + b)然後回傳。
  • 超簡單,就像計算機一樣!

用變數的範例

假設我們有一個大學資料庫,想知道有多少學生註冊。

來寫個函式:

CREATE FUNCTION count_students() RETURNS INT AS $$
DECLARE
    total INT; -- 宣告一個變數來存結果
BEGIN
    SELECT COUNT(*) INTO total FROM students; -- 算表格裡有幾列
    RETURN total; -- 回傳結果
END;
$$ LANGUAGE plpgsql;

呼叫函式:

SELECT count_students(); -- 假設結果:120

這裡我們看到:

  • 用變數 total 來存 SQL 查詢的結果。
  • SELECT ... INTO 指令會把查詢結果存進變數。

這種寫法很方便,如果你要先處理資料再回傳。

回傳多個值:RETURNS TABLE

剛剛的例子只回傳一個值。如果我們要回傳一組資料,比如學生清單?這時 RETURNS TABLE 就超好用。

範例:

CREATE FUNCTION get_students() RETURNS TABLE(id INT, name TEXT) AS $$
BEGIN
    RETURN QUERY SELECT id, name FROM students;
END;
$$ LANGUAGE plpgsql;

呼叫函式:

SELECT * FROM get_students();

可能的結果:

id name
1 Alice
2 Bob
3 Charlie

RETURN QUERY 的好處:直接在函式裡查詢

RETURN QUERY 讓我們可以直接把 SQL 查詢的結果回傳,省去中間步驟,函式更簡潔。

來寫個只回傳 active 學生的函式:

CREATE FUNCTION get_active_students() RETURNS TABLE(id INT, name TEXT) AS $$
BEGIN
    RETURN QUERY SELECT id, name FROM students WHERE active = TRUE;
END;
$$ LANGUAGE plpgsql;

在呼叫 get_active_students() 之前,要先建立 students 表格並塞一些測試資料。可以這樣做:

-- 建立學生表格
CREATE TABLE students (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    active BOOLEAN DEFAULT TRUE
);

-- 加幾筆資料
INSERT INTO students (name, active) VALUES
('Alice', FALSE),
('Bob', TRUE),
('Charlie', TRUE),
('Dana', FALSE);

表格:

id name active
1 Alice false
2 Bob true
3 Charlie true
4 Dana false

現在呼叫:

SELECT * FROM get_active_students();

結果:

id name
2 Bob
3 Charlie

執行前檢查資料正確性

函式可以用 IF 來檢查資料正不正確。比如我們可以寫一個函式,只有學生通過所有考試才讓他升級。

範例:

CREATE FUNCTION promote_student(student_id INT) RETURNS TEXT AS $$
DECLARE
    passed_exams INT;
BEGIN
    -- 算學生通過的考試數量
    SELECT COUNT(*) INTO passed_exams
    FROM exams
    WHERE student_id = promote_student.student_id AND status = 'passed';

    -- 檢查條件
    IF passed_exams < 5 THEN
        RETURN '學生通過的考試不夠多';
    END IF;

    -- 更新學生的課程
    UPDATE students
    SET course = course + 1
    WHERE id = promote_student.student_id;

    RETURN '學生升級了!';
END;
$$ LANGUAGE plpgsql;

寫函式時常見錯誤

沒寫回傳型別。 PostgreSQL 一定要你指定函式會回傳什麼。例如:

CREATE FUNCTION fail() AS $$ -- 錯誤:沒有 RETURNS
BEGIN
    RETURN 1;
END;
$$ LANGUAGE plpgsql;

修正:

CREATE FUNCTION succeed() RETURNS INT AS $$
BEGIN
    RETURN 1;
END;
$$ LANGUAGE plpgsql;

回傳型別不符。 如果你寫 RETURNS INT,就一定要回傳數字。回傳字串會出錯。

函式裡的 SQL 查詢寫錯。 一定要先測試查詢,才放進函式。最好先在 psqlpgAdmin 手動跑過。

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