1. PL/SQL简介

PL/SQL(Procedural Language)是Oracle数据库支持的一种过程化语言,它扩展了SQL语言,使得开发人员可以编写具有复杂逻辑的程序。PL/SQL主要用于编写存储过程、函数、触发器和包等数据库程序单元

PL/SQL程序由三个主要部分组成:声明部分、执行部分和异常处理部分,例如:

DECLARE

-- 声明部分

v_name VARCHAR(50);

BEGIN

-- 执行部分

SELECT ename INTO v_name FROM emp WHERE empno = 111;

DBMS_OUTPUT.PUT_LINE('员工姓名: ' || v_name);

EXCEPTION

-- 异常处理部分

WHEN NO_DATA_FOUND THEN

DBMS_OUTPUT.PUT_LINE('没有找到数据');

END;

2. 存储过程

在达梦数据库中,存储过程(Stored Procedure) 是一组预编译的 SQL 语句和业务逻辑的集合,存储在数据库中,可通过名称被多次调用。它封装了复杂的业务逻辑,简化了数据库操作,提高了代码复用性和安全性。

语法格式:

语法格式

CREATE [OR REPLACE ] PROCEDURE <存储过程名定义>

[(<参数名> <参数模式> <参数类型> [<默认值表达式>] {,<参数名> <参数模式> <参数类型>  [<默认值表达式>] })]

[WITH  ENCRYPTION]

AS | IS

[<说明部分>]

BEGIN

<执行部分>

[<异常处理部分>]

END;

创建一个简单的存储过程PROC_TEST1,计算输入的数与10相加后的结果:

调用PROC_TEST1,并传入参数12:

调用存储过程的语法格式:CALL 存储过程名(参数);

删除存储过程PROC_TEST1,语法格式:DROP PROCEDURE 存储过程名;

3. 存储模块控制结构

存储模块控制结构包括:顺序结构、循环结构、分支结构等。

3.1 顺序结构

顺序结构就是按照语句出现的先后顺序执行。

3.2 分支结构

语法格式:

条件分支控制结构语法如下:

IF <条件表达式>

THEN <执行部分>;

[{ELSEIF|ELSIF <条件表达式> THEN <执行部分>;}]

[ELSE <执行部分>;]

[END IF]

END IF

存储模块的控制语句中支持的条件谓词有:

比较谓词、BETWEENINLIKEIS NULL

创建一个简单的存储过程PROC_IF:

调用PROC_IF,并传入参数11,开始执行:

由于传入的参数11大于10,满足IF后的条件,打印输出‘yes’。

在分支结构中使用含有LIKE的条件表达式进行判断:

传入的sentence含有“JPC”,所以输出结果为“传入的语句中包含JPC!”

3.3 循环结构

循环结构有四种基本类型的循环语句,包括:LOOP语句、WHILE语句、FOR语句、REPEAT语句。

LOOP语句:直到EXIT语句终止循环为止

语法格式:

LOOP语句的语法如下

LOOP

<执行部分>;

END LOOP

没有明显的终点,必须借助EXIT语句来跳出循环

创建一个存储过程PROC_LOOP,用于将某个输入的数字打印并自增,直至该数字大于或等于10后退出循环:

调用PEOC_LOOP,并传入1,开始执行:

WHILE语句:当表达式的值为TRUE时就执行循环体的语句,为FALSE则跳出循环。

语法格式:

WHILE <条件表达式> LOOP

<执行部分>;

END LOOP

创建一个存储过程PROC_WHILE,用于计算输入数字以内之和:

调用PROC_WHILE,传入10,计算10以内的数字之和,开始执行:

FOR语句:对一系列的语句重复执行指定次数的循环

FOR <循环计数器> IN [REVERSE] <下限表达式> .. <上限表 达式> LOOP

<执行部分>;

END LOOP

创建一个存储过程PROC_FOR,利用for循环结构计算1到10的数字之和:

调用PROC_FOR,计算1到10的数字之和,开始执行:

REPEAT语句 :重复执行一系列语句直至达到条件表达式的限制要求,先执行<执行部分>,然后再判断条件,类似do..whlie循环结构。

REPEAT

<执行部分>;

UNTIL <条件表达式>

END

创建一个存储过程PROC_REPEAT,用于计算1到10的数字之和:

调用PROC_REPEAT,执行结果:

 

4. 存储模块的异常处理

异常处理的定义:

在存储模块的正常执行过程中,可能会出现未预料的事件,这就是异常(EXCEPTION)。

异常事件会导致代码的不正确结束,因此用户需要在程序中对异常进行处理,以保证不可预知的错误不会终止DM PL/SQL模块。为此,DM提供了异常处理机制,使用户可以在语句块的异常处理部分中处理异常。

异常,可以是系统预定义异常,也可以是用户自定义异常

4.1 用户自定义异常

语法格式:

自定义异常:

<异常变量名> EXCEPTION;

PRAGMA EXCEPTION_INIT(<异常变量名>, <错误号>);

抛出异常:

RAISE <异常名>;

异常处理部分:

EXCEPTION

           WHEN exception1[OR excetpion2…]THEN statements1;

           ……

           WHEN OTHERS THEN statementsn;

自定义了一个用于检验输入的数字是否在合法范围内的异常,异常名称为e_illegal,错误代码号为-1111,具体实现如下图所示:

检验效果:

输入合法范围内的数字:50

输入不合法的数字:200

4.2 系统预定义异常

NO_DATA_FOUND异常:

根据stu_id查找学生表STUDENTS中的学生姓名,若成功找到,则输出学生姓名;若该stu_id无效,则进行NO_DATA_FOUND的异常处理,输出“没有该学生”,具体实现如下图所示:

检验效果:

查找成功:

查找失败:

ZERO_DIVIDE异常:

对传入的num进行除0操作,会抛出ZERO_DIVIDE异常,并进行相应异常处理。

检验效果:

 

5. 游标

定义:游标(CURSOR)是指向一条DML语句或者是一个查询操作运行后的一个结果集区域

游标分为显示游标和隐式游标:

显示游标:由用户定义、操作,用于处理返回多行数据的SELECT查询。

隐式游标:由系统自动进行操作,用于处理DML语句和返回单行数据的SELECT查询。

5.1 显示游标

定义一个游标c_stu,指向的查询语句的主要操作是查询students表中爱好hobby都为“唱歌跳舞”的学生。使用%ROWTYPE定义了一个变量v_stu,在loop中循环检索游标并将记录传入到v_stu中,最后打印出v_stu中的name。

检验效果:

5.2 隐式游标

对students表执行更新操作,更新stu_id为2025的学生的兴趣爱好,将SQL%NOTFOUND作为if的判断条件,当不存在这个id的学生后,SQL%NOTFOUND为true,所以执行插入语句。

检验效果:

5.3 游标FOR循环

语法格式:

声明部分:

CURSOR cursor_name IS SELECT…;

执行体部分:

FOR loop_variable IN cursor_name  LOOP

      ......

END LOOP;

游标for循环的特性:

系统隐含地定义了一个数据类型为%ROWTYPE的变量,并以此作为循环的计算器 (即loop_variable) ;

系统自动打开游标,不用显式地使用OPEN语句打开;

系统自动重复地从游标工作区中提取数据并放入计数器变量中;

系统自动进行%FOUND属性检查以确定是否有数据;

当游标工作区中所有的记录都被提取完毕或循环中断时,系统自动地关闭游标。

将定义的游标c_stu指向的查询操作运行后的一个结果集利用for循环进行打印输出:

检验效果:

达梦技术社区 | 达梦数据库: 达梦数据库 - 新一代大型通用关系型数据库 | 达梦在线服务平台

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐