调用存储过程

可以使用 SQL CALL 命令调用存储过程。

为了让用户调用存储过程,用户的角色必须具有对存储过程的 USAGE 权限

具有调用存储过程的权限之后,就可以使用 CALL 语句来调用存储过程。

备注

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

指定实参

如果存储过程具有实参,则可以按名称或位置指定这些实参。

例如,以下存储过程接受三个实参:

CREATE OR REPLACE PROCEDURE sp_concatenate_strings(
    first_arg VARCHAR,
    second_arg VARCHAR,
    third_arg VARCHAR)
  RETURNS VARCHAR
  LANGUAGE SQL
  AS
  $$
  BEGIN
    RETURN first_arg || second_arg || third_arg;
  END;
  $$;
Copy

调用过程时,可以按名称指定实参:

CALL sp_concatenate_strings(
  first_arg => 'one',
  second_arg => 'two',
  third_arg => 'three');
Copy
+------------------------+
| SP_CONCATENATE_STRINGS |
|------------------------|
| onetwothree            |
+------------------------+

如果按名称指定实参,则不需要按任何特定顺序指定实参:

CALL sp_concatenate_strings(
  third_arg => 'three',
  first_arg => 'one',
  second_arg => 'two');
Copy
+------------------------+
| SP_CONCATENATE_STRINGS |
|------------------------|
| onetwothree            |
+------------------------+

您还可以按位置指定实参:

CALL sp_concatenate_strings(
  'one',
  'two',
  'three');
Copy
+------------------------+
| SP_CONCATENATE_STRINGS |
|------------------------|
| onetwothree            |
+------------------------+

请注意以下事项:

  • 必须按名称或位置指定所有实参。不能按名称指定某些实参,也不能按位置指定其他实参。

    按名称指定实参时,不能在实参名称前后使用双引号。

  • 如果两个函数或两个过程的名称相同但实参类型不同,那么在实参名称不同的情况下,可以使用实参名称来指定要执行的函数或过程。请参阅:ref:label-procedure_function_name_overloading

指定可选实参

如果存储过程具有:ref:可选实参<label-procedure_function_arguments_optional>,则可以在调用中省略可选实参。每个可选实参都有一个默认值,当省略该实参时将使用该默认值。

例如,以下存储过程具有一个必填实参和两个可选实参。每个可选实参都有一个默认值。

CREATE OR REPLACE PROCEDURE build_string_proc(
    word VARCHAR,
    prefix VARCHAR DEFAULT 'pre-',
    suffix VARCHAR DEFAULT '-post'
  )
  RETURNS VARCHAR
  LANGUAGE SQL
  AS
  $$
    BEGIN
      RETURN prefix || word || suffix;
    END;
  $$
  ;
Copy

您可以在调用中省略任何可选实参。省略实参时,将使用该实参的默认值。

CALL build_string_proc('hello');
Copy
+-------------------+
| BUILD_STRING_PROC |
|-------------------|
| pre-hello-post    |
+-------------------+
CALL build_string_proc('hello', 'before-');
Copy
+-------------------+
| BUILD_STRING_PROC |
|-------------------|
| before-hello-post |
+-------------------+

如果需要省略可选实参,并在签名中指定出现在被省略实参之后的另一个可选实参,请使用命名实参,而不是位置实参。

例如,假设您要省略 prefix 实参,并指定 suffix 实参。suffix 实参显示在签名中的 prefix 之后,因此必须按名称指定实参:

CALL build_string_proc(word => 'hello', suffix => '-after');
Copy
+-------------------+
| BUILD_STRING_PROC |
|-------------------|
| pre-hello-after   |
+-------------------+

示例

若要执行存储过程,请使用 CALL 语句。例如:

call stproc1(5.14::FLOAT);
Copy

存储过程的每个实参都可以是通用表达式:

CALL stproc1(2 * 5.14::FLOAT);
Copy

实参可以是子查询:

CALL stproc1(SELECT COUNT(*) FROM stproc_test_table1);
Copy

每个 CALL 语句只能调用一个存储过程。例如,以下语句失败:

call proc1(1), proc2(2);                          -- Not allowed
Copy

此外,不能将存储过程 CALL 用作表达式的一部分。例如,以下所有语句都失败:

call proc1(1) + proc1(2);                         -- Not allowed
call proc1(1) + 1;                                -- Not allowed
call proc1(proc2(x));                             -- Not allowed
select * from (call proc1(1));                    -- Not allowed
Copy

但是,在存储过程中,存储过程可以调用另一个存储过程,也可以以递归方式调用自身。

小心

嵌套调用可能会超过允许的最大堆栈深度,因此在嵌套调用时要小心,尤其是在使用递归时。

语言: 中文