选择是编写存储过程还是用户定义函数¶
本主题介绍存储过程和 UDFs 之间的主要区别,包括调用方式和功能方面的区别。
概括地说,存储过程和 UDFs 的不同之处在于它们通常的使用方式,如下所述。
存储过程用途 |
用户定义函数用途 |
---|---|
一般通过执行 SQL 语句来执行管理操作。允许(但不是必需)存储过程的正文显式返回值(如错误指示符)。 |
计算并返回一个值。函数始终通过指定表达式显式返回值。例如,JavaScript UDF 正文必须具有返回值的 |
本主题内容:
何时创建存储过程或 UDF¶
通常,在决定是创建存储过程还是 UDF 时,请考虑以下建议:
在以下情况下创建存储过程... |
在以下情况下创建 UDF... |
---|---|
|
|
支持的处理程序语言¶
编写过程或 UDF 时,使用一种受支持的语言将其逻辑编写为处理程序。下表列出了支持的语言。
存储过程 |
用户定义的函数 |
---|---|
使用和行为差异¶
以下各节介绍过程和 UDFs 支持的行为的具体差异。
UDFs 返回值;存储过程不需要返回值¶
UDF 始终通过指定表达式显式返回值。UDF 的用途是计算并返回值。例如,JavaScript UDF 正文必须具有返回值的
return
语句。允许(但不是必需)存储过程显式返回值(如错误指示符)。存储过程的用途通常是通过执行 SQL 语句来执行管理操作。如果过程未显式返回值,则会隐式返回 NULL。
请注意,每个 CREATE PROCEDURE 语句都必须包含一个指定返回类型的 RETURNS 子句,即使该过程没有显式返回任何内容。如果过程未显式返回值,则会隐式返回 NULL。
以下示例中的代码用 RETURNS 子句为过程声明了一个返回类型,但只有在出错时才会返回值。换言之,并非每个代码路径都返回值。
CREATE OR REPLACE PROCEDURE do_stuff(input NUMBER) RETURNS VARCHAR LANGUAGE SQL AS $$ DECLARE ERROR VARCHAR DEFAULT 'Bad input. Number must be less than 10.'; BEGIN IF (input > 10) THEN RETURN ERROR; END IF; -- Perform an operation that doesn't return a value. END; $$ ;
UDF 返回值可直接用于 SQL;存储过程返回值不能¶
如果不是从 Snowflake Scripting 块中调用存储过程,则不能在 SQL 中直接使用存储过程返回的值(与函数返回的值不同)。CALL 命令的语法不提供存储返回值的位置,也不提供对其进行操作或将值传递给其他操作的方法。换言之,以下语句不是有效 SQL 语句:
y = stored_procedure1(x); -- Not allowed.
如果在 Snowflake Scripting 块 获取存储过程 返回的值。
还可以间接使用存储过程的返回值(在 Snowflake Scripting 块之外),如以下列表所述:
可以在另一个存储过程中调用该存储过程。例如,当用 JavaScript 编写存储过程处理程序时,外部存储过程中的 JavaScript 可以检索和存储内部存储过程的输出。但是,请记住,外部存储过程(以及每个内部存储过程)仍然无法向其调用方返回多个值。
可以调用存储过程,然后调用 RESULT_SCAN 函数并向其传递为存储过程生成的语句 ID。
可以将结果集存储在临时表或永久表中,并在从存储过程调用返回后使用该表。
如果数据量不太大,可以在一个 VARIANT 中存储多行和多列(例如,作为 JSON 值)并返回该 VARIANT。
UDFs 可以在另一个语句的上下文中调用;存储过程是独立调用的¶
UDF 的计算结果为一个值,可在可以使用通用表达式的上下文中使用,如下所示:
SELECT MyFunction_1(column_1) FROM table1;
存储过程的计算结果不为值,并且不能在可以使用常规表达式的所有上下文中使用。例如,不能执行
SELECT my_stored_procedure()...
。将存储过程作为独立语句调用,如以下示例所示:
CALL MyStoredProcedure_1(argument_1);
有关调用函数和过程的更多详细信息,请参阅以下内容:
可以用一个语句调用多个 UDFs;用一个语句调用单个存储过程¶
单个 SQL 语句可以调用多个 UDFs。
单个 SQL 语句只能调用一个存储过程。
同样,存储过程与 UDF 不同,不能作为表达式的一部分进行调用。但是,在存储过程中,存储过程可以调用另一个存储过程,也可以以递归方式调用自身。例如,请参阅代码示例部分 示例。
有关调用函数和过程的更多详细信息,请参阅以下内容:
UDFs 只能通过简单的查询来访问数据库;存储过程可以执行 DDL 和 DML 语句¶
在 UDF 中,只能使用 SQL 执行查询(不能使用 DML 或 DDL 语句)。
在存储过程中,您可以执行数据库操作,如 SELECT、UPDATE 和 CREATE:
例如,在 JavaScript 存储过程中,可以使用 JavaScript API 来执行这些操作。
下面的示例演示了存储过程如何创建和执行 SQL 语句,以调用另一个存储过程。
$$
表示存储过程中 JavaScript 处理程序代码的开始和结束。CREATE PROCEDURE ... $$ // Create a Statement object that can call a stored procedure named // MY_PROCEDURE(). var stmt1 = snowflake.createStatement( { sqlText: "call MY_PROCEDURE(22)" } ); // Execute the SQL command; in other words, call MY_PROCEDURE(22). stmt1.execute(); // Create a Statement object that executes a SQL command that includes // a call to a UDF. var stmt2 = snowflake.createStatement( { sqlText: "select MY_UDF(column1) from table1" } ); // Execute the SQL statement and store the output (the "result set") in // a variable named "rs", which we can access later. var rs = stmt2.execute(); // etc. $$;
在 Snowflake Scripting 存储过程中,可以执行 SQL 语句。
下面的示例演示了存储过程如何创建和执行 SQL 语句,以调用另一个存储过程。
$$
表示存储过程中 Snowflake Scripting 代码的开始和结束。CREATE PROCEDURE ... -- Call a stored procedure named my_procedure(). CALL my_procedure(22); -- Execute a SQL statement that includes a call to a UDF. SELECT my_udf(column1) FROM table1;