CREATE PROCEDURE — 定义一个新过程
CREATE [ OR REPLACE ] PROCEDURE
name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] )
{ LANGUAGE lang_name
| TRANSFORM { FOR TYPE type_name } [, ... ]
| [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER
| SET configuration_parameter { TO value | = value | FROM CURRENT }
| AS 'definition'
| AS 'obj_file', 'link_symbol'
| sql_body
} ...
CREATE PROCEDURE 定义一个新过程。CREATE OR REPLACE PROCEDURE 将创建一个新过程,或者替换一个现有的定义。要能定义一个过程,用户必须拥有该语言上的 USAGE 特权。
如果包含模式名,则该过程会在指定的模式中创建。否则它会在当前模式中创建。新过程的名称不能与同一模式中任何具有相同输入参数类型的现有过程或函数重名。不过,不同参数类型的过程和函数可以共用一个名称(这被称为 重载)。
要替换现有过程的当前定义,请使用 CREATE OR REPLACE PROCEDURE。无法通过这种方式更改过程的名称或参数类型(如果尝试这样做,实际上会创建一个新的、不同的过程)。
当使用 CREATE OR REPLACE PROCEDURE 替换一个现有过程时,该过程的拥有者和权限不会改变。过程的所有其他属性都会被赋予命令中指定或隐含的值。你必须拥有该过程才能替换它(这包括作为拥有该过程的角色的成员)。
创建该过程的用户将成为该过程的拥有者。
要能创建一个过程,你必须拥有参数类型上的 USAGE 特权。
有关编写过程的更多信息,请参见 Section 36.4。
name要创建的过程的名称(可以用模式限定)。
argmode 参数的模式:IN、OUT、INOUT 或 VARIADIC。如果省略,默认为 IN。
argname参数的名称。
argtype过程参数的数据类型(如果有的话,可以用模式限定)。参数类型可以是基本类型、组合类型或域类型,也可以引用表列的类型。
根据实现语言的不同,可能还允许指定 “伪类型”,例如 cstring。伪类型表示实际的参数类型要么未完全指定,要么不在普通 SQL 数据类型的集合之内。
通过书写 来引用一个列的类型。使用这一特性有时有助于使过程独立于表定义的更改。 table_name.column_name%TYPE
default_expr在未指定该参数时用作默认值的表达式。该表达式必须能被强制转换成参数的参数类型。位于带有默认值的参数之后的所有输入参数也都必须有默认值。
lang_name 实现该过程所用的语言的名称。它可以是 sql、c、internal 或某个用户定义的过程语言的名称,例如 plpgsql。默认值为 sql,前提是指定了 sql_body。把名称放在单引号中的做法已被弃用,并且要求大小写完全匹配。
TRANSFORM { FOR TYPE type_name } [, ... ] }列出对该过程的调用应当应用哪些转换。转换会在 SQL 类型和语言特定的数据类型之间进行转换;参见 CREATE TRANSFORM。过程语言的实现通常内建地了解那些内建类型,因此这些类型不需要在这里列出。如果过程语言的实现不知道如何处理某个类型且没有提供转换,它将退回到转换数据类型的默认行为,但这取决于具体的实现。
[EXTERNAL] SECURITY INVOKER[EXTERNAL] SECURITY DEFINERSECURITY INVOKER 表示该过程要用调用它的用户的特权来执行。这是默认值。SECURITY DEFINER 表示该过程要用拥有它的用户的特权来执行。
关键字 EXTERNAL 是为了符合 SQL 而允许的,但它是可选的,因为与 SQL 不同,此特性适用于所有过程,而不仅仅是外部过程。
SECURITY DEFINER 过程不能执行事务控制语句(例如 COMMIT 和 ROLLBACK,取决于所用的语言)。
configuration_parametervalue SET 子句使得指定的配置参数在进入过程时被设置为指定的值,然后在过程退出时恢复为先前的值。SET FROM CURRENT 把执行 CREATE PROCEDURE 时该参数的当前值保存下来,作为进入过程时要应用的值。
如果一个 SET 子句被附加到某个过程上,那么在过程内部对同一变量执行的 SET LOCAL 命令的效果将被限制在该过程内:配置参数的先前值仍会在过程退出时被恢复。不过,普通的 SET 命令(不带 LOCAL)会覆盖 SET 子句,这与它对先前的 SET LOCAL 命令所起的作用差不多:除非当前事务被回滚,否则这种命令的效果会在过程退出之后持续存在。
如果一个 SET 子句被附加到某个过程上,那么该过程就不能执行事务控制语句(例如 COMMIT 和 ROLLBACK,取决于所用的语言)。
有关允许的参数名称和值的更多信息,请参见 SET 和 Chapter 19。
definition定义该过程的字符串常量;其含义取决于所用的语言。它可以是内部过程名、目标文件的路径、一条 SQL 命令,或者用过程语言写的文本。
编写过程定义字符串时,使用美元符引用(参见 Section 4.1.2.4)通常比使用普通的单引号语法更有帮助。如果不使用美元符引用,过程定义中的任何单引号或反斜线都必须通过双写来转义。
obj_file, link_symbol 这种形式的 AS 子句用于动态载入的 C 语言过程,此时 C 语言源代码中的过程名与 SQL 过程的名称不同。字符串 obj_file 是包含已编译 C 过程的共享库文件的名称,其解释方式与 LOAD 命令相同。字符串 link_symbol 是该过程的链接符号,也就是 C 语言源代码中该过程的名称。如果省略链接符号,则假定它与被定义的 SQL 过程的名称相同。
当重复的 CREATE PROCEDURE 调用引用同一个目标文件时,该文件在每个会话中只被载入一次。要卸载并重新载入该文件(也许在开发期间),请启动一个新会话。
sql_body LANGUAGE SQL 过程的过程体。它应当是如下形式的一个块
BEGIN ATOMICstatement;statement; ...statement; END
这类似于把过程体的文本写成一个字符串常量(见上文的 definition),但存在一些差别:这种形式只能用于 LANGUAGE SQL,而字符串常量的形式适用于所有语言。这种形式在过程定义时被解析,而字符串常量形式则在执行时被解析;因此这种形式不能支持多态参数类型以及在过程定义时无法解析的其他构造。这种形式会跟踪过程与过程体中使用的对象之间的依赖关系,因此 DROP ... CASCADE 能够正确工作,而使用字符串常量的形式则可能留下悬空的过程。最后,这种形式与 SQL 标准以及其他 SQL 实现更加兼容。
CREATE PROCEDURE insert_data(a integer, b integer) LANGUAGE SQL AS $$ INSERT INTO tbl VALUES (a); INSERT INTO tbl VALUES (b); $$;
或者
CREATE PROCEDURE insert_data(a integer, b integer) LANGUAGE SQL BEGIN ATOMIC INSERT INTO tbl VALUES (a); INSERT INTO tbl VALUES (b); END;
然后像这样调用:
CALL insert_data(1, 2);
SQL 标准中定义了 CREATE PROCEDURE 命令。PostgreSQL 的实现可以用兼容的方式使用,但有许多扩展。详情另见 CREATE FUNCTION。