VastbaseG100

基于openGauss内核开发的企业级关系型数据库。

Menu

CREATE FUNCTION

功能描述

创建新的函数。在MySQL兼容模式下,支持以下语法:

  • SQL DATA Access

    • CONTAINS SQL
    • NO SQL
    • READS SQL DATA
    • MODIFIES SQL DATA
  • LANGUAGE SQL

  • SQL SECURITY

语法格式

CREATE [ OR REPLACE  ] [DEFINER = usr] FUNCTION function_name
    ( [  { argname [ argmode  ] argtype [  { DEFAULT  | :=  | =  } expression  ]}  [, ...]  ] )
    [ RETURNS rettype [ DETERMINISTIC | PIPELINED ]
        | RETURNS TABLE (  { column_name column_type  }  [, ...] )]
    LANGUAGE lang_name
    [
        {IMMUTABLE  | STABLE  | VOLATILE}
        | {SHIPPABLE | NOT SHIPPABLE}
        | [ NOT  ] LEAKPROOF
        | WINDOW
        | {CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT}
        | {[ EXTERNAL  ] SECURITY INVOKER  | [ EXTERNAL  ] SECURITY DEFINER | AUTHID DEFINER  | AUTHID CURRENT_USER}
        | SQL SECURITY { DEFAULT | INVOKER }
        | {FENCED | NOT FENCED}
        | {PACKAGE}
        | COST execution_cost
        | ROWS result_rows
        | SET configuration_parameter { {TO | =} value | FROM CURRENT }
        | [NOT] DETERMINISTIC
        | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
    ] [...]
    {
        AS 'definition'
        | AS 'obj_file', 'link_symbol'
    }

CREATE [ OR REPLACE  ] [DEFINER = usr] FUNCTION function_name
    ( [  { argname [ argmode  ] argtype [  { DEFAULT | := | =  } expression  ] }  [, ...]  ] )
    RETURN rettype [ DETERMINISTIC | PIPELINED ]
    [
        {IMMUTABLE  | STABLE  | VOLATILE }
        | {SHIPPABLE | NOT SHIPPABLE}
        | {PACKAGE}
        | [ NOT  ] LEAKPROOF
        | {CALLED ON NULL INPUT  | RETURNS NULL ON NULL INPUT  | STRICT }
        | {[ EXTERNAL  ] SECURITY INVOKER  | [ EXTERNAL  ] SECURITY DEFINER | | AUTHID DEFINER  | AUTHID CURRENT_USER}
        | SQL SECURITY { DEFAULT | INVOKER }
        | COST execution_cost
        | ROWS result_rows
        | SET configuration_parameter { {TO | =} value | FROM CURRENT }
        | LANGUAGE SQL
        | [NOT] DETERMINISTIC
        | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
     ][...]
     {
        IS | AS
     } plsql_body
/

参数说明

  • 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或者是用户定义的过程语言名称。为了保证向下兼容,该名称可以用单引号包围。若采用单引号,则引号内必须为小写。

  • 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行。

  • configuration_parameter

    • value

      把指定的数据库会话参数值设置为给定的值。如果value是DEFAULT或者RESET,则在新的会话中使用系统的缺省设置。OFF关闭设置。

      取值范围:字符串

      • DEFAULT
      • OFF
      • RESET

      指定默认值。

    • from current

      取当前会话中的值设置为configuration_parameter的值。

  • LANGUAGE SQL

    用以实现函数的语言的名称。在函数中如果使用LANGUAGE SQL用法,则在plsql_body 部分除了出现SQL语句时能正常执行以外,出现逻辑代码如变量赋值、逻辑控制、异常处理等行为时也可以正常执行。

    与[NOT] DETERMINISTIC 的顺序可以随意排列。

  • [NOT] DETERMINISTIC

    说明函数执行的结果是否为确定值。

    • DETERMINISTIC:表示结果确定。每次执行函数时,相同的输入会得到相同的输出。
    • NOT DETERMINISTIC:表示结果不确定,相同的输入可能得到不同的输出。
  • CONTAINS SQL

    表示函数中不包含读或写数据的语句。

  • NO SQL

    表示函数中不包含SQL语句。

  • READS SQL DATA

    表示函数中包含读数据的语句,但不包含写数据的语句。

  • MODIFIES SQL DATA

    表示函数中包含写数据的语句。

  • SQL SECURITY

    表示函数的权限。

    默认值为:SQL SECURITY DEFINER。

    • SECURITY INVOKER:表明该函数将带着调用它的用户的权限执行。
    • SECURITY DEFINER:声明该函数将以创建它的用户的权限执行。
  • plsql_body

    PL/SQL存储过程体。

当在函数体中进行创建用户等涉及用户密码相关操作时,系统表及csv日志中会记录密码的明文。因此不建议用户在函数体中进行涉及用户密码的相关操作。

注意事项

  • 功能描述中的特性仅在数据库兼容模式为MySQL时支持(即数据库实例初始化时指定DBCOMPATIBILITY='B')
  • 当未指定SQL DATA Access特性时,默认为CONTAINS SQL。
  • 指定多个特性时,排列位于后的特性生效。
  • 特性语法小写时可识别。
  • DEFINER与SQL SECURITY INVOKER同时定义时,SQL SECURITY INVOKER优先级更高,即在执行该函数时,使用”调用者“的用户权限判断其是否有访问该函数中的具体对象的权限。
  • DEFINER与SQL SECURITY DEFINER同时定义时,使用“定义者”的用户权限判断其是否有访问该函数中的具体对象的权限。

示例

示例1:创建含有CONTAINS SQL语法的函数。

1、创建测试表,并插入数据,查看表内容。

create table test1(id int,age int,name varchar2(16)); 

insert into test1 values(1,22,'小王'); 
insert into test1 values(2,23,'小张'); 
insert into test1 values(3,21,'小弓'); 

select * from test1 order by id;

查询结果为:

 id | age | name
----+-----+------
  1 |  22 | 小王
  2 |  23 | 小张
  3 |  21 | 小弓
(3 rows)

2、创建带有CONTAINS SQL语法的函数。

create function fun_test1(age1 int,name1 varchar2)return int 
CONTAINS SQL 
as 
declare 
a1 int; 
begin 
for i in 4..6 loop 
insert into test1 values(i,age1,name1); 
end loop; 
update test1 set age=23 where id=3; 
delete from test1 where id=2; 
select count(*) into a1 from test1; 
return a1; 
end; 
/ 

3、调用函数。

select fun_test1(25,'asdf'); 

结果显示为:

 fun_test1
-----------
         5
(1 row)

4、查看测试表结果。

select * from test1 order by id;

结果显示为:

 id | age | name
----+-----+------
  1 |  22 | 小王
  3 |  23 | 小弓
  4 |  25 | asdf
  5 |  25 | asdf
  6 |  25 | asdf
(5 rows)

示例2: 创建带NOT DETERMINISTIC语法的函数

1、创建函数。

create function fun_deter(c1 int,c2 int)return varchar2 
NOT DETERMINISTIC 
as 
a1 varchar2(36); 
begin 
if c1>c2 then 
a1:='c1 > c2'; 
else 
if c1<c2 then 
a1:='c1 < c2'; 
else 
a1:='c1 = c2'; 
end if; 
end if; 
return a1; 
end; 
/ 

2、调用函数。

select fun_deter(5,3); 
select fun_deter(2,3); 
select fun_deter(3,3); 

返回结果为:

 fun_deter
-----------
 c1 > c2
(1 row)

 fun_deter
-----------
 c1 < c2
(1 row)

 fun_deter
-----------
 c1 = c2
(1 row)

示例3: 创建带LANGUAGE SQL的函数。

1、创建测试表并插入数据,查看表内容。

create table test1(id int,age int,name varchar2(16)); 

insert into test1 values(1,22,'小王'); 
insert into test1 values(2,23,'小张'); 
insert into test1 values(3,21,'小弓'); 

select * from test1 order by id;

结果显示为:

 id | age | name
----+-----+------
  1 |  22 | 小王
  2 |  23 | 小张
  3 |  21 | 小弓
(3 rows)

2、创建带有SQL语句的函数。

create function func_test1(id1 int,age1 int,name1 varchar2) return bigint
LANGUAGE SQL
AS
a1 int;
begin
insert into test1 values(id1,age1,name1);
update test1 set age=23 where id=3;
delete from test1 where id=2;
select count(*) into a1 from test1;
return a1;
end;
/

3、调用函数。

select func_test1(6,25,'小郝'); 

结果显示为:

 func_test1
------------
          3
(1 row)

4、查看测试表结果。

select * from test1 order by id;

结果显示为:

 id | age | name
----+-----+------
  1 |  22 | 小王
  3 |  23 | 小弓
  6 |  25 | 小郝
(3 rows)

示例4:创建带有SQL SECURITY的函数。

1、创建测试表security_test。

CREATE TABLE security_test(id int DEFAULT NULL ,id1 int DEFAULT NULL);

2、创建测试用户b。

CREATE USER b password 'Bb@123456';

3、给b授予表security_test的所有权限。

grant all privileges on security_test to b;

4、创建函数,定义DEFINER为b 同时使用SQL SECURITY INVOKER。

create definer=b function fun_test1(n int,id1 int) return int
SQL SECURITY INVOKER
as
c1 int;
c2 int;
begin
for i in 1..n loop
c2:='111' || i;
insert into security_test values(i,c2);
end loop;
update security_test set id='100' where id=id1;
delete from security_test where id=1;
select count(*) into c1 from security_test;
return c1;
end;
/

5、使用用户b调用函数。

\c - b
SELECT fun_test1(5,3);

结果返回如下,表示调用成功:

 fun_test1
-----------
         4
(1 row)