存储过程和函数是为了执行一定任务而组合在一起的一种命名的PL/SQL块,编译后作为一种数据库对象存储在数据字典中,可以被用户多次调用来完成某种功能。
触发器是在触发一定事件的时候隐式执行的一段PL/SQL块,编译后作为一种数据库对象存储在数据字典中,只能被事件触发。
创建存储 过程 ,需 要有CREATE PROCEDURE或CREATE ANY
PROCEDURE的系统权限。
创建一个存储过程的基本语句如下:
CREATE [OR REPLACE] PROCEDURE 存储过程名[(参数
[IN|OUT|IN OUT] 数据类型...)]
{AS|IS}
[说明部分]
BEGIN
可执行部分
[EXCEPTION 错误处理部分]
END [过程名];
储存过程储存过程- -说明说明
可选关键字OR REPLACE 表示如果存储过程已经存在,则用新的存储
过程覆盖,通常用于存储过程的重建。
参数部分用于定义多个参数(如果没有参数,就可以省略)。参数有三种
形式:IN、OUT和IN OUT。如果没有指明参数的形式,则默认为IN。
关键字AS也可以写成IS,后跟过程的说明部分,可以在此定义过程的局
部变量。
编写好的存储过程必须要进行编译,生成编译代码,原代码和编译代码
在编译过程中都会被存入数据库。编译成功的存储过程就可以在Oracle
环境下进行调用了。
create or replace procedure sayhello
as
begin
dbms_output.put_line('Hello FZW'); //这就是一个输出语句
end;
存储过程的执行:
begin
sayhello(); //经试验必须要加上括号和分号
end;
删除存储过程
drop procedure sayhello(存储过程名);
create or replace procedure testtime
is
t_start number;
t_end number;
sam number;
use_time number;
begin
t_start:=dbms_utility.get_time; //注:赋值的是时候是:=
select count(*) into sam from mdm_test_db1;
t_end:=dbms_utility.get_time;
use_time:=t_end-t_start;
dbms_output.put_line('花费时间:'||use_time||'s'); //此处的||就是连接符
end;
create or replace procedure test_parameter(num in number)
is
begin
dbms_output.put_line('The input number is:'||num);
end;
执行:
declare
n number;
begin
n:=5;
test_parameter(num=>n);
end;
或者: =>后面的参数必须是实际传入的参数,当然可以不定义变量存参数
begin
test_parameter(num=>9);
end;
CREATE OR REPLACE procedure proc_test_Insert_Single(e_no in number,e_name in varchar ,s in varchar,d in varchar)
as
begin
insert into emp (emp_id,emp_name,salary,birthday) values (e_no,e_name,s,d);
end;
调用:
DECLARE
i NUMBER;
n varchar(5);
s varchar(11);
d varchar(10);
BEGIN
i:=10;
n := 'text11';
s:='3998';
d:='1998-02-02';
PROc_TEST_Insert_single(e_no => i,e_name=>n,s=>s,d=>d);
END;
注:调用存储过程声明varchar时,必须限定长度,即斜体的部分不能少。同时如果给变量赋值时大于限定的长度了,则会提示ORA-06502: PL/SQL: 数字或值错误 : 字符串缓冲区太小。
============================================================
函数(function)为一命名的存储程序,可带参数,并返回一计算值。函数和过程的结构类似,但必须有一个return子句,用于返回函数值。函数说明要指定函数名、结果值的类型,以及参数类型等。
存储函数语法:
create[or replace] functiion 函数名(参数列表)
return函数值类型
as
PLSQL子程序体;
例子:
查询员工年收入
--查询某个员工的年收入
create or replace function queryempincome(eno in number)
return number
as
--月薪和奖金
psal emp.sal%type;
pcomm emp.comm%type;
begin
select sal,comm into psal,pcomm from emp where empno=eno;
--返回年收入
return psal*12+nvl(pcomm,0);
end;
/
===================
用存储过程实现:
create or replace procedure queryEmpInfo(eno in number,
pname out varchar2,
psal out number,
pjob out varchar2)
as
begin
select ename,sal,empjob into pname,psal,pjob from emp where empno=eno;
end;
一般来讲,函数和过程的区别在与函数是有返回值,而过程没有,但过程和函数都可以通过out来指定一个或多个输出参数,我们可以利用out在函数和过程中实现返回多个值。
如果有一个返回值,我们就用函数,没有返回值我们就用过程,过程也可以包含return语句,但不同的是这个return不能有返回值,此return用于直接跳至程序末尾,结束控制循环。
触发器是一种特殊的PL/SQL块,在特定事件发生时被触发被触发执行.
触发器的触发事件分可为3类,分别是DML事件、DDL事件和数据库事件。
每类事件包含若干个事件,如下表所示。数据库的事件是具体的,在创建触发器时要指明触发的事件。
事件种类 关 键 字 含 义
DML事件(3种) 级别(2种) INSERT 在表或视图中插入数据时触发
UPDATE 修改表或视图中的数据时触发
DELETE 在删除表或视图中的数据时触发
DDL事件(3种) CREATE 在创建新对象时触发
ALTER 修改数据库或数据库对象时触发
DROP 删除对象时触发
数据库事件(5种)
STARTUP 数据打开时触发
SHUTDOWN 在使用NORMAL或IMMEDIATE选项关闭数据库时触发
LOGON 当用户连接到数据库并建立会话时触发
LOGOFF 当一个会话从数据库中断开时触发
SERVERERROR 发生服务器错误时触发
触发器的类型可划分为4种:数据操纵语言数据操纵语言(DML)触发器触发器、替代
(INSTEAD OF)触发器、数据定义语言(DDL)触发器和数据库事件触发器。
种 类 简 称 作 用
数据操纵语言触发器 DML触发器 创建在表上,由DML事件引发的触发器
替代触发器 INSTEAD OF触发器 创建在视图上,用来替换对视图进行的插入、删除和修改操作
数据定义语言触发器 DDL触发器 定义在模式上,触发事件是数据库对象的创建和修改
数据库事件触发器 — 定义在整个数据库或模式上,触发事件是数据库事件
============================================
1.要求更新后的年龄不能小于更新前的年龄
create or replace trigger checkage
before update
on MYTEST
for each row
declare
-- 如果要声明本地变量,可以在这里书写
begin
-- if 增加之后的年龄小于增加之前的年龄 then
-- raise_applicatioin_error(-2001,'错误信息')
--*/
--下边的:new 和 :old两个关键字可以根据表中字段来获取表中操作前后的实际数据,以此来判断操作前后数据发生变化的情况。
if:new.age<:old.age then
raise_application_error(-20002,'增加之后年龄不能小于增加之前的年龄.增前:'||:old.age||'||增后:'||:new.age);
end if;
end checkage;
测试:
把年龄大于原来的值在此进行测试发现,测试成功。
示例二:
要求不允许在非工作时间修改数据。
create or replace trigger security
before insert
on mdm_test_db2
for each row
declare
-- local variables here
begin
if to_char(sysdate,'day') in ('星期天','星期五','星期六') or to_number(to_char(sysdate,'hh24')) not between 9 and 17 then
raise_application_error(20001,'禁止在非工作时间修改数据');
end if;
end security;
–security是为触发器起的别名
before insert on MYTEST 意思就是在插入MYTEST表之前进行执行触发器操作
BEGIN 后边开始进行书写触发器的操作。
raise_application_error(20001,’禁止在非工作时间插入新员工’);这是抛出一个例外的书写格式。记住就行
end if; if之后如果后边没有没有内容,切记写上
end security; 这是最后的结束标记他不是固定的而是根据别名来生成的,然后通过按年F8按键进行编译如果没有错误则说明编译成功,进入监视数据库的状态。
测试
测试成功。