pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
CREATE FUNCTION — 定义一个新函数
CREATE [ OR REPLACE ] FUNCTION
name ( [ [ argmode ] [ argname ] argtype [, ...] ] )
[ RETURNS rettype ]
{ LANGUAGE langname
| IMMUTABLE | STABLE | VOLATILE
| CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT
| [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER
| AS 'definition'
| AS 'obj_file', 'link_symbol'
} ...
[ WITH ( attribute [, ...] ) ]
CREATE FUNCTION定义一个新函数。CREATE OR REPLACE FUNCTION将创建一个新函数,或者替换现有定义。
如果包含模式名,则函数将在指定的模式中创建。否则将在当前模式中创建。新函数的名称不能与同一模式中具有相同输入参数类型的任何现有函数匹配。然而,不同参数类型的函数可以共享一个名称(这称为 重载)。
要替换一个现有函数的当前定义,可以使用CREATE OR REPLACE FUNCTION。但不能用这种方式更改函数的名称或者参数类型(如果尝试这样做,实际上就会创建一个新的不同函数)。此外,CREATE OR REPLACE FUNCTION也不允许更改现有函数的返回类型。要做到这一点,必须删除该函数并重新创建。(使用OUT参数时,这意味着除非删除该函数,否则不能更改任何OUT参数的名称或类型。)
如果删除函数后再重新创建,新函数就不再是旧函数的同一实体;你将必须删除引用旧函数的现有规则、视图、触发器等。使用CREATE OR REPLACE FUNCTION可以在不破坏引用该函数的对象的情况下更改函数定义。
创建该函数的用户将成为该函数的拥有者。
name要创建的函数名称(可以被模式限定)。
argmode参数的模式:IN、OUT或INOUT。如果省略,默认为IN。
argname参数的名称。某些语言(包括 SQL 和 PL/pgSQL)允许在函数体中使用该名称。对于其他语言,就函数本身而言,输入参数的名称只是额外文档。但输出参数的名称很重要,因为它定义了结果行类型中的列名。(如果省略输出参数的名称,系统将选择一个默认列名。)
argtype该函数参数(如果有)的数据类型(可以是模式限定的)。参数类型可以是基础类型、复合类型或者域类型,也可以引用一个表列的类型。
根据实现语言的不同,也可能允许指定诸如cstring这样的“伪类型”。伪类型表示实际参数类型要么没有被完整指定,要么不属于普通 SQL 数据类型集合。
写成即可引用一个列的类型。使用这种特性有时有助于让函数独立于表定义的变化。tablename.columnname%TYPE
rettype该函数的返回数据类型(可以是模式限定的)。返回类型可以是基础类型、复合类型或者域类型,也可以引用一个表列的类型。根据实现语言的不同,也可能允许指定诸如cstring这样的“伪类型”。如果函数不应该返回值,请把返回类型指定为void。
当存在OUT或INOUT参数时,可以省略RETURNS子句。如果写出该子句,它必须与输出参数所隐含的结果类型一致:如果有多个输出参数,则为RECORD;如果只有一个输出参数,则为该输出参数的类型。
SETOF修饰符表示该函数将返回一组项,而不是单个项。
写成即可引用一个列的类型。tablename.columnname%TYPE
langname实现该函数所用语言的名称。它可以是SQL、C、internal,也可以是用户定义的过程语言的名称。为了向后兼容,名称可以用单引号括起。
IMMUTABLESTABLEVOLATILE这些属性会告诉查询优化器该函数的行为。最多只能指定其中一个。如果这些属性都没有出现,则默认假定为VOLATILE。
IMMUTABLE表示该函数不能修改数据库,并且在给定相同参数值时总会返回相同结果;也就是说,它不会执行数据库查找,也不会以其他方式使用未直接出现在其参数列表中的信息。如果给出此选项,任何使用全常量参数对该函数的调用都可以立即替换为该函数值。
STABLE表示该函数不能修改数据库,并且在一次表扫描内,对于相同参数值会一致地返回相同结果,但其结果可能在不同 SQL 语句之间发生变化。这适用于结果依赖于数据库查找、参数变量(例如当前时区)等的函数。另请注意,current_timestamp函数族也属于稳定函数,因为它们的值在一个事务内不会变化。
VOLATILE表示该函数的值即使在一次表扫描内也可能发生变化,因此无法进行任何优化。从这个意义上说,真正不稳定的数据库函数相对较少;一些例子是random()、currval()、timeofday()。但请注意,任何有副作用的函数都必须归类为不稳定,即使其结果相当可预测,也必须如此,以防其调用被优化掉;例如setval()。
更多细节见第 33.6 节。
CALLED ON NULL INPUTRETURNS NULL ON NULL INPUTSTRICTCALLED ON NULL INPUT(默认)表示当某些参数为空值时,仍会正常调用该函数。如果有需要,则由函数作者负责检查空值并作出适当响应。
RETURNS NULL ON NULL INPUT或STRICT表示只要任一参数为空值,该函数总是返回空值。如果指定了这个选项,那么在参数中出现空值时不会执行该函数,而是自动假定结果为空值。
[EXTERNAL] SECURITY INVOKER[EXTERNAL] SECURITY DEFINERSECURITY INVOKER表示该函数将以调用它的用户的权限执行。这是默认设置。SECURITY DEFINER指定该函数将以创建它的用户的权限执行。
为了符合 SQL,允许使用关键字EXTERNAL。但它是可选的,因为与 SQL 不同,这个特性适用于所有函数,而不仅仅是外部函数。
definition一个定义该函数的字符串常量,其含义取决于所用语言。它可以是一个内部函数名称、一个对象文件的路径、一个 SQL 命令,或者用一种过程语言编写的文本。
obj_file, link_symbol当 C 语言源代码中的函数名称与 SQL 函数名称不同时,这种形式的 AS 子句用于可动态加载的 C 语言函数。字符串 obj_file 是包含该动态可加载对象的文件名,而 link_symbol 是函数的链接符号,即 C 语言源代码中函数的名称。如果省略链接符号,则假定它与正在定义的 SQL 函数名称相同。
attribute用于指定函数可选信息的历史方式。以下属性可以出现在此处:
isStrict等同于STRICT或RETURNS NULL ON NULL INPUT。
isCachableisCachable是IMMUTABLE的已废弃等价写法;出于向后兼容的原因,目前仍接受它。
属性名称不区分大小写。
有关编写函数的详细信息,请参阅第 33.3 节。
允许使用完整的SQL类型语法来声明输入参数和返回值。不过,类型规范的某些细节(例如numeric类型的精度字段)是底层函数实现的责任,CREATE FUNCTION命令会静默地忽略它们(即不识别也不强制)。
PostgreSQL 允许函数重载;也就是说,只要输入参数类型不同,同一个名称就可以用于多个不同的函数。但是,所有函数的 C 名称都必须不同,因此必须为重载的 C 函数指定不同的 C 名称(例如,把参数类型用作 C 名称的一部分)。
如果两个函数具有相同的名称和输入参数类型,它们被认为相同(不考虑任何OUT参数)。因此这些声明会冲突:
CREATE FUNCTION foo(int) ... CREATE FUNCTION foo(int, out text) ...
当重复的CREATE FUNCTION调用引用同一个对象文件时,该文件在每个会话中只装载一次。要卸载并重新装载该文件(例如在开发期间),请启动一个新会话。
使用DROP FUNCTION可以移除用户定义的函数。
使用美元引用(见第 4.1.2.2 节)来书写函数定义字符串通常会更有帮助,而不是使用普通的单引号语法。如果没有美元引用,函数定义中的任何单引号或者反斜线都必须用双写来转义。
要定义函数,用户必须具有该语言上的USAGE权限。
当CREATE OR REPLACE FUNCTION被用来替换一个现有函数时,该函数的拥有权和权限不会改变。所有其他的函数属性会按照该命令中指定的或者隐含的值赋值。必须拥有(包括成为拥有角色的成员)该函数才能替换它。
下面给出一些简单示例,帮助你开始使用。有关更多信息和示例,请参见第 33.3 节。
CREATE FUNCTION add(integer, integer) RETURNS integer
AS 'select $1 + $2;'
LANGUAGE SQL
IMMUTABLE
RETURNS NULL ON NULL INPUT;
在PL/pgSQL中,使用参数名把一个整数加 1:
CREATE OR REPLACE FUNCTION increment(i integer) RETURNS integer AS $$
BEGIN
RETURN i + 1;
END;
$$ LANGUAGE plpgsql;
返回一个包含多个输出参数的记录:
CREATE FUNCTION dup(in int, out f1 int, out f2 text)
AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$
LANGUAGE SQL;
SELECT * FROM dup(42);
你也可以用一个显式命名的复合类型,更详细地表达同样的意思:
CREATE TYPE dup_result AS (f1 int, f2 text);
CREATE FUNCTION dup(int) RETURNS dup_result
AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$
LANGUAGE SQL;
SELECT * FROM dup(42);
SECURITY DEFINER函数因为 SECURITY DEFINER 函数要以创建它的用户的权限执行,所以必须小心确保该函数不会被滥用。出于安全考虑,应将 search_path 设置为排除任何可被不受信任用户写入的模式。这可以防止恶意用户创建对象来遮蔽该函数使用的对象。在这方面尤其重要的是临时表模式;默认情况下它最先被搜索,而且通常任何人都可写。一个安全的安排是强制把临时模式放到搜索顺序的最后。要做到这一点,应把 pg_temp 写成 search_path 中的最后一项。下面这个函数展示了安全用法:
CREATE FUNCTION check_password(uname TEXT, pass TEXT)
RETURNS BOOLEAN AS $$
DECLARE passed BOOLEAN;
old_path TEXT;
BEGIN
-- Save old search_path; notice we must qualify current_setting
-- to ensure we invoke the right function
old_path := pg_catalog.current_setting('search_path');
-- Set a secure search_path: trusted schemas, then 'pg_temp'.
-- We set is_local = true so that the old value will be restored
-- in event of an error before we reach the function end.
PERFORM pg_catalog.set_config('search_path', 'admin, pg_temp', true);
-- Do whatever secure work we came for.
SELECT (pwd = $2) INTO passed
FROM pwds
WHERE username = $1;
-- Restore caller's search_path
PERFORM pg_catalog.set_config('search_path', old_path, true);
RETURN passed;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
CREATE FUNCTION命令在 SQL:1999 及更高版本中定义。PostgreSQL版本与其相似,但并不完全兼容。这些属性和可用的不同语言都不具备可移植性。
为与某些其他数据库系统兼容,argmode可以写在argname之前或之后,但只有前一种写法符合标准。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。