创建用户定义的函数

您可以使用 Snowflake 提供的几种方法中的任意一种来创建 用户定义的函数 (UDF)。本主题将介绍这些方法。

创建 UDF

  1. 使用几种支持的语言(包括 Python、Java 和 Scala)之一,将函数逻辑编写为处理程序。

  2. 选择一个工具或 API,使用您编写的处理程序创建函数。

    有关各项的更多信息,请参阅 创建 UDFs 的工具

    SQL

    使用 SQL 以及使用几种语言中的一种编写逻辑。

    Snowpark

    为 Java、Python 或 Scala 使用 Snowpark API。

    命令行

    执行 CLI 命令以创建函数。

    Python API

    执行客户端 Python 命令以创建函数。

    REST

    向 RESTful API 发出请求以创建函数。

  3. 根据需要,使用几种工具中的一种 执行函数

创建 UDFs 的工具

您可以使用 Snowflake 提供的几种方法中的任意一种来创建 UDF,具体取决于您可用的语言和技能集。从下表中选择适合您需求的工具。

语言

方法

SQL

执行 SQL 命令,例如使用 Snowsight。

执行 SQL CREATE FUNCTION 命令,使用以下一种语言编写的处理程序代码创建函数:

使用 Snowpark 的 Java、Python 或 Scala

使用受支持的语言之一编写代码,然后在本地执行代码,以在 Snowflake 中执行操作。

使用以下列语言之一执行使用 Snowpark APIs 的客户端代码。

命令行

通过从命令行执行命令来创建和管理 Snowflake 实体。

执行 Snowflake CLI 的命令。

Python

在客户端,编写在 Snowflake 上执行管理操作的代码。

执行使用 Snowflake Python API 的代码。

**RESTful APIs**(与语言无关)

请求 RESTful 端点以创建和管理 Snowflake 实体。

发出请求以使用 Snowflake REST API 创建过程

关键属性

下面介绍创建函数时需要或通常使用的一些属性。

函数名称:

函数名称不需要与处理程序的名称一致。有关名称约束和约定的更多信息,请参阅 命名和重载过程和 UDFs

实参:

有关要求的更多信息,请参阅 定义 UDFs 和存储过程的实参

返回类型:

有关 Snowflake 如何将 SQL 数据类型映射到处理程序数据类型的信息,请参阅 SQL 与处理程序语言之间的数据类型映射

处理程序名称:

需要此属性时,它是类或方法的名称,该类或方法包含了执行函数时执行的代码。只需要为用 Java、Python 和 Scala 编写的处理程序指定处理程序名称。对于 JavaScript 和 SQL 处理程序,以内联方式指定的所有代码都将作为处理程序执行。

依赖关系:

对于使用 Java、Python 或 Scala 编写的处理程序,您可能还需要指定 Snowpark 库,例如在创建函数时。

有关使依赖项可供处理程序使用的更多信息,请参阅 为代码提供依赖项

处理程序语言运行时:

当处理程序语言是 Java、Python 或 Scala 时,指定运行时版本以指明要使用哪个受支持的运行时版本。请记住,如果您使用默认版本,该默认版本将随时间而改变。

访问控制要求

用于执行此操作的 角色 必须至少具有以下 权限

权限

对象

备注

CREATE FUNCTION

架构

该权限仅允许在架构中创建用户定义的函数。

如果您要允许创建数据指标函数,则角色必须具有 CREATE DATA METRIC FUNCTION 权限。

USAGE

函数

通过向角色授予对新创建函数的 USAGE 权限,具有该角色的用户可以在 Snowflake 中的其他位置调用该函数(例如,External Tokenization 的掩码策略所有者角色)。

USAGE

外部访问集成

对于由 EXTERNAL_ACCESS_INTEGRATIONS 参数指定的集成(如果有)来说是必需的。有关更多信息,请参阅 CREATE EXTERNAL ACCESS INTEGRATION

READ

密钥

对于由 SECRETS 参数指定的密钥(如果有)来说是必需的。有关更多信息,请参阅 创建表示凭据的密钥在函数或过程中使用外部访问集成

USAGE

架构

对于包含由 SECRETS 参数指定的密钥(如果有)的架构来说是必需的。有关更多信息,请参阅 创建表示凭据的密钥在函数或过程中使用外部访问集成

要对架构中的任何对象执行操作,需要对父数据库和架构具有 USAGE 权限。

有关创建具有指定权限集的自定义角色的说明,请参阅 创建自定义角色

有关对 安全对象 执行 SQL 操作的相应角色和权限授予的一般信息,请参阅 访问控制概述

使用说明

以下说明介绍了与编写处理程序支持的语言相关的使用说明。虽然以下各节中的说明提到了 SQL CREATE FUNCTION 命令的子句,但这些子句通常在可用于创建函数的其他工具中以其他方式表示。

所有语言

  • function_definition 有大小限制。最大允许大小可能会发生变化。

  • 周围的 function_definition 分隔符可以是单引号或一对美元符号。

    使用 $$ 作为分隔符可以更轻松地编写包含单引号的函数。

    如果函数主体的分隔符是单引号字符,则 function_definition 中的任何单引号(例如字符串字面量):emph:必须 用单引号转义。

  • 如果在 :doc:` 掩码策略 </sql-reference/sql/create-masking-policy>` 中使用 UDF,请确保列的数据类型、UDF 和掩码策略匹配。有关更多信息,请参阅 掩码策略中的用户定义函数

  • 如果在 UDF 的处理程序代码中指定 CURRENT_DATABASECURRENT_SCHEMA 函数,该函数会返回包含 UDF 的数据库或架构,而不是会话中使用的数据库或架构。

  • 关于元数据:

    注意

    客户应确保在使用 Snowflake 服务时,不会将个人数据(用户对象除外)、敏感数据、出口管制数据或其他受监管数据作为元数据输入。有关更多信息,请参阅 Snowflake 中的元数据字段

  • OR REPLACEIF NOT EXISTS 子句互斥。它们不能同时用于同一条语句中。

  • CREATE OR REPLACE <object> 语句是原子的。也就是说,当对象被替换时,旧对象将被删除,新对象将在单个事务中创建。

Java

  • 在 Java 中,原始数据类型不允许 NULL 值,因此为此类类型的实参传递 NULL 会导致错误。

  • 在 HANDLER 子句中,方法名称区分大小写。

  • 在 IMPORTS 和 TARGET_PATH 子句中:

    • 包、类和文件名区分大小写。

    • 暂存区名称不区分大小写。

  • 您可以使用 PACKAGES 子句指定 Snowflake 系统定义的依赖项(例如来自 Snowpark 的依赖项)的包名称和版本号。对于其他依赖项,请使用 IMPORTS 子句指定依赖项 JAR 文件。

  • Snowflake 验证:

    • CREATE FUNCTION 语句的 HANDLER 中指定的 JAR 文件存在并且包含指定的类和方法。

    • UDF 声明中指定的输入和输出类型与 Java 方法的输入和输出类型兼容。

    验证可以在创建时间或执行时间进行,具体取决于您是否连接到活动的 Snowflake 仓库。

    • 创建时间 – 如果在执行 CREATE FUNCTION 语句时您连接到活动的 Snowflake 仓库,则 UDF 在创建时进行验证。

    • 执行时间 – 如果您没有连接到活动的 Snowflake 仓库,则 UDF 会创建,但不会立即验证,并且 Snowflake 返回以下消息:

      Function <name> created successfully, but could not be validated since there is no active warehouse

JavaScript

  • Snowflake 在 UDF 创建时间不验证 JavaScript 代码。换句话说,无论代码是否有效,UDF 的创建都会成功。如果代码无效,则在查询时调用 UDF 时,Snowflake 将返回错误。

Python

  • 在 HANDLER 子句中,处理程序函数名称区分大小写。

  • 在 IMPORTS 子句中:

    • 文件名区分大小写。

    • 暂存区名称不区分大小写。

  • 您可以使用 PACKAGES 子句指定依赖项(例如来自 Snowpark 的依赖项)的包名称和版本号。对于其他依赖项,请使用 IMPORTS 子句指定依赖项文件。

  • Snowflake 验证:

    • CREATE FUNCTION 语句的 HANDLER 中指定的函数或类存在。

    • UDF 声明中指定的输入和输出类型与处理程序的输入和输出类型兼容。

Scala

  • 在 HANDLER 子句中,方法名称区分大小写。

  • 在 IMPORTS 和 TARGET_PATH 子句中:

    • 包、类和文件名区分大小写。

    • 暂存区名称不区分大小写。

  • 您可以使用 PACKAGES 子句指定 Snowflake 系统定义的依赖项(例如来自 Snowpark 的依赖项)的包名称和版本号。对于其他依赖项,请使用 IMPORTS 子句指定依赖项 JAR 文件。

  • Snowflake 验证:

    • CREATE FUNCTION 语句的 HANDLER 中指定的 JAR 文件存在并且包含指定的类和方法。

    • UDF 声明中指定的输入和输出类型与 Scala 方法的输入和输出类型兼容。

    验证可以在创建时间或执行时间进行,具体取决于您是否连接到活动的 Snowflake 仓库。

    • 创建时间 – 如果在执行 CREATE FUNCTION 语句时您连接到活动的 Snowflake 仓库,则 UDF 在创建时进行验证。

    • 执行时间 – 如果您没有连接到活动的 Snowflake 仓库,则 UDF 会创建,但不会立即验证,并且 Snowflake 返回以下消息:

      Function <name> created successfully, but could not be validated since there is no active warehouse

SQL

  • 目前,SQL UDFs 不强制使用 NOT NULL 子句。

创建带有 SQL 的 UDF

您可以按照以下步骤创建带有 SQL 的 UDF。

使用 CREATE FUNCTION 语句将处理程序方法与 UDF 名称相关联

按照以下步骤创建 UDF :

  1. 编写在调用 UDF 时执行的处理程序代码。

    可以使用受支持的某种处理程序语言。有关更多信息,请参阅 支持的语言和工具

  2. 选择是使用 CREATE FUNCTION SQL 语句将处理程序代码内联,还是在暂存区上引用该代码。

    每种做法都有其优点。有关更多信息,请参阅 将处理程序代码保持内联或保留在暂存区

  3. 在 SQL 中执行 CREATE FUNCTION 语句,指定函数的属性。

    以下示例中的代码创建一个名为 function_name 的 UDF,其包含内联处理程序 HandlerClass.handlerMethod

    create function function_name(x integer, y integer)
      returns integer
      language java
      handler='HandlerClass.handlerMethod'
      target_path='@~/HandlerCode.jar'
      as
      $$
          class HandlerClass {
              public static int handlerMethod(int x, int y) {
                return x + y;
              }
          }
      $$;
    
    Copy

    下面介绍创建函数时需要或通常使用的一些属性。

    • 函数名称。

      UDF 名称不需要与处理程序的名称匹配。CREATE FUNCTION 语句会将 UDF 名称与处理程序相关联。

      有关名称约束和约定的更多信息,请参阅 命名和重载过程和 UDFs

    • 函数实参(如果有)。

      请参阅 定义 UDFs 和存储过程的实参

    • RETURNS 子句的返回类型。

      对于标量返回值,RETURNS 子句将指定单个返回类型;对于表格返回值,RETURNS 将指定在表格返回值中指定列类型的 TABLE 关键字。

      有关 Snowflake 如何将 SQL 数据类型映射到处理程序数据类型的信息,请参阅 命名和重载过程和 UDFs

    • HANDLER 子句的处理程序名称。

      需要此属性时,它是类或方法的名称,该类或方法包含了调用 UDF 时执行的代码。您只需要为使用 Java 和 Python 编写的处理程序指定处理程序名称。对于 JavaScript 和 SQL 处理程序,以内联方式指定的所有代码都将作为处理程序执行。

      下表描述了基于处理程序语言和函数类型的 HANDLER 子句值的形式。

      处理程序语言

      UDF

      UDTF

      Java

      类和方法名称。

      例如:MyClass.myMethod

      仅限类名称。处理程序方法名称由所需的接口预先确定。

      JavaScript

      无。

      无。

      Python

      类和方法名称(如果使用类),否则为函数名称。

      例如:module.my_functionmy_function

      仅限类名称。处理程序方法名称由所需的接口预先确定。

      SQL

      无。

      无。

    • 使用 IMPORTS 或 PACKAGES 子句时,处理程序所需的依赖项(如果有)。

      有关使依赖项可供处理程序使用的更多信息,请参阅 为代码提供依赖项

    • RUNTIME_VERSION 子句的处理程序语言运行时。

      当处理程序语言是 Java 或 Python 时,使用 RUNTIME_VERSION 子句指定要使用的受支持的运行时版本。省略该子句将提示 Snowflake 使用默认值(将来可能会有变)。

语言: 中文