CREATE FUNCTION
功能描述
创建一个函数。
注意事项
- 如果创建函数时参数或返回值带有精度,不进行精度检测。
- 创建函数时,函数定义中对表对象的操作建议都显式指定模式,否则可能会导致函数执行异常。
- 在创建函数时,函数内部通过SET语句设置current_schema和search_path无效。执行完函数search_path和current_schema与执行函数前的search_path和current_schema保持一致。
- 如果函数参数中带有出参,SELECT调用函数必须缺省出参,CALL调用函数必须指定出参,对于调用重载的带有PACKAGE属性的函数,CALL调用函数可以缺省出参,具体信息参见CALL的示例。
- 兼容Postgresql风格的函数或者带有PACKAGE属性的函数支持重载。在指定REPLACE的时候,如果参数个数、类型、返回值有变化,不会替换原有函数,而是会建立新的函数。
- 不能创建仅形参名字不同(函数名和参数列表类型都一样)的重载函数。
- 重载的函数在调用时变量需要明确具体的类型。
- 不能创建与存储过程拥有相同名称和参数列表的函数。
- 不支持形式参数仅在自定义ref cursor类型和sys_refcursor类型不同的重载。
- 在函数内部使用未声明的变量,函数被调用时会报错。
- SELECT调用可以指定不同参数来进行同名函数调用。由于语法不支持调用不带有PACKAGE属性的同名函数。
- 在创建function时,不能在avg函数外面嵌套其他agg函数,或者其他系统函数。
- 新创建的函数默认会给PUBLIC授予执行权限(详见GRANT)。用户可以选择收回PUBLIC默认执行权限,然后根据需要将执行权限授予其他用户,为了避免出现新函数能被所有人访问的时间窗口,应在一个事务中创建函数并且设置函数执行权限。
- 在函数内部调用其它无参数的函数时,可以省略括号,直接使用函数名进行调用。
- 在函数内部调用其他有出参的函数,如果在赋值表达式中调用时,被调函数的出参可以省略,给出了也会被忽略。
- 兼容Oracle风格的函数支持参数注释的查看与导出、导入。
- 兼容Oracle风格的函数支持介于IS/AS与plsql_body之间的注释的查看与导出、导入。
- 被授予CREATE ANY FUNCTION权限的用户,可以在用户模式下创建/替换函数。
- 函数默认为SECURITY INVOKER权限,如果想将默认行为改为SECURITY DEFINER权限,需要设置guc参数behavior_compat_options=’plsql_security_definer’。
- 对于plpgsql函数,打开参数behavior_compat_options=’proc_outparam_override’后,out/inout的行为会改变,函数中如果return和out/inout,可以同时返回,参数打开前只会返回return,见示例。
- 对于plpgsql函数,打开参数behavior_compat_options=’proc_outparam_override’后,有以下限制:
- 如果同一schema和package中已存在带有out/inout参数函数,不能再次创建带有out/inout参数的同名函数。
- 无论使用select还是call调用存储过程,都必须加上out参数。
- 部分场景不支持函数参与表达式(与参数打开前相比),如存储过程中左赋值,call function等,见示例。
- 不支持调用无return的函数,perform function调用。
- 存储过程中调用函数,不支持out/inout参数传入常量,见示例。
- 不可与同一模式下已存在的synonym产生命名冲突。
- 当language为internal时,自定义函数的参数类型和返回值类型(void除外)需要与引用的系统函数保持一致,参数个数超出系统函数的部分不做对比校验。当未指定strict时,此选项与系统函数保持一致。
语法格式
- 兼容PostgreSQL风格的创建自定义函数语法。
1. CREATE [ OR REPLACE ] FUNCTION function_name
2. ( [ { argname [ argmode ] argtype [ { DEFAULT | := | = } expression ]
3. } [, ...] ] )
4. [ RETURNS rettype [ DETERMINISTIC ]
5. | RETURNS TABLE ( { column_name column_type } [, ...] )]
6. LANGUAGE lang_name
7. [
8. {IMMUTABLE | STABLE | VOLATILE}
9. | {SHIPPABLE | NOT SHIPPABLE}
10. | [ NOT ] LEAKPROOF
11. | WINDOW
12. | {CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT}
13. | {[ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER | AU
14. THID DEFINER | AUTHID CURRENT_USER}
15. | {FENCED | NOT FENCED}
16. | {PACKAGE}
17. | COST execution_cost
18. | ROWS result_rows
19. | SET configuration_parameter { {TO | =} value | FROM CURRENT }
20. | COMMENT 'text'
21. ] [...]
22. {
23. AS 'definition'
24. | AS 'obj_file', 'link_symbol'
25. }
- O风格的创建自定义函数的语法。
1. CREATE [ OR REPLACE ] FUNCTION function_name
2. ( [ { argname [ argmode ] argtype [ { DEFAULT | := | = } expression ] }
3. [, ...] ] )
4. RETURN rettype [ DETERMINISTIC ]
5. [
6. {IMMUTABLE | STABLE | VOLATILE }
7. | {SHIPPABLE | NOT SHIPPABLE}
8. | {PACKAGE}
9. | [ NOT ] LEAKPROOF
10. | {CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT }
11. | {[ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER | |
12. AUTHID DEFINER | AUTHID CURRENT_USER}
13. | COST execution_cost
14. | ROWS result_rows
15. | SET configuration_parameter { {TO | =} value | FROM CURRENT }
16. | COMMENT 'text'
17. ][...]
18. {
19. IS | AS
20. } plsql_body
21. /
参数说明
- function_name
要创建的函数名称(可以用模式修饰)。
取值范围:字符串,要符合标识符的命名规范。且最多为63个字符。若超过63个字符,数据库会截断并保留前63个字符当做函数名称。 - argname
函数参数的名称。
取值范围:字符串,要符合标识符的命名规范。且最多为63个字符。若超过63个字符,数据库会截断并保留前63个字符当做函数参数名称。 - argmode
函数参数的模式。
取值范围:IN,OUT,INOUT或VARIADIC。缺省值是IN。并且OUT和INOUT模式的参数不能用在RETURNS TABLE的函数定义中。
说明:
VARIADIC用于声明数组类型的参数。 - argtype
函数参数的类型。可以使用%TYPE或%ROWTYPE间接引用变量或表的类型,详细可参考存储过程章节定义变量。 - expression
参数的默认表达式。 - rettype
函数返回值的数据类型。
如果存在OUT或INOUT参数,可以省略RETURNS子句。如果存在,该子句必须和输出参数所表示的结果类型一致:如果有多个输出参数,则为RECORD,否则与单个输出参数的类型相同。
SETOF修饰词表示该函数将返回一个集合,而不是单独一项。
与argtype相同,同样可以使用%TYPE或%ROWTYPE间接引用类型。 - column_name
字段名称。 - column_type
字段类型。 - definition
一个定义函数的字符串常量,含义取决于语言。它可以是一个内部函数名称、一个指向某个目标文件的路径、一个SQL查询、一个过程语言文本。 - DETERMINISTIC
SQL语法兼容接口,未实现功能,不推荐使用。 - LANGUAGE lang_name
用以实现函数的语言的名称。可以是SQL,internal,或者是用户定义的过程语言名称。为了保证向下兼容,该名称可以用单引号(包围)。若采用单引号,则引号内必须为小写。
说明:
internel函数在定义时,如果AS指定为内部系统函数,则新创建函数的参数类型,参数个数,与返回值类型需要与内部系统函数保持一致,且需要有执行此内部系统函数的权限。 - WINDOW
表示该函数是窗口函数。替换函数定义时不能改变WINDOW属性。
须知:
自定义窗口函数只支持LANGUAGE是internal,并且引用的内部函数必须是窗口函数。 - IMMUTABLE
表示该函数在给出同样的参数值时总是返回同样的结果。 - STABLE
表示该函数不能修改数据库,对相同参数值,在同一次表扫描里,该函数的返回值不变,但是返回值可能在不同SQL语句之间变化。 - VOLATILE
表示该函数值可以在一次表扫描内改变,因此不会做任何优化。 - SHIPPABLE|NOT SHIPPABLE
表示该函数是否可以下推执行。预留接口,不推荐使用。 - FENCED|NOT FENCED
声明用户定义的C函数是在保护模式还是非保护模式下执行。预留接口,不推荐使用。 - PACKAGE
表示该函数是否支持重载。PostgreSQL风格的函数本身就支持重载,此参数主要是针对其它风格的函数。
- 不允许package函数和非package函数重载或者替换。
- package函数不支持VARIADIC类型的参数。
- 不允许修改函数的package属性。
- LEAKPROOF
指出该函数的参数只包括返回值。LEAKPROOF只能由系统管理员设置。 - CALLED ON NULL INPUT
表明该函数的某些参数是NULL的时候可以按照正常的方式调用。该参数可以省略。 - RETURNS NULL ON NULL INPUT
STRICT
STRICT用于指定如果函数的某个参数是NULL,此函数总是返回NULL。如果声明了这个参数,当有NULL值参数时该函数不会被执行;而只是自动返回一个NULL结果。
RETURNS NULL ON NULL INPUT和STRICT的功能相同。 - EXTERNAL
目的是和SQL兼容,是可选的,这个特性适合于所有函数,而不仅是外部函数。 - SECURITY INVOKER
AUTHID CURRENT_USER
表明该函数将带着调用它的用户的权限执行。该参数可以省略。
SECURITY INVOKER和AUTHID CURRENT_USER的功能相同。 - SECURITY DEFINER
AUTHID DEFINER
声明该函数将以创建它的用户的权限执行。
AUTHID DEFINER和SECURITY DEFINER的功能相同。 - COST execution_cost
用来估计函数的执行成本。
execution_cost以cpu_operator_cost为单位。
取值范围:正数 - ROWS result_rows
估计函数返回的行数。用于函数返回的是一个集合。
取值范围:正数,默认值是1000行。 - COMMENT ‘text’
函数注释。 - configuration_parameter
-
value
把指定的数据库会话参数值设置为给定的值。如果value是DEFAULT或者RESET,则在新的会话中使用系统的缺省设置。OFF关闭设置。
取值范围:字符串
- DEFAULT
- OFF
- RESET
指定默认值。 - from current
取当前会话中的值设置为configuration_parameter的值。 - plsql_body
PL/SQL存储过程体。
须知:
当在函数体中创建用户时,日志中会记录密码的明文。因此不建议用户在函数体中创建用户。
示例
1. --定义函数为SQL查询。
2. openGauss=# CREATE FUNCTION func_add_sql(integer, integer) RETURNS integer
3. AS 'select $1 + $2;'
4. LANGUAGE SQL
5. IMMUTABLE
6. RETURNS NULL ON NULL INPUT;
8. --利用参数名用 PL/pgSQL 自增一个整数。
9. openGauss=# CREATE OR REPLACE FUNCTION func_increment_plsql(i integer) RETURNS integer AS $$
10. BEGIN
11. RETURN i + 1;
12. END;
13. $$ LANGUAGE plpgsql;
15. --返回RECORD类型
16. openGauss=# CREATE OR REPLACE FUNCTION func_increment_sql(i int, out result_1 bigint, out result_2 bigint)
17. returns SETOF RECORD
18. as $$
19. begin
20. result_1 = i + 1;
21. result_2 = i * 10;
22. return next;
23. end;
24. $$language plpgsql;
26. --返回一个包含多个输出参数的记录。
27. openGauss=# CREATE FUNCTION func_dup_sql(in int, out f1 int, out f2 text)
28. AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$
29. LANGUAGE SQL;
31. openGauss=# SELECT * FROM func_dup_sql(42);
33. --计算两个整数的和,并返回结果。如果输入为null,则返回null。
34. openGauss=# CREATE FUNCTION func_add_sql2(num1 integer, num2 integer) RETURN integer
35. AS
36. BEGIN PAC
37. RETURN num1 + num2;
38. END;
39. /
40. --修改函数func_add_sql2的执行规则为IMMUTABLE,即参数不变时返回相同结果。
41. openGauss=# ALTER FUNCTION func_add_sql2(INTEGER, INTEGER) IMMUTABLE;
43. --将函数func_add_sql2的名称修改为add_two_number。
44. openGauss=# ALTER FUNCTION func_add_sql2(INTEGER, INTEGER) RENAME TO add_two_number;
46. --将函数add_two_number的属者改为omm。
47. openGauss=# ALTER FUNCTION omm(INTEGER, INTEGER) OWNER TO omm;
49. --删除函数。
50. openGauss=# DROP FUNCTION add_two_number;
51. openGauss=# DROP FUNCTION func_increment_sql;
52. openGauss=# DROP FUNCTION func_dup_sql;
53. openGauss=# DROP FUNCTION func_increment_plsql;
54. openGauss=# DROP FUNCTION func_add_sql;
56. --设置参数
57. openGauss=# set behavior_compat_options='proc_outparam_override';
58. --创建函数
59. openGauss=# CREATE or replace FUNCTION func1(in a integer, out b integer)
60. RETURNS int
61. AS $$
62. DECLARE
63. c int;
64. BEGIN
65. c := 1;
66. b := a + c;
67. return c;
68. END; $$
69. LANGUAGE 'plpgsql' NOT FENCED;
70. --同时返回return和出参
71. openGauss=# declare
72. result integer;
73. a integer := 2;
74. b integer := NULL;
75. begin
76. result := func1(a => a, b => b);
77. raise info 'b is: %', b;
78. raise info 'result is: %', result;
79. end;
80. /
81. INFO: b is: 3
82. INFO: result is: 1
83. ANONYMOUS BLOCK EXECUTE
84. --不支持左赋值表达式
85. openGauss=# declare
86. result integer;
87. a integer := 2;
88. b integer := NULL;
89. begin
90. result := func1(a => a, b => b) + 1;
91. raise info 'b is: %', b;
92. raise info 'result is: %', result;
93. end;
94. /
95. ERROR: when invoking function func1, maybe input something superfluous.
96. CONTEXT: compilation of PL/pgSQL function "inline_code_block" near line 3
97. --存储过程中不支持out/inout传入常量
98. openGauss=# declare
99. result integer;
100. a integer := 2;
101. b integer := NULL;
102. begin
103. result := func1(a => a, b => 10);
104. raise info 'b is: %', b;
105. raise info 'result is: %', result;
106. end;
107. /
108. ERROR: when invoking function func1, no destination for argments "b"
109. CONTEXT: compilation of PL/pgSQL function "inline_code_block" near line 3
说明: