FOR (Snowflake Scripting)

FOR 循环将一系列步骤重复特定的次数。次数可能由用户指定,也可能由 光标 中的行数指定。这两种 FOR 循环的语法略有不同。

有关循环的更多信息,请参阅 使用循环

备注

Snowflake Scripting 结构仅在 Snowflake Scripting 区块 内有效。

另请参阅:

BREAKCONTINUE

语法

要循环 光标 中的所有行,请使用:

FOR <row_variable> IN <cursor_name> DO
    statement;
    [ statement; ... ]
END FOR [ <label> ] ;
Copy

要循环指定次数,请使用:

FOR <counter_variable> IN [ REVERSE ] <start> TO <end> { DO | LOOP }
    statement;
    [ statement; ... ]
END { FOR | LOOP } [ <label> ] ;
Copy

其中:

row_variable

指定遵循 对象标识符 规则的变量名。

不要在 DECLARE 或 BEGIN ...END 部分。不应在本地块的作用域中定义该名称。

该名称在 FOR 循环内有效,但在 FOR 循环外无效。

row_variable 保存光标中的一行。使用点表示法访问该行中的字段。例如:

my_row_variable.my_column_name

下面的示例中包含一个更完整的示例。

counter_variable

指定遵循 对象标识符 规则的变量名。

counter_variable 的名称仅在 FOR 循环内有效。如果在循环外部声明了同名变量,则外部变量和循环变量是分开的。在循环中,对该名称的引用将解析为循环变量。

允许 FOR 循环中的代码读取计数器变量的值,但不应更改它。例如,不要手动递增计数器变量以更改步长。

start

这是 counter_variable 的初始值。

起始值应该是 INTEGER 或计算结果为 INTEGER 的表达式。

end

counter_variable 随着循环而递增后,这是 counter_variable 的最终值。

结束值应为 INTEGER 或计算结果为 INTEGER 的表达式。

end 值应该大于或等于 start 值。如果 end 小于 start,则循环执行 0 次(即使使用了 REVERSE 关键字)。

statement

语句可以是以下任一语句:

  • 单个 SQL 语句(包括 CALL)。

  • 控制流语句(例如 循环 语句或 分支 语句)。

  • 嵌套 区块

cursor_name

要循环访问的光标的名称。

label

可选标签。此类标签可以是 BREAK (Snowflake Scripting)CONTINUE (Snowflake Scripting) 语句的跳转目标。标签必须遵循 对象标识符 的命名规则。

使用说明

  • 循环迭代到 end 点(包括该点)。

    例如,FOR i IN 1 TO 10 循环 10 次,在最后一次迭代中,i 的值为 10。

    如果使用 REVERSE 关键字,则循环向下向后迭代到 start 值(包括起始值)。

  • 一个循环可以包含多个语句。您可以使用(但不是必须使用):doc:begin :doc:` 块 </developer-guide/snowflake-scripting/blocks>` 来包含这些语句。

  • 可选关键字 REVERSE 使 Snowflake 从 end 值开始,递减到 start 值。

  • 尽管您可以在循环内部更改 counter_variable 的值,但 Snowflake 建议避免这样做。更改值会使代码更难理解。

  • 如果使用关键字 DO,则在 FOR 循环的末尾使用 END FOR。如果使用关键字 LOOP,则在 END LOOP 循环的末尾使用 FOR

示例

基于游标的 FOR 循环:

此示例演示如何使用 光标 对查询返回的所有行的 price 列中的值进行求和。此存储过程的行为有点像聚合函数。

CREATE or replace TABLE invoices (price NUMBER(12, 2));
INSERT INTO invoices (price) VALUES
    (11.11),
    (22.22);
Copy
CREATE OR REPLACE PROCEDURE for_loop_over_cursor()
RETURNS FLOAT
LANGUAGE SQL
AS
$$
DECLARE
    total_price FLOAT;
    c1 CURSOR FOR SELECT price FROM invoices;
BEGIN
    total_price := 0.0;
    OPEN c1;
    FOR rec IN c1 DO
        total_price := total_price + rec.price;
    END FOR;
    CLOSE c1;
    RETURN total_price;
END;
$$
;
Copy

下面是存储过程的输出:

CALL for_loop_over_cursor();
+----------------------+
| FOR_LOOP_OVER_CURSOR |
|----------------------|
|                33.33 |
+----------------------+
Copy
基于计数器的 FOR 循环:

此示例演示如何使用 FOR 循环迭代指定的次数:

CREATE PROCEDURE simple_for(iteration_limit INTEGER)
RETURNS INTEGER
LANGUAGE SQL
AS
$$
    DECLARE
        counter INTEGER DEFAULT 0;
    BEGIN
        FOR i IN 1 TO iteration_limit DO
            counter := counter + 1;
        END FOR;
        RETURN counter;
    END;
$$;
Copy

下面是存储过程的输出:

CALL simple_for(3);
+------------+
| SIMPLE_FOR |
|------------|
|          3 |
+------------+
Copy

以下示例演示如何使用 REVERSE 关键字倒计数。

CREATE PROCEDURE reverse_loop(iteration_limit INTEGER)
RETURNS VARCHAR
LANGUAGE SQL
AS
$$
    DECLARE
        values_of_i VARCHAR DEFAULT '';
    BEGIN
        FOR i IN REVERSE 1 TO iteration_limit DO
            values_of_i := values_of_i || ' ' || i::varchar;
        END FOR;
        RETURN values_of_i;
    END;
$$;
Copy

下面是存储过程的输出:

CALL reverse_loop(3);
+--------------+
| REVERSE_LOOP |
|--------------|
|  3 2 1       |
+--------------+
Copy

以下示例演示循环计数器变量与已声明的变量同名 (i) 时的行为。在 FOR 循环中,对 i 的引用解析为循环计数器变量(而不是在循环外声明的变量)。

CREATE PROCEDURE p(iteration_limit INTEGER)
RETURNS VARCHAR
LANGUAGE SQL
AS
$$
    DECLARE
        counter INTEGER DEFAULT 0;
        i INTEGER DEFAULT -999;
        return_value VARCHAR DEFAULT '';
    BEGIN
        FOR i IN 1 TO iteration_limit DO
            counter := counter + 1;
        END FOR;
        return_value := 'counter: ' || counter::varchar || '\n';
        return_value := return_value || 'i: ' || i::VARCHAR;
        RETURN return_value;
    END;
$$;
Copy

下面是存储过程的输出:

CALL p(3);
+------------+
| P          |
|------------|
| counter: 3 |
| i: -999    |
+------------+
Copy
语言: 中文