用户定义函数概述¶
您可以编写用户定义函数 (UDFs) 来扩展系统,以执行 Snowflake 提供的内置系统定义函数无法执行的操作。创建 UDF 之后,可以多次重用它。
UDF 只是扩展 Snowflake 的一种方式。对于其他内容,请参阅以下内容:
备注
UDF 类似于存储过程,但两者存在重要区别。有关更多信息,请参阅 选择是编写存储过程还是用户定义函数。
本主题内容:
什么是用户定义函数 (UDF)?¶
用户定义函数 (UDF) 是您定义的函数,因此您可以从 SQL 中调用它。类似于从 SQL 中调用的 内置函数,UDF 的逻辑通常使用 SQL 不具备或表现不佳的功能来扩展或增强 SQL。UDF 还为您提供了一种封装功能的方法,以便您可以从代码中的多个位置重复调用它。
您可以使用 受支持的语言 之一编写 UDF 的逻辑(其处理程序)。拥有处理程序后,就可以使用 CREATE FUNCTION 命令 创建 UDF,然后使用 SELECT 语句 调用 UDF。
标量函数和表格函数¶
您可以编写返回单个值(标量 UDF)或返回表格值(用户定义的表函数或 UDTF)的 UDF。
标量 函数 (UDF) 为每个输入行返回一个输出行。返回的行由单个列/值组成。
表格 函数 (UDTF) 返回每个输入行的表格值。在 UDTF 的处理程序中,编写符合 Snowflake 所需接口的方法。这些方法将:
处理分区中的每一行(必填)。
为每个分区初始化一次处理程序(可选)。
完成每个分区的处理(可选)。
方法的名称因处理程序语言而异。有关支持的语言列表,请参阅 支持的语言。
注意事项¶
如果查询调用 UDF 来访问暂存文件,则如果 SQL 语句还查询调用 任何 UDF 或 UDTF 的视图,则无论视图中的函数是否访问暂存文件,操作都将失败并显示用户错误。
UDTFs 可以并行处理多个文件;但是,UDFs 当前以串行方式处理文件。解决方法是使用 GROUP BY 子句对子查询中的行进行分组。有关示例,请参阅 使用 UDTF 处理 CSV。
目前,如果在查询运行时修改或删除了查询中引用的暂存文件,则函数调用将失败并显示错误。
如果在 UDF 的处理程序代码中指定 CURRENT_DATABASE 或 CURRENT_SCHEMA 函数,该函数会返回包含 UDF 的数据库或架构,而不是会话中使用的数据库或架构。
开始使用¶
有关使用 SQL 编写的处理程序编写 UDTF 的教程,请参阅 ` 快速入门:开始使用用户定义的 SQL 函数 <https://quickstarts.snowflake.com/guide/getting_started_with_user_defined_sql_functions/?index=..%2F..index#0 (https://quickstarts.snowflake.com/guide/getting_started_with_user_defined_sql_functions/?index=..%2F..index#0)>`_
UDF 示例¶
以下示例中的代码创建一个名为 addone
的 UDF,其中包含一个使用 Python 编写的处理程序。处理程序函数为 addone_py
。UDF 返回一个 int
。
CREATE OR REPLACE FUNCTION addone(i int)
RETURNS INT
LANGUAGE PYTHON
RUNTIME_VERSION = '3.8'
HANDLER = 'addone_py'
as
$$
def addone_py(i):
return i+1
$$;
以下示例中的代码执行 addone
UDF。
SELECT addone(3);
支持的语言¶
您可以用几种编程语言中的任何一种编写函数的处理程序(其逻辑)。每种语言都允许您在语言及其运行时环境的约束范围内操作数据。无论使用哪种处理程序语言,创建存储过程本身的方法都是一样的,都是使用 SQL,指定处理程序和处理程序语言。
您可以使用以下任一语言编写处理程序:
语言 |
开发者指南 |
---|---|
Java |
|
JavaScript |
|
Python |
|
Scala |
|
SQL |
语言选择¶
您可以用几种编程语言中的任何一种编写 UDF 的处理程序(其逻辑)。每种语言都允许您在语言及其运行时环境的约束范围内操作数据。
在以下情况下,您可能会选择某种特定的语言:
您已经有该语言的代码。
例如,如果您已经有一个可以用作处理程序的 Java 方法,并且该方法的对象位于 .jar 文件中,则可以将.jar 复制到暂存区,将处理程序指定为类和方法,然后将语言指定为 Java。
该语言具有其他语言所不具备的功能。
该语言具有可以帮助您执行所需处理的库。
选择语言时,还要考虑以下几点:
支持的处理程序位置。 并非所有语言都支持在暂存区中引用处理程序(处理程序代码必须是内联的)。有关更多信息,请参阅 将处理程序代码保持内联或保留在暂存区。
处理程序是否生成可共享的 UDF。 可共享的 UDF 可与 Snowflake Secure Data Sharing 功能一起使用。
语言 |
处理程序位置 |
共享 |
---|---|---|
Java |
内联或暂存 |
否 [1] |
JavaScript |
内联 |
是 |
Python |
内联或暂存 |
否 [2] |
Scala |
内联或暂存 |
否 [3] |
SQL |
内联 |
是 |
开发者指南¶
准则和约束¶
- Snowflake 约束:
您可以通过在 Snowflake 约束内进行开发来确保 Snowflake 环境的稳定性。有关更多信息,请参阅 设计保持在 Snowflake 施加的约束范围内的处理程序。
- 命名:
请确保在命名函数时避免与其他函数发生冲突。有关更多信息,请参阅 命名和重载过程和 UDFs。
- 实参:
指定实参,并指示哪些实参是可选的。有关更多信息,请参阅 定义 UDFs 和存储过程的实参。
- 数据类型映射:
每种处理程序语言的数据类型与用于实参和返回值的 SQL 类型之间都有一套单独的映射。有关每种语言的映射的更多信息,请参阅 SQL 与处理程序语言之间的数据类型映射。
处理程序写入¶
- 处理程序语言:
有关编写处理程序的特定于语言的内容,请参阅 支持的语言。
- 外部网络访问:
您可以使用 外部网络访问 访问外部网络位置。您可以创建对 Snowflake 外部的特定网络位置的安全访问,然后从处理程序代码中使用该访问。
- 日志记录和跟踪:
您可以通过 获取日志消息和跟踪事件 来记录代码活动,将数据存储在以后可以查询的数据库中。
安全¶
您可以授予对象使用 UDF 或 UDTF 执行特定 SQL 操作所需的权限。有关更多信息,请参阅 向用户定义函数授予权限
函数与存储过程共享某些安全问题。有关更多信息,请参阅以下内容:
您可以通过遵循 UDFs 和过程的安全实践 中所述的最佳实践,帮助存储过程的处理程序代码安全地执行
确保对不应访问敏感信息的用户隐藏敏感信息。有关更多信息,请参阅 使用安全 UDFs 和存储过程保护敏感信息
处理程序代码部署¶
在创建函数时,可以将实现函数逻辑的处理程序指定为与 CREATE FUNCTION 语句内联的代码,也可以指定为语句外部的代码,例如打包并复制到暂存区的编译代码。
有关更多信息,请参阅 将处理程序代码保持内联或保留在暂存区。
创建和调用函数¶
使用 SQL 创建和调用用户定义函数。