您的位置:首页 > 数据库 > Oracle

Oracle 数据库基础教程 孙风栋等编著

2011-01-07 14:56 661 查看
Unit1
---数据是描述事物的符号,是数据库中存储的基本对象。
---数据库是按一定的数据模型组织、描述和存储的数据的集合。
---数据库管理系统是位于操作系统和用户之间的一层数据管理软件。
:是一款软件。
---数据库、数据库管理系统与计算机系统结合后就就形成了一个数据库系统。
:数据库系统 = 数据库+数据库管理系统+计算机系统
---数据库管理技术经历了人工管理、文件系统管理和数据库系统管理3个阶段。
:人工阶段靠手工完成,数据一次性使用;文件系统阶段以文件形式存储,但无整体结构性,管理上很不方便;数据系统阶段遵循数据模型进行设计存储,由专门的软件来管理数据。
---概念模型转换为关系模型的
基本方法是将概念模型中的实体、属性、联系分别转换为关系模型中的二维表、列、表与表之间的关系。
:ER图中的实体名 变为 二维表名,属性名 变为 列名,联系 变为 表间的关系。
---关系:关系就是二维表。
---元组:表中的每一行数据称作是一个元组,它相当于一个记录。
---属性:表中的每一列是一个属性。
---主码:又称主键,是表中用于唯一确定一个元组的属性或属性组。
---外码:又称外键。
---域:属性的取值范围。例如学生信息表中“性别”域是“男、女”两个值。
---分量:元组中的一个属性值。
---关系模型中的关系完整性约束:
实体完整性:关系中必须定义主键。
参照完整性:表中的外键的取值必须参照表中的主键。
用户定义完整性:符合自定义的约束条件。
---Oracle数据库系统是世界上第一个关系数据库管理系统。 ---ORacle数据库物理文件的管理由Oracle自动进行,而不再由操作系统进行管理。数据库存储空间的分配与回收由Oracle系统自动进行。   Unit4 :三层体系结构。Oracle企业管理器OEM = 客户端控制台 +  Oracle管理服务器OMS + 目标节点(数据库服务器、HTTP服务器……)
管理员利用OEM进行数据库管理操作,OEM将命令传送给OMS处理,OMS处理后发送到目标节点,目标节点安装了智能代理监听器,用于接收、分配和处理上级命令,并将执行结果返回给OMS,OMS再向上返回。
ps:三层体系结构的好处在于,控制台将繁重的作业管理任务从客户端分离出来,交给中间层处理,中间层通过分布式处理、负荷调配、共享服务等手段使整个管理过程具有良好的可靠性和灵活性。
 
Unit5
---启动SQL*PLUS:sqlplus [用户名]  /  [密码]  [@数据库的网络服务名]  |  [nolog]
:举例:1、只启动 sqlplus /nolog
          2、启动并且连接到数据库 sqlplus yeml/test123 @orcl
---退出SQL*PLUS:exit +回车 或者 quit + 回车
---连接命令:conn[ect] [用户名]/[密码][@数据库的网络服务名]
---断开命令:disc[onnect]
---结束输入:1、语句最后加空格后按2次回车;2、回车换行后按点号(.);
---结束输入并执行:1、语句最后加分号并回车;2、语句最后加斜杠(/);
 
缓冲区命令:
---显示缓冲区:list
---编辑缓冲区:ed[it]   ps:还有一些增删减操作的命令
---执行缓冲区:run 或者 /
---清除缓冲区:clear [buffer]
 
脚本文件命令:
---创建脚本并把缓冲区的内容写入:save 带后缀的全路径文件名 [replace]
:举例:创建脚本文件newsql.sql:  save c:\newsql.sql
         替换上述文件:   save c:\newsql.sql replace
---读取脚本存入缓冲区:get 不带后缀的全路径文件名 [ l[ist] ] | [ nol[ist] ]
---读取脚本并执行:start 不带后缀的全路径文件名   或者  @不带后缀的全路径文件名
 
交互式命令:
---变量:1、&Value                 ps:每次都要紧跟着输入其值,如 &v 表示要输入一个数值类型的值,若含单引号‘&V’ 表示要输入字符串类型的值
             2、&&Value               ps:类似于C语言的静态变量static,第一次赋值后就不必再输入其值
             3、define num=’10’    ps:类似C语言的宏定义,可直接使用,类型为char,既字符串。对于undefine num 可清除该变量
             4、variable value type ps:真正的变量,可自由赋值,如variable age number 然后 :age := 22 即可,
---用户通信:1、prompt + 提示信息 2、pause ps:暂停运行脚本内容,按enter键继续 3、accept +含输入操作的语句
       举例:input
               prompt 员工年龄,按enter键继续
               pause
               accept age number prompt ‘输入年龄:’
               insert…(一般SQL语句)
ps:交互式命令适用于自动化操作功能的实现。
 
Unit6
:oracle数据库系统 = 数据库实例 + 物理存储结构(!=逻辑存储结构)
:物理存储结构 = 数据文件(.bdf文件) + 控制文件 + 重做日志文件 +归档文件 + ……
--数据文件的存储策略:1、把不同存储内容的数据文件放置在不同的硬盘上,可以并行访问数据,提高系统读写效率;
                               2、初始化参数文件、控制文件、重做日志文件最好不要与数据文件存放在同一个磁盘上,以免数据库发生介质故障时无法恢复数据库。
                   ps:频繁对文件进行读写操作时,合理分配存储位置可以提高I/O效率
 
:重做日志文件的工作原理:



:LGWR写文件的条件是:日志中的操作记录确保已完成 && ((归档模式 && 归档模式完成)||(非归档模式))
ps:先把各种操作对应的日志信息保存到 缓冲区,缓冲区满后,由LGWR写入 日志文件1, 文件1写满后,切换到日志文件2继续写,文件2也满了就写文件3,以此类推。这种方式称为“循环写”,好处是最旧的数据会被最新的数据覆盖,在物理层达到缓冲的效果,起码命名文件和操作范围容易控制。
 
---归档模式下,数据库中所有的历史重做日志文件全部被保存,即用户的所有操作都被记录下来,因此在数据库出席故障时即使是介质故障,利用数据库备份、归档重做日志文件和联机重做日志文件也可以完全恢复数据库。
---非归档模式下,由于没有保存过去的重做日志文件,数据库只能从实例崩溃中恢复,而无法进行介质恢复。
 
Unit7
---oracle数据库的逻辑存储结构分为 数据块 、 区、 段、 表空间 4种。
---数据块是数据库中最小的I/O单元
---区是数据库中最小的存储空间分配/回收单元。
---段是数据库中相同类型的存储分配区域。
:一个数据库 = (逻辑上)(表空间 + 表空间 + ……)
:一个表空间 = (物理上)(数据文件 + 数据文件 + ……) ||  (逻辑上)(段 + 段 + ……)
 
:表空间分类:1、系统表 2、a.撤销表 b.临时表 c.用户表
:表空间管理:1、字典管理方式:使用数据字典来管理存储空间的分配,管理方便但效率不高。
                   2、本地管理方式:在每个数据文件中维护一个“位图”结构来记录分配情况,优于字典管理方式。
 
数据块管理策略:
---当向表格中插入数据时,如果行的长度大于块的大小,行的信息无法存放在一个块中,就需要使用多个块存放行信息,这称为行链接
---当表格数据被更新时,如果更新后的数据长度大于块长度,oracle会将整行的数据从原数据块迁移到新的数据块中,只在原数据块中留下一个指针指向新的数据块,这称为行迁移
---PCTFREE参数指定块中的最小空闲空间比,当数据块的空闲空间比例低于这个参数时,此数据块被标识为USED,此时只可以对数据块进行更新操作,不可以插入操作。
---PCTUSED参数指定块中插入数据块时已使用的最大空间比,当数据块使用空间比低于这个参数时,此块标志为FREE,可以对数据块进行插入操作。反之标记为PCTUSED,不可插入操作。
---对oracle表空间中的每一个数据段,用一个“可用块列表”作为索引表列出所有未分配使用的块和可以继续插入数据的块。插入的数据不能占用保留空闲的空间,只有在对数据块进行更新时,才能够诗意哦能够保留空闲的空间。
ps:参考其内存管理策略
 
段:
数据段用来存储表或簇的数据。
索引段用来存放各分区的索引信息。
临时段用来存储增删查减时产生的临时数据。
回退段用于保存数据修改前的信息,包括数据修改前的值及其位置,为正在访问相同数据的其他用户提供一份未修改前的原始视图。例如:事务回滚、数据库恢复、读一致性
 
Unit8
:oracle实例 是 数据库管理系统,即对物理数据库进行管理的中间层软件,由一系列内存结构和后台进程组成。


1对1,1对n  ps:参考其调用关系,宏观接口
 
 


ps:参考其整体软件结构,模块化的构件
:SGA区:系统全局区,共享内存区, 可供多个用户共享的数据和控制信息。
:PGA区:程序全局区,私有全局区,保存当前用户私有的数据和控制信息。
 
数据高速缓冲区的工作原理



ps:参考其设计原理,用于I/O读写频繁的情况
---脏缓冲区 保存的是已经被修改过的数据。
---空闲缓冲块不包含任何数据,等待后台进程向其写入数据。
---命中缓冲区是那些正被使用或经常使用的数据块。      ps:采用LRU(最近最少使用算法)替换数据
高速缓冲区详见P134:

, 共享池过程详见P136:

PS:很有参考价值
 
---用户可以在参数文件中设置数据高速缓冲区的大小。数据高速缓冲区越大,用户需要的数据在内存中的可能性就越大,即缓存命中率越高,从而减少了oracle访问硬盘数据的次数,提高数据库系统执行的效率。然而,如果数据高速缓存区的值太大oracle就不得不在内存中寻找更多的块来定位所需要的数据反而降低了系统的性能。所以需要确定一个合理的数据高速缓冲区的大小。                                                   ps:参考其双面性

专用服务器模式:



ps:SGA区执行过程与下面类似,但由单独服务器进程处理队列的命令。适用于用户线程短时间内执行大量操作任务的情况。
 
共享服务器模式:


 
ps:监听程序 负责分派 调度程序 给客户线程;调度程序 负责直接接收客户的任务命令;空闲的服务器进程负责主动处理队列里的任务,而不管是来自谁的请求命令。

 
unit9
:oracle数据库的启动/关闭过程:1、创建并启动实例(读取初始化参数文件并启动服务进程);/  关闭数据库;
                                          2、装载数据库(读取控制文件,初始化实例的信息);         /  卸载数据库;
                                          3、打开数据库(读取数据文件和重做日志文件)。              /  关闭实例。
ps: 一般的启动过程,归纳为3步走 = 创建对象 + 初始化对象 + 给对象加载数据。(这里的对象,即数据库)
 
 
U14
逻辑操作
1.select empno,ename,sal,deptno from emp where comm is not null and sal >1500;
2.select ename, job, sal from emp
where ( job='SALESMAN' or job= ‘CLERK') and sal>1500;
升序、降序
1、SELECT empno,ename,sal FROM emp ORDER BY sal;
2、SELECT empno,ename,sal FROM emp ORDER BY sal DESC;
3、SELECT * FROM emp ORDER BY deptno,sal DESC; //以deptno为主序
 
查询统计
1、SELECT count(*),avg(sal),max(sal),min(sal) FROM emp WHERE deptno=10;
2、SELECT avg(comm),sum(comm) FROM emp ;
3、SELECT count(DISTINCT deptno) FROM emp; //不重复的数目
4、SELECT variance(sal),stddev(sal) FROM emp; //方差、标准差
 
WHERE子句是对表中的记录进行过滤,而
HAVING子句是对分组后形成的组进行过滤。
 
分组查询
SELECT deptno,count(*),avg(sal) FROM emp GROUP BY deptno HAVING avg(sal)>1500;
 
内连接 执行过程:
      首先在表1中找到第一个元组,然后从头开始扫描表2,逐一查找满足连接条件的元组,找到后就将表1中的第1个元组与该元组拼接形成结果表中的一个元组。表2全部找完后,再找表1中的第2个元组,然后再从头扫描表2,逐一查找满足连接条件的元组,找到后就将表1中的第2个元组与该元组拼接形成结果表中的一个元组。重复执行,直到表1中的全部元组都处理完毕为止。
形式1:
SELECT empno,ename,sal,emp.deptno,dname FROM emp,dept WHERE emp.deptno=10 AND emp.deptno=dept.deptno;
形式2:
SELECT empno,ename,sal,emp.deptno,dname FROM emp JOIN dept ON emp.deptno=10 AND emp.deptno=dept.deptno;
 
插入单行记录
INSERT INTO emp(empno,ename,sal,hiredate)
VALUES(1234,'JOAN',2500,'20-4月-2007');
 
向多个表中插入数据
INSERT FIRST
WHEN deptno=10 THEN INTO emp10
WHEN deptno=20 THEN INTO emp20
WHEN deptno=30 THEN INTO emp30
ELSE INTO emp_other
SELECT * FROM emp;
 
修改数据
UPDATE emp SET sal=300+ (SELECT avg(sal) FROM emp WHERE deptno=10),comm=200 WHERE deptno=30;
 
删除数据
DELETE FROM emp WHERE deptno=10;
 
TRUNCATE与DELETE区别 (TRUNCATE TABLE table_name)
1.释放存储空间
2.不写入日志文件,因此执行效率较高,但该操作不可回滚。
 
原子性(Atomicity):事务是数据库的逻辑工作单位,事务中的所有操作要么都做,要么都不做,不存在第三种情况。
一致性(Consistency):事务执行的结果必须是使数据库从一个一致性状态转变到另一个一致性状态,不存在中间的状态。
隔离性(Isolation):数据库中一个事务的执行不受其他事务干扰,每个事务都感觉不到还有其他事务在并发执行。
持久性(Durability):一个事务一旦提交,则对数据库中数据的改变是永久性的,以后的操作或故障不会对事务的操作结果产生任何影响。
 
U15
PL/SQL简单例子:
DECLARE
v1 NUMBER(4);
v2 NUMBER(4) NOT NULL :=10;
v3 CONSTANT NUMBER(4) DEFAULT 100;
BEGIN
IF v1 IS NULL THEN
DBMS_OUTPUT.PUT_LINE('V1 IS NULL!');
END IF;
DBMS_OUTPUT.PUT_LINE(v2||' '||v3);
END;
 
PL/SQL提供以下四种编译指示:
1、EXCEPTION_INIT
告诉编译程序将一个特定的错误号与程序中所声明的异常标识符关联起来。
2、RESTRICT_REFERENCES
告诉编译程序打包程序的纯度,即对函数中可以使用的SQL语句和包变量进行限制。
3、SERIALLY_REUSEABLE
告诉PL/SQL运行时引擎,在数据引用之间不要保持包级数据。
4、AUTONOMOUS_TRANSACTION
告诉编译程序,该程序块为自治事务,即该事务的提交和回滚是独立进行的。
 
使用变量示例
DECLARE
v_emp emp%ROWTYPE;
v_ename emp.ename%type;
v_sal emp.sal%type;
BEGIN
SELECT * INTO v_emp FROM emp WHERE ename='SMITH';
DBMS_OUTPUT.PUT_LINE(v_emp.empno||' '||v_emp.sal);
select ename,sal INTO v_ename,v_sal FROM emp WHERE empno=7900;
DBMS_OUTPUT.PUT_LINE(v_ename||' '||v_sal);
END;
 
修改查询示例
DECLARE
v_empno emp.empno%TYPE :=7500;
BEGIN
INSERT INTO emp(empno,ename,sal,deptno)
VALUES(v_empno,'JOAN',2300,20);
UPDATE emp SET sal=sal+100 WHERE
empno=v_empno;
DELETE FROM emp WHERE empno=v_empno;
END;
 
控制语句示例
DECLARE
v_deptno emp.deptno%type;
v_increment NUMBER(4);
v_empno emp.empno%type;
BEGIN
v_empno:=&x;
SELECT deptno INTO v_deptno FROM emp WHERE empno=v_empno;
IF v_deptno=10 THEN v_increment:=100;
ELSIF v_deptno=20 THEN v_increment:=150;
ELSIF v_deptno=30 THEN v_increment:=200;
ELSE v_increment:=300;
END IF;
UPDATE emp SET sal=sal+v_increment WHERE empno=v_empno;
END;
 
case语句示例
DECLARE
v_deptno emp.deptno%type;
v_increment NUMBER(4);
v_empno emp.empno%type;
BEGIN
v_empno:=&x;
SELECT deptno INTO v_deptno FROM emp WHERE empno=v_empno;
CASE v_deptno
WHEN 10 THEN v_increment:=100;
WHEN 20 THEN v_increment:=150;
WHEN 30 THEN v_increment:=200;
ELSE v_increment:=300;
END CASE;
UPDATE emp SET sal=sal+v_increment WHERE empno=v_empno;
END;
 
Loop循环语句示例
DECLARE
v_counter BINARY_INTEGER :=1;
BEGIN
WHILE v_counter <= 50 LOOP
INSERT INTO temp_table VALUES (v_counter, 'Loop index');
v_counter := v_counter + 1;
END LOOP;
END;
 
游标(CURSOR)是Oracle系统在内存中开辟的一个工作区,在其中存放SELECT语句返回的查询结果。
显式游标:由用户定义、操作,用于处理返回多行数据的SELECT查询。
隐式游标:由系统自动进行操作,用于处理DML语句和返回单行数据的SELECT查询。
 
使用游标示例
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;
 
%ISOPEN
布尔型。如果游标已经打开,返回TRUE,否则为FALSE。
%FOUND
布尔型,如果最近一次使用FETCH语句,有返回结果则为TRUE,否则为FALSE;
%NOTFOUND
布尔型,如果最近一次使用FETCH语句,没有返回结果则为TRUE,否则为FALSE;
 
隐式FOR游标示例:
BEGIN
FOR v_emp IN
(select * from emp where deptno=10) LOOP
DBMS_OUTPUT.PUT_LINE(v_emp.empno||' '||
v_emp.ename);
END LOOP;
END;
 
利用游标更新或删除数据:
DECLARE
CURSOR c_emp IS SELECT * FROM emp FOR UPDATE;
v_increment NUMBER;
BEGIN
FOR v_emp IN c_emp LOOP
CASE v_emp.deptno
WHEN 10 THEN v_increment:=100;
WHEN 20 THEN v_increment:=150;
WHEN 30 THEN v_increment:=200;
ELSE v_increment:=250;
END CASE;
UPDATE emp SET sal=sal+v_increment WHERE CURRENT OF c_emp;
END LOOP;
END;
 
异常处理器的基本形式为
EXCEPTION
WHEN exception1[OR excetpion2…]THEN
sequence_of_statements1;
WHEN exceptioin3[OR exception4…]THEN
sequence_of_statements2;
……
WHEN OTHERS THEN
sequence_of_statementsn;
END;
 
查询名为SMITH的员工工资,如果该员工不存在,则输出“There is not such an employee!”;如果存在多个同名的员工,则输出其员工号和工资。
DECLARE
v_sal emp.sal%type;
BEGIN
SELECT sal INTO v_sal FROM emp WHERE ename='SMITH';
DBMS_OUTPUT.PUT_LINE(v_sal);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('There is not such an emplyee!');
WHEN TOO_MANY_ROWS THEN
FOR v_emp IN (SELECT * FROM emp WHERE ename='SMITH') LOOP
DBMS_OUTPUT.PUT_LINE(v_emp.empno||' '||v_emp.sal);
END LOOP;
END;
 
修改7844员工的工资,保证修改后工资不超过6000。
DECLARE
e_highlimit EXCEPTION;
v_sal emp.sal%TYPE;
BEGIN
UPDATE emp SET sal=sal+100 WHERE empno=7844 RETURNING sal INTO v_sal;
IF v_sal>6000 THEN
RAISE e_highlimit;
END IF;
EXCEPTION
WHEN e_highlimit THEN
DBMS_OUTPUT.PUT_LINE('The salary is too large!');
ROLLBACK;
END;
 
存储子程序是指被命名的PL/SQL块,以编译的形式存储在数据库服务器中,可以在应用程序中进行调用,是PL/SQL程序模块化的一种体现。
函数用于返回特定数据,可以返回一个或多个值。在一个函数中必须包含一个或多个RETURN 语句,函数调用是PL/SQL表达式的一部分,而过程调用可以是一个独立的PL/SQL语句 .
 
创建一个存储过程,以部门号为参数,查询该部门的平均工资,并输出该部门中比平均工资高的员工号、员工名。
CREATE OR REPLACE PROCEDURE show_emp(p_deptno emp.deptno%TYPE)
AS
v_sal emp.sal%TYPE;
BEGIN
SELECT avg(sal) INTO v_sal FROM emp WHERE deptno=p_deptno;
DBMS_OUTPUT.PUT_LINE(p_deptno||' '||'average salary is:'||v_sal);
FOR v_emp IN (SELECT * FROM emp WHERE deptno=p_deptno AND sal>v_sal) LOOP
DBMS_OUTPUT.PUT_LINE(v_emp.empno||' '||v_emp.ename);
END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('The department doesn’’t exists!');
END show_emp;
 
 
创建一个存储过程,以部门号为参数,返回该部门的人数和最高工资。
CREATE OR REPLACE PROCEDURE return_deptinfo(
p_deptno emp.deptno%TYPE,
p_avgsal OUT emp.sal%TYPE,
p_count OUT emp.sal%TYPE)
AS
BEGIN
SELECT avg(sal),count(*) INTO p_avgsal,p_count FROM emp
WHERE deptno=p_deptno;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('The department don’’t exists!');
END return_deptinfo;
 
函数:
创建一个以部门号为参数,返回该部门最高工资的函数。
CREATE OR REPLACE FUNCTION return_maxsal(p_deptno emp.deptno%TYPE)
RETURN emp.sal%TYPE //声明返回的类型
AS
v_maxsal emp.sal%TYPE;
BEGIN
SELECT max(sal) INTO v_maxsal FROM emp
WHERE deptno=p_deptno;
RETURN v_maxsal;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('The deptno is invalid!');
END return_maxsal;

存储子程序与局部子程序区别在于:
存储子程序己经编译好放在数据库服务器端,可以直接调用,而局部子程序存在于定义它的语句块中,在运行时先进行编译;
存储子程序不能重载,而局部子程序可以进行重载;
存储子程序可以被任意的PL/SQL块调用,而局部子程序只能在定义它的块中被调用。
 
p包是包含一个或多个子程序单元(过程、函数等)的容器。
 
1、创建一个软件包(包规范),包括2个变量、2个过程和1个异常。
CREATE OR REPLACE PACKAGE pkg_emp
AS
minsal NUMBER;
maxsal NUMBER;
e_beyondbound EXCEPTION;
PROCEDURE update_sal(
p_empno NUMBER, p_sal NUMBER);
PROCEDURE add_employee(
p_empno NUMBER,p_sal NUMBER);
END pkg_emp;
2、创建包体
使用语句:CREATE OR REPLACE PACKAGE BODY pkg_emp
在软件包头部声明的任何元素是公有的,在包外都是可见的。
在包体中定义而没有在包头中声明的元素是私有的,只能在包体中引用。
 
 
在一个包中重载两个过程,分别以部门号和部门名称为参数,查询相应部门员工名、员工号信息。
CREATE OR REPLACE PACKAGE pkg_overload //创建包规范
AS
PROCEDURE show_emp(p_deptno NUMBER);//声明过程
PROCEDURE show_emp(p_dname VARCHAR2);//声明过程
END pkg_overload;
 
CREATE OR REPLACE PACKAGE BODY pkg_overload //创建包体
AS
PROCEDURE show_emp(p_deptno NUMBER);
AS
BEGIN
FOR v_emp IN (SELECT * FROM emp WHERE deptno=p_deptno) LOOP
DBMS_OUTPUT.PUT_LINE(v_emp.empno||' '||
v_emp.ename);
END LOOP;
END show_emp;
PROCEDURE show_emp(p_dname VARCHAR2)
AS
v_deptno NUMBER;
BEGIN
SELECT deptno INTO v_deptno FROM dept
WHERE dname=p_dname;
FOR v_emp IN (SELECT * FROM emp WHERE deptno=v_deptno) LOOP
DBMS_OUTPUT.PUT_LINE(v_emp.empno||' '||
v_emp.ename);
END LOOP;
END show_emp;
END pkg_overload;
 
触发器:
创建一个触发器,禁止在休息日改变雇员信息,
create or replace trigger tr_sec_emp
before insert or update or delete on emp
begin
if to_char(sysdate,'DY') in ('星期六','星期日') then
raise_application_error(-20001,'不能在休息日修改员工信息');
end if;
end;

示例:
CREATE OR REPLACE TRIGGER trg_emp_dml
AFTER INSERT OR UPDATE OR DELETE ON emp
DECLARE
v_count NUMBER;
v_sal NUMBER(6,2);
BEGIN
IF INSERTING THEN
SELECT count(*) INTO v_count FROM emp;
DBMS_OUTPUT.PUT_LINE(v_count);
ELSIF UPDATING THEN
SELECT avg(sal) INTO v_sal FROM emp;
DBMS_OUTPUT.PUT_LINE(v_sal);
ELSE
FOR v_dept IN (SELECT deptno,count(*) num FROM emp GROUP BY deptno) LOOP
DBMS_OUTPUT.PUT_LINE(v_dept.deptno||' '||v_dept.num);
END LOOP;
END IF;
END trg_emp_dml;

INSTEAD OF触发器
n只能定义在视图上,是行级触发器,由DML操作激发。
 
创建视图的触发器 示例:
CREATE OR REPLACE TRIGGER trig_view
INSTEAD OF INSERT ON empdept //empdept是某视图名称
FOR EACH ROW
DECLARE
v_deptno dept.deptno%type;
BEGIN
SELECT deptno INTO v_deptno FROM dept WHERE dname=:new.dname;
INSERT INTO emp(empno,ename,sal,deptno) VALUES(:new.empno,:new.ename,v_deptno,:new.sal);
END trig_view;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: