CREATE [ OR REPLACE ] FUNCTION name ( [ 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 将要么创建一个新函数, 要么替换现有的定义.
创建这个函数的用户成为函数的所有者。
参数
要创建的函数名字. 如果包含模式名,那么该函数将在指定模式中创建. 否则它就会在当前模式中创建(在搜索路径前面的那个;参阅 CURRENT_SCHEMA()). 新函数的名字不能和同一模式中的任何现存函数有相同的名字和参数类型. 不过,不同参数类型的函数可以共享一个名字(这叫重载).
该函数的数据类型(如果有).输入类型可以是基本类型,也可以是 复合类型,域类型,或者和一个现有字段相同的类型. 一个字段的类型是用 tablename.columnname%TYPE 表示的;使用这个东西可以帮助函数独立于表定义的修改. 根据实现语言的不同,我们还可以在这上面声明 "伪类型", 比如 cstring。伪类型表示实际的参数类型要么是没有完整 地声明,要么是在普通的 SQL 数据类型之外。
返回数据类型.输出类型可以声明为一个基本类型,复合类型, 域类型, 或者和现有字段同类型. 根据实现语言的不同,我们还可以在这上面声明 "伪类型", 比如 cstring。 setof 修饰词表示该函数将返回一套条目, 而不是一条条目.
用以实现函数的语言的名字。 可以是 SQL,C, internal,或者是用户定义的过程语言名字。 (又见 createlang。 ) 为了保持向下兼容,该名字可以用单引号包围.
这些属性告诉系统把对该函数的多次调用替换成一次是否安全. 主要用于运行时优化。 至少应该声明一个选择.如果任何一个都没有出现,那么 isVolatile 是缺省假设.
IMMUTABLE 表示该函数在给出同样的参数值时 总是返回相同的结果;也就是说,它不做数据库查找或者是使用那些 并没有直接出现在其参数列表里面的信息.如果给出这个选项,那么任何带着 全部是常量参数对该函数的调用都将立即替换为该函数的值.
STABLE 表示在一次表扫描里,对相同参数值, 该函数将稳定返回相同的值,但是它的结果可能在不同 SQL 语句之间变化. 这个选项对那些结果倚赖数据库查找,参数变量(比如当前时区),等等 的函数是很合适的.还要注意 CURRENT_TIMESTAMP 族函数是 stable (稳定)的,因为它们的值在一次事务中不会变化.
VOLATILE 表示该函数值甚至可以在一次表扫描内改变, 因此不会做任何优化.很少数据库函数在这个概念上是易变的; 一些例子是 random(),currval(), timeofday().请注意任何有副作用的函数都必需列为易变类, 即使其结果相当有规律也应该这样,这样才能避免它被优化;一个例子就是 setval().
CALLED ON NULL INPUT (缺省)表明该函数 在自己的某些参数是空值的时候还是可以按照正常的方式调用。 剩下的事情是函数的作者必须负责检查空值以及相应地做出反应。
RETURNS NULL ON NULL INPUT 或 STRICT 表明如果它的任何参数是 NULL,此函数总是返回 NULL. 如果声明了这个参数,则如果存在 NULL 参数时不会执行该函数; 而只是自动假设一个 NULL 结果.
SECURITY INVOKER 表明该函数将带着调用它地 用户的权限执行。这是缺省。SECURITY DEFINER 声明该函数将以创建它的用户的权限执行。
关键字 EXTERNAL 的目的是和 SQL 兼容, 但是我们和 SQL 不同的是,这个特性不仅仅适用于外部的函数, 所以它是可选的。
一个定义函数的字串;含义取决于语言.它可以是一个内部函数名字, 一个指向某个目标文件的路径,一个 SQL 查询,或者一个用过程语言 写的文本.
这个形式的 AS 子句用于在函数的 C 源文件 里的函数名字和 SQL 函数的名字不同的时候动态联接 C 语言函数. 字串 obj_file 是包含可动态装载的对象的文件名,而 link_symbol 是对象的联接符号,也就是该函数在 C 源文件里的名字.
历史遗留的函数可选信息。下面的属性可以在此出现:
等效于 STRICT 或者 RETURNS NULL ON NULL INPUT
isCachable 是 IMMUTABLE 的过时的等效物;不过出于向下兼容,我们仍然接受它。
属性名是大小写无关的.
请参阅 PostgreSQL 7.3.3 程序员手册 关于通过函数扩展 PostgreSQL 的章节获取更多关于书写外部函数的信息.
我们允许你将完整的 SQL 类型语法用于 输入参数和返回值.不过,有些类型声明的细节(比如, numeric 类型的精度域)是由下层函数实现负责的, 并且会被 CREATE FUNCTION 命令悄悄地吞掉. (也就是说,不再被识别或强制).
PostgreSQL 允许函数 重载; 也就是说,同一个函数名可以用于几个不同的函数, 只要它们的参数可以区分它们。不过,这个功能在用于 internal(内部)和 C 语言 的函数时要小心。
两个 internal 函数拥有相同 C 名称时肯定会发生链接时错误。 要解决这个问题,给它们赋予不同的 C 名称(例如,使用参数类 型做为 C 名称的一部分),然后在 CREATE FUNCTION 的 AS 子句里面声明这些名字。 如果 AS 子句为空,那么 CREATE FUNCTION 假设函数的 C 名称与SQL名称一样。
类似的还有,如果用多个 C 语言函数重载 SQL 函数, 给每个 C 语言函数的实例一个独立的名称,然后使用 CREATE FUNCTION 语法里的 AS 句的不同形式来选择每个重载的 SQL 函数的正确的 C 语言实现.
如果重复调用 CREATE FUNCTION,并且都 指向同一个目标文件,那么该文件只装载一次.要卸载和恢复装载 该文件(可能是在开发过程中),你可以使用 LOAD 命令.
使用 DROP FUNCTION 删除一个用户定义函数.
要更新现存函数的定义,用 CREATE OR REPLACE FUNCTION. 请注意不可能用这种方法改变一个函数的名字或者参数类型 (如果你这么干,你只是会创建一个新的,不同的函数). 同样,CREATE OR REPLACE FUNCTION 也不会 让你改变一个现存函数的返回类型.要干这些事,你必须删除并 重新创建该函数.
如果你删除然后重新创建一个函数,新函数和旧的并非相同实体; 你会破坏现存的引用了原有函数的规则,视图,触发器等等. 使用 CREATE OR REPLACE FUNCTION 可以改变一个 函数的定义而又不会破坏引用该函数的对象.
要能定义函数,用户必须对该语言有 USAGE 权限.
缺省时,只有函数的所有者(创建者)拥有执行它的权限. 其它用户在使用该函数之前必须被赋予 EXECUTE 权限.
要创建一个简单的 SQL 函数∶
CREATE FUNCTION one() RETURNS integer AS 'SELECT 1 AS RESULT;' LANGUAGE SQL; SELECT one() AS answer; answer -------- 1
这个例子通过调用一个用户创建的名为 funcs.so (扩展名因平台而异)的共享库过程创建一个 C 函数. 该共享库文件应该位于服务器的动态搜索路径里. 该路径计算一个检测位并且如果函数参数里的检测位 正确就返回一个 TRUE .这些可以通过用一个 CHECK 约束实现的.
CREATE FUNCTION ean_checkdigit(char, char) RETURNS boolean AS 'funcs' LANGUAGE C; CREATE TABLE product ( id char(8) PRIMARY KEY, eanprefix char(8) CHECK (eanprefix ~ '[0-9]{2}-[0-9]{5}') REFERENCES brandname(ean_prefix), eancode char(6) CHECK (eancode ~ '[0-9]{6}'), CONSTRAINT ean CHECK (ean_checkdigit(eanprefix, eancode)) );
这个例子创建一个把用户定义类型 complex 转换成内部类型 point 的函数。该函数是用一个从 C 源代码编译的 动态装载的对象来实现的。(我们演示了使用声明共享目标文件 的绝对文件名的过时方法). 对于 PostgreSQL 而言, 要自动寻找类型转换函数,SQL 函数必须和返回类型同名, 因而重载是不可避免的。 该函数名通过使用 SQL定义里 AS 子句的第二种类型来重载:
CREATE FUNCTION point(complex) RETURNS point AS '/home/bernie/pgsql/lib/complex.so', 'complex_to_point' LANGUAGE C WITH (isStrict);
该函数的 C 声明可以是∶
Point * complex_to_point (Complex *z) { Point *p; p = (Point *) palloc(sizeof(Point)); p->x = z->x; p->y = z->y; return p; }
注意该函数被标记为 "strict";这样就允许我们在函数体中忽略对 NULL 输入的检查.