oracle-触发器练习
- 格式:docx
- 大小:488.83 KB
- 文档页数:13
第一章PL/SQL简介一、PL/SQL:过程化的SQL语言,也就是在SQL语句的基础上加入了条件判断、循环等过程化的语句。
用SQL语句进行编程使SQL能够完成更加复杂的操作和计算。
二、PL/SQL块1、块结构Declare--声明部分,所有的变量或常量,在此部分声明--如果程序中不需要变量或常量,此部分可省略Begin--可执行部分,功能的实现部分,不能省略Exception--异常处理部分--此部分可以省略End;--结束部分,标识了程序的边界,不能省略--end关键字末尾一定要加;结尾--每一条语句用一行书写,末尾用;结尾2、编辑和运行PL/SQL块a.要在SQLplus环境下编辑,运行。
--也可以在PL/SQL developer 中新建Command Window中b.用/来运行PL/SQL块----------------------------------------------------------------------------C:\Documents and Settings\ttc>sqlplus scott/tiger@orclSQL*Plus: Release 10.2.0.1.0 - Production on 星期一2月21 09:20:20 2011Copyright (c) 1982, 2005, Oracle. All rights reserved.连接到:Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - ProductionWith the Partitioning, OLAP and Data Mining optionsSQL> declare2 ...3 ...4 begin5 ...6 exception7 ...8 end;9 /----------------------------------------------------------------------------3、输出语句dbms_output.put_line(列|表达式|变量);--包.过程(参数),向屏幕上输出列|表达式|变量的值serveroutput 环境变量--在一个会话开始的时候,要设置环境变量serveroutput为打开状态,此会话中的所有的PL/SQL块才能输出值到屏幕上--PL/SQL developer中,一个会话就是一个新建的Command Window文件--通常在PL/SQL developer中的Command Window文件,使用Editor编辑(F8执行) Set serveroutput On练习1:编辑一个PL/SQL块,输出hello world.--------------------------------------------------------------------------------------------SQL> begin2 dbms_output.put_line('Hello world');3 end;4 /Hello worldPL/SQL procedure successfully completed--------------------------------------------------------------------------------------------4、块的类型a.匿名块:没有名字的PL/SQL块,不能够存储,只能写一次执行一次,也是不能被调用。
oracle-触发器练习触发器课堂练习11、当向SC表插入数据时,修改(或添加)SC_NUMBER(包括学生学号和选课门数两列)表格中的数据。
create or replace trigger tr_sc_AR_Iafter insert on scfor each rowbeginupdate sc_number set scnum=scnum+1where sno=:new.sno;if sql%notfound theninsert into sc_number values(:new.sno,1);end if;end;测试结果:2、当删除SC表中数据时,修改(或添加)SC_NUMBER中的数据。
create or replace trigger tr_sc_AR_Dafter delete on scfor each rowbeginupdate sc_number set scnum=scnum-1where sno=:old.sno;select scnum into pk_trigger.tr_scnum from sc_number where sno=:old.sno;if(pk_trigger.tr_scnum=0) thendelete from sc_number where sno=:old.sno;end if;end;测试结果:3、当修改SC表中数据时,若修改的是学号,则对应修改SC_NUMBER表中的选课门数,否则打印“某某(学生姓名)的学生选课信息已经修改”信息。
create or replace trigger tr_sc_AR_Uafter update on scfor each rowbeginif(:old.sno = :new.sno) thenselect sname into pk_trigger.tr_sname from student where sno=:new.sno;dbms_output.put_line(pk_trigger.tr_sname||'的学生选课信息已经修改,由原课程'|| trim(:o)||'修改为新课程'||trim(:o));end if;if(:old.sno <> :new.sno) thenupdate sc_number set scnum=scnum+1where sno=:new.sno;if sql%notfound theninsert into sc_number values(:new.sno,1);end if;update sc_number set scnum=scnum-1where sno=:old.sno;select scnum into pk_trigger.tr_scnum from sc_number where sno=:old.sno;if(pk_trigger.tr_scnum=0) thendelete from sc_number where sno=:old.sno;end if;end if;end;测试结果:触发器课堂练习 21、修改STUDENT表数据时,限制不能修改学生的系别(不能修改CS系学生的系别)。
Oracle触发器语法及实例Oracle 触发器语法及实例Oracle触发器语法(一)一Oracle触发器语法触发器是特定事件出现的时候,自动执行的代码块。
类似于存储过程,触发器与存储过程的区别在于:存储过程是由用户或应用程序显式调用的,而触发器是不能被直接调用的。
功能:1、允许/限制对表的修改2、自动生成派生列,比如自增字段3、强制数据一致性4、提供审计和日志记录5、防止无效的事务处理6、启用复杂的业务逻辑触发器触发时间有两种:after和before。
1、触发器的语法:CREATE [OR REPLACE] TIGGER触发器名触发时间触发事件ON表名[FOR EACH ROW]BEGINpl/sql语句END其中:触发器名:触发器对象的名称。
由于触发器是数据库自动执行的,因此该名称只是一个名称,没有实质的用途。
触发时间:指明触发器何时执行,该值可取:before---表示在数据库动作之前触发器执行;after---表示在数据库动作之后出发器执行。
触发事件:指明哪些数据库动作会触发此触发器:insert:数据库插入会触发此触发器;Oracle触发器语法(二)update:数据库修改会触发此触发器;delete:数据库删除会触发此触发器。
表名:数据库触发器所在的表。
for each row:对表的每一行触发器执行一次。
如果没有这一选项,则只对整个表执行一次。
2、举例:下面的触发器在更新表auths之前触发,目的是不允许在周末修改表:create triggerauth_secure before insert or update or delete //对整表更新前触发on authsbeginif(to_char(sysdate,'DY')='SUN'RAISE_APPLICATION_ERROR(-20600,'不能在周末修改表auths');end if;end例子:CREATE OR REPLACE TRIGGER CRM.T_SUB_USERINFO_AUR_NAME AFTER UPDATE OF STAFF_NA MEON CRM.T_SUB_USERINFOREFERENCING OLD AS OLD NEW AS NEWFOR EACH ROWdeclarebeginif :NEW.STAFF_NAME!=:OLD.STAFF_NAME thenbegin客户投诉update T_COMPLAINT_MANAGE set SERVE_NAME=:NEW.STAFF_NAME where SERVE_SEED=:OL D.SEED;客户关怀update T_CUSTOMER_CARE set EXECUTOR_NAME=:NEW.STAFF_NAMEwhere EXECUTOR_SEED=:OLD.SEED;客户服务update T_CUSTOMER_SERVICE set EXECUTOR_NAME=:NEW.STAFF_NAMEwhere EXECUTOR_SEED=:OLD.SEED;end;end if;end T_sub_userinfo_aur_name;/Oracle触发器语法(三)二 Oracle触发器详解开始:create trigger biufer_employees_department_idbefore insert or update of department_id on employeesreferencing oldasold_value newasnew_valuefor each rowwhen (new_value.department_id<>80 )begin:new_/doc/3d14459295.html,mission_pct := 0;end;/1、触发器的组成部分:1、触发器名称2、触发语句3、触发器限制4、触发操作1.1、触发器名称create trigger biufer_employees_department_id命名习惯:biufer(before insert update for each row)employees表名department_id列名1.2、触发语句比如:表或视图上的DML语句DDL语句Oracle触发器语法(四)数据库关闭或启动,startup shutdown等等before insert or updateof department_idon employeesreferencing old as old_valuenew as new_valuefor each row说明:1、无论是否规定了department_id,对employees表进行insert的时候2、对employees表的department_id列进行update的时候1.3、触发器限制when (new_value.department_id<>80 )限制不是必须的。
触发器练习(一)1、画出图题5-1所示的RS 触发器输出端Q 、Q 端的波形,输入端S 与R 的波形如图所示。
(设Q 初始状态为0)S RSRSRQQ....图题5-12、画出图题5-2所示的RS 触发器输出端Q 、Q 端的波形,输入端S 与R 的波形如图所示。
(设Q 初始状态为0)S RS RQQ...SR....图题5-23、画出图题5-3所示的同步RS 触发器输出端Q 、Q 端的波形,输入端S 、R 与CLK 的波形如图所示。
(设Q 初始状态为0)C1S RS RQQ....CLKS RCLK...图题5-34、画出图题5-4所示的同步D 触发器输出Q 端的波形,输入端D 与CLK 的波形如图所示。
(设Q 初始状态为0)C1DDQQ....CLKDCLK..图题5-45、若在图5-5电路中的CP 、S 、R 输入端,加入如图4.27所示波形的信号,试画出其 Q 和Q端波形,设初态Q =0。
SRCP触发器练习(二)1、画出图题5-6所示的同步JK 触发器输出Q 端的波形,输入端J 、K 与CLK 的波形如图所示。
(设Q 初始状态为0)J KQQ..CLKJKCLK ......C11J 1K..图题5-62、画出图题5-6所示的边沿触发D 触发器输出端Q 端的波形,输入端D 与CLK的波形如图所示。
(设Q 初始状态为0)C11D D QQ....CLKDCLK...D QQ....CLKDCLK...C11D (1)(2)3、画出图题5-7所示的边沿D 触发器输出Q 端的波形,CLK 的波形如图所示。
(设Q 初始状态为0)C11D Q 1CLK....CLK.1C11D Q 2CLK .CLK .图题5-74、画出图题5-8所示的JK 触发器输出Q 端的波形,输入端J 、K 与CLK 的波形如图所示。
(设Q 初始状态为0)J KQQ....CLKJ KCLK ...C11J 1KJ KCLK ......图题5-85、试画出图题5-9所示T 触发器输出Q 端的波形,输入端CLK 的波形如图所示。
1.( )程序包用于读写操作系统文本文件。
(选一项)A、Dbms_outputB、Dbms_lobC、Dbms_randomD、Utl_file2.( )触发器允许触发操作的语句访问行的列值。
(选一项)A、行级B、语句级C、模式D、数据库级3.( )是oracle在启动期间用来标识物理文件和数据文件的二进制文件。
(选一项)A、控制文件B、参数文件C、数据文件D、可执行文件4.CREATE TABLE 语句用来创建(选一项)A、表B、视图C、用户D、函数5.imp命令的哪个参数用于确定是否要倒入整个导出文件。
(选一项)A、constranintsB、tablesC、fullD、file6.ORACLE表达式NVL(phone,'0000-0000')的含义是(选一项)A、当phone为字符串0000-0000时显示空值B、当phone为空值时显示0000-0000C、判断phone和字符串0000-0000是否相等D、将phone的全部内容替换为0000-00007.ORACLE交集运算符是(选一项)A、intersectB、unionC、setD、minus8.ORACLE使用哪个系统参数设置日期的格式(选一项)A、nls_languageB、nls_dateC、nls_time_zoneD、nls_date_format9.Oracle数据库中,通过()访问能够以最快的方式访问表中的一行(选一项)A、主键B、RowidC、唯一索引D、整表扫描10.Oracle数据库中,下面()可以作为有效的列名。
(选一项)A、ColumnB、123_NUMC、NUM_#123D、#NUM12311.Oracle数据库中,以下()命令可以删除整个表中的数据,并且无法回滚(选一项)A、dropB、deleteC、truncateD、cascade12.Oracle中, ( )函数将char或varchar数据类型转换为date数据类型。
--采用信息表create table cg(id number,goodName varchar2(10),goodNum number)--商品库存create table stock(goodName varchar2(10),goodNum number)create or replace trigger t_cgafter insert on cg for each rowbegininsert into stock values(:new.goodName,:new.goodNum);end;创建一个触发器,禁止用户删除dept表中的记录create or replace trigger mytrigger3before delete on emp_testbeginif deleting thenraise_application_error(-20020, '禁止删除表dept中的记录 ');end if;end;instead-of触发器(了解):当向一个由多个表联接成的视图作DML操作时,一般情况下是不允许的,这时候就可以用Instead-of触发器来解决这种问题(在触发器写代码分别对各表作相应DML操作),语法:create or replace trigger trigger_nameinstead of insert|update|deleteon view_namefor each row如:下面视图是按部门统计,员工人数,工资数。
想要从视图中删除部门为10的信息。
CREATE OR REPLACE VIEW emp_view ASSELECT deptno, count(*) total_employeer, sum(sal) total_salary。
oracle触发器if写法
在Oracle 数据库中,触发器(Triggers)是一种在表上自动执行的存储过程,它在表上的特定事件(如插入、更新或删除)发生时被触发。
当编写Oracle 触发器时,你可能需要使用条件语句(`IF` 语句)来控制触发器的行为。
以下是Oracle 触发器中使用`IF` 语句的一般写法:
```sql
CREATE OR REPLACE TRIGGER trigger_name
BEFORE INSERT OR UPDATE OR DELETE ON your_table
FOR EACH ROW
DECLARE
--声明变量或其他声明
BEGIN
--触发器的主体部分
--使用IF 语句进行条件判断
IF condition THEN
--在满足条件时执行的操作
ELSIF another_condition THEN
--在满足另一个条件时执行的操作
ELSE
--如果没有条件被满足时执行的操作
END IF;
--触发器的其他逻辑
END;
/
```
上述示例中,`IF` 语句用于执行条件判断,如果条件为真,则执行相应的操作。
可以使用`ELSIF` 子句来添加更多的条件分支,也可以使用`ELSE` 子句来指定如果没有条件被满足时要执行的操作。
在触发器的主体部分,你可以包含任何你需要执行的逻辑,例如设置变量、执行SQL 语句等。
请注意,在触发器中使用`:NEW` 和`:OLD` 伪记录来引用插入或更新前后的行数据。
请根据实际需求调整触发器的条件和操作。
此外,触发器的编写需要小心,确保不会导致性能问题或死锁等数据库问题。
oracle触发器的实例(转)触发器使⽤教程和命名规范⽬录触发器使⽤教程和命名规范 11,触发器简介 12,触发器⽰例 23,触发器语法和功能 34,例⼀:⾏级触发器之⼀ 45,例⼆:⾏级触发器之⼆ 46,例三:INSTEAD OF触发器 67,例四:语句级触发器之⼀ 88,例五:语句级触发器之⼆ 99,例六:⽤包封装触发器代码 1010,触发器命名规范 111,触发器简介触发器(Trigger)是数据库对象的⼀种,编码⽅式类似存储过程,与某张表(Table)相关联,当有DML语句对表进⾏操作时,可以引起触发器的执⾏,达到对插⼊记录⼀致性,正确性和规范性控制的⽬的。
在当年C/S时代盛⾏的时候,由于客户端直接连接数据库,能保证数据库⼀致性的只有数据库本⾝,此时主键(Primary Key),外键(Foreign Key),约束(Constraint)和触发器成为必要的控制机制。
⽽触发器的实现⽐较灵活,可编程性强,⾃然成为了最流⾏的控制机制。
到了B/S时代,发展成4层架构,客户端不再能直接访问数据库,只有中间件才可以访问数据库。
要控制数据库的⼀致性,既可以在中间件⾥控制,也可以在数据库端控制。
很多的青睐Java的开发者,随之将数据库当成⼀个⿊盒,把⼤多数的数据控制⼯作放在了Servlet中执⾏。
这样做,不需要了解太多的数据库知识,也减少了数据库编程的复杂性,但同时增加了Servlet编程的⼯作量。
从架构设计来看,中间件的功能是检查业务正确性和执⾏业务逻辑,如果把数据的⼀致性检查放到中间件去做,需要在所有涉及到数据写⼊的地⽅进⾏数据⼀致性检查。
由于数据库访问相对于中间件来说是远程调⽤,要编写统⼀的数据⼀致性检查代码并⾮易事,⼀般采⽤在多个地⽅的增加类似的检查步骤。
⼀旦⼀致性检查过程发⽣调整,势必导致多个地⽅的修改,不仅增加⼯作量,⽽且⽆法保证每个检查步骤的正确性。
触发器的应⽤,应该放在关键的,多⽅发起的,⾼频访问的数据表上,过多使⽤触发器,会增加数据库负担,降低数据库性能。
Oracle 经典练习题一.创建一个简单的PL/SQL程序块1.编写一个程序块,从emp表中显示名为“SMITH”的雇员的薪水和职位。
declarev_emp emp%rowtype;beginselect * into v_emp from emp where ename='SMITH';dbms_output.put_line('员工的工作是:'||v_emp.job||' ;他的薪水是:'||v_emp.sal);end;2.编写一个程序块,接受用户输入一个部门号,从dept表中显示该部门的名称与所在位置。
方法一:(传统方法)declarepname dept.dname%type;ploc dept.loc%type;pdeptno dept.deptno%type;beginpdeptno:=&请输入部门编号;select dname,loc into pname,ploc from dept where deptno=pdeptno; dbms_output.put_line('部门名称: '||pname||'所在位置:'||ploc); exception –异常处理when no_data_foundthen dbms_output.put_line('你输入的部门编号有误!!');when othersthen dbms_output.put_line('其他异常');end;方法二:(使用%rowtype)declareerow dept%rowtype;beginselect * into erow from dept where deptno=&请输入部门编号;dbms_output.put_line(erow.dname||'--'||erow.loc);exceptionwhen no_data_foundthen dbms_output.put_line('你输入的部门号有误');when othersthen dbms_output.put_line('其他异常');end;3.编写一个程序块,利用%type属性,接受一个雇员号,从emp表中显示该雇员的整体薪水(即,薪水加佣金)。
Oracle数据库——触发器的创建与应⽤⼀、涉及内容1.理解触发器的概念、作⽤和类型。
2.练习触发器的创建和使⽤。
⼆、具体操作(实验)1.利⽤触发器对在scott.emp表上执⾏的DML操作进⾏安全性检查,只有scott⽤户登录数据库后才能向该表中执⾏DML操作。
(第1题中,user是系统函数,返回当前⽤户。
字符串中使⽤两个单引号表⽰⼀个单引号。
)要求:分别以system⽤户和scott⽤户对emp 表执⾏DML操作,试验触发器的运⾏效果。
(1)在scott⽤户下创建触发器语句:create or replace trigger tri_dm1before insert or update or delete on scott.empbeginif user<>'SCOTT'thenraise_application_error(-20001,'You don''t have access to modify this table.');end if;end;/截图:(2)以system ⽤户连接,并对emp表执⾏DML操作语句:conn system/orcl1234;insert into scott.emp(empno,ename) values(8888,'shenxiao');截图:(3)以scott⽤户连接,并对emp表执⾏DML操作语句:conn scott/tiger;insert into scott.emp(empno,ename) values(8888,'shenxiao');截图:2.利⽤触发器进⾏表和备份表之间的同步复制。
(1)在scott ⽤户下创建scott.emp 表的复本 employee。
语句:conn scott/tiger;create table employee as select * from scott.emp;截图:(2)在scott⽤户下创建能实现scott.emp和employee 两表之间同步复制的DML触发器。
Oracle_EBS_Form_触发器学习大全Oracle EBS Form Trigger学习大全打开,关闭,创建,更新记录的trigger次序PRE-……在进入一个form,或是导航到一个新的block时触发,PRE-……系列的触发器一般是在WHEN-NEW-……-INSTANCE系列之前,它们如果失败了的话,就不能成功导航到下一个对象了,只能留在当前的位置。
在这些触发器里可以设置一些判断条件来限制是否可以导航到新的位置。
WHEN-NEW-……-INSTANCE这一类的trigger都是当鼠标光标每次落到一个新的block,record,item上时触发的,而且就算失败了,也不会发生什么错误。
但是when-new-form-instance,只有当form 启动时,光标导航到第一个导航块的第一个导航item时触发,如果一个应用有多个form,当光标在各个form之间转换时,并不会触发它。
POST-TEXT-ITEM和WHEN-VALIDATE-ITEMPost-text-item的触发点:当输入的光标从一个Text-Item 转到其它item,可以用它来改变item的值,而when-Validate-item虽然也是在离开前触发,但是作用不同,Post-Text-Item本身是没有验证的,when-Validate-item可以用来补充一些验证(除了form本身的验证),但是当form验证成功以后,会把item标志为…valid?,而不会再去验证了,如果这时我们再去修改它的值,那么就有可能会把无效的值导入到数据库。
在创建和更新一条记录时,先触发when-Validate-item,再触发Post-T ext-Item,然后是when-Validate-record。
POST-……系列的都是离开当前的block,record,item时触发的WHEN-WINDOW-ACTIVATED做原材料属性修改平台时,第一次使用这个触发器,用来从另一个window返回时,刷新当前window,代码写在了这个触发器里。
在Navicat中创建Oracle触发器的示例如下:
1. 首先,打开Navicat并连接到Oracle数据库。
2. 在左侧的数据库列表中,找到要创建触发器的表,右键点击该表,选择"设计表"。
3. 在弹出的"设计表"窗口中,找到需要添加触发器的字段,右键点击该字段,选择"创建触发器"。
4. 在弹出的"创建触发器"窗口中,输入触发器的名称、类型(BEFORE或AFTER)以及触发时机(INSERT、UPDATE或DELETE)。
5. 编写触发器的逻辑代码。
例如,创建一个在插入数据之前自动将某个字段值加1的触发器:
```sql
CREATE OR REPLACE TRIGGER trg_example
BEFORE INSERT ON example_table
FOR EACH ROW
BEGIN
:new.some_field := :new.some_field + 1;
END;
/
```
6. 保存并关闭"设计表"窗口。
7. 在Navicat的主界面,找到刚刚创建的触发器,右键点击它,选择"执行SQL脚本"。
这将在数据库中实际创建触发器。
oracle中触发器写判断语句,Oracle触发器介绍语句级触发器语句级触发器我们先看⼀个AFTER-INSERT-STATEMENT触发器:CREATE OR REPLACE TRIGGER temp_aisAFTER INSERT ON TEMPBEGINdbms_output.put_line(‘executing temp_ais‘);END;看⼀下下⾯语句的结果:SQL> set feedback offSQL> INSERT INTO temp VALUES (1); -- insert 1 rowexecuting temp_aisSQL> INSERT INTO temp VALUES (1); -- insert 1 rowexecuting temp_aisSQL> INSERT INTO temp SELECT * FROM temp; -- insert 2 rowsexecuting temp_ais每个SQL插⼊语句将触发⼀次,⾏级触发器最后⼀条语句要触发两次。
⼀、事件顺序⽤Insert 语句级触发器可以做:·可以在表上执⾏⼀个合计运算,可以在insert前或后来计算。
·可以使⽤语句级触发器去处理⾏级触发器控制的数据。
·可以给事件发信号。
可以仅仅是⼀个打印语句。
也可以是⼀个email或使⽤DBMS_ALERT包向其他处理过程发送信号。
Tasks PerformedStages ----------------------------------------------------- ———> | Rehect the |Fires once | BIS function | | Transaction |per statement | Statement Level Trigger | ------------------------------------------------------ ———> -------------------| | Take Action || -------------------insert |3⾏记录 | -------------------------- |————> | | Row Trigger | | -------------------------------————> | -------------------------- | |每⼀个⾏触发器插⼊⼀|————> | | | |⾏触发⼀次,插⼊三⾏|| ---------------------------------------- | |触发三次,语句级触发|| | Oracle enforces constraints | | |器在⾏操作和⾏数据上|| ---------------------------------------- | |不可见 || | | | || -------------------------- | -------------------------------| | Row Trigger | || -------------------------- ||| -------------------------------------------------------- ————> | Rehect the |Fires once | AIS function | | Transaction |per statement | Statement Level Trigger | ------------------------------------------------------- ————> --------------------| Take Action |--------------------上图显⽰了语句级出发器的⾏为。
触发器课堂练习11、当向SC表插入数据时,修改(或添加)SC_NUMBER(包括学生学号和选课门数两列)表格中的数据。
create or replace trigger tr_sc_AR_Iafter insert on scfor each rowbeginupdate sc_number set scnum=scnum+1where sno=:new.sno;if sql%notfound theninsert into sc_number values(:new.sno,1);end if;end;测试结果:2、当删除SC表中数据时,修改(或添加)SC_NUMBER中的数据。
create or replace trigger tr_sc_AR_Dafter delete on scfor each rowbeginupdate sc_number set scnum=scnum-1where sno=:old.sno;select scnum into pk_trigger.tr_scnum from sc_number where sno=:old.sno;if(pk_trigger.tr_scnum=0) thendelete from sc_number where sno=:old.sno;end if;end;测试结果:3、当修改SC表中数据时,若修改的是学号,则对应修改SC_NUMBER表中的选课门数,否则打印“某某(学生)的学生选课信息已经修改”信息。
create or replace trigger tr_sc_AR_Uafter update on scfor each rowbeginif(:old.sno = :new.sno) thenselect sname into pk_trigger.tr_sname from student where sno=:new.sno;dbms_output.put_line(pk_trigger.tr_sname||'的学生选课信息已经修改,由原课程'|| trim(:o)||'修改为新课程'||trim(:o));end if;if(:old.sno <> :new.sno) thenupdate sc_number set scnum=scnum+1where sno=:new.sno;if sql%notfound theninsert into sc_number values(:new.sno,1);end if;update sc_number set scnum=scnum-1where sno=:old.sno;select scnum into pk_trigger.tr_scnum from sc_number where sno=:old.sno;if(pk_trigger.tr_scnum=0) thendelete from sc_number where sno=:old.sno;end if;end if;end;测试结果:触发器课堂练习 21、修改STUDENT表数据时,限制不能修改学生的系别(不能修改CS系学生的系别)。
create or replace trigger tr_student_BR_U1before update of sdept on studentfor each rowwhen (old.sdept='CS') --old前没有":"beginraise_application_error(-20001,'不能修改CS系学生的系别!');end;测试结果:2、插入课程时,课程号以‘S’开头的课程的学分不能低于3分。
create or replace trigger tr_course_BR_Ibefore insert on coursefor each rowwhen (new.credit<3and o like'S%')beginraise_application_error(-20002,'S开头的课程学分不能低于3分!'); end;测试结果:3、不能删除90分以上学生的选课信息。
create or replace trigger tr_sc_BR_Dbefore delete on scfor each rowwhen (old.grade>90)beginraise_application_error(-20003,'不能删除90分以上学生的选课信息!'); end;测试结果:练习 11、插入Student表中数据时,CS系学生的年龄不能大于30岁。
create or replace trigger tr_student_BR_Ibefore insert on studentfor each row--when(new.sage>30 and new.sdept='CS')beginif(:new.sage>30and :new.sdept='CS') thenraise_application_error(-20004,'CS系学生的年龄不能大于30岁!');end if;end;测试结果:2、当修改Student表中的年龄字段时,使其只能增加,不能减少。
create or replace trigger tr_student_BR_Ubefore update of sage on studentfor each rowwhen (new.sage<old.sage)beginraise_application_error(-20005,'年龄只能增加不能减少!');end;测试结果:3、删除Student表中的学生信息时,判断在SC表中该学生的平均成绩是否高于60,若高于60,则不能删除,否则允许删除,同时删除SC表该学生对应的选课信息。
create or replace trigger tr_student_BR_Dbefore delete on studentfor each rowdeclareavg_score number;beginselect avg(grade) into avg_score from sc where sc.sno =:old.sno;if(avg_score > 60) thenraise_application_error(-20006,'不能删除平均分大于60的学生信息!');end if;if(avg_score <= 60) thendelete from sc where sc.sno=:old.sno;end if;end;测试结果:练习 2在Student表中添加列:sum_Grade(总成绩),avg_grade(平均成绩)。
在SC表中作一触发器,当添加,删除或修改一行之后,将该学生在Student表中的总成绩和平均成绩相应改变。
create or replace package pk_triggeristr_scnum smallint;--sc_number表中的当前选课数量tr_sname student.sname%type;tr_cno o%type;--记录正在更新的课程号tr_newsno sc.sno%type;--记录更新后的学生号tr_oldsno sc.sno%type;--记录更新前的学生号end pk_trigger;create or replace trigger tr_sc_BR_I_U_Dbefore insert or update or delete on scfor each rowbeginpk_trigger.tr_newsno := :new.sno;pk_trigger.tr_oldsno := :old.sno;end;create or replace trigger tr_sc_AL_I_U_Dafter insert or update or delete on scdeclarev_sum number;v_avg number;begin--更新变化之前的学生的总分和平均成绩select sum(grade),avg(grade) into v_sum,v_avg from sc where sno=pk_trigger.tr_oldsno;update student set sum_grade=v_sum,avg_grade=v_avg where sno=pk_trigger.tr_oldsno;--更新变化之后的学生总分和平均分select sum(grade),avg(grade) into v_sum,v_avg from sc where sno=pk_trigger.tr_newsno;update student set sum_grade=v_sum,avg_grade=v_avg where sno=pk_trigger.tr_newsno;end;测试结果:修改学号删除插入或修改(修改课程号时)选课信息时,若该课程的选课人数已满,则不允许操作,并抛出相应的错误提示。
create or replace package pk_triggeristr_scnum smallint;--sc_number表中的当前选课数量tr_sname student.sname%type;tr_cno o%type;--记录正在更新的课程号tr_newsno sc.sno%type;--记录更新后的学生号tr_oldsno sc.sno%type;--记录更新前的学生号end pk_trigger;create or replace trigger tr_sc_BR_IUbefore insert or update on scfor each rowbeginpk_trigger.tr_cno:=:o;end;create or replace trigger tr_sc_AL_IUafter insert or update on scdeclarev_snumber smallint;v_scnt smallint;begin--查询课程最大选课人数select snumber into v_snumber from course where o=pk_trigger.tr_cno;--查询当前选课人数select count(sno) into v_scnt from sc where o=pk_trigger.tr_cno;--如果选课人数已满,则抛出相应错误提示if(v_snumber < v_scnt) thenraise_application_error(-20008,'课程'||trim(pk_trigger.tr_cno)||'选课人数已满!');end if;end;测试结果:。