diff --git a/.translation-init b/.translation-init index 411f917197..7a429bb811 100644 --- a/.translation-init +++ b/.translation-init @@ -1 +1 @@ -Translation initialization: 2025-10-22T01:38:35.795002 +Translation initialization: 2025-10-22T10:18:22.737414 diff --git a/docs/cn/guides/54-query/02-advanced/stored-procedure.md b/docs/cn/guides/54-query/02-advanced/stored-procedure.md index b287a346cb..143681733e 100644 --- a/docs/cn/guides/54-query/02-advanced/stored-procedure.md +++ b/docs/cn/guides/54-query/02-advanced/stored-procedure.md @@ -3,31 +3,31 @@ title: 存储过程 sidebar_position: 3 --- -存储过程(Stored Procedure)是一组存储在数据库中的可执行命令或逻辑块,用 SQL 或其他编程语言编写,旨在通过可重用方式高效完成特定任务或操作。 +存储过程(Stored Procedure)是一组存储在数据库中的可执行命令或逻辑块,用 SQL 或其他编程语言编写,旨在可重用以高效地执行特定任务或操作。 -## 支持语言 +## 支持的语言 -**Databend 目前仅支持 [SQL 脚本](/sql/sql-reference/sql-scripting)**。借助 SQL 脚本,用户可定义包含循环(FOR、WHILE、REPEAT)和条件(IF、CASE)等控制流结构的存储过程,从而实现复杂逻辑并高效执行多步操作。 +**Databend 目前仅支持 [SQL 脚本](/sql/stored-procedure-scripting/)**。通过使用 SQL 脚本,用户可以定义带有控制流结构(如循环(FOR、WHILE、REPEAT)和条件(IF、CASE))的过程,从而实现复杂的逻辑和高效的多步操作。 ## 限制 -使用存储过程时存在以下限制: +在使用存储过程时,存在以下限制: -- 存储过程为实验性功能。使用前请将 `enable_experimental_procedure` 设为 1; +- 存储过程是一项实验性功能。在使用它们之前,请将 `enable_experimental_procedure` 设置为 1; ```sql SET enable_experimental_procedure = 1; ``` -- 无论声明的返回类型为何,存储过程均以字符串形式返回结果,且不会对返回值强制执行声明的类型。 +- 存储过程以字符串形式返回结果,无论指定的返回类型是什么,都不会对返回的值强制执行声明的类型。 ## 管理存储过程 -Databend 提供了一系列用于管理存储过程的命令。更多详情请参阅 [存储过程](/sql/sql-commands/ddl/procedure/)。 +Databend 提供了一系列用于管理存储过程的命令。更多详细信息,请参阅 [存储过程](/sql/sql-commands/ddl/procedure/)。 ## 使用示例 -假设我们要计算给定范围内所有偶数的和。以下存储过程接受起始值 `start_val` 和结束值 `end_val`,并计算该范围内所有偶数的和。 +假设我们想要计算给定范围内所有偶数的和。此存储过程接受一个起始值 start_val 和一个结束值 end_val,并计算此范围内所有偶数的和。 ```sql SET enable_experimental_procedure = 1; @@ -50,14 +50,14 @@ END; $$; ``` -若要计算 1 到 10 的所有偶数的和,可按如下方式调用该存储过程: +如果我们想计算从 1 到 10 的所有偶数的和,可以如下调用该过程: ```sql CALL PROCEDURE sum_even_numbers(1, 10); --- 结果:2 + 4 + 6 + 8 + 10 = 30 +-- 结果: 2 + 4 + 6 + 8 + 10 = 30 ┌────────┐ -│ 结果 │ +│ Result │ ├────────┤ │ 30 │ └────────┘ diff --git a/docs/cn/sql-reference/00-sql-reference/index.md b/docs/cn/sql-reference/00-sql-reference/index.md index ef30a59cda..05832f241a 100644 --- a/docs/cn/sql-reference/00-sql-reference/index.md +++ b/docs/cn/sql-reference/00-sql-reference/index.md @@ -3,10 +3,12 @@ title: SQL 参考 slug: '/' --- -欢迎来到 SQL 参考 - 您的 Databend 基础知识快速访问指南! +欢迎来到 SQL 参考——您快速掌握 Databend 核心功能的指南! -- **通用参考:** 提供对基础要素(如数据类型、系统表和表引擎)的深入了解,帮助您构建对 Databend 结构的扎实理解。 +- **通用参考:** 深入介绍数据类型(Data Types)、系统表(System Tables)和表引擎(Table Engines)等基础元素,助您全面理解 Databend 的架构。 -- **SQL 命令:** 详细的信息、语法和用于执行命令的实际示例,使您能够在 Databend 中自信地进行数据管理。 +- **SQL 命令:** 提供执行命令的详细信息、语法和实用示例,让您在 Databend 中自信地管理数据。 -- **SQL 函数:** Databend 函数的简明指南,提供对其多样化功能的深入了解,以实现有效的数据管理和分析。 \ No newline at end of file +- **SQL 函数:** Databend 函数的简明指南,深入剖析其多样化功能,实现高效的数据管理与分析。 + +- **存储过程与脚本:** 涵盖 SQL 脚本语言,包括变量、控制流、结果处理及存储过程中的动态执行。 \ No newline at end of file diff --git a/docs/cn/sql-reference/10-sql-commands/00-ddl/18-procedure/index.md b/docs/cn/sql-reference/10-sql-commands/00-ddl/18-procedure/index.md index 61f6d9335b..be56ebb9e7 100644 --- a/docs/cn/sql-reference/10-sql-commands/00-ddl/18-procedure/index.md +++ b/docs/cn/sql-reference/10-sql-commands/00-ddl/18-procedure/index.md @@ -1,16 +1,16 @@ --- -title: 存储过程(Stored Procedure) +title: 存储过程 --- -本页面全面概述了 Databend 中存储过程(Stored Procedure)的操作,按功能分类组织,便于查阅。 +本页面按功能组织,全面概述了 Databend 中的存储过程(Stored Procedure)操作,方便您参考。 ## 过程管理 | 命令 | 描述 | |---------|-------------| -| [CREATE PROCEDURE](create-procedure.md) | 创建新的存储过程 | -| [DROP PROCEDURE](drop-procedure.md) | 删除存储过程 | -| [CALL](call-procedure.md) | 执行存储过程 | +| [CREATE PROCEDURE](create-procedure.md) | 创建一个新的存储过程 | +| [DROP PROCEDURE](drop-procedure.md) | 移除一个存储过程 | +| [CALL](call-procedure.md) | 执行一个存储过程 | ## 过程信息 @@ -20,5 +20,9 @@ title: 存储过程(Stored Procedure) | [SHOW PROCEDURES](show-procedures.md) | 列出当前数据库中的所有存储过程 | :::note -Databend 的存储过程允许将系列 SQL 语句封装为可重用单元,通过单条命令执行,从而提升代码组织性和可维护性。 -::: \ No newline at end of file +Databend 中的存储过程(Stored Procedure)允许您将一系列 SQL 语句封装到一个可重用的单元中,该单元可以作为单个命令执行,从而提高代码的组织性和可维护性。 +::: + +## 延伸阅读 + +探索 [存储过程与 SQL 脚本](/sql/stored-procedure-scripting/) 获取完整的语言参考,包括变量处理、控制流、游标(Cursor)以及在过程中的动态 SQL 使用。 \ No newline at end of file diff --git a/docs/cn/sql-reference/10-sql-commands/50-administration-cmds/execute-immediate.md b/docs/cn/sql-reference/10-sql-commands/50-administration-cmds/execute-immediate.md index 8fe6055c3c..2ab8f63669 100644 --- a/docs/cn/sql-reference/10-sql-commands/50-administration-cmds/execute-immediate.md +++ b/docs/cn/sql-reference/10-sql-commands/50-administration-cmds/execute-immediate.md @@ -3,9 +3,9 @@ title: EXECUTE IMMEDIATE --- import FunctionDescription from '@site/src/components/FunctionDescription'; - + -执行一个 SQL 脚本。关于如何为 Databend 编写 SQL 脚本,请参考 [SQL Scripting](/sql/sql-reference/sql-scripting)。 +执行一个 SQL 脚本。关于如何为 Databend 编写 SQL 脚本,请参阅 [存储过程与 SQL 脚本](/sql/stored-procedure-scripting/)。 ## 语法 @@ -22,7 +22,7 @@ $$; ## 示例 -本示例使用循环从 -1 迭代到 2 来递增 sum,结果为总和 (2): +以下示例使用循环,通过从 -1 到 2 的迭代累加 sum,最终结果为 2: ```sql EXECUTE IMMEDIATE $$ @@ -44,7 +44,7 @@ $$; └────────┘ ``` -以下示例返回一个包含列 `1 + 1` 和值 2 的表: +以下示例返回一个包含列 `1 + 1` 且值为 2 的表: ```sql EXECUTE IMMEDIATE $$ diff --git a/docs/cn/sql-reference/20-sql-functions/10-semi-structured-functions/1-array/array-filter.md b/docs/cn/sql-reference/20-sql-functions/10-semi-structured-functions/1-array/array-filter.md index 2718b18376..fc2524f5db 100644 --- a/docs/cn/sql-reference/20-sql-functions/10-semi-structured-functions/1-array/array-filter.md +++ b/docs/cn/sql-reference/20-sql-functions/10-semi-structured-functions/1-array/array-filter.md @@ -6,7 +6,7 @@ import FunctionDescription from '@site/src/components/FunctionDescription'; -根据指定的 Lambda 表达式 (Lambda Expression) 筛选 JSON 数组中的元素,仅返回满足条件的元素。有关 Lambda 表达式的更多信息,请参见 [Lambda 表达式](../../../00-sql-reference/42-lambda-expressions.md)。 +根据指定的 Lambda 表达式(Lambda Expression)筛选 JSON 数组中的元素,仅返回满足条件的元素。有关 Lambda 表达式的更多信息,请参阅 [Lambda 表达式](/sql/stored-procedure-scripting/#lambda-expressions)。 ## 语法 diff --git a/docs/cn/sql-reference/20-sql-functions/10-semi-structured-functions/1-array/array-reduce.md b/docs/cn/sql-reference/20-sql-functions/10-semi-structured-functions/1-array/array-reduce.md index d2c8381853..21e1f1018c 100644 --- a/docs/cn/sql-reference/20-sql-functions/10-semi-structured-functions/1-array/array-reduce.md +++ b/docs/cn/sql-reference/20-sql-functions/10-semi-structured-functions/1-array/array-reduce.md @@ -6,7 +6,7 @@ import FunctionDescription from '@site/src/components/FunctionDescription'; -通过应用指定的 Lambda 表达式(Lambda Expression),将一个 JSON 数组归约为单个值。有关 Lambda 表达式的更多信息,请参阅 [Lambda 表达式](../../../00-sql-reference/42-lambda-expressions.md)。 +通过应用指定的 Lambda 表达式(Lambda Expression),将 JSON 数组归约为单个值。有关 Lambda 表达式的更多信息,请参见 [Lambda 表达式](/sql/stored-procedure-scripting/#lambda-expressions)。 ## 语法 @@ -16,7 +16,7 @@ ARRAY_REDUCE(, ) ## 示例 -此示例将数组中的所有元素相乘(2 * 3 * 4): +本示例将数组中的所有元素相乘(2 * 3 * 4): ```sql SELECT ARRAY_REDUCE( diff --git a/docs/cn/sql-reference/20-sql-functions/10-semi-structured-functions/1-array/array-transform.md b/docs/cn/sql-reference/20-sql-functions/10-semi-structured-functions/1-array/array-transform.md index 6771d69c76..59b328b467 100644 --- a/docs/cn/sql-reference/20-sql-functions/10-semi-structured-functions/1-array/array-transform.md +++ b/docs/cn/sql-reference/20-sql-functions/10-semi-structured-functions/1-array/array-transform.md @@ -4,9 +4,9 @@ title: JSON_ARRAY_TRANSFORM import FunctionDescription from '@site/src/components/FunctionDescription'; - + -使用指定的转换 Lambda 表达式(Lambda expression)转换 JSON 数组(JSON array)中的每个元素。有关 Lambda 表达式的更多信息,请参阅 [Lambda 表达式](../../../00-sql-reference/42-lambda-expressions.md)。 +使用指定的转换 Lambda 表达式(Lambda Expression)转换 JSON 数组中的每个元素。有关 Lambda 表达式的更多信息,请参见 [Lambda 表达式](/sql/stored-procedure-scripting/#lambda-expressions)。 ## 语法 diff --git a/docs/cn/sql-reference/20-sql-functions/10-semi-structured-functions/3-map/map-filter.md b/docs/cn/sql-reference/20-sql-functions/10-semi-structured-functions/3-map/map-filter.md index 4b6643e116..6961929c8a 100644 --- a/docs/cn/sql-reference/20-sql-functions/10-semi-structured-functions/3-map/map-filter.md +++ b/docs/cn/sql-reference/20-sql-functions/10-semi-structured-functions/3-map/map-filter.md @@ -5,7 +5,7 @@ import FunctionDescription from '@site/src/components/FunctionDescription'; -根据指定的条件(使用 [lambda 表达式 (Lambda Expression)](../../../00-sql-reference/42-lambda-expressions.md) 定义)筛选 JSON 对象中的键值对。 +使用 [lambda 表达式](/sql/stored-procedure-scripting/#lambda-expressions) 定义的条件,过滤 JSON 对象中的键值对。 ## 语法 @@ -15,11 +15,11 @@ MAP_FILTER(, (, ) -> ) ## 返回类型 -返回一个仅包含满足指定条件的键值对的 JSON 对象。 +返回仅包含满足指定条件的键值对的 JSON 对象。 ## 示例 -此示例仅从 JSON 对象中提取 `"status":"active"` 键值对,并过滤掉其他字段: +以下示例从 JSON 对象中仅提取 `"status": "active"` 键值对,并过滤掉其他字段: ```sql SELECT MAP_FILTER('{"status":"active", "user":"admin", "time":"2024-11-01"}'::VARIANT, (k, v) -> k = 'status') AS filtered_metadata; diff --git a/docs/cn/sql-reference/20-sql-functions/10-semi-structured-functions/3-map/map-transform-keys.md b/docs/cn/sql-reference/20-sql-functions/10-semi-structured-functions/3-map/map-transform-keys.md index 2e77ec1f72..25909d45a5 100644 --- a/docs/cn/sql-reference/20-sql-functions/10-semi-structured-functions/3-map/map-transform-keys.md +++ b/docs/cn/sql-reference/20-sql-functions/10-semi-structured-functions/3-map/map-transform-keys.md @@ -5,7 +5,7 @@ import FunctionDescription from '@site/src/components/FunctionDescription'; -使用 [lambda 表达式 (Lambda Expression)](../../../00-sql-reference/42-lambda-expressions.md) 对 JSON 对象中的每个键应用转换。 +使用 [lambda 表达式](/sql/stored-procedure-scripting/#lambda-expressions) 对 JSON 对象中的每个键应用转换。 ## 语法 @@ -19,7 +19,7 @@ MAP_TRANSFORM_KEYS(, (, ) -> ) ## 示例 -此示例将 "_v1" 附加到每个键上,从而创建一个具有修改后键的新 JSON 对象: +此示例在每个键后追加 `_v1`,从而创建一个键已修改的新 JSON 对象: ```sql SELECT MAP_TRANSFORM_KEYS('{"name":"John", "role":"admin"}'::VARIANT, (k, v) -> CONCAT(k, '_v1')) AS versioned_metadata; diff --git a/docs/cn/sql-reference/20-sql-functions/10-semi-structured-functions/3-map/map-transform-values.md b/docs/cn/sql-reference/20-sql-functions/10-semi-structured-functions/3-map/map-transform-values.md index 21fef90562..e4865019b6 100644 --- a/docs/cn/sql-reference/20-sql-functions/10-semi-structured-functions/3-map/map-transform-values.md +++ b/docs/cn/sql-reference/20-sql-functions/10-semi-structured-functions/3-map/map-transform-values.md @@ -3,9 +3,9 @@ title: MAP_TRANSFORM_VALUES --- import FunctionDescription from '@site/src/components/FunctionDescription'; - + -使用 [Lambda 表达式(Lambda Expression)](../../../00-sql-reference/42-lambda-expressions.md) 对 JSON 对象(JSON Object)中的每个值执行转换。 +使用 [lambda 表达式](/sql/stored-procedure-scripting/#lambda-expressions) 对 JSON 对象中的每个值应用转换。 ## 语法 @@ -15,7 +15,7 @@ MAP_TRANSFORM_VALUES(, (, ) -> ) ## 返回类型 -返回一个 JSON 对象(JSON Object),其键与输入的 JSON 对象(JSON Object)相同,但值已根据指定的 Lambda 变换(Lambda Transformation)进行了修改。 +返回一个 JSON 对象,其键与输入的 JSON 对象相同,但值已根据指定的 lambda 转换进行了修改。 ## 示例 diff --git a/docs/cn/sql-reference/30-stored-procedure-scripting/index.md b/docs/cn/sql-reference/30-stored-procedure-scripting/index.md new file mode 100644 index 0000000000..fc9160556f --- /dev/null +++ b/docs/cn/sql-reference/30-stored-procedure-scripting/index.md @@ -0,0 +1,632 @@ +--- +title: 存储过程与 SQL 脚本 +slug: /stored-procedure-scripting/ +--- + +Databend 中的存储过程(Stored Procedure)允许你将 SQL 逻辑打包并在服务器端运行,同时可使用控制流(Control Flow)、变量(Variable)、游标(Cursor)和动态语句(Dynamic Statement)。本页介绍如何创建存储过程并编写其内联脚本。 + +## 定义存储过程 + +```sql +CREATE [OR REPLACE] PROCEDURE ( , ...) +RETURNS [NOT NULL] +LANGUAGE SQL +[COMMENT = ''] +AS $$ +BEGIN + -- 声明与语句 + RETURN ; + -- 或返回查询结果 + -- RETURN TABLE(); +END; +$$; +``` + +| 组件 | 描述 | +|-----------|-------------| +| `` | 存储过程标识符,可省略模式限定。 | +| ` ` | 使用 Databend 标量类型定义的输入参数,按值传递。 | +| `RETURNS [NOT NULL]` | 声明逻辑返回类型;`NOT NULL` 强制非空。 | +| `LANGUAGE SQL` | 当前仅支持 `SQL`。 | +| `RETURN` / `RETURN TABLE` | 结束执行并返回标量或表结果。 | + +使用 [`CREATE PROCEDURE`](/sql/sql-commands/ddl/procedure/create-procedure) 持久化定义,[`CALL`](/sql/sql-commands/ddl/procedure/call-procedure) 运行,[`DROP PROCEDURE`](/sql/sql-commands/ddl/procedure/drop-procedure) 删除。 + +### 最小示例 + +```sql +CREATE OR REPLACE PROCEDURE convert_kg_to_lb(kg DOUBLE) +RETURNS DOUBLE +LANGUAGE SQL +COMMENT = '将千克转换为磅' +AS $$ +BEGIN + RETURN kg * 2.20462; +END; +$$; + +CALL PROCEDURE convert_kg_to_lb(10); +``` + +## 存储过程内的语言基础 + +### 声明部分 + +存储过程可在可执行部分前使用可选的 `DECLARE` 块初始化变量。 + +```sql +CREATE OR REPLACE PROCEDURE sp_with_declare() +RETURNS INT +LANGUAGE SQL +AS $$ +DECLARE + counter := 0; +BEGIN + counter := counter + 5; + RETURN counter; +END; +$$; + +CALL PROCEDURE sp_with_declare(); +``` + +`DECLARE` 部分支持 `LET` 的所有定义,包括 `RESULTSET` 和 `CURSOR` 声明;每项以分号结尾。 + +### 变量与赋值 + +使用 `LET` 声明变量或常量;重新赋值时省略 `LET`。 + +```sql +CREATE OR REPLACE PROCEDURE sp_demo_variables() +RETURNS FLOAT +LANGUAGE SQL +AS $$ +BEGIN + LET total := 100; + LET rate := 0.07; + + total := total * rate; -- 乘以比率 + total := total + 5; -- 重新赋值 + + RETURN total; +END; +$$; + +CALL PROCEDURE sp_demo_variables(); +``` + +### 变量作用域 + +变量作用域限定于所在块;内部块可遮蔽外部绑定,退出后恢复外部值。 + +```sql +CREATE OR REPLACE PROCEDURE sp_demo_scope() +RETURNS STRING +LANGUAGE SQL +AS $$ +BEGIN + LET threshold := 10; + LET summary := 'outer=' || threshold; + + IF threshold > 0 THEN + LET threshold := 5; -- 遮蔽外部值 + summary := summary || ', inner=' || threshold; + END IF; + + summary := summary || ', after=' || threshold; + RETURN summary; +END; +$$; + +CALL PROCEDURE sp_demo_scope(); +``` + +### 注释 + +支持单行(`-- text`)与多行(`/* text */`)注释。 + +```sql +CREATE OR REPLACE PROCEDURE sp_demo_comments() +RETURNS FLOAT +LANGUAGE SQL +AS $$ +BEGIN + -- 计算含税价格 + LET price := 15; + LET tax_rate := 0.08; + + /* + 多行注释便于记录复杂逻辑。 + 下一行返回含税价格。 + */ + RETURN price * (1 + tax_rate); +END; +$$; + +CALL PROCEDURE sp_demo_comments(); +``` + +### Lambda 表达式 + +Lambda 表达式(Lambda Expression)定义可传递给数组函数或在查询中调用的内联逻辑,形式为 ` -> `;多参数时用括号包裹。表达式可含类型转换、条件逻辑,甚至引用过程变量。 + +- 在 SQL 语句中运行的 Lambda 内,用 `:variable_name` 引用过程变量。 +- `ARRAY_TRANSFORM`、`ARRAY_FILTER` 等函数会对输入数组的每个元素求值 Lambda。 + +```sql +CREATE OR REPLACE PROCEDURE sp_demo_lambda_array() +RETURNS STRING +LANGUAGE SQL +AS $$ +BEGIN + RETURN TABLE( + SELECT ARRAY_TRANSFORM([1, 2, 3, 4], item -> (item::Int + 1)) AS incremented + ); +END; +$$; + +CALL PROCEDURE sp_demo_lambda_array(); +``` + +Lambda 也可出现在过程执行的查询中。 + +```sql +CREATE OR REPLACE PROCEDURE sp_demo_lambda_query() +RETURNS STRING +LANGUAGE SQL +AS $$ +BEGIN + RETURN TABLE( + SELECT + number, + ARRAY_TRANSFORM([number, number + 1], val -> (val::Int + 1)) AS next_values + FROM numbers(3) + ); +END; +$$; + +CALL PROCEDURE sp_demo_lambda_query(); +``` + +在 SQL 上下文中,通过在变量名前加 `:` 捕获过程变量。 + +```sql +CREATE OR REPLACE PROCEDURE sp_lambda_filter() +RETURNS STRING +LANGUAGE SQL +AS $$ +BEGIN + LET threshold := 2; + RETURN TABLE( + SELECT ARRAY_FILTER([1, 2, 3, 4], element -> (element::Int > :threshold)) AS filtered + ); +END; +$$; + +CALL PROCEDURE sp_lambda_filter(); +``` + +也可在 Lambda 体内放置复杂表达式,如 `CASE` 逻辑。 + +```sql +CREATE OR REPLACE PROCEDURE sp_lambda_case() +RETURNS STRING +LANGUAGE SQL +AS $$ +BEGIN + RETURN TABLE( + SELECT + number, + ARRAY_TRANSFORM( + [number - 1, number, number + 1], + val -> (CASE WHEN val % 2 = 0 THEN 'even' ELSE 'odd' END) + ) AS parity_window + FROM numbers(3) + ); +END; +$$; + +CALL PROCEDURE sp_lambda_case(); +``` + +## 控制流 + +### IF 语句 + +使用 `IF ... ELSEIF ... ELSE ... END IF;` 在过程内分支。 + +```sql +CREATE OR REPLACE PROCEDURE sp_evaluate_score(score INT) +RETURNS STRING +LANGUAGE SQL +AS $$ +BEGIN + IF score >= 90 THEN + RETURN 'Excellent'; + ELSEIF score >= 70 THEN + RETURN 'Good'; + ELSE + RETURN 'Review'; + END IF; +END; +$$; + +CALL PROCEDURE sp_evaluate_score(82); +``` + +### CASE 表达式 + +`CASE` 表达式可替代嵌套 `IF`。 + +```sql +CREATE OR REPLACE PROCEDURE sp_membership_discount(level STRING) +RETURNS FLOAT +LANGUAGE SQL +AS $$ +BEGIN + RETURN CASE + WHEN level = 'gold' THEN 0.2 + WHEN level = 'silver' THEN 0.1 + ELSE 0 + END; +END; +$$; + +CALL PROCEDURE sp_membership_discount('silver'); +``` + +### Range `FOR` + +基于范围的循环从下限迭代到上限(含上限)。可选 `REVERSE` 关键字反向遍历。 + +```sql +CREATE OR REPLACE PROCEDURE sp_sum_range(start_val INT, end_val INT) +RETURNS INT +LANGUAGE SQL +AS $$ +BEGIN + LET total := 0; + FOR i IN start_val TO end_val DO + total := total + i; + END FOR; + RETURN total; +END; +$$; + +CALL PROCEDURE sp_sum_range(1, 5); +``` + +正向步进时下限须 ≤ 上限。 + +```sql +CREATE OR REPLACE PROCEDURE sp_reverse_count(start_val INT, end_val INT) +RETURNS STRING +LANGUAGE SQL +AS $$ +BEGIN + LET output := ''; + FOR i IN REVERSE start_val TO end_val DO + output := output || i || ' '; + END FOR; + RETURN TRIM(output); +END; +$$; + +CALL PROCEDURE sp_reverse_count(1, 5); +``` + +#### `FOR ... IN` 查询 + +直接遍历查询结果;循环变量以字段形式暴露列。 + +```sql +CREATE OR REPLACE PROCEDURE sp_sum_query(limit_rows INT) +RETURNS BIGINT +LANGUAGE SQL +AS $$ +BEGIN + LET total := 0; + FOR rec IN SELECT number FROM numbers(:limit_rows) DO + total := total + rec.number; + END FOR; + RETURN total; +END; +$$; + +CALL PROCEDURE sp_sum_query(5); +``` + +`FOR` 也可遍历先前声明的 RESULTSET 变量或 CURSOR(见[使用查询结果](#working-with-query-results))。 + +### `WHILE` + +```sql +CREATE OR REPLACE PROCEDURE sp_factorial(n INT) +RETURNS INT +LANGUAGE SQL +AS $$ +BEGIN + LET result := 1; + WHILE n > 0 DO + result := result * n; + n := n - 1; + END WHILE; + RETURN result; +END; +$$; + +CALL PROCEDURE sp_factorial(5); +``` + +### `REPEAT` + +```sql +CREATE OR REPLACE PROCEDURE sp_repeat_sum(limit_val INT) +RETURNS INT +LANGUAGE SQL +AS $$ +BEGIN + LET counter := 0; + LET total := 0; + + REPEAT + counter := counter + 1; + total := total + counter; + UNTIL counter >= limit_val END REPEAT; + + RETURN total; +END; +$$; + +CALL PROCEDURE sp_repeat_sum(3); +``` + +### `LOOP` + +```sql +CREATE OR REPLACE PROCEDURE sp_retry_counter(max_attempts INT) +RETURNS INT +LANGUAGE SQL +AS $$ +BEGIN + LET retries := 0; + LOOP + retries := retries + 1; + IF retries >= max_attempts THEN + BREAK; + END IF; + END LOOP; + + RETURN retries; +END; +$$; + +CALL PROCEDURE sp_retry_counter(5); +``` + +### Break 与 Continue + +使用 `BREAK` 提前退出循环,使用 `CONTINUE` 跳过本次迭代。 + +```sql +CREATE OR REPLACE PROCEDURE sp_break_example(limit_val INT) +RETURNS INT +LANGUAGE SQL +AS $$ +BEGIN + LET counter := 0; + LET total := 0; + + WHILE TRUE DO + counter := counter + 1; + IF counter > limit_val THEN + BREAK; + END IF; + IF counter % 2 = 0 THEN + CONTINUE; + END IF; + total := total + counter; + END WHILE; + + RETURN total; +END; +$$; + +CALL PROCEDURE sp_break_example(5); +``` + +使用 `BREAK