第五章游标和触发器
游标:
隐式游标:%FOUND, %NOTFOUND ,%ROWCOUNT
1.%FOUND 用法,只有在DML 语句影响一行或者多行时,%FOUND 属性才返回 TRUE。下列示例演示了 %FOUND 的用法:
begin
update employees2 set first_name = 'scott' where employee_id = 2;
if SQL%found then
dbms_output.put_line('数据已经更新');
-- dbms_output.put_line('rowCount = '||mrowcount);
else
dbms_output.put_line('数据没有找到');
end if;
end;
/
以下代码演示了创建了一个游标,返回employees2 表中 salary 大于300000 的记录,注意type 的使用:
declare
csalary employees2.salary%type;
cursor emp2_cursor is select salary from employees2 where salary >300000;
begin
open emp2_cursor ;
loop
fetch emp2_cursor into csalary;
exit when emp2_cursor%notfound;
dbms_output.put_line('csalary = '||csalary);
end loop;
end;
/
以下代码演示了创建了一个游标,返回employees2 表中 division_id=’SAL’ 的记录。
注意rowtype 的使用:
declare
cursor employee2_cursor is select * from employees2 where division_id='SAL';
myrecord employees2%rowtype;
begin
open employee2_cursor;
fetch employee2_cursor into myrecord;
while employee2_cursor%found loop
dbms_output.put_line('employee id ='||myrecord.employee_id);
dbms_output.put_line('first Name ='||myrecord.first_name);
dbms_output.put_line('last name ='||myrecord.last_name);
fetch employee2_cursor into myrecord;
end loop;
end;
/
以下代码演示了带参数的游标,根据division id 查询指定的记录:
declare
myrecord employees2%rowtype;
cursor emp_cursor(divisionid varchar2) is select * from employees2 where division_id =divisionid;
begin
open emp_cursor('&divisionid');
--loop
fetch emp_cursor into myrecord;
while emp_cursor%found loop
-- exit when emp_cursor%notfound;
dbms_output.put_line('employee id = '||myrecord.employee_id);
dbms_output.put_line('division id = ' ||myrecord.division_id);
dbms_output.put_line('first name = ' ||myrecord.first_name);
fetch emp_cursor into myrecord;
end loop;
close emp_cursor;
end;
/
以下代码演示了在创建游标时指定更新表中的字段。更新 employees2 表中的 first_name 字段:
set serveroutput on
declare
firstName varchar2(20);
cursor employees2_cursor is select first_name from employees2 where employee_id=1 for update of
first_name;
begin
open employees2_cursor;
loop
fetch employees2_cursor into firstName;
exit when employees2_cursor%notfound;
update employees2
set first_Name='jeff ' where current of employees2_cursor;
end loop;
close employees2_cursor;
commit;
end; /
触发器:
触发器是当特定事件出现时自动执行的存储过程
特定事件可以是执行更新的DML语句和DDL语句
触发器不能被显式调用
触发器的功能:
自动生成数据
自定义复杂的安全权限
提供审计和日志记录
启用复杂的业务逻辑
触发器的类型包括:行级触发器,语句级触发器、INSTEAD OF 触发器、模式触发器、数据库级触发器。
创建触发器语法:
CREATE [OR REPLACE] TRIGGER trigger_name
AFTER | BEFORE | INSTEAD OF
[INSERT] [[OR] UPDATE [OF column_list]]
[[OR] DELETE]
ON table_or_view_name
[REFERENCING {OLD [AS] old / NEW [AS] new}]
[FOR EACH ROW]
[WHEN (condition)]
pl/sql_block;
创建行级触发器,以下代码演示了插入或者修改 employees2 表中的first_name 如果等于 ‘scott’时触发器就会执行:
create or replace trigger tri_employees2
before insert or update of first_name
on employees2
referencing NEW as newdata OLD as olddata
for each row
when (newdata.first_name='scott')
begin
: newdata.salary :=20000;
dbms_output.put_line('new.salary:' || :newdata.salary);
dbms_output.put_line('old.salary:' || :olddata.salary);
end;
执行以上触发器:
insert into employees2 values(38,'SUP','WOR','scott','mp',50000);
或者:
update employees2 set salary=90000,first_name='scott' where employee_id=38;
以下代码针对数据完整性进行操作(删除dept 表中的ID 同时把外键表emp