oracle 学习笔记

/*
  游标 cursor 
*/
declare
  cursor c is   --声明游标时并不从数据库查询数据
    select * from emp ;
  v_emp c%rowtype;
begin
  open c;  --open游标才真正的查询数据保存到内存
  loop 
    fetch c into v_emp;
    exit when (c%notfound);
    dbms_output.put_line(v_emp.ename);
  end loop;
	close c;  --关闭游标
end;
/


declare
  cursor c is   
    select * from emp ;
  v_emp c%rowtype;
begin
  open c;    
  fetch c into v_emp;
  while(c%found) loop   
    dbms_output.put_line(v_emp.ename);
    fetch c into v_emp ;
  end loop;
	close c;  
end;
/




declare
  cursor c is   
    select * from emp ; 
begin
  for v_emp in c loop
      dbms_output.put_line(v_emp.ename);
  end loop;
end;
/


--带参数游标
declare
	cursor c(v_deptno emp.deptno%type,v_job emp.job%type) is
		select ename,sal from emp where deptno=v_deptno and job=v_job;
	--v_temp c%rowtype;
begin
	for v_temp in c(30,'CLERK') loop
		dbms_output.put_line(v_temp.ename);
	end loop;
end;
/
--可更新游标
declare
	cursor c is 
		select * from emp2 for update;
begin
	for v_temp in c loop
		if(v_temp.sal<2000) then
			update emp2 set sal=sal*2 where current of c ;
		elsif(v_temp.sal=5000) then
			delete from emp2 where current of c;
		end if;
	end loop;
	commit;
end;
/
/*
  存储过程 Procedure
  创建存储过程必须有create procedure权限
*/

--打开显示
set serveroutput on;
--创建一个存储过程
create or replace procedure p_update_emp
as 
	cursor c is 
		select * from emp for update;
begin
	for v_emp in c loop
		if(v_emp.deptno = 10) then
			update emp set sal=sal+10 where current of c;
		elsif(v_emp.deptno = 20) then
			update emp set sal=sal+20 where current of c;
		else
			update emp set sal=sal+50 where current of c;
		end if ;
	end loop;
	commit;
end;
/

--查询所有存储过程
/*
  这里比较好玩:根据一般数据字典表中的列命名,这里p_update应为procedure_name
  但是不是,它是object_name,procedure_name为空
*/
select * from user_procedures;

--执行存储过程 (方式一)
begin
  p_update_emp;
end;
--执行存储过程 (方式二)
exec p_update_emp;

--创建带参数存储过程
/*
	in : 表输入参数
	out: 表输出参数
	不加关键字的表示默认输入参数
	两个都加的既表示输入参数又表示输出参数

	注意:存储过程的参数只能指定类型,而不能指定大小
	如  v_a number(2)是错误的,正确为v_a number
*/
create or replace procedure p_in_out
	(v_a in number,v_b number,v_ret out number,v_temp in out number)
as
	begin
		if(v_a > v_b) then
			v_ret := v_a ;
		else
			v_ret := v_b ;
		end if ;
		v_temp := v_temp +1 ;
	end;
/

--执行带参存储过程
declare
	v_a number := 3 ;
	v_b number := 4 ;
	v_ret number;
	v_temp number := 5 ;
begin
	p_in_out(v_a,v_b,v_ret,v_temp);
	dbms_output.put_line(v_ret);
	dbms_output.put_line(v_temp);
end;
/
--结果打印 4 和 6 


--删除存储过程
drop procedure p_update_emp;  


declare 
  v_a number :=1;
  v_b number :=2;
  v_set number:=3;
  v_temp number :=4;
begin
  p_in_out(v_a,v_b,v_set,v_temp);
  dbms_output.put_line(v_set);
  dbms_output.put_line(v_temp);
end;
/
/*
  触发器 trigger
	触发器必须依附于表才能起作用
*/

--创建日志表 emp_log,用于记录对表emp的所有操作日志
create table emp_log
(
	uname varchar2(20),
	action varchar2(10),
	atime date
);

--创建触发器
/*
	触发条件:insert|delete|update 对某张表做插入|删除|更新的操作
	触发时间:after|before 操作之后|操作之前
	触发行:each row 操作影响一行触发一次,不写表求一次操作触发一次
*/
create or replace trigger trig
	after insert or delete or update on emp for each row
begin
	if inserting then
		insert into emp_log(uname,action,atime) values(USER,'insert',sysdate);
	elsif updating then
		insert into emp_log(uname,action,atime) values(USER,'update',sysdate);
	elsif deleting then
		insert into emp_log(uname,action,atime) values(USER,'delete',sysdate);
	end if ;
end;
/

--触发
update emp set sal=sal*2 where deptno=30;
delete from emp where empno = 7369 ;


--查看日志表
select * from emp_log;

--? : 有外键关系时,主表中的主键存在外表的引用关系,因此不能随意更新,但可以用触发器解决这个问题
    --如: update dept set deptno=99 where deptno=10

--删除触发器
drop trigger trig;

create or replace trigger trig
	after update on dept for each row
begin
	update emp set deptno = :NEW.deptno where deptno = :OLD.deptno ;
end;
/
/*
	通常一条update语句会产生新旧两个状态 :NEW代表新状态 :OLD代表旧状态
*/
update dept set deptno=99 where deptno=10;



原文地址:https://www.cnblogs.com/java20130726/p/3218314.html