自学内容网 自学内容网

第五章:存储过程和触发器

  🌈个人主页:小新_-

🎈个人座右铭:“成功者不是从不失败的人,而是从不放弃的人!”🎈

🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝

🏆所属专栏Oracle网络数据库 欢迎订阅,持续更新中~~~

                      

                               ✨让小新带着你快乐的学习吧~✨

目录

一、存储过程

(一)存储过程的创建

1.以命令方式创建存储过程

2.以界面方式创建存储过程

(二)存储过程的调用

(三)存储过程的修改

二、触 发 器

(一)以命令方式创建触发器

1.创建DML触发器

​编辑

2.创建替代触发器

3.创建系统触发器

(二)触发器的删除

1.以命令方式删除触发器

2.以界面方式删除触发器


存储过程是数据库对象之一,存储过程可以理解成数据库的子程序,在客户端和服务器端可以直接调用它。触发器是与表直接关联的特殊存储过程,是在对表记录进行操作时出发点的。

一、存储过程

在Oracle 11g中,可以在数据库中定义子程序,这种程序块称为存储过程(procedure)。它存放在数据字典中,可以在不同用户和应用程序之间共享,并可实现程序的优化和重用。存储过程的优点如下。

(一)存储过程的创建

1.以命令方式创建存储过程

 创建存储过程使用CREATE PROCEDURE语句,语法格式为:

CREATE [OR REPLACE] PROCEDURE <过程名>  /*定义过程名*/
[ (<参数名> <参数类型> <数据类型> [ DEFAULT <默认值>] [, …n])]
/*定义参数类型及属性*/
{ IS | AS }
[<变量声明>]/*变量声明部分*/
BEGIN
<过程体>/*PL/SQL过程体*/
END [<过程名>][;]

相关参数说明如下:

(1)过程名:存储过程名称要符合标识符规则,并且在所属方案中必须是唯一的。关键字OR REPLACE表示在创建存储过程时,如果已存在同名的过程,则重新创建

(2)参数名:存储过程的参数名也要符合标识符规则,创建过程时,可以声明一个或多个参数,执行过程时应提供相对应的参数。存储过程的参数模式和函数参数一样,也有三种模式,分别为IN、OUT和IN OUT。

(3)DEFAULT:指定过程中IN参数的默认值,默认值必须是常量

(4)过程体:其中包含PL/SQL语句块。

 在存储过程的定义体中,不能使用下列对象创建语句:

CREATE VIEW
CREATE DEFAULT
CREATE RULE 
CREATE PROCEDURE
CREATE TRIGGER

【例1】  创建一个简单的存储过程,输出hello world。

CREATE PROCEDURE proc
AS
BEGIN
DBMS_OUTPUT.PUT_LINE('hello world');
END;

【例2】  创建存储过程,计算指定学生的总学分。

CREATE OR REPLACE PROCEDURE totalcredit
 ( xh IN varchar2)
AS
xf number;
BEGIN
SELECT 总学分
INTO xf
FROM XSB
WHERE 学号=xh AND rownum=1;
DBMS_OUTPUT.PUT_LINE(xf);
END;

注意: 在存储过程体中,不能使用SELECT语句直接查询,否则会出现编译错误。

【3】计算机某专业总学分大于50分的人数,该存储过程使用了一个输入(IN)参数和一个(OUT)参数。

2.以界面方式创建存储过程

如果要通过界面方式定义上面的存储过程count_grade,步骤如下。

(1)启动SQL Developer,选择myorcl连接的“过程”节点,右击鼠标,选择“新建过程”菜单项进入“创建 PL/SQL 过程”对话框,如图所示。

(2)在“名称”文本框中输入存储过程的名称,单击     按钮添加一个参数,在“参数”选项页的“Name”栏中输入各参数名称,在“Type”栏中选择参数的类型,在“Mode”栏中选择参数的模式,在“Default Value”栏中输入参数默认值(如果有的话)。

(3)单击“确定”按钮,在出现的“COUNT_GRADE”过程的编辑框中编写过程语句块,如图7.2所示,单击“编译以进行调试”按钮完成过程的创建。

(二)存储过程的调用

调用存储过程一般使用EXEC语句,语法格式为:

[ { EXEC | EXECUTE } ]  <过程名> 
[ ( [<参数名> =>] <实参> | @<实参变量> [,…n]) ] [;]

说明:EXEC是EXECUTE的缩写,<参数名>为CREATE PROCUDURE中定义的参数名称。在传递参数的实参时,如果指定了变量名,该变量则用于保存OUT参数返回的值;如果省略“<参数名>=>”,则后面的实参顺序要与定义时参数的顺序一致。

【例4】  调用【例1】中的存储过程proc。

EXEC proc;

//或者
BEGIN
proc;
END;

【例5】  从XSCJ数据库的XSB表中查询某人的总学分,根据总学分写评语。

CREATE OR REPLACE PROCEDURE update_info
 ( xh in char )
AS
xf number;
BEGIN
SELECT 总学分 INTO xf
FROM XSB
WHERE 学号=xh AND ROWNUM=1;
IF xf>50 THEN
UPDATE XSB SET 备注= '三好学生' WHERE 学号=xh;
END IF;
IF xf<42 THEN
UPDATE XSB SET 备注= '学分未修满' WHERE 学号=xh;
END IF;
END;

执行存储过程update_info:

EXEC update_info(xh=>'151242');

【例6】  统计XSB表中男女同学的人数。

CREATE OR REPLACE PROCEDURE count_number
( sex IN char, num OUT number )
AS
BEGIN
IF sex= '男' THEN
SELECT COUNT(性别) INTO num
FROM XSB
WHERE 性别= '男';
ELSE
SELECT COUNT(性别) INTO num
FROM XSB
WHERE 性别= '女';
END IF;
END;

在调用过程count_number时,需要先定义OUT类型参数,如下:

DECLARE 
girl_num number;
BEGIN
count_number('女', girl_num);
DBMS_OUTPUT.PUT_LINE(girl_num);
END;

(三)存储过程的修改

修改存储过程和修改视图一样,虽然也有ALTER PROCEDURE语句,但它是用于重新编译或验证现有过程的。如果要修改过程定义,仍然使用CREATE OR REPLACE PROCEDURE命令,语法格式一样。 其实,修改已有过程本质就是使用CREATE OR REPLEACE PROCEDURE重新创建一个新的过程,只要保持名字与原来的过程相同即可。 使用界面方式也可很方便地修改存储过程定义。在SQL Developer中,在“过程”节点下选择要修改的存储过程,右击鼠标,选择“编辑”菜单项,在打开的存储过程编辑窗口中修改定义后单击“编译以进行调试”按钮即可。

当某个过程不再需要时,应将其删除,以释放它占用的内存资源。 删除过程的语法格式为:

DROP PROCEDURE [<用户方案名>.] <过程名>;

【例7】  删除XSCJ数据库中的count_number存储过程。

DROP PROCEDURE count_number;

也可以使用界面方式删除存储过程,具体操作如图所示,请读者自行尝试。

二、触 发 器

触发器是被指定关联到一个表的数据对象,它不需要调用,当对一个表的特别事件出现时,它就会被激活。触发器的代码也是由SQL语句组成的,因此用在存储过程中的语句也可以用在触发器的定义中。触发器是一类特殊的存储过程,与表的关系密切,用于保护表中的数据。当有操作影响到触发器保护的数据时,触发器将自动执行。

(一)以命令方式创建触发器

1.创建DML触发器

创建DML触发器 语法格式为:

CREATE [OR REPLACE] TRIGGER [<用户方案名>.] <触发器名>
{ BEFORE∣AFTER∣INSTEAD OF }/*定义触发动作*/
{ DELETE | INSERT | UPDATE [ OF <列名>[,…n] ]}/*定义触发器种类*/
[OR { DELETE | INSERT | UPDATE [ OF <列名>[,…n] ]}]
ON  {<表名>∣<视图名>}              /*在指定表或视图中建立触发器*/
[ FOR EACH ROW [ WHEN(<条件表达式>) ] ]
<PL/SQL语句块>

【例8】  创建一个表table1,其中只有一列a。在表上创建一个触发器,每次插入操作时,将变量str的值设为“TRIGGER IS WORKING”并显示。

创建表table1:

CREATE TABLE table1(a number);

创建INSERT触发器table1_insert:

CREATE OR REPLACE TRIGGER table1_insert
AFTER INSERT ON table1
DECLARE 
str char(100) :='TRIGGER IS WORKING';
BEGIN
DBMS_OUTPUT.PUT_LINE(str);
END;

向table1中插入一行数据:

INSERT INTO table1 VALUES(10);

【例9】  在XSCJ数据库中增加一个日志表XSB_HIS,表结构和XSB表相同,用来存放从XSB表中删除的记录。创建一个触发器,当XSB表被删除一行时,把删除的记录写到XSB_HIS表中。

CREATE OR REPLACE TRIGGER del_xs
BEFORE DELETE ON XSB FOR EACH ROW
BEGIN
INSERT INTO XSB_HIS (学号, 姓名, 性别, 出生时间, 专业, 总学分, 备注)
VALUES(:OLD.学号,:OLD.姓名, :OLD.性别, :OLD.出生时间, :OLD.专业, :OLD.总学分, :OLD.备注);
END;

OLD修饰访问操作完成前列的值。触发器建立后向XSB表中插入一行数据,之后查看XSB_HIS表中并没有添加了该行数据,这是因为触发器中的DML语句并没有使用提交语句提交,但触发器中不能使用COMMIT语句,所以需要定义自治事务来提交

【例10】  利用触发器在数据库XSCJ的XSB表执行插入、更新和删除三种操作后给出相应提示。

CREATE TRIGGER cue_xs
AFTER INSERT OR UPDATE OR DELETE ON XSB FOR EACH ROW
DECLARE
Infor char(10);
BEGIN
IF INSERTING THEN/*INSERT语句激活了触发器*/
Infor:= '插入';
ELSIF UPDATING THEN/*UPDATE语句激活了触发器*/
Infor:= '更新';
ELSIF DELETING THEN/*DELETE语句激活了触发器*/
Infor:= '删除';
END IF;
DBMS_OUTPUT.PUT_LINE(Infor);
END;

说明:程序中使用条件谓词IF通过谓词INSERTING、UPDATING和DELETING分别判断是否是INSERT、UPDATE和DELETE激活了触发器。另外,在UPDATE触发器中使用UPDATING(列名)的形式来判断特定列是否被更新。

2.创建替代触发器

创建替代触发器使用INSTEAD OF关键字,一般用于对视图的DML触发。由于视图有可能由多个表进行关联而成,因而并非所有的关联都是可更新的。INSTEAD OF触发器触发时只执行触发器内部的SQL语句,而不执行激活该触发器的SQL语句。 例如,若在一个多表视图上定义了INSTEAD OF INSERT触发器,视图各列的值可能允许为空也可能不允许。若视图某列的值不允许为空,则INSERT语句必须为该列提供相应的值。

【例7.11】  在XSCJ数据库中创建视图stu_view,包含学生学号、专业、课程号、成绩。该视图依赖于表XSB和CJB,是不可更新视图。可以在视图上创建INSTEAD OF触发器,当向视图中插入数据时分别向表XSB和CJB插入数据,从而实现向视图插入数据的功能。

首先创建视图:

CREATE VIEW stu_view
AS 
SELECT XSB.学号, 专业, 课程号, 成绩
FROM XSB, CJB
WHERE XSB.学号=CJB.学号

创建INSTEAD OF触发器:

CREATE TRIGGER InsteadTrig
INSTEAD OF INSERT ON stu_view FOR EACH ROW
DECLARE 
xm char(8);
xb char(2);
cssj date;
BEGIN
xm:='徐鹤';
xb:= '男';
cssj:= '1997-07-28';
INSERT INTO XSB(学号, 姓名, 性别, 出生时间, 专业) 
VALUES(:NEW.学号,xm, xb, cssj, :NEW.专业);
INSERT INTO CJB VALUES(:NEW.学号, :NEW.课程号, :NEW.成绩);
END;

向视图插入一行数据:

INSERT INTO stu_view VALUES('151116', '计算机', '101', 85 );

查看数据是否插入:

SELECT * FROM stu_view WHERE 学号= '151116';

执行结果如图所示。

查看与视图关联的XSB表的情况:

SELECT * FROM XSB WHERE 学号= '151116';

执行结果如图所示。

3.创建系统触发器

系统触发器可以在DDL或数据库系统事件上被触发。DDL指的是数据定义语句,如CREATE、ALTER和DROP等。而数据库系统事件包括数据库服务器的启动(STARTUP)、关闭(SHUTDOWN)、出错(SERVERERROR)等。 创建系统触发器的语法格式为:

CREATE OR REPLACE TRIGGER [<用户方案名>.] <触发器名>
{ BEFORE︱AFTER }
{ <DDL事件>︱<数据库事件> }
ON { DATABASE︱[用户方案名.] SCHEMA }
<触发器的PL/SQL语句块>

【例12】  创建一个用户事件触发器,记录用户SYSTEM所删除的所有对象。 首先以用户SYSTEM身份连接数据库,创建一个存储用户信息的表:

CREATE TABLE dropped_objects
(
object_name varchar2(30),
object_type varchar(20),
dropped_date date
);

创建BEFORE DROP触发器,在用户删除对象之前记录到信息表dropped_objects中。

CREATE OR REPLACE TRIGGER dropped_obj_trigger
BEFORE DROP ON SYSTEM.SCHEMA
BEGIN
INSERT INTO dropped_objects
VALUES(ora_dict_obj_name, ora_dict_obj_type, SYSDATE);
END;

现在删除SYSTEM模式下的一些对象,并查询表dropped_objects:

DROP TABLE table1;
DROP TABLE table2;
SELECT * FROM dropped_objects;

以界面方式创建触发器

触发器也可以利用SQL Developer的界面方式创建。

(1)选择myorcl连接的“触发器”节点,右击鼠标,选择“新建触发器”菜单项,进入“创建触发器”窗口,如图所示。

(2)在“名称”栏中输入触发器名称,在“触发器”选项卡中的“触发器类型”下拉列表中选择触发依据,有“Table”“View”“SCHEMA”和“Database”等选项。例如,如果是在表中创建触发器,则这里就选择“TABLE”。可以在“表名”栏中选择触发器所在的表,选中“早于”或“晚于”选项对应BEFORE和AFTER关键字,勾选“插入”、“删除”和“更新”复选框对应触发事件,完成后单击“确定”按钮。

(3)在出现的触发器代码编辑框中编写触发器定义中的PL/SQL语句,完成后单击工具栏的“编译以进行调试”按钮完成触发器的创建,如图所示。

(二)触发器的删除

1.以命令方式删除触发器

删除触发器使用DROP TRIGGER语句,语法格式为:

DROP TRIGGER [<用户方案名>.] <触发器名>

【例13】  删除触发器del_xs。

DROP TRIGGER del_xs;

2.以界面方式删除触发器

在“触发器”节点中选择要删除的触发器,右击鼠标,选择“删除触发器”菜单项,在弹出的“删除触发器”对话框中单击“应用”按钮即可。操作如图所示。

  

最后,感谢大家的观看


原文地址:https://blog.csdn.net/2302_76674204/article/details/143721241

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!