【6】PostgreSQL 循环

前言

在PostgreSQL中,可以通过以下几种方法进行循环:

  1. WHILE循环:使用WHILE条件循环语句,当满足条件时执行循环体内的代码,直到条件不再满足时跳出循环。
WHILE condition LOOP
-- 循环体内的代码
END LOOP;
  1. FOR循环:使用FOR循环语句,可以遍历一个集合或者执行一定次数的循环。
FOR i IN 1..10 LOOP
-- 循环体内的代码
END LOOP;
  1. LOOP循环:使用简单的LOOP语句创建一个无限循环,在循环体内部可以通过条件语句和BREAK语句来控制循环的终止条件。
LOOP
  -- 循环体内的代码
  IF condition THEN
    EXIT;
  END IF;
END LOOP;

笔记

WHILE 循环

基本结构

在PL/pgSQL中,WHILE循环的基本结构如下:

DECLARE
    counter INT := 0;
BEGIN
    WHILE counter < 10 LOOP
        -- 执行一些操作
        counter := counter + 1;
    END LOOP;
END;

简单示例

WHILE 循环在执行循环体之前先检查条件,如果条件为真,则执行循环体。

DO $$
DECLARE
    counter INT := 0;
BEGIN
    WHILE counter < 10 LOOP
        RAISE NOTICE 'Counter: %', counter;
        counter := counter + 1;
    END LOOP;
END $$;

详细示例

假设我们要实现一个函数,该函数接受一个字符串,并在每个单词前添加一个编号。我们可以使用WHILE循环来遍历字符串中的每个单词,并为每个单词添加编号。

创建示例函数
CREATE OR REPLACE FUNCTION add_number_to_words(input_str TEXT) 
RETURNS TEXT 
LANGUAGE plpgsql 
AS $$
DECLARE
    result TEXT := '';        -- 用于存储结果字符串
    word TEXT;                -- 用于存储当前处理的单词
    counter INT := 1;         -- 用于编号
    word_array TEXT[];        -- 用于存储拆分的单词数组
    i INT := 1;               -- 循环计数器
BEGIN
    -- 使用正则表达式将输入字符串拆分为单词数组
    word_array := regexp_split_to_array(input_str, '\s+');
    
    -- 获取单词数组的长度
    WHILE i <= array_length(word_array, 1) LOOP
        word := word_array[i];
        
        -- 如果结果字符串不为空,则添加空格
        IF result <> '' THEN
            result := result || ' ';
        END IF;
        
        -- 将编号和单词添加到结果字符串中
        result := result || counter || '. ' || word;
        
        -- 增加编号和循环计数器
        counter := counter + 1;
        i := i + 1;
    END LOOP;
    
    RETURN result;
END;
$$;
解释
  1. 变量声明
  • result:用于存储最终结果字符串。
  • word:用于存储当前处理的单词。
  • counter:用于为每个单词添加编号。
  • word_array:用于存储输入字符串拆分后的单词数组。
  • i:循环计数器,用于遍历单词数组。
  1. 字符串拆分
  • regexp_split_to_array(input_str, '\s+'):使用正则表达式将输入字符串按空格拆分成单词数组。
  1. **WHILE**** 循环**:
  • WHILE i <= array_length(word_array, 1) LOOP:循环遍历单词数组。
  • 在循环体内,首先将当前单词存储到word变量中。
  • 如果result字符串不为空,则在result字符串后添加一个空格。
  • 将编号和当前单词添加到result字符串中。
  • 增加编号counter和循环计数器i
  1. 返回结果
  • 循环结束后,返回结果字符串result
调用示例函数
SELECT add_number_to_words('Hello world this is a test');
预期输出
1. Hello 2. world 3. this 4. is 5. a 6. test

在这个例子中,WHILE循环用于遍历输入字符串拆分后的单词数组,并为每个单词添加一个编号。

FOR 循环

在PL/pgSQL中,FOR循环有几种形式:

  1. Numeric FOR Loop:用于遍历一系列数值。
  2. Reverse Numeric FOR Loop:用于反向遍历一系列数值。
  3. FOREACH Loop:用于遍历数组或集合类型。

Numeric FOR Loop

用于执行一系列数值的循环。

基本结构

Numeric FOR Loop 在 PL/pgSQL 中的基本结构如下所示:

FOR 变量名 IN 开始值..结束值 LOOP
    -- 循环体
END LOOP;

在这个结构中:

  • 变量名:循环计数器的名称,用于迭代循环。
  • 开始值:循环计数器的起始值。
  • 结束值:循环计数器的结束值。
  • 循环体:在 LOOP 和 END LOOP 之间的部分,包含需要重复执行的代码块。

在循环的每次迭代中,变量名将从 开始值 递增(或递减)到 结束值,并在每次迭代中执行循环体中的代码。

简单示例

例如,以下是一个简单的示例,演示如何使用 Numeric FOR Loop 打印出 1 到 10 之间的所有整数:

DO $$
DECLARE
    i INT;
BEGIN
    FOR i IN 1..10 LOOP
        RAISE NOTICE 'Value: %', i;
    END LOOP;
END $$;

在上面的示例中,i 是循环计数器,它的初始值是 1,结束值是 10。在每次循环中,i 的值从 1 递增到 10,并且在每次迭代中打印出当前的值。

在或者,

DO $$
BEGIN
    FOR counter IN 0..9 LOOP
        RAISE NOTICE 'Counter: %', counter;
    END LOOP;
END $$;

详细示例

假设我们要实现一个函数,该函数接受一个整数N,并返回从1到N的所有数值的平方。我们可以使用FOR循环来实现这个功能。

创建示例函数
CREATE OR REPLACE FUNCTION generate_squares(N INT) 
RETURNS TEXT 
LANGUAGE plpgsql 
AS $$
DECLARE
    result TEXT := '';  -- 用于存储结果字符串
    i INT;              -- 循环计数器
BEGIN
    -- 使用 FOR 循环遍历从 1 到 N 的数值
    FOR i IN 1..N LOOP
        -- 将当前数值的平方添加到结果字符串
        IF result <> '' THEN
            result := result || ', ';
        END IF;
        result := result || i || '^2=' || (i * i);
    END LOOP;
    
    RETURN result;
END;
$$;
解释
  1. 变量声明
  • result:用于存储最终结果字符串。
  • i:循环计数器,用于遍历从1到N的数值。
  1. **FOR**** 循环**:
  • FOR i IN 1..N LOOP:循环遍历从1到N的数值。
  • 在循环体内,首先检查result字符串是否为空,如果不为空,则在result字符串后添加一个逗号和空格。
  • 将当前数值的平方(格式为i^2=x)添加到result字符串中。
  1. 返回结果
  • 循环结束后,返回结果字符串result
调用示例函数
SELECT generate_squares(5);
预期输出
1^2=1, 2^2=4, 3^2=9, 4^2=16, 5^2=25

在这个例子中,FOR循环用于遍历从1到N的数值,并生成这些数值的平方。

Reverse Numeric FOR Loop

用于执行一系列数值的反向循环。

基本格式
FOR 变量名 IN REVERSE 结束值..开始值 LOOP
    -- 循环体
END LOOP;

在这个结构中:

  • 变量名:循环计数器的名称,用于迭代循环。
  • 结束值:循环计数器的结束值。
  • 开始值:循环计数器的起始值。
  • 循环体:在 LOOPEND LOOP 之间的部分,包含需要重复执行的代码块。

在 Reverse Numeric FOR Loop 中,循环计数器的值从 结束值 开始递减,直到达到 开始值

简单示例

例如,以下是一个简单的示例,演示如何使用 Reverse Numeric FOR Loop 打印出 10 到 1 之间的所有整数:

DO $$
DECLARE
    i INT;
BEGIN
    FOR i IN REVERSE 10..1 LOOP
        RAISE NOTICE 'Value: %', i;
    END LOOP;
END $$;

在上面的示例中,i 是循环计数器,它的结束值是 10,起始值是 1。在每次循环中,i 的值从 10 递减到 1,并且在每次迭代中打印出当前的值。

在或者,

DO $$
BEGIN
    FOR counter IN REVERSE 9..0 LOOP
        RAISE NOTICE 'Counter: %', counter;
    END LOOP;
END $$;

详细说明

假设你需要编写一个函数,该函数接受一个整数 N 作为输入,然后从 N 开始递减,直到 1,并计算每个数的阶乘。

创建函数
CREATE OR REPLACE FUNCTION calculate_factorial(N INT)
RETURNS BIGINT
LANGUAGE plpgsql
AS $$
DECLARE
    result BIGINT := 1;  -- 用于存储最终结果
    i INT;               -- 循环计数器
BEGIN
    FOR i IN REVERSE N..1 LOOP
        result := result * i;
    END LOOP;
    
    RETURN result;
END;
$$;
解释

在上面的示例中,我们创建了一个名为 calculate_factorial 的函数,它接受一个整数 N 作为输入,并返回 N 的阶乘。函数内部使用 Reverse Numeric FOR Loop 来递减地遍历从 N 到 1 的整数,并计算它们的乘积。在每次迭代中,循环计数器 i 的值递减,直到达到 1。

这个函数的执行过程如下:

  • 当 N = 5 时,循环将从 5 开始递减到 1,计算 5 _ 4 _ 3 _ 2 _ 1 的乘积,即 120。

Reverse Numeric FOR Loop 是在这个示例中实现递减序列的理想选择,它提供了一种简洁而清晰的方式来处理从大到小的循环迭代。

调用函数
SELECT calculate_factorial(5);
预期输出
120

FOREACH Loop

用于遍历数组或其他集合类型。

基本结构

FOREACH Loop 在 PL/pgSQL 中的基本结构如下所示:

FOREACH 循环变量 IN ARRAY 数组变量 LOOP
    -- 循环体
END LOOP;

在这个结构中:

  • 循环变量:用于迭代循环的临时变量,它将依次取数组中的每个元素。
  • 数组变量:要迭代的数组。
  • 循环体:在 LOOPEND LOOP 之间的部分,包含需要重复执行的代码块。

在每次迭代中,循环变量 将依次取数组中的每个元素,并执行循环体中的代码。

简单示例

例如,以下是一个简单的示例,演示如何使用 FOREACH Loop 遍历一个整数数组并打印出每个元素的值:

DO $$
DECLARE
    arr INT[] := ARRAY[1, 2, 3, 4, 5];
    elem INT;
BEGIN
    FOREACH elem IN ARRAY arr LOOP
        RAISE NOTICE 'Element: %', elem;
    END LOOP;
END $$;

在上面的示例中,elem 是循环变量,它依次取数组 arr 中的每个元素。在每次迭代中,elem 的值将是数组中的当前元素,并且在每次迭代中打印出当前元素的值。

在或者,

DO $$
DECLARE
    arr INT[] := ARRAY[1, 2, 3, 4, 5];
    elem INT;
BEGIN
    FOREACH elem IN ARRAY arr LOOP
        RAISE NOTICE 'Element: %', elem;
    END LOOP;
END $$;

详细示例

假设我们要实现一个函数,该函数接受一个整数数组,并返回数组中每个元素的平方。我们可以使用FOREACH循环来实现这个功能。

创建示例函数
CREATE OR REPLACE FUNCTION square_elements(input_array INT[]) 
RETURNS INT[] 
LANGUAGE plpgsql 
AS $$
DECLARE
    result_array INT[] := '{}';  -- 用于存储结果数组
    elem INT;                    -- 用于存储当前处理的数组元素
BEGIN
    -- 使用 FOREACH 循环遍历数组中的每个元素
    FOREACH elem IN ARRAY input_array LOOP
        -- 将当前元素的平方添加到结果数组
        result_array := array_append(result_array, elem * elem);
    END LOOP;
    
    RETURN result_array;
END;
$$;
调用示例函数
SELECT square_elements(ARRAY[1, 2, 3, 4, 5]);
预期输出
{1, 4, 9, 16, 25}

在这个例子中,FOREACH循环用于遍历输入数组,并生成每个元素的平方。

Loop 循环

在 PL/pgSQL 中,LOOP 循环是一种无限循环结构,它不会像 FORWHILE 循环那样有明确的退出条件。

基本结构

基本的 LOOP 循环结构如下所示:

LOOP
    -- 循环体
END LOOP;

在这个结构中:

  • LOOP:表示进入循环的开始标记。
  • 循环体:在 LOOPEND LOOP 之间的部分,包含需要重复执行的代码块。
  • END LOOP:表示循环的结束标记。

LOOP 循环将一直执行循环体中的代码,直到遇到 EXIT 语句才会终止循环。

退出 LOOP 循环

要从 LOOP 循环中退出,可以使用 EXIT 语句。例如:

LOOP
    -- 循环体
    IF some_condition THEN
        EXIT; -- 退出循环
    END IF;
END LOOP;

在上面的示例中,如果 some_condition 条件满足,则会执行 EXIT 语句,从而终止循环。

简单示例

以下是一个简单的示例,演示如何使用 LOOP 循环输出 1 到 5 的所有整数:

DO $$
DECLARE
    i INT := 1;
BEGIN
    LOOP
        EXIT WHEN i > 5; -- 当 i 大于 5 时退出循环
        RAISE NOTICE 'Value: %', i;
        i := i + 1;
    END LOOP;
END $$;

在上面的示例中,LOOP 循环将一直执行,直到 i 的值大于 5,然后通过 EXIT 语句退出循环。在每次循环中,会打印出当前 i 的值。

详细示例

假设我们要实现一个简单的倒计时器,从某个初始值开始,每秒递减并打印出当前值,直到计时器归零。

创建函数
CREATE OR REPLACE FUNCTION countdown_timer(start_value INT)
RETURNS VOID
LANGUAGE plpgsql
AS $$
DECLARE
    current_value INT := start_value;
BEGIN
    LOOP
        EXIT WHEN current_value <= 0; -- 当当前值小于等于 0 时退出循环
        RAISE NOTICE 'Countdown: %', current_value;
        PERFORM pg_sleep(1); -- 暂停 1 秒
        current_value := current_value - 1; -- 递减当前值
    END LOOP;
END;
$$;
解释

在上面的示例中,我们创建了一个名为 countdown_timer 的函数,它接受一个整数 start_value 作为输入,并使用 LOOP 循环实现了倒计时器的逻辑。函数内部的循环将一直执行,直到 current_value 小于等于 0 时才退出循环。在每次循环中,会打印出当前的倒计时值,并通过 pg_sleep(1) 函数暂停 1 秒,然后将 current_value 递减 1。

调用函数
SELECT countdown_timer(10);
预期输出
Countdown: 10
Countdown: 9
Countdown: 8
Countdown: 7
Countdown: 6
Countdown: 5
Countdown: 4
Countdown: 3
Countdown: 2
Countdown: 1

这个示例展示了如何使用 LOOP 循环创建一个简单的倒计时器。LOOP 循环提供了一种简单而灵活的方式来实现这样的循环逻辑,而不需要明确的退出条件,只需在需要时使用 EXIT 语句即可退出循环。

扩展

EXIT 和 CONTINUE 控制

你可以使用EXIT从循环中提前退出,使用CONTINUE跳过本次循环并继续下一次循环。

使用 EXIT
DO $$
BEGIN
    FOR counter IN 0..9 LOOP
        RAISE NOTICE 'Counter: %', counter;
        IF counter = 5 THEN
            EXIT; -- 退出循环
        END IF;
    END LOOP;
END $$;

-- 输出结果:
NOTICE:  Counter: 0
NOTICE:  Counter: 1
NOTICE:  Counter: 2
NOTICE:  Counter: 3
NOTICE:  Counter: 4
NOTICE:  Counter: 5
DO
postgres=# 
使用 CONTINUE
DO $$
BEGIN
    FOR counter IN 0..9 LOOP
        IF counter = 5 THEN
            CONTINUE; -- 跳过本次循环
        END IF;
        RAISE NOTICE 'Counter: %', counter;
    END LOOP;
END $$;

-- 输出结果:
NOTICE:  Counter: 0
NOTICE:  Counter: 1
NOTICE:  Counter: 2
NOTICE:  Counter: 3
NOTICE:  Counter: 4
NOTICE:  Counter: 6
NOTICE:  Counter: 7
NOTICE:  Counter: 8
NOTICE:  Counter: 9
DO
postgres=# 

  • 28
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PostgreSQL中有多种循环语句可以使用,包括FOR循环、WHILE循环和FOREACH循环。其中,FOR循环可以用于遍历查询结果集,WHILE循环可以用于在满足条件的情况下重复执行一段代码,而FOREACH循环可以用于遍历数组。 在引用\[1\]中的例子中,使用了FOR循环来遍历用户和角色表,并将它们的ID插入到另一个表中。这个函数的目的是将之前已经使用的数据和现在的数据关联起来。具体的代码如下: ```sql create or replace function insert_user_roles() returns void as $$ declare user RECORD; role RECORD; begin for user in (select id from user where is_delete = false) loop for role in (select * from role where is_delete = false) loop insert into '实际要插入数据的表' ('字段') values (user.id, role.id); end loop; end loop; end; $$ language plpgsql; select insert_user_roles(); ``` 在引用\[2\]中的例子中,使用了WHILE循环来重复执行一段代码,直到满足退出条件。这个函数的目的是循环输出计数器的值,直到计数器达到100。具体的代码如下: ```sql CREATE OR REPLACE FUNCTION mydb.mysc.learn_conditional05(OUT loopcnt integer) AS $BODY$ DECLARE counter integer = 1; BEGIN WHILE counter<=100 LOOP RAISE notice '这是第%次循环',counter; counter:=counter+1; END LOOP; loopcnt = counter; END; $BODY$ LANGUAGE plpgsql; ``` 在引用\[3\]中的例子中,使用了FOREACH循环来遍历传入的整数数组,并将数组中的元素累加起来。这个函数的目的是实现传入数组的累加功能。具体的代码如下: ```sql CREATE OR REPLACE FUNCTION mydb.mysc.learn_conditional07(IN intarray int\[\],OUT resultnum integer)AS $BODY$ DECLARE x int; tmp integer := 0; BEGIN FOREACH x IN ARRAY intarray LOOP RAISE notice '这是%',x; tmp := tmp + x; END LOOP; resultnum = tmp; END; $BODY$ LANGUAGE plpgsql; ``` 这些例子展示了在PostgreSQL中使用循环的不同方式,可以根据具体的需求选择适合的循环语句来实现相应的功能。 #### 引用[.reference_title] - *1* [PostgreSQL 函数 for循环使用](https://blog.csdn.net/londa/article/details/109399884)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [PostgreSQL存储过程(六):结构控制和循环](https://blog.csdn.net/yanlei_open/article/details/115641462)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值