CREATE EXTERNAL FUNCTION

创建新的 外部函数

该命令支持以下变体:

另请参阅:

ALTER FUNCTIONSHOW EXTERNAL FUNCTIONSDROP FUNCTIONDESCRIBE FUNCTIONCREATE API INTEGRATIONCREATE OR ALTER <对象>

语法

CREATE [ OR REPLACE ] [ SECURE ] EXTERNAL FUNCTION <name> ( [ <arg_name> <arg_data_type> ] [ , ... ] )
  RETURNS <result_data_type>
  [ [ NOT ] NULL ]
  [ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
  [ { VOLATILE | IMMUTABLE } ]
  [ COMMENT = '<string_literal>' ]
  API_INTEGRATION = <api_integration_name>
  [ HEADERS = ( '<header_1>' = '<value_1>' [ , '<header_2>' = '<value_2>' ... ] ) ]
  [ CONTEXT_HEADERS = ( <context_function_1> [ , <context_function_2> ...] ) ]
  [ MAX_BATCH_ROWS = <integer> ]
  [ COMPRESSION = <compression_type> ]
  [ REQUEST_TRANSLATOR = <request_translator_udf_name> ]
  [ RESPONSE_TRANSLATOR = <response_translator_udf_name> ]
  AS '<url_of_proxy_and_resource>';
Copy

变体语法

CREATE OR ALTER EXTERNAL FUNCTION

如果外部函数尚不存在,则创建一个新外部函数,或者将现有外部函数转换为在语句中定义的函数。CREATE OR ALTER EXTERNAL FUNCTION 语句遵循 CREATE EXTERNAL FUNCTION 语句的语法规则,并具有与 ALTER FUNCTION 语句相同的限制。

支持的功能更改包括对以下内容的更改:

  • API_INTEGRATION

  • COMMENTS

  • COMPRESSION

  • CONTEXT_HEADERS

  • HEADERS

  • MAX_BATCH_ROWS

  • RESPONSE_TRANSLATOR

  • REQUEST_TRANSLATOR

  • SECURE

有关更多信息,请参阅 CREATE OR ALTER EXTERNAL FUNCTION 使用说明

CREATE [ OR ALTER ] EXTERNAL FUNCTION ...
Copy

必填参数

name

指定函数的标识符。

标识符可以包含架构名称和数据库名称,以及函数名称。

对于在其中创建函数的架构,标识符不需要是唯一的,因为函数由其名称和实参类型标识和解析。但是,签名(名称和实参数据类型)在架构中必须唯一。

name 必须遵循 Snowflake :doc:` 标识符 </sql-reference/identifiers>` 的规则。有关更多详细信息,请参阅 标识符要求

name 设置为与远程服务名称相同,这样可以使关系更加清晰。但是,这不是必需的。

( [ arg_name arg_data_type ] [ , ... ] )

指定外部函数的实参/输入。这些实参应该与远程服务所期望的实参相对应。

如果没有实参,则包括不带任何实参名称和数据类型的括号。

RETURNS result_data_type

指定函数返回的数据类型。

API_INTEGRATION = api_integration_name

这是应该用于验证对代理服务调用的 API 集成对象的名称。

AS 'url_of_proxy_and_resource'

这是代理服务(例如 API Gateway 或 API 管理服务)和资源的调用 URL,借此 Snowflake 可以调用远程服务。

可选参数

SECURE

指定函数为安全函数。如果某函数安全,则属于函数所有者的所有用户看不到 URL、HTTP 标头和上下文标头。

[ [ NOT ] NULL ]

此子句指明函数是可以返回 NULL 值,还是必须仅返回 NON-NULL 值。如果指定 NOT NULL,则函数必须只返回非 NULL 值。如果指定 NULL,则函数可以返回 NULL 值。

默认值:默认值为 NULL(即,函数可以返回 NULL 值)。

CALLED ON NULL INPUT . { RETURNS NULL ON NULL INPUT | STRICT }

指定在使用 Null 输入调用时函数的行为。与输入为 Null 时始终返回 Null 的系统定义的函数相反,外部函数可以处理 Null 输入,即使输入为 Null 时也会返回非 Null 值:

  • CALLED ON NULL INPUT 将始终使用 Null 输入调用函数。这取决于函数是否适当地处理这些值。

  • 如果任何输入为 Null,则 RETURNS NULL ON NULL INPUT (或其同义词 STRICT)将不会调用函数。相反,将始终为该行返回 null 值。请注意,对于非 Null 输入,该函数仍可能返回 Null。

默认:CALLED ON NULL INPUT

{ VOLATILE | IMMUTABLE }

指定在返回结果时函数的行为:

  • VOLATILE:该函数可以为不同的行返回不同的值,即使是相同的输入也如此(例如,由于非确定性和有状态性)。

  • IMMUTABLE:当使用相同的输入调用时,该函数始终返回相同的结果。Snowflake 不会检查或保证这一点;远程服务必须设计成这种行为方式。为实际为相同输入返回不同值的函数指定 IMMUTABLE,这样会导致未定义的行为。

默认:VOLATILE

Snowflake 建议您明确设置此值,而不是接受默认值。明确设置此值可以减少出错的机会,并告诉用户函数的行为方式。(SHOW EXTERNAL FUNCTIONS 命令显示函数是易变,还是不可变。

有关 VOLATILE 与 IMMUTABLE 外部函数的重要补充信息,请参阅 将函数分类为可变或不可变

COMMENT = 'string_literal'

指定函数的注释,该注释在 SHOW FUNCTIONSSHOW EXTERNAL FUNCTIONS 输出的 DESCRIPTION 列中显示。

默认:user-defined function

HEADERS = ( 'header_1' = 'value_1' [ , 'header_2' = 'value_2' ... ] )

此子句允许用户指定随每个请求一起发送的键值元数据。外部函数的创建者决定标头中的内容,调用方对此没有任何控制权。Snowflake 在所有指定的标头名称前面追加前缀“sf-custom-”,并将它们作为 HTTP 标头发送。

该值必须是常量字符串,而不是表达式。

下面是一个示例:

HEADERS = (
    'volume-measure' = 'liters',
    'distance-measure' = 'kilometers'
)
Copy

此示例使 Snowflake 在每个 HTTP 请求中添加 2 个 HTTPS 标头:sf-custom-volume-measuresf-custom-distance-measure,以及它们相应的值。

标头名称的规则与 Snowflake 数据库标识符的规则不同。标头名称可以由大多数可见的标准 ASCII 字符(十进制 32-126)组成,但以下字符除外:

  • 空格字符

  • (

  • )

  • ,

  • /

  • :

  • ;

  • <

  • >

  • =

  • "

  • ?

  • @

  • [

  • ]

  • \

  • {

  • }

  • _

请特别注意,标头名称中不允许使用下划线字符。

标头名称和值由单引号分隔,因此标头名称或值中的任何单引号都必须用反斜杠字符进行转义。

如果反斜杠字符在标头值中用作字面量字符,则必须对其进行转义。

在标头值中,空格和制表符都是允许的,但是标头值不应该在一行中包含多个空格字符。此限制适用于空格字符的组合(例如空格后跟制表符)以及单个空格字符(例如一行中的两个空格)。

如果函数作者将函数标记为安全(采用 CREATE SECURE EXTERNAL FUNCTION...),则标头、上下文标头、二进制上下文标头和 URL 对函数用户不可见。

外部函数的标头名称和标头值的大小之和必须小于或等于 8 KB。

CONTEXT_HEADERS = ( context_function_1 [ , context_function_2 ...] )

此函数类似于 HEADERS,但不使用常量字符串,而是将 Snowflake 上下文函数结果绑定到 HTTP 标头。(有关 Snowflake 上下文函数的更多信息,请参阅:上下文函数。)

上下文标头并非支持所有上下文函数。支持以下内容:

  • CURRENT_ACCOUNT()

  • CURRENT_CLIENT()

  • CURRENT_DATABASE()

  • CURRENT_DATE()

  • CURRENT_IP_ADDRESS()

  • CURRENT_REGION()

  • CURRENT_ROLE()

  • CURRENT_SCHEMA()

  • CURRENT_SCHEMAS()

  • CURRENT_SESSION()

  • CURRENT_STATEMENT()

  • CURRENT_TIME()

  • CURRENT_TIMESTAMP()

  • CURRENT_TRANSACTION()

  • CURRENT_USER()

  • CURRENT_VERSION()

  • CURRENT_WAREHOUSE()

  • LAST_QUERY_ID()

  • LAST_TRANSACTION()

  • LOCALTIME()

  • LOCALTIMESTAMP()

当函数名在 CONTEXT_HEADERS 子句中列出时,函数名不应加引号。

Snowflake 在写入 HTTP 请求之前会将 sf-context 追加到标头。

示例:

CONTEXT_HEADERS = (current_timestamp)
Copy

在此示例中,Snowflake 将标头 sf-context-current-timestamp 写入 HTTP 请求。

上下文标头名称和值中允许的字符与 :ref:` 自定义标头名称和值 <label-external_function_headers_valid_characters>` 中允许的字符相同。

上下文函数可以生成 HTTP 标头值中非法的字符,包括(但不限于):

  • 换行符

  • Ä

  • Î

  • ß

  • ë

  • ¬

  • ±

  • ©

  • ®

Snowflake 将每个包含一个或多个非法字符的序列替换为一个空格字符。(替换是按序列,而不是按字符。)

例如,假设上下文函数 CURRENT_STATEMENT() 返回:

select
  /*ÄÎß묱©®*/
  my_external_function(1);
Copy

sf-context-current-statement 中发送的值为:

select /* */ my_external_function(1);
Copy

为确保远程服务可以通过上下文函数访问原始结果(包含非法字符),即使非法字符已替换,Snowflake 也会发送一个二进制上下文标头,其中包含使用 base64 编码的上下文函数结果。

在上面的示例中,base64 标头中发送的值是调用的结果:

base64_encode('select\n/ÄÎß묱©®/\nmy_external_function(1)')
Copy

如果需要,远程服务负责解码 base64 值。

每个此类 base64 标头都根据以下惯例命名:

sf-context-<context-function>-base64
Copy

在上面的示例中,标头的名称为

sf-context-current-statement-base64
Copy

如果没有发送上下文标头,则不会发送 base64 上下文标头。

如果发送到外部函数的行拆分为多个批次,则所有批次都包含相同的上下文标头和相同的二进制上下文标头。

MAX_BATCH_ROWS = integer

此参数指定发送到代理服务的每个批次中的 最大 行数。

此参数的目的是限制具有内存约束或其他限制的远程服务的批次大小。此参数不是性能调整参数。此参数指定大小上限,而不是建议的大小。

如果未指定 MAX_BATCH_ROWS,Snowflake 将估计最佳批次大小并使用该大小。

Snowflake 建议不设置此参数,除非远程服务需要限制。

COMPRESSION = compression_type

如果指定了此子句,则在 Snowflake 与代理服务之间发送的 JSON 负载会被压缩。

有效值为:

  • NONE

  • GZIP

  • DEFLATE

  • AUTO

    • 在 AWS 上,AUTO 等同于 GZIP

    • 在 Azure 上,AUTO 等同于 NONE

    • 在 GCP 上,AUTO 等同于 NONE

Amazon API Gateway 会自动压缩/解压缩请求。有关 Amazon API Gateway 压缩和解压缩的更多信息,请参阅:https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-gzip-compression-decompression.html (https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-gzip-compression-decompression.html)

有关其他云平台代理服务的压缩和解压缩的信息,请参阅关于这些云平台的文档。

默认值:默认值为 AUTO

REQUEST_TRANSLATOR = request_translator_udf_name

此参数指定请求转换器函数的名称。有关更多信息,请参阅 将请求和响应转换器与远程服务的数据结合使用

RESPONSE_TRANSLATOR = response_translator_udf_name

此参数指定响应转换器函数的名称。有关更多信息,请参阅 将请求和响应转换器与远程服务的数据结合使用

访问控制要求

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

权限

对象

备注

CREATE EXTERNAL FUNCTION

架构

Operating on functions also requires the USAGE privilege on the parent database and schema.

:emph:` ` OWNERSHIP 或 USAGE

API 集成

在创建引用 API 集成的外部函数时需要。

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

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

一般使用说明

  • 当使用压缩时,Snowflake 设置 HTTP 标头文件“Content-Encoding”和“Accept-Encoding”。

  • 实参类型和返回类型不能为 GEOGRAPHY。

  • 关于元数据:

    注意

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

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

CREATE OR ALTER EXTERNAL FUNCTION 使用说明

  • 不支持更改函数定义及其返回类型。

示例

通过 Amazon API Gateway 代理服务创建外部函数

下面的示例演示通过 Amazon API Gateway 代理服务调用的 CREATE EXTERNAL FUNCTION 语句:

CREATE OR REPLACE EXTERNAL FUNCTION local_echo(string_col VARCHAR)
  RETURNS VARIANT
  API_INTEGRATION = demonstration_external_api_integration_01
  AS 'https://xyz.execute-api.us-west-2.amazonaws.com/prod/remote_echo';
Copy

在此示例中:

  • local_echo 是从 SQL 语句调用的名称(例如,您可以执行 SELECT local_echo(varchar_column) ...;)。

  • string_col VARCHAR 包含输入参数的名称和数据类型。外部函数可以有 0 个或多个输入参数。

  • variant 是外部函数返回值的数据类型。

  • 名称 demonstration_external_api_integration_01 是之前在 API 语句中创建的 CREATE API INTEGRATION 集成的名称。

  • URL https://xyz.execute-api.us-west-2.amazonaws.com/prod/remote_echo 是用于标识代理服务和资源的字符串。HTTP POST 命令会发送到此 URL。

使用 CREATE OR ALTER EXTERNAL FUNCTION 命令更改外部函数

更改上面创建的外部函数 local_echo,将批处理行的最大数量设置为 100,压缩为 GZIP,并添加标题和上下文标题:

CREATE OR ALTER SECURE EXTERNAL FUNCTION local_echo(string_col VARCHAR)
  RETURNS VARIANT
  API_INTEGRATION = demonstration_external_api_integration_01
  HEADERS = ('header_variable1'='header_value', 'header_variable2'='header_value2')
  CONTEXT_HEADERS = (current_account)
  MAX_BATCH_ROWS = 100
  COMPRESSION = "GZIP"
  AS 'https://xyz.execute-api.us-west-2.amazonaws.com/prod/remote_echo';
Copy
语言: 中文