openGauss SQL表值函数应用

举报
redtea 发表于 2024/08/08 11:02:13 2024/08/08
【摘要】 openGauss支持表值函数(Table-Valued Function, TVF),这类函数可以返回一个表结构的结果集set of tableName。表值函数在 SQL 查询中非常有用,尤其是在需要从函数中获取多行数据时。

一、用户自定义函数与表值函数

1.用户自定义函数

函数一般用于计算和返回一个值,可以将经常需要进行的计算写成函数。

函数的调用是表达式的一部分。

函数在创建编译后放在内存中供用户使用,调用时函数要用表达式。

函数必须返回特定数据,可以返回一个或多个值。在一个函数中必须包含一个或多个RETURN语句。

创建自定义函数时,最后的“/”符号用于标示自定义函数定义语句的结束,不能省略,且必须单独成行。

用户自定义函数可以直接被存储过程调用,也可以像普通函数一样在SQL语句中使用。

2.自定义函数语法格式

CREATE OR REPLACE FUNCTION function_name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_value ] [, ...] ] )

RETURNS return_type

AS $$

  -- 函数体

  -- 这里是 SQL 语句和/ PL/pgSQL 代码

$$ LANGUAGE language_name [ IMMUTABLE | STABLE | VOLATILE ] [ CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT ]

/

参数说明:

function_name 是用户创建的函数的名称。

argmode 是参数模式,可以是 INOUTINOUT VARIADIC

argname 是参数的名称。

argtype 是参数的数据类型。

default_value 是参数的默认值。

return_type 是函数返回的数据类型。

$$ 内是函数的实现代码,可以是 SQL 语句、PL/pgSQL 代码等。

LANGUAGE 指定了函数的实现语言,常见的有 plpgsqlsql 等。

IMMUTABLE、STABLEVOLATILE 定义了函数的稳定性。

IMMUTABLE 表示函数的结果不依赖于外部参数,对于相同的输入总是返回相同的结果。

STABLE 表示函数的结果在同一个数据库会话中对于相同的输入是不变的,但在不同的会话中可能会改变。

VOLATILE 表示函数的结果可能会在每次调用时都不同。

CALLED ON NULL INPUT 表示函数即使在输入参数为 NULL 时也会被调用。

RETURNS NULL ON NULL INPUT 表示如果输入参数为 NULL,函数将返回 NULL

STRICT 表示如果输入参数为 NULL,函数将不会执行,而是直接返回 NULL。参数说明:

argname参数的名称。取值范围:字符串,要符合标识符的命名规范。

argtype 参数的数据类型。可以使用%TYPE%ROWTYPE间接引用变量或表的类型。取值范围:可用的数据类型。

3.函数调用

openGauss SQL 中调用已定义的函数与在其他 SQL 数据库中调用函数非常类似。函数调用的基本语法格式如下:

SELECT function_name([argument1, argument2, ...]);

这里的 function_name 是用户自定义的函数名称,而 argument1, argument2, ... 是传递给函数的实际参数列表。

如果函数定义为返回多列数据,可以这样调用:

SELECT  *  FROM function_name([argument1, argument2, ...]);

函数也可以在 SQL 语句的其他部分被调用,例如在 WHERE 子句中、或者在 ORDER BY 子句中等。

调用函数时需确保函数的参数与定义时的参数类型和数量相匹配,否则会抛出错误。

4.删除自定义函数

语法格式:

DROP FUNCTION [ IF EXISTS ] function_name

[ ( [ {[ argname ] [ argmode ] argtype} [, ...] ] ) [ CASCADE | RESTRICT ] ];

4.表值函数

openGauss支持表值函数(Table-Valued Function, TVF),这类函数可以返回一个表结构的结果集set of tableName。表值函数在 SQL 查询中非常有用,尤其是在需要从函数中获取多行数据时。

二、表值函数应用

1.表值函数应用1:定义返回简单的表数据集的表值函数。

--创建根据课程编号返回课程信息的函数(O风格)

CREATE OR REPLACE FUNCTION f_getCourse(in cid course.courseId%type)

 RETURN SETOF course

AS

--$$

DECLARE

BEGIN

    RETURN QUERY

    SELECT *

    FROM course

    WHERE courseId=cid; 

END;

--$$ LANGUAGE SQL;

/

--创建根据课程编号返回课程信息的函数(兼容PostgreSQL风格)

CREATE OR REPLACE FUNCTION f_getCourse(in cid course.courseId%type)

 RETURNS SETOF course

AS

$$

DECLARE

BEGIN

    RETURN QUERY

    SELECT *

    FROM course

    WHERE courseId=cid; 

END;

$$ LANGUAGE PLPGSQL;

/

--调用函数f_getCourse(),获得课程编号为“B083804”的课程信息

SELECT * FROM student.f_getCourse('B083804');

2.表值函数应用2:定义表值函数获取某学期每个教师的排课信息。

已知排课记录表courseScheduleRecord-排课记录序列seq_courserscheduleRecordsn

--排课记录序列seq_courserscheduleRecordsn

 CREATE  SEQUENCE seq_courserscheduleRecordsn

 START  WITH  1

 INCREMENT  BY  1

 NO MINVALUE 

 CACHE 1;

--排课记录表coursescheduleRecord

CREATE TABLE coursescheduleRecord (

    courseScheduleRecordSn bigint not null default(nextval('seq_courserscheduleRecordsn')),

    coursescheduleid character varying(40) NOT NULL,

    studentNumber integer NOT NULL,

    courseid character(7) NOT NULL,

    termid character(20) NOT NULL,

    teacherids character varying(120) NOT NULL,

    CONSTRAINT pk_coursescheduleRecord PRIMARY KEY (coursescheduleRecordSn),

    CONSTRAINT fk2_courserscheduleRecord FOREIGN KEY (termid) REFERENCES term(termid),

    CONSTRAINT fk1_courserscheduleRecord FOREIGN KEY (courseid) REFERENCES course(courseid)

);

--向courserschedulerecord表中添加记录

INSERT INTO coursescheduleRecord (

coursescheduleid,

studentNumber,

courseid,

termid,

teacherids)

VALUES( '(2023-2024-2-B083804-01',37,'B083804','2023-2024-2','00542;01232');

INSERT INTO coursescheduleRecord (

coursescheduleid,

studentNumber,

courseid,

termid,

teacherids)

VALUES( '(2023-2024-2-B083852-01',47,'B083852','2023-2024-2','00542');

 

--查询coursescheduleRecord

SELECT * FROM coursescheduleRecord;

2.创建表值函数tf_courseScheduleByTerm获取某学期每个教师的排课信息

1)创建表t_courseSchedule

CREATE TABLE t_courseSchedule(

   courseScheduleRecordSn bigint,

   courseScheduleId varchar(40),

   termId varchar(20),

   courseId varCHAR(10),

   studentNumber INTEGER,

   teacherId CHAR(5)

);

2)创建表值函数tf_courseScheduleByTerm

CREATE OR REPLACE FUNCTION

tf_courseScheduleByTerm(IN termId_1 courseScheduleRecord.termid%type)

RETURNS SETOF t_courseSchedule

AS

$$

DECLARE

    i INTEGER; --循环变量,每一条排课记录中教师标号对应的序号

    tid CHAR(5); --临时教师编号

    teacherIds VARCHAR(120); --每一条教师编号序列

    c INTEGER; --某学期的排课记录数

    snMin INTEGER;--courseScheduleRecordSn的最小值

    snMax INTEGER;--courseScheduleRecordSn的最大值

    sn INTEGER; --循环变量,每一条排课记录序号,取值范围是[snMIn,snMax]

BEGIN 

    --清除本termId_1学期的教师排课记录

    DELETE FROM t_courseSchedule WHERE termId=termId_1;

    --得到c

    SELECT COUNT(courseScheduleRecordSn) INTO c

    FROM courseScheduleRecord

    WHERE termId=termId_1;

    --得到snMax

    SELECT MAX(courseScheduleRecordSn) INTO snMax FROM courseScheduleRecord 

    WHERE termId=termId_1;

    --得到snMin

    SELECT MIN(courseScheduleRecordSn) INTO snMIN FROM courseScheduleRecord 

    WHERE termId=termId_1;

    --给sn赋初值

    sn:=snMin;

   

    WHILE sn<=snMAX LOOP

        teacherIds:=(SELECT teacherIds

        FROM courseScheduleRecord

        WHERE courseScheduleRecordSn=sn);

          IF length(teacherIds)=5 THEN

                INSERT INTO t_courseSchedule(courseScheduleRecordSn,courseScheduleId,termId,courseId,studentNumber,teacherId)

              SELECT courseScheduleRecordSn,courseScheduleId,termId,courseId,studentNumber,teacherIds

                FROM courseScheduleRecord

                WHERE courseScheduleRecordSn=sn

                  AND termId=termId_1;

          ELSE

                i:=0;

              WHILE i < (length(teacherIds)+1)/6 LOOP

                  tid := SUBSTRING(teacherIds,i*6+1,5);

                  INSERT INTO t_courseSchedule(courseScheduleRecordSn,courseScheduleId,termId,courseId,studentNumber,teacherId)

                  SELECT courseScheduleRecordSn,courseScheduleId,termId,courseId,studentNumber,tid

                  FROM courseScheduleRecord

                    WHERE courseScheduleRecordSn=sn

                          AND termId=termId_1;           

                    i := i+1;

              END LOOP;

          END IF;

            sn := sn+1;

    END LOOP;

   

    RETURN QUERY

    SELECT courseScheduleRecordSn,courseScheduleId,termId,courseId,studentNumber,teacherId

    FROM t_courseSchedule;

END;

$$ LANGUAGE PLPGSQL;

/

3)调用表值函数tf_courseScheduleByTerm

SELECT tcs.*,term.termName

FROM term, tf_courseScheduleByTerm('2023-2024-2') AS tcs

WHERE tcs.termId=term.termId;

--或者

SELECT tcs.*,term.termName

FROM term

INNER JOIN tf_courseScheduleByTerm('2023-2024-2') AS tcs

ON tcs.termId=term.termId;

4)查询表courseScheduleRecord

SELECT * FROM courseScheduleRecord

WHERE termed='2023-2024-2';

4)查询表t_courseSchedule

SELECT * FROM t_courseSchedule

WHERE termed='2023-2024-2';

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。