命名和重载过程和 UDFs¶
创建或调用存储过程或用户定义函数 (UDF) 时,需要了解 Snowflake 允许并强制执行的命名约定。
还可以重载存储过程和 UDFs,为给定过程或函数提供不同的签名。
备注
用户定义函数名称的长度(其名称、返回类型和所有参数名称的总长度)不得超过 10,000 字节。尝试创建其名称超过此限制的函数将导致以下错误消息:
Function name (including parameter and return type) too long.
为过程或 UDF 选择名称¶
过程和 UDFs 的名称必须符合 对象标识符 的规则。
备注
Snowflake 不允许创建与任何系统定义函数同名的函数。
调用过程或 UDF¶
创建存储过程或 UDF 时,在指定的数据库和架构中创建。过程和 UDFs 具有由其命名空间以 db.schema.procedure_or_function_name
形式定义的完全限定名称。
以下语句使用完全限定的名称来调用存储过程:
CALL mydatabase.myschema.myprocedure();
在没有完全限定名称的情况下调用时,过程和 UDFs 将 根据会话中使用的数据库和架构进行解析。如果 指定了搜索路径,该搜索路径将用于 确定要调用的函数或过程。
相比之下,Snowflake 提供的许多内置系统定义函数没有命名空间。因此,可以从任何地方调用这些函数。
重载过程和函数¶
Snowflake 支持 重载过程和函数 (link removed)。在给定架构中,可以定义具有相同名称但不同签名的多个过程或函数。签名必须因实参数量和/或实参类型而异。
例如,对于 UDFs:
CREATE OR REPLACE FUNCTION myudf (number_argument NUMBER) ...
CREATE OR REPLACE FUNCTION myudf (varchar_argument VARCHAR) ...
CREATE OR REPLACE FUNCTION myudf (number_argument NUMBER, varchar_argument VARCHAR) ...
对于存储过程:
CREATE OR REPLACE PROCEDURE myproc (number_argument NUMBER) ...
CREATE OR REPLACE PROCEDURE myproc (varchar_argument VARCHAR) ...
CREATE OR REPLACE PROCEDURE myproc (number_argument NUMBER, varchar_argument VARCHAR) ...
如果多个签名使用相同数量的实参,但具有不同类型的实参,则可以为实参使用不同的名称,以指示在调用函数或过程时要使用的签名。
CREATE OR REPLACE FUNCTION echo_input (numeric_input NUMBER)
RETURNS NUMBER
AS 'numeric_input';
CREATE OR REPLACE FUNCTION echo_input (varchar_input VARCHAR)
RETURNS VARCHAR
AS 'varchar_input';
SELECT echo_input(numeric_input => 10);
SELECT echo_input(varchar_input => 'hello world');
备注
对于调用函数或过程以外的命令(例如,执行 DESCRIBE FUNCTION、DROP PROCEDURE、GRANT <privileges> 等),必须使用实参的数据类型来标识要使用的签名。
调用重载的过程和函数¶
与调用任何其他 过程 或 函数 一样,可以通过名称或位置来指定实参。
SELECT myudf(text_input => 'hello world');
SELECT myudf('hello world');
如果省略实参名称,或者对不同类型的实参使用相同的实参名称,则 Snowflake 将使用实参数量和实参类型来确定要使用的签名。在这些情况下,自动类型转换(强制)<label-when_coercion_occurs>`会影响所选的签名。有关详细信息,请参阅 :ref:`label-procedure_function_name_overloading_caveat。
关于依赖实参数据类型来标识要调用的签名的注意事项¶
请注意,如果依靠实参的数据类型(而不是实参名称)来标识要调用的函数或过程的签名,自动类型转换和重载的组合会使得轻微的用户错误很容易导致意外结果。
考虑以下示例,这些示例创建了两个名为 add5
的 SQL UDFs :
CREATE OR REPLACE FUNCTION add5 (n NUMBER)
RETURNS NUMBER
AS 'n + 5';
CREATE OR REPLACE FUNCTION add5 (s VARCHAR)
RETURNS VARCHAR
AS
$$
s || '5'
$$;
如果调用 add5
并指定一个不带实参名称的数值实参,则调用第一个实现。如果改为指定字符串类型的实参,则调用第二个实现。
如果实参既不是数字也不是字符串,那么实现取决于 Snowflake 的隐式类型转换规则。例如,日期类型的实参被转换为字符串,因为不支持从 DATE 到 NUMBER 的转换。因此,将调用字符串实现。
例如:
SELECT add5(1);
+---------+
| ADD5(1) |
|---------|
| 6 |
+---------+
SELECT add5('1');
+-----------+
| ADD5('1') |
|-----------|
| 15 |
+-----------+
SELECT add5('hello');
+---------------+
| ADD5('HELLO') |
|---------------|
| hello5 |
+---------------+
SELECT add5(TO_DATE('2014-01-01'));
+-----------------------------+
| ADD5(TO_DATE('2014-01-01')) |
|-----------------------------|
| 2014-01-015 |
+-----------------------------+
为避免潜在的混淆,请为不同的签名分配不同的实参名称,并在调用函数时使用实参名称。
在上面的示例中,两个签名使用不同的实参名称(n
代表 NUMBER 实参,s
代表 VARCHAR 实参)。可以通过指定实参名称来指定要使用的签名:
SELECT add5(n => 1);
SELECT add5(s => '1');
搜索路径如何确定要调用的函数或过程¶
如果 指定了搜索路径,则按照搜索路径中出现的架构顺序,搜索搜索路径中出现的每个架构以查找匹配的函数。对于每个搜索到的架构,Snowflake 会尝试查找匹配函数,并在必要时使用隐式类型转换。如果在架构中找不到匹配项,则考虑下一个架构。如果 add5
函数是在不同的架构中定义的,请再次考虑它们:
USE SCHEMA s1;
CREATE OR REPLACE FUNCTION add5 ( n number)
RETURNS number
AS 'n + 5';
USE SCHEMA s2;
CREATE OR REPLACE FUNCTION add5 ( s string)
RETURNS string
AS 's || ''5''';
选择用于数值或字符串实参的函数将取决于搜索路径:
USE SCHEMA s3;
ALTER SESSION SET SEARCH_PATH='s1,s2';
SELECT add5(5);
+---------+
| ADD5(5) |
+---------+
| 10 |
+---------+
ALTER SESSION SET SEARCH_PATH='s2,s1';
SELECT add5(5);
+---------+
| ADD5(5) |
*---------+
| 55 |
+---------+
如果搜索路径设置为首先搜索架构 s2
,则使用 s2
中的函数,即使它要求对实参应用隐式类型转换。