Oracle --- 存储过程函数包游标触发器
Posted 劳埃德·福杰
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Oracle --- 存储过程函数包游标触发器相关的知识,希望对你有一定的参考价值。
存储过程和函数也是一种PL/SQL块,是存入数据库的PL/SQL块。
但存储过程和函数不同于已经介绍过的PL/SQL程序,我们通常把PL/SQL程序称为无名块,而存储过程和函数是以命名的方式存储于数据库中的。
1.存储过程
创建存储过程,需要有CREATE PROCEDURE或CREATE ANY PROCEDURE的系统权限。
AS关键字后面可以定义过程的局部变量
CREATE [OR REPLACE] PROCEDURE 存储过程名[(参数[IN|OUT|IN OUT] 数据类型...)]
AS|IS[说明部分]
BEGIN
可执行部分
[EXCEPTION 错误处理部分]
END [过程名];
创建一个显示雇员总人数的存储过程
CREATE OR REPLACE PROCEDURE EMP_COUNT
AS
V_TOTAL NUMBER(10);
BEGIN
SELECT COUNT(*) INTO V_TOTAL FROM EMP;
DBMS_OUTPUT.PUT_LINE('雇员总人数为:'||V_TOTAL);
END;
参数传递
编写给雇员增加工资的存储过程CHANGE_SALARY,通过IN类型的参数传递要增加工资的雇员编号和增加的工资额。
CREATE OR REPLACE PROCEDURE CHANGE_SALARY(P_EMPNO IN NUMBER DEFAULT 7788,P_RAISE NUMBER DEFAULT 10)
AS
V_ENAME VARCHAR2(10);
V_SAL NUMBER(5);
BEGIN
SELECT ENAME,SAL INTO V_ENAME,V_SAL FROM EMP WHERE EMPNO=P_EMPNO;
UPDATE EMP SET SAL=SAL+P_RAISE WHERE EMPNO=P_EMPNO;
DBMS_OUTPUT.PUT_LINE('雇员'||V_ENAME||'的工资被改为'||TO_CHAR(V_SAL+P_RAISE));
COMMIT;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('发生错误,修改失败!');
ROLLBACK;
END;
使用OUT类型的参数返回存储过程的结果
CREATE OR REPLACE PROCEDURE EMP_COUNT(P_TOTAL OUT NUMBER)
AS
BEGIN
SELECT COUNT(*) INTO P_TOTAL FROM EMP;
END;
使用IN OUT类型的参数,给电话号码增加区码。
CREATE OR REPLACE PROCEDURE ADD_REGION(P_HPONE_NUM IN OUT VARCHAR2)
AS
BEGIN
P_HPONE_NUM:='024-'||P_HPONE_NUM;
END;
删除存储过程
DROP PROCEDURE 存储过程名;
2.函数
创建函数,需要有CREATE PROCEDURE或CREATE ANY PROCEDURE的系统权限。
CREATE [OR REPLACE] FUNCTION 函数名[(参数[IN] 数据类型...)] RETURN 数据类型
AS|IS
[说明部分]
BEGIN
可执行部分
RETURN (表达式)
[EXCEPTION
错误处理部分]
END [函数名];
删除函数
DROP FUNCTION 函数名;
创建一个通过雇员编号返回雇员名称的函数GET_EMP_NAME。
CREATE OR REPLACE FUNCTION GET_EMP_NAME(P_EMPNO NUMBER DEFAULT 7788) RETURN VARCHAR2
AS
V_ENAME VARCHAR2(10);
BEGIN
SELECT ENAME INTO V_ENAME FROM EMP WHERE EMPNO=P_EMPNO;
RETURN(V_ENAME);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('没有该编号雇员!');
RETURN (NULL);
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('有重复雇员编号!');
RETURN (NULL);
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('发生其他错误!');
RETURN (NULL);
END;
3.包
包是用来存储相关程序结构的对象,它存储于数据字典中。
包由两个分离的部分组成:包头(PACKAGE)和包体(PACKAGE BODY)。
包头是包的说明部分,是对外的操作接口,对应用是可见的;包体是包的代码和实现部分,对应用来说是不可见的黑盒。
出现在包头中的称为公有元素
出现在包体中的称为私有元素
出现在包体的过程(或函数)中的称为局部变量
系统包:DBMS_OUTPUT包...
创建管理雇员信息的包EMPLOYE,它具有从EMP表获得雇员信息,修改雇员名称和写回EMP表的功能。
CREATE OR REPLACE PACKAGE EMPLOYE --包头部分
IS
PROCEDURE SHOW_DETAIL;
PROCEDURE GET_EMPLOYE(P_EMPNO NUMBER);
PROCEDURE SAVE_EMPLOYE;
END EMPLOYE;
CREATE OR REPLACE PACKAGE BODY EMPLOYE --包体部分
IS
EMPLOYE EMP%ROWTYPE;
-------------- 显示雇员信息 ---------------
PROCEDURE SHOW_DETAIL
AS
BEGIN
DBMS_OUTPUT.PUT_LINE(‘----- 雇员信息 -----’);
DBMS_OUTPUT.PUT_LINE('雇员编号:'||EMPLOYE.EMPNO);
DBMS_OUTPUT.PUT_LINE('雇员名称:'||EMPLOYE.ENAME);
DBMS_OUTPUT.PUT_LINE('雇员职务:'||EMPLOYE.JOB);
DBMS_OUTPUT.PUT_LINE('雇员工资:'||EMPLOYE.SAL);
DBMS_OUTPUT.PUT_LINE('部门编号:'||EMPLOYE.DEPTNO);
END SHOW_DETAIL;
---------------------- 保存雇员到EMP表 --------------------------
PROCEDURE SAVE_EMPLOYE
AS
BEGIN
UPDATE EMP
SET ENAME=EMPLOYE.ENAME,SAL=EMPLOYE.SAL
WHERE EMPNO=EMPLOYE.EMPNO;
DBMS_OUTPUT.PUT_LINE('雇员信息保存完成!');
END SAVE_EMPLOYE;
---------------------------- 修改雇员名称 ------------------------------
PROCEDURE CHANGE_NAME(P_NEWNAME VARCHAR2)
AS
BEGIN
EMPLOYE.ENAME:=P_NEWNAME;
DBMS_OUTPUT.PUT_LINE('修改名称完成!');
END CHANGE_NAME;
// 测试
SET SERVEROUTPUT ON
EXECUTE EMPLOYE.GET_EMPLOYE(7788);
EXECUTE EMPLOYE.SHOW_DETAIL;
EXECUTE EMPLOYE.SAVE_EMPLOYE;
4.游标
游标(CURSOR)是Oracle系统在内存中开辟的一个工作区,在其中存放SELECT语句返回的查询结果。游标工作区中,存在着一个指针(POINTER),在初始状态它指向查询结果的首记录。
游标的类型
- 显式游标:由用户定义、操作,用于处理返回多行数据的SELECT查询。
- 隐式游标(又称SQL游标):由系统自动进行操作,用于处理DML语句和返回单行数据的SELECT查询。 (所有的SQL语句都有一个执行的缓冲区,隐式游标就是指向该缓冲区的指针,由系统隐含地打开、处理和关闭。)
声明游标:就是使一个游标与一条查询语句建立联系。
CURSOR <游标名>[(参数1 数据类型[,…n])] IS 查询语句;
打开游标:就是执行游标定义时所对应的查询语句,并把查询返回的结果集存储在游标对应的工作区中。
OPEN <游标名>[(参数1 [,…n])];
提取游标数据:就是从定义游标的工作区中检索一条数据记录作为当前数据记录。
FETCH <游标名> INTO 变量1 [,… n]
关闭游标:CLOSE <游标名>;
游标属性
- %ISOPEN 描述游标是否已经打开,返回布尔型值。
- %FOUND 描述最近一次FETCH操作的执行情况,返回布尔型值。如果最近一次使用FETCH语句提取游标数据得到结果则返回TRUE,否则返回FALSE。
- %NOTFOUND 用于描述最近一次FETCH操作的执行情况,返回布尔型值。但与%FOUND属性不同的是,如果最近一次使用FETCH语句提取游标数据没有得到结果则返回TRUE,否则返回FALSE。
- %ROWCOUNT 用于描述截至目前从游标工作区提取的实际记录数。
DECLARE
v_deptno emp.deptno%TYPE;
CURSOR c_emp IS SELECT * FROM emp WHERE deptno=v_deptno;
v_emp c_emp%ROWTYPE;
BEGIN
v_deptno:=&x;
OPEN c_emp;
LOOP
FETCH c_emp INTO v_emp;
EXIT WHEN c_emp%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_emp.empno||' '||v_emp.ename||' '|| v_emp.sal ||' '|| v_deptno);
END LOOP;
CLOSE c_emp;
END;
5.触发器
触发器是一种在事件发生时隐式地自动执行的PL/SQL块,不能接受参数,不能被显式调用。
分为两类:
- 系统触发器:由系统事件触发的PL/SQL,比如登陆oracle数据库,登出oracle。
- DML触发器:由DML语句触发的PL/SQL,比如INSERT、UPDATE、DELETE等。
我们一般用到的是DML触发器。
语句触发器:每次对表进行DML操作时只触发一次
CREATE [OR REPLACE] TRIGGER trigger_tname
[before|after] --在触发事件前还是后发生
[update | OR insert | OR delete] --触发事件
ON table_name --是哪张表
declare
--变量声明区
begin
trigger_body --需要触发的事件
end;
定义一个不在规定时间无法添加往students表中添加数据的触发器
create or replace trigger dml_students_time
before --在触发事件发生前
insert or update or delete --触发事件为增删改
on students --对表students
begin --执行触发器体
if to_char(sysdate,'HH24:MI') not between '08:00' and '18:00'
or to_char(sysdate,'DY') in ('SAT','SUN')
then
dbms_output.put_line('You may only make changes during normal office hours');
end if;
end ;
/
行级触发器:数据库表中的每一行受影响就触发一次触发器
// 创建和测试行触发器
CREATE [OR REPLACE] TRIGGER trigger_tname
[before|after] --在触发事件前还是后发生
[update of 字段 | OR insert of 字段 | OR delete of 字段] --触发事件of后可选择,不写代表整个表的所有行
ON table_name --是哪张表
[REFERENCING OLD AS old|NEW AS new]
FOR EACH ROW
[WHEN(condition)]
declare
--变量声明区
begin
trigger_body --需要触发的事件
end;
/
创建触发器,用来记录表的删除数据
--创建表
CREATE TABLE employee(
id VARCHAR2(4) NOT NULL,
name VARCHAR2(15) NOT NULL,
age NUMBER(2) NOT NULL,
sex CHAR NOT NULL
);
--插入数据
INSERT INTO employee VALUES('e101','zhao',23,'M');
INSERT INTO employee VALUES('e102','jian',21,'F');
--创建记录表(包含数据记录)
CREATE TABLE old_employee AS SELECT * FROM employee;
--创建触发器
CREATE OR REPLACE TRIGGER TIG_OLD_EMP
AFTER DELETE ON EMPLOYEE
FOR EACH ROW --语句级触发,即每一行触发一次
BEGIN
INSERT INTO OLD_EMPLOYEE VALUES (:OLD.ID, :OLD.NAME, :OLD.AGE, :OLD.SEX); --:old代表旧值
END;
/
--下面进行测试
DELETE employee;
SELECT * FROM old_employee;
以上是关于Oracle --- 存储过程函数包游标触发器的主要内容,如果未能解决你的问题,请参考以下文章
Oracle03——游标异常存储过程存储函数触发器和Java代码访问Oracle对象
Oracle-4 - :超级适合初学者的入门级笔记:plsql,基本语法,记录类型,循环,游标,异常处理,存储过程,存储函数,触发器