CREATE PROCEDURE

创建新的 存储过程

过程可以用以下语言之一编写:

备注

如果要创建和调用匿名(而不是存储)过程,请使用 CALL(使用匿名过程)。创建匿名过程不需要具有 CREATE PROCEDURE 架构权限的角色。

另请参阅:

ALTER PROCEDUREDROP PROCEDURESHOW PROCEDURESDESCRIBE PROCEDURECALL

语法

Java 处理程序

可以创建一个包含内联处理程序代码或在 JAR 文件中引用其处理程序代码的存储过程。有关更多信息,请参阅 将处理程序代码保持内联或保留在暂存区

对于内联存储过程,请使用以下语法:

CREATE [ OR REPLACE ] [ SECURE ] PROCEDURE <name> (
    [ <arg_name> <arg_data_type> [ DEFAULT <defaut_value> ] ] [ , ... ] )
  [ COPY GRANTS ]
  RETURNS { <result_data_type> [ [ NOT ] NULL ] | TABLE ( [ <col_name> <col_data_type> [ , ... ] ] ) }
  LANGUAGE JAVA
  RUNTIME_VERSION = '<java_runtime_version>'
  PACKAGES = ( 'com.snowflake:snowpark:<version>' [, '<package_name_and_version>' ...] )
  [ IMPORTS = ( '<stage_path_and_file_name_to_read>' [, '<stage_path_and_file_name_to_read>' ...] ) ]
  HANDLER = '<fully_qualified_method_name>'
  [ EXTERNAL_ACCESS_INTEGRATIONS = ( <name_of_integration> [ , ... ] ) ]
  [ SECRETS = ('<secret_variable_name>' = <secret_name> [ , ... ] ) ]
  [ TARGET_PATH = '<stage_path_and_file_name_to_write>' ]
  [ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
  [ { VOLATILE | IMMUTABLE } ] -- Note: VOLATILE and IMMUTABLE are deprecated.
  [ COMMENT = '<string_literal>' ]
  [ EXECUTE AS { CALLER | OWNER } ]
  AS '<procedure_definition>'
Copy

对于使用预编译处理程序的存储过程,请使用以下语法。

CREATE [ OR REPLACE ] [ SECURE ] PROCEDURE <name> (
    [ <arg_name> <arg_data_type> [ DEFAULT <default_value> ] ] [ , ... ] )
  [ COPY GRANTS ]
  RETURNS { <result_data_type> [ [ NOT ] NULL ] | TABLE ( [ <col_name> <col_data_type> [ , ... ] ] ) }
  LANGUAGE JAVA
  RUNTIME_VERSION = '<java_runtime_version>'
  PACKAGES = ( 'com.snowflake:snowpark:<version>' [, '<package_name_and_version>' ...] )
  [ IMPORTS = ( '<stage_path_and_file_name_to_read>' [, '<stage_path_and_file_name_to_read>' ...] ) ]
  HANDLER = '<fully_qualified_method_name>'
  [ EXTERNAL_ACCESS_INTEGRATIONS = ( <name_of_integration> [ , ... ] ) ]
  [ SECRETS = ('<secret_variable_name>' = <secret_name> [ , ... ] ) ]
  [ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
  [ VOLATILE | IMMUTABLE ] -- Note: VOLATILE and IMMUTABLE are deprecated.
  [ COMMENT = '<string_literal>' ]
  [ EXECUTE AS { CALLER | OWNER } ]
Copy

JavaScript 处理程序

CREATE [ OR REPLACE ] [ SECURE ] PROCEDURE <name> (
    [ <arg_name> <arg_data_type> [ DEFAULT <default_value> ] ] [ , ... ] )
  [ COPY GRANTS ]
  RETURNS <result_data_type> [ NOT NULL ]
  LANGUAGE JAVASCRIPT
  [ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
  [ VOLATILE | IMMUTABLE ] -- Note: VOLATILE and IMMUTABLE are deprecated.
  [ COMMENT = '<string_literal>' ]
  [ EXECUTE AS { CALLER | OWNER } ]
  AS '<procedure_definition>'
Copy

重要

JavaScript 区分大小写,而 SQL 不区分大小写。有关在 JavaScript 代码中使用存储过程实参名称的重要信息,请参阅 JavaScript 实参区分大小写

Python 处理程序

对于内联存储过程,请使用以下语法:

CREATE [ OR REPLACE ] [ SECURE ] PROCEDURE <name> (
    [ <arg_name> <arg_data_type> [ DEFAULT <default_value> ] ] [ , ... ] )
  [ COPY GRANTS ]
  RETURNS { <result_data_type> [ [ NOT ] NULL ] | TABLE ( [ <col_name> <col_data_type> [ , ... ] ] ) }
  LANGUAGE PYTHON
  RUNTIME_VERSION = '<python_version>'
  PACKAGES = ( 'snowflake-snowpark-python[==<version>]'[, '<package_name>[==<version>]' ... ])
  [ IMPORTS = ( '<stage_path_and_file_name_to_read>' [, '<stage_path_and_file_name_to_read>' ...] ) ]
  HANDLER = '<function_name>'
  [ EXTERNAL_ACCESS_INTEGRATIONS = ( <name_of_integration> [ , ... ] ) ]
  [ SECRETS = ('<secret_variable_name>' = <secret_name> [ , ... ] ) ]
  [ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
  [ { VOLATILE | IMMUTABLE } ] -- Note: VOLATILE and IMMUTABLE are deprecated.
  [ COMMENT = '<string_literal>' ]
  [ EXECUTE AS { CALLER | OWNER } ]
  AS '<procedure_definition>'
Copy

对于代码位于暂存区文件中的存储过程,请使用以下语法:

CREATE [ OR REPLACE ] PROCEDURE <name> (
    [ <arg_name> <arg_data_type> [ DEFAULT <default_value> ] ] [ , ... ] )
  [ COPY GRANTS ]
  RETURNS { <result_data_type> [ [ NOT ] NULL ] | TABLE ( [ <col_name> <col_data_type> [ , ... ] ] ) }
  LANGUAGE PYTHON
  RUNTIME_VERSION = '<python_version>'
  PACKAGES = ( 'snowflake-snowpark-python[==<version>]'[, '<package_name>[==<version>]' ... ])
  [ IMPORTS = ( '<stage_path_and_file_name_to_read>' [, '<stage_path_and_file_name_to_read>' ...] ) ]
  HANDLER = '<module_file_name>.<function_name>'
  [ EXTERNAL_ACCESS_INTEGRATIONS = ( <name_of_integration> [ , ... ] ) ]
  [ SECRETS = ('<secret_variable_name>' = <secret_name> [ , ... ] ) ]
  [ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
  [ { VOLATILE | IMMUTABLE } ] -- Note: VOLATILE and IMMUTABLE are deprecated.
  [ COMMENT = '<string_literal>' ]
  [ EXECUTE AS { CALLER | OWNER } ]
Copy

Scala 处理程序

可以创建一个包含内联处理程序代码或在 JAR 文件中引用其处理程序代码的存储过程。有关更多信息,请参阅 将处理程序代码保持内联或保留在暂存区

对于内联存储过程,请使用以下语法:

CREATE [ OR REPLACE ] [ SECURE ] PROCEDURE <name> (
    [ <arg_name> <arg_data_type> [ DEFAULT <default_value> ] ] [ , ... ] )
  [ COPY GRANTS ]
  RETURNS { <result_data_type> [ [ NOT ] NULL ] | TABLE ( [ <col_name> <col_data_type> [ , ... ] ] ) }
  LANGUAGE SCALA
  RUNTIME_VERSION = '<scala_runtime_version>'
  PACKAGES = ( 'com.snowflake:snowpark:<version>' [, '<package_name_and_version>' ...] )
  [ IMPORTS = ( '<stage_path_and_file_name_to_read>' [, '<stage_path_and_file_name_to_read>' ...] ) ]
  HANDLER = '<fully_qualified_method_name>'
  [ TARGET_PATH = '<stage_path_and_file_name_to_write>' ]
  [ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
  [ { VOLATILE | IMMUTABLE } ] -- Note: VOLATILE and IMMUTABLE are deprecated.
  [ COMMENT = '<string_literal>' ]
  [ EXECUTE AS { CALLER | OWNER } ]
  AS '<procedure_definition>'
Copy

对于使用预编译处理程序的存储过程,请使用以下语法。

CREATE [ OR REPLACE ] [ SECURE ] PROCEDURE <name> (
    [ <arg_name> <arg_data_type> [ DEFAULT <default_value> ] ] [ , ... ] )
  [ COPY GRANTS ]
  RETURNS { <result_data_type> [ [ NOT ] NULL ] | TABLE ( [ <col_name> <col_data_type> [ , ... ] ] ) }
  LANGUAGE SCALA
  RUNTIME_VERSION = '<scala_runtime_version>'
  PACKAGES = ( 'com.snowflake:snowpark:<version>' [, '<package_name_and_version>' ...] )
  [ IMPORTS = ( '<stage_path_and_file_name_to_read>' [, '<stage_path_and_file_name_to_read>' ...] ) ]
  HANDLER = '<fully_qualified_method_name>'
  [ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
  [ VOLATILE | IMMUTABLE ] -- Note: VOLATILE and IMMUTABLE are deprecated.
  [ COMMENT = '<string_literal>' ]
  [ EXECUTE AS { CALLER | OWNER } ]
Copy

Snowflake Scripting 处理程序

CREATE [ OR REPLACE ] PROCEDURE <name> (
    [ <arg_name> <arg_data_type> [ DEFAULT <default_value> ] ] [ , ... ] )
  [ COPY GRANTS ]
  RETURNS { <result_data_type> | TABLE ( [ <col_name> <col_data_type> [ , ... ] ] ) }
  [ NOT NULL ]
  LANGUAGE SQL
  [ { CALLED ON NULL INPUT | { RETURNS NULL ON NULL INPUT | STRICT } } ]
  [ { VOLATILE | IMMUTABLE } ] -- Note: VOLATILE and IMMUTABLE are deprecated.
  [ COMMENT = '<string_literal>' ]
  [ EXECUTE AS { CALLER | OWNER } ]
  AS <procedure_definition>
Copy

备注

如果要在 SnowSQL 或 Classic Console 中创建 Snowflake Scripting 过程,则必须在 procedure definition 两边使用 字符串字面量分隔符'$$)。请参阅 在 SnowSQL、Classic Console 和 Python Connector 中使用 Snowflake Scripting

必填参数

所有语言

name ( [ arg_name arg_data_type [ DEFAULT default_value ] ] [ , ... ] )

指定存储过程的标识符 (name)、任何输入实参以及任何可选实参的默认值。

  • 对于标识符:

    • 对于在其中创建过程的架构,标识符不需要是唯一的,因为存储过程 由名称和实参类型的组合标识和解析

    • 标识符必须以字母字符开头,且不能包含空格或特殊字符,除非整个标识符字符串放在双引号内(例如 "My object")。放在双引号内的标识符也区分大小写。请参阅 标识符要求

  • 对于输入实参:

    • 对于 arg_name,请指定输入实参的名称。

    • 对于 arg_data_type,使用与所用语言相对应的 Snowflake 数据类型。

      备注

      对于用 Java、Python 或 Scala(使用 Snowpark APIs)编写的存储过程,省略 Snowpark Session 对象的实参。

      Session 实参不是在 CREATE PROCEDURE 或 CALL 中指定的正式参数。调用存储过程时,Snowflake 会自动创建一个 Session 对象并将其传递给存储过程的处理程序函数。

    • 若要指示实参是可选的,请使用 DEFAULT default_value 指定实参的默认值。对于默认值,可以使用字面量或表达式。

      如果指定任何可选实参,则必须将这些实参放在必需实参之后。

      如果过程具有可选实参,则无法定义具有相同名称和不同签名的其他过程。

      有关详细信息,请参阅 指定可选实参

RETURNS result_data_type [ NOT NULL ]

指定存储过程返回的结果的类型。

  • 对于 result_data_type,使用与所用语言类型相对应的 Snowflake 数据类型。

    备注

    在 Snowpark(Java 或 Scala)中编写的存储过程必须具有返回值。在 Snowpark (Python) 中,当存储过程不返回任何值时,被视为返回 None。请注意,每个 CREATE PROCEDURE 语句都必须包含一个定义返回类型的 RETURNS 子句,即使该过程没有显式返回任何内容。

  • 对于 RETURNS TABLE ( [ col_name col_data_type [ , ... ] ] ),如果知道返回表中各列的 Snowflake 数据类型,请指定列名称和类型:

    CREATE OR REPLACE PROCEDURE get_top_sales()
      RETURNS TABLE (sales_date DATE, quantity NUMBER)
    ...
    
    Copy

    否则(例如,如果您在运行时确定列类型),则可以省略列名称和类型:

    CREATE OR REPLACE PROCEDURE get_top_sales()
      RETURNS TABLE ()
    
    Copy

    备注

    目前,在 RETURNS TABLE(...) 子句中,您无法指定 GEOGRAPHY 为列类型。这在创建存储过程和匿名过程中均适用。

    CREATE OR REPLACE PROCEDURE test_return_geography_table_1()
      RETURNS TABLE(g GEOGRAPHY)
      ...
    
    Copy
    WITH test_return_geography_table_1() AS PROCEDURE
      RETURNS TABLE(g GEOGRAPHY)
      ...
    CALL test_return_geography_table_1();
    
    Copy

    如果尝试指定 GEOGRAPHY 为列类型,则调用存储过程会导致该错误:

    Stored procedure execution error: data type of returned table does not match expected returned table type
    
    Copy

    要解决这个问题,可以省略 RETURNS TABLE() 中的列实参和类型。

    CREATE OR REPLACE PROCEDURE test_return_geography_table_1()
      RETURNS TABLE()
      ...
    
    Copy
    WITH test_return_geography_table_1() AS PROCEDURE
      RETURNS TABLE()
      ...
    CALL test_return_geography_table_1();
    
    Copy

    仅当处理程序以下列语言编写时,才支持 RETURNS TABLE(...):

实际上,在 Snowflake Scripting 块 之外,无法使用返回值,因为该调用不能成为表达式的一部分

LANGUAGE language

指定存储过程代码的语言。请注意,这对于用 Snowflake Scripting 编写的存储过程是可选的。

目前,language 支持的值包括:

  • JAVA`(适用于 :doc:`Java </developer-guide/stored-procedure/stored-procedures-java>

  • JAVASCRIPT`(适用于 :doc:`JavaScript </developer-guide/stored-procedure/stored-procedures-javascript>

  • PYTHON`(适用于 :doc:`Python </developer-guide/stored-procedure/stored-procedures-python>

  • SCALA`(适用于 :doc:`Scala </developer-guide/stored-procedure/stored-procedures-scala>

  • SQL`(适用于 :doc:`Snowflake Scripting </developer-guide/snowflake-scripting/index>

默认:SQL

AS procedure_definition

定义存储过程执行的代码。该定义可以包含任何有效的代码。

请注意以下事项:

  • 对于代码未内联的存储过程,省略 AS 子句。这包括具有暂存处理程序的存储过程。

    相反,使用 IMPORTS 子句指定包含存储过程代码的文件的位置。有关详细信息,请参阅:

    有关内联处理程序和暂存处理程序的更多信息,请参阅 将处理程序代码保持内联或保留在暂存区

  • 如果出现以下情况,必须在 procedure definition 两边使用 字符串字面量分隔符'$$):

  • 对于 JavaScript 中的存储过程,如果要编写包含换行符的字符串,则可以在字符串两边使用反引号。

    以下 JavaScript 存储过程示例使用 $$ 和反引号,因为存储过程的正文包含单引号和双引号:

    CREATE OR REPLACE TABLE table1 ("column 1" VARCHAR);
    
    Copy
    CREATE or replace PROCEDURE proc3()
      RETURNS VARCHAR
      LANGUAGE javascript
      AS
      $$
      var rs = snowflake.execute( { sqlText: 
          `INSERT INTO table1 ("column 1") 
               SELECT 'value 1' AS "column 1" ;`
           } );
      return 'Done.';
      $$;
    
    Copy
  • 对于非 Snowflake Scripting 语言,当执行 CREATE PROCEDURE 命令时,Snowflake 不会完全验证代码。

    例如,对于 Snowpark (Scala) 存储过程,将验证输入实参的数量和类型,但不会验证函数的正文。如果数量或类型不匹配(例如,如果实参为非数字类型时使用了 Snowflake 数据类型 NUMBER),则执行 CREATE PROCEDURE 命令会导致错误。

    如果代码无效,CREATE PROCEDURE 命令将成功,调用存储过程时将返回错误。

有关存储过程的更多详细信息,请参阅 使用存储过程

Java

RUNTIME_VERSION = 'language_runtime_version'

要使用的语言运行时版本。当前,支持的版本是:

  • 11

PACKAGES = ( 'snowpark_package_name' [, 'package_name' ...] )

在 Snowflake 中所部署包的名称的逗号分隔列表,应包含在处理程序代码执行环境中。Snowpark 包对于存储过程是必需的,因此必须始终在 PACKAGES 子句中引用该包。有关 Snowpark 的更多信息,请参阅 Snowpark API

默认情况下,Snowflake 运行存储过程的环境包括一组受支持语言的选定包。当您在 PACKAGES 子句中引用这些包时,无需在 IMPORTS 子句中引用包含该包的文件,因为该包已在 Snowflake 中可用。还可以指定包版本。

有关 Java 支持的包和版本的列表,请查询 INFORMATION_SCHEMA.PACKAGES 视图 中的行,并指定语言。例如:

SELECT * FROM INFORMATION_SCHEMA.PACKAGES WHERE LANGUAGE = 'java';
Copy

要指定包名称和版本号,请使用以下形式:

domain:package_name:version
Copy

要指定最新版本,请为 version 指定 latest

例如,要在 Snowflake 中加入来自新版 Snowpark 库的包,请使用以下方法:

PACKAGES = ('com.snowflake:snowpark:latest')
Copy

从 Snowpark 库中指定包时,必须指定版本 1.3.0 或更高版本。

HANDLER = 'fully_qualified_method_name'

为存储过程使用方法或函数的完全限定名称。这通常采用以下形式:

com.my_company.my_package.MyClass.myMethod
Copy

其中:

com.my_company.my_package
Copy

对应于包含该对象或类的包:

package com.my_company.my_package;
Copy

Python

RUNTIME_VERSION = 'language_runtime_version'

要使用的语言运行时版本。当前,支持的版本是:

  • 3.8

  • 3.9

  • 3.10

  • 3.11

PACKAGES = ( 'snowpark_package_name' [, 'package_name' ...] )

在 Snowflake 中所部署包的名称的逗号分隔列表,应包含在处理程序代码执行环境中。Snowpark 包对于存储过程是必需的,因此必须始终在 PACKAGES 子句中引用该包。有关 Snowpark 的更多信息,请参阅 Snowpark API

默认情况下,Snowflake 运行存储过程的环境包括一组受支持语言的选定包。当您在 PACKAGES 子句中引用这些包时,无需在 IMPORTS 子句中引用包含该包的文件,因为该包已在 Snowflake 中可用。还可以指定包版本。

有关 Python 支持的包和版本的列表,请查询 INFORMATION_SCHEMA.PACKAGES 视图 中的行,并指定语言。例如:

SELECT * FROM INFORMATION_SCHEMA.PACKAGES WHERE LANGUAGE = 'python';
Copy

Snowflake 包含大量可通过 Anaconda 购买的软件包;有关更多信息,请参阅 使用第三方包

要指定包名称和版本号,请使用以下形式:

package_name[==version]
Copy

要指定新版本,请省略版本号。

例如,要包括空间包版本 2.3.5(以及所需的 Snowpark 包的新版本),请使用以下命令:

PACKAGES = ('snowflake-snowpark-python', 'spacy==2.3.5')
Copy

从 Snowpark 库中指定包时,必须指定版本 0.4.0 或更高版本。省略版本号即可使用 Snowflake 中可用的最新版本。

HANDLER = 'fully_qualified_method_name'

使用存储过程的函数或方法的名称。这可能会有所不同,具体取决于代码是内联还是在某个暂存区引用。

  • 当代码为内联时,您只需指定函数名称,如以下示例所示:

    CREATE OR REPLACE PROCEDURE MYPROC(from_table STRING, to_table STRING, count INT)
      ...
      HANDLER = 'run'
    AS
    $$
    def run(session, from_table, to_table, count):
      ...
    $$;
    
    Copy
  • 从暂存区导入代码时,将完全受限的处理程序函数名称指定为 <module_name>.<function_name>

    CREATE OR REPLACE PROCEDURE MYPROC(from_table STRING, to_table STRING, count INT)
      ...
      IMPORTS = ('@mystage/my_py_file.py')
      HANDLER = 'my_py_file.run';
    
    Copy

Scala

RUNTIME_VERSION = 'language_runtime_version'

要使用的语言运行时版本。当前,支持的版本是:

  • 2.12

PACKAGES = ( 'snowpark_package_name' [, 'package_name' ...] )

在 Snowflake 中所部署包的名称的逗号分隔列表,应包含在处理程序代码执行环境中。Snowpark 包对于存储过程是必需的,因此必须始终在 PACKAGES 子句中引用该包。有关 Snowpark 的更多信息,请参阅 Snowpark API

默认情况下,Snowflake 运行存储过程的环境包括一组受支持语言的选定包。当您在 PACKAGES 子句中引用这些包时,无需在 IMPORTS 子句中引用包含该包的文件,因为该包已在 Snowflake 中可用。还可以指定包版本。

有关 Scala 支持的包和版本的列表,请查询 INFORMATION_SCHEMA.PACKAGES 视图 中的行,并指定语言。例如:

SELECT * FROM INFORMATION_SCHEMA.PACKAGES WHERE LANGUAGE = 'scala';
Copy

要指定包名称和版本号,请使用以下形式:

domain:package_name:version
Copy

要指定最新版本,请为 version 指定 latest

例如,要在 Snowflake 中加入来自新版 Snowpark 库的包,请使用以下方法:

PACKAGES = ('com.snowflake:snowpark:latest')
Copy

Snowflake 支持在 Scala 存储过程中使用 Snowpark 版本 0.9.0 或更高版本。但是请注意,这些版本有局限性。例如,1.1.0 之前的版本不支持在存储过程中使用事务。

HANDLER = 'fully_qualified_method_name'

为存储过程使用方法或函数的完全限定名称。这通常采用以下形式:

com.my_company.my_package.MyClass.myMethod
Copy

其中:

com.my_company.my_package
Copy

对应于包含该对象或类的包:

package com.my_company.my_package;
Copy

可选参数

所有语言

SECURE

指定过程是安全的。有关安全过程的详细信息,请参阅 使用安全 UDFs 和存储过程保护敏感信息

[ [ NOT ] NULL ]

指定存储过程是可以返回 NULL 值还是只能返回 NON-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`(或其同义词 :code:`STRICT)不会调用存储过程,因此不会执行存储过程中的语句。相反,该行将始终返回 null 值。请注意,对于非 null 输入,该过程可能仍返回 null 值。

默认:CALLED ON NULL INPUT

VOLATILE | IMMUTABLE

已弃用

注意

对于存储过程,这些关键字已弃用。这些关键字不适用于存储过程。在将来的版本中,这些关键字将从文档中移除。

COMMENT = 'string_literal'

指定存储过程的注释,该注释显示在 SHOW PROCEDURES 输出的 DESCRIPTION 列中。

默认:stored procedure

EXECUTE AS CALLER . EXECUTE AS OWNER

指定存储过程是以所有者的权限(“所有者权限”存储过程)还是以调用方的权限(“调用方权限”存储过程)执行:

  • 如果执行语句 CREATE PROCEDURE ...EXECUTE AS CALLER,那么将来该过程将以调用方权限过程执行。

  • 如果执行 CREATE PROCEDURE ...EXECUTE AS OWNER,那么该过程将以所有者权限过程执行。

默认情况下(如果在创建过程时没有显式指定 OWNER 或 CALLER),该过程以所有者权限存储过程运行。

所有者权限存储过程对调用方环境(例如调用方的会话变量)的访问权限较少,Snowflake 默认采用这种更高级别的隐私和安全性。

有关更多信息,请参阅 了解调用方权限和所有者权限存储过程

默认:OWNER

COPY GRANTS

指定在使用 CREATE OR REPLACE PROCEDURE 创建新过程时保留原始过程的访问权限。

该参数将 除 OWNERSHIP 以外 的所有权限从现有过程复制到新过程。新过程将继承架构中为该对象类型定义的任何未来授权。默认情况下,执行 CREATE PROCEDURE 语句的角色拥有新过程。

注意:

  • 替换过程的 SHOW GRANTS 输出会将复制权限的获得者列为执行 CREATE PROCEDURE 语句的角色,并附带执行语句时的当前时间戳。

  • 复制授权的操作在 CREATE PROCEDURE 命令中会以原子方式发生(即在同一事务中)。

Java

IMPORTS = ( 'stage_path_and_file_name_to_read' [, 'stage_path_and_file_name_to_read' ...] )

要导入的文件的位置(暂存区)、路径和名称。必须将 IMPORTS 子句设置为包含存储过程所依赖的任何文件:

  • 如果要编写内联存储过程,则可以省略此子句,除非代码依赖于在存储过程或资源文件外部定义的类。

  • 如果要使用暂存处理程序编写存储过程,则还必须包括包含存储过程处理程序代码的 JAR 文件的路径。

  • IMPORTS 定义不能从传递到存储过程的实参中引用变量。

IMPORTS 子句中的每个文件都必须具有唯一的名称,即使这些文件位于不同的子目录或不同的暂存区。

TARGET_PATH = 'stage_path_and_file_name_to_write'

对于具有内联处理程序代码的存储过程,指定在编译 procedure_definition 中指定的源代码后,Snowflake 应将编译后的代码(JAR 文件)写入的位置。如果省略此子句,则每次需要代码时,Snowflake 都会重新编译源代码。

如果指定此子句:

  • 不能将其设置为现有文件。如果 TARGET_PATH 指向现有文件,Snowflake 将返回错误。

  • 如果同时指定了 IMPORTS 和 TARGET_PATH 子句,即使文件位于不同的子目录或不同的暂存区,TARGET_PATH 子句中的文件名也必须不同于 IMPORTS 子句中的每个文件名。

  • 如果不再需要使用存储过程(例如,如果弃用存储过程),则必须手动移除此 JAR 文件。

EXTERNAL_ACCESS_INTEGRATIONS = ( integration_name [ , ... ] )

此过程的处理程序代码访问外部网络所需的 外部访问集成 的名称。

外部访问集成指定 网络规则密钥,这些规则和密钥指定了处理程序代码在请求外部网络(如外部 REST API)时可以使用的外部位置和凭据(如果有)。

SECRETS = ( 'secret_variable_name' = secret_name [ , ...  ] )

将密钥的名称分配给变量,以便在从处理程序代码中的密钥中检索信息时,可以使用这些变量引用密钥。

对于您在此处指定的密钥,其必须获得指定为此 CREATE PROCEDURE 命令的 EXTERNAL_ACCESS_INTEGRATIONS 参数值的 外部访问集成 的允许。

此参数的值是以逗号分隔的赋值表达式列表,其中包含以下部分:

  • secret_name,即允许使用的密钥的名称。

    如果指定的 SECRETS 值的密钥未包含在由 EXTERNAL_ACCESS_INTEGRATIONS 参数指定的集成中,将收到错误消息。

  • 'secret_variable_name' 作为从密钥中检索信息时将在处理程序代码中使用的变量。

有关更多信息(包括示例),请参阅 在函数或过程中使用外部访问集成

Python

IMPORTS = ( 'stage_path_and_file_name_to_read' [, 'stage_path_and_file_name_to_read' ...] )

要导入的文件的位置(暂存区)、路径和名称。必须将 IMPORTS 子句设置为包含存储过程所依赖的任何文件:

  • 如果要编写内联存储过程,则可以省略此子句,除非代码依赖于在存储过程或资源文件外部定义的类。

  • 如果存储过程的代码将位于暂存区中,则还必须包含代码所在的模块文件的路径。

  • IMPORTS 定义不能从传递到存储过程的实参中引用变量。

IMPORTS 子句中的每个文件都必须具有唯一的名称,即使这些文件位于不同的子目录或不同的暂存区。

EXTERNAL_ACCESS_INTEGRATIONS = ( integration_name [ , ... ] )

此过程的处理程序代码访问外部网络所需的 外部访问集成 的名称。

外部访问集成指定 网络规则密钥,这些规则和密钥指定了处理程序代码在请求外部网络(如外部 REST API)时可以使用的外部位置和凭据(如果有)。

SECRETS = ( 'secret_variable_name' = secret_name [ , ...  ] )

将密钥的名称分配给变量,以便在从处理程序代码中的密钥中检索信息时,可以使用这些变量引用密钥。

对于您在此处指定的密钥,其必须获得指定为此 CREATE PROCEDURE 命令的 EXTERNAL_ACCESS_INTEGRATIONS 参数值的 外部访问集成 的允许。

此参数的值是以逗号分隔的赋值表达式列表,其中包含以下部分:

  • secret_name,即允许使用的密钥的名称。

    如果指定的 SECRETS 值的密钥未包含在由 EXTERNAL_ACCESS_INTEGRATIONS 参数指定的集成中,将收到错误消息。

  • 'secret_variable_name' 作为从密钥中检索信息时将在处理程序代码中使用的变量。

有关更多信息(包括示例),请参阅 在函数或过程中使用外部访问集成

Scala

IMPORTS = ( 'stage_path_and_file_name_to_read' [, 'stage_path_and_file_name_to_read' ...] )

要导入的文件的位置(暂存区)、路径和名称。必须将 IMPORTS 子句设置为包含存储过程所依赖的任何文件:

  • 如果要编写内联存储过程,则可以省略此子句,除非代码依赖于在存储过程或资源文件外部定义的类。

  • 如果要使用暂存处理程序编写存储过程,则还必须包括包含存储过程处理程序代码的 JAR 文件的路径。

  • IMPORTS 定义不能从传递到存储过程的实参中引用变量。

IMPORTS 子句中的每个文件都必须具有唯一的名称,即使这些文件位于不同的子目录或不同的暂存区。

TARGET_PATH = 'stage_path_and_file_name_to_write'

对于具有内联处理程序代码的存储过程,指定在编译 procedure_definition 中指定的源代码后,Snowflake 应将编译后的代码(JAR 文件)写入的位置。如果省略此子句,则每次需要代码时,Snowflake 都会重新编译源代码。

如果指定此子句:

  • 不能将其设置为现有文件。如果 TARGET_PATH 指向现有文件,Snowflake 将返回错误。

  • 如果同时指定了 IMPORTS 和 TARGET_PATH 子句,即使文件位于不同的子目录或不同的暂存区,TARGET_PATH 子句中的文件名也必须不同于 IMPORTS 子句中的每个文件名。

  • 如果不再需要使用存储过程(例如,如果弃用存储过程),则必须手动移除此 JAR 文件。

访问控制要求

用于执行此 SQL 命令的 角色 必须至少具有以下 权限

权限

对象

备注

CREATE PROCEDURE

架构

USAGE

过程

将新建过程的 USAGE 权限授予某个角色可允许拥有该角色的用户在 Snowflake 中的其他位置调用该过程。

USAGE

外部访问集成

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

READ

密钥

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

USAGE

架构

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

请注意,对架构中的对象进行操作还需要对父数据库和架构具有 USAGE 权限。

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

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

使用说明

  • 对于所有存储过程:

    • 存储过程支持 重载。如果两个过程具有不同数量的参数或不同的参数数据类型,则它们可以具有相同的名称。

    • 存储过程不是原子的;如果存储过程中的一条语句失败,则存储过程中的其他语句不一定会回滚。有关存储过程和事务的信息,请参阅 事务管理

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

    • 关于元数据:

      注意

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

    小技巧

    如果组织混合使用调用方权限和所有者权限存储过程,则可能需要对存储过程使用命名约定,以指示单个存储过程是调用方权限存储过程还是所有者权限存储过程。

  • 对于 JavaScript 存储过程:

    • JavaScript 存储过程只能返回单个值,例如字符串(例如,成功/失败指示符)或数字(例如,错误代码)。如果您需要返回更广泛的信息,则可以返回包含由分隔符(例如逗号)分隔的值的 VARCHAR,也可以返回半结构化数据类型,例如 VARIANT

  • 有关 Java 存储过程,请参阅 已知限制

  • 有关 Python 存储过程,请参阅 已知限制

  • 有关 Scala 存储过程,请参阅 已知限制

示例

这将创建一个返回硬编码值的简单存储过程。这是不真实的,但用最少的 JavaScript 代码展示了基本的 SQL 语法:

create or replace procedure sp_pi()
    returns float not null
    language javascript
    as
    $$
    return 3.1415926;
    $$
    ;
Copy

这显示了一个更真实的示例,其中包括对 JavaScript API 的调用。此过程的更广泛版本可能允许用户将数据插入到用户无权直接插入的表中。JavaScript 语句可以检查输入参数,并仅在满足某些要求的情况下执行 SQL INSERT

create or replace procedure stproc1(FLOAT_PARAM1 FLOAT)
    returns string
    language javascript
    strict
    execute as owner
    as
    $$
    var sql_command = 
     "INSERT INTO stproc_test_table1 (num_col1) VALUES (" + FLOAT_PARAM1 + ")";
    try {
        snowflake.execute (
            {sqlText: sql_command}
            );
        return "Succeeded.";   // Return a success/error indicator.
        }
    catch (err)  {
        return "Failed: " + err;   // Return a success/error indicator.
        }
    $$
    ;
Copy

有关更多示例,请参阅 使用存储过程

语言: 中文