CodeGym /課程 /SQL SELF /在 PL/pgSQL 裡用循環:LOOP、FOR、WHILE

在 PL/pgSQL 裡用循環:LOOP、FOR、WHILE

SQL SELF
等級 51 , 課堂 1
開放

循環可以讓你重複執行一段程式碼,只要某個條件成立,或是針對某個資料集做迭代。這超級適合自動化工作、處理大量資料或是做重複的操作。

想像一下,你要手動把糖果發給每個小朋友,肯定會亂成一團!不如你直接走過小朋友的名單,一個一個發糖果。這個「走過名單」就是循環啦。

PostgreSQL 支援幾種循環:

  1. LOOP — 通用型循環,要你自己明確結束它。
  2. FOR — 針對數字範圍或查詢結果做固定次數的循環。
  3. WHILE — 只要條件成立就一直跑的循環。

我們一個一個來看。

無限循環:LOOP

LOOP 是 PL/pgSQL 裡最基本的循環型態,會一直重複執行區塊。這個循環會無限跑下去,除非你用 EXIT 手動跳出來。

語法:

LOOP
    -- 你的程式碼寫這裡
END LOOP;

來個例子,用 LOOP 算 1 到 10 的總和:

DO $$
DECLARE
    counter INT := 1;
    sum INT := 0;
BEGIN
    LOOP
        sum := sum + counter; -- 加上目前的計數器值
        counter := counter + 1; -- 計數器加一

        -- 如果計數器大於 10 就結束循環
        IF counter > 10 THEN
            EXIT;
        END IF;
    END LOOP;

    RAISE NOTICE '1 到 10 的總和: %', sum;
END $$;
  1. 變數 counter 每次循環都會加一。
  2. 條件 IF counter > 10 THEN EXIT; 讓計數器超過 10 時結束循環。
  3. 最後會印出總和。

針對範圍或資料集的循環:FOR

第二種循環,FOR,可以用來:

  1. 跑數字範圍。
  2. 跑 SQL 查詢結果。

數字範圍的循環

語法:

FOR variable IN [REVERSE] start..end LOOP
    -- 你的程式碼寫這裡
END LOOP;

印出 1 到 5:

DO $$
BEGIN
    FOR i IN 1..5 LOOP
        RAISE NOTICE '目前的值: %', i;
    END LOOP;
END $$;

反向範例:

DO $$
BEGIN
    FOR i IN REVERSE 5..1 LOOP
        RAISE NOTICE '反向順序: %', i;
    END LOOP;
END $$;

SQL 查詢結果的循環

這種方式很適合處理資料表的每一列。

語法:

FOR variable IN QUERY (SELECT ...) LOOP
    -- 你的程式碼寫這裡
END LOOP;

來個例子,針對 students 資料表的每一列做迭代:

DO $$
DECLARE
    student_name TEXT;
BEGIN
    FOR student_name IN QUERY (SELECT name FROM students) LOOP
        RAISE NOTICE '哈囉, %!', student_name;
    END LOOP;
END $$;

條件循環:WHILE

WHILE 只要條件成立就會一直跑。

語法:

WHILE 條件 LOOP
    -- 你的程式碼寫這裡
END LOOP;

來算 1 到 10 的總和,用 WHILE

DO $$
DECLARE
    counter INT := 1;
    sum INT := 0;
BEGIN
    WHILE counter <= 10 LOOP
        sum := sum + counter;
        counter := counter + 1;
    END LOOP;

    RAISE NOTICE '1 到 10 的總和: %', sum;
END $$;

生活中的例子

現在我們已經搞懂循環的基本用法,來看看一些實際應用的例子。

例子 1:產生乘法表

DO $$
DECLARE
    i INT;
    j INT;
BEGIN
    FOR i IN 1..5 LOOP
        FOR j IN 1..5 LOOP
            RAISE NOTICE '% x % = %', i, j, i * j;
        END LOOP;
    END LOOP;
END $$;

例子 2:針對查詢結果做迭代。 假設我們有個 products 資料表,欄位有 idprice。我們要把所有價格都加 10%。

DO $$
DECLARE
    prod RECORD;
BEGIN
    FOR prod IN QUERY (SELECT id, price FROM products) LOOP
        UPDATE products
        SET price = prod.price * 1.1
        WHERE id = prod.id;
    END LOOP;
END $$;

常見錯誤跟怎麼避免

LOOPWHILE 裡跑無限循環。 如果你忘了加結束條件(EXITWHILE 裡的正確條件),循環就永遠不會停。這就像開車沒煞車一樣可怕。

查詢結果迭代時出錯。 如果查詢回來的資料結構跟你預期的不一樣,FOR IN QUERY 的循環就會出錯。

在循環裡寫沒效率的查詢。 像是每次循環都 UPDATE,這樣會讓執行速度超慢。這種情況下最好直接用一個 SQL 查詢搞定,不要用循環。

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