三篇拿下oracle【篇三】

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jmkmlm123456/article/details/85224467

游标

是用来操作查询结果集,相当于是jdbc中的ResultSet;

语法:cursor 游标名 is 查询结果集
		
		开发步骤:
			1.声明游标
			2.打开游标  open name
			3.从游标中取数据 fetch name into 变量
					游标名%found :找到数据
					游标名%notfound :没有找到数据
			4.关闭游标  	close 游标名;
			
		系统引用游标:
			1.声明游标:游标名 sys_refcursor
			2.打开游标:open 游标名 for 结果集
			3.取数据
			4.关闭游标
	

例子

			
	---输出员工表所有员工姓名和工资(不带参数的游标)
		
		游标---结果集:所有员工
		声明一个变,用来记录一行数据 %rowtype
		
	declare
		--游标
		cursor vrows is select * from emp;
		--s声明变量,记录一行数据
		vrow emp%rowtype;
	begin
	--1.打开游标
		open vrows;
	--2.取数据
		loop
			fetch vrows into vrow;
			exit when vrows%notfound;
			dbms_output.put_line('姓名:'||vrow.ename||'工资:'||vrow.sal);
		end loop;
		close vrows;
	end;
		
	--输出指定部门下的员工姓名和工资(带参数)
	declare
		cursor vrows(dno number) is select * from emp where deptno = dno;
		vrow emp%rowtype;
	begin
	--指定10号部门
		open vrows(10);
		loop
			fetch vrows into vrow;
			exit when vrows%notfound;
			dbms_output.put_line('姓名:'||vrow.ename||'工资:'||vrow.sal);
		end loop;
		close vrows;
	end;
	

	--系统引用游标:
		declare
			vrows sys_refcursor;
			vrow emp%rowtype;
		begin
			open vrows for select * from emp;
			loop
				fetch vrows into vrow;
				exit when vrows%notfound;
				dbms_output.put_line('姓名:'||vrow.ename||'工资:'||vrow.sal);
			end loop;
			close vrows;
		end;
		
--使用for循环遍历游标(简化流程)
			不需要打开、关闭、声明游标;
	declare 
	--声明游标
		cursor vrows is select * from emp;
	begin
		for vrow in vrows loop
			dbms_output.put_line('姓名:'||vrow.ename||'工资:'||vrow.sal);
		end loop;
	end;
	
--按照员工工作给所有员工涨工资,总裁1000,经理800,其他400

	游标:所有员工
	声明一个记录一行数据
	
	declare
		cursor vrows is select * from emp;
		vrow emp%rowtype;
	begin
		open vrows;
		loop
			fetch vrows into vrow;
			exit when vrows%notfound;
			if vrow.job = 'PRESIDENT' then
				update emp set sal = sal+1000 where empno=vrow.empno;
			elseif vrow.job ='MANAGER' then
				update emp set sal = sal+800 where empno=vrow.empno;
			else
				update emp set sal = sal+400 where empno=vrow.empno;
			end if;
		end loop;
		close vrows;
		commit;
	end;

PLSql异常

例外(意外):程序运行过程中的异常

exception 
		--处理异常
		when 1 then
		when 2 then
		when others then

zero_divide:除0异常
value_error:类型转换异常
too_many_rows:查询多行记录,但是赋值给了rowtype记录一行数据变量
no_data_found:没有找到数据

自定义异常:
	异常名 exception;
	raise 异常名

存储过程

实际上是封装在服务器上的一段plsql代码片段,已经编译好的代码;
客户端调用存储过程,执行高效

语法:
	create [or replace] procedure 名称(参数名 in|out 参数类型,参数名 in|out 参数类型)
		is|as
			--声明部分
		begin
			--业务逻辑
		end;

–给指定员工长薪,并打印涨薪前后的工资
参数:in员工编号
参数:in涨多少
声明一个变量:存储涨工资前的工资
查询当前工资多少
打印涨工资前的工资
更新工资
打印涨薪后的工资

	create or replace procedure proc_updatesal(vempno in number,vnum in number)
	is
		--声明变量:记录当前工资
		vsal number;
		
	begin
		--查询当前工资多少
			select sal into vsal from emp where empno=vempno;
			dbms_output.put_line('涨薪前:'||vsal);
		--更新工资
			update emp set sal = vsal+vnum where empno =vempno;
		--输出涨薪后工资
			dbms_output.put_line('涨薪后:'||(vsal+vnum));
		--提交
		commit;
	end;
	
------**调用**:
	方式1:
		call proc_updatesal(7788,10);
	方式2:(常用)
	declare
	
	begin
		proc_updatesal(7788,-100);
	end;

存储函数

实际上是一段封装在oracle服务器中的一段plsql代码片段,它是已经编译好的代码片段;

语法:
		create [or replace] function 函数名称(参数名 in|out 参数类型) return 参数类型
		is|as
		
		begin
		
		end;

存储过程和函数的区别
1.本质上没有区别
2.函数存在的意义是给过程调用
3.函数可以在sql语句中直接调用
4.存储过程能实现的,存储函数也能实现;
默认是in

--查询指定员工年薪
	
	参数:员工编号
	返回:年薪
	
	create or replace function func_getsal(vempno number) return number
	
	is
		--声明变量,保存年薪
		vtotalsal number;
	begin
		select sal*12+nvl(comm,0) into vtotalsal from emp where empno=vempno;
		return vtotalsal;
	end;
	
	--调用存储函数
	declare
		vsal number;
	begin
		vsal = func_getsal(7788);
		dbms_output.put_line(vsal);
	end;
	
	--sql语句直接调用函数
	select ename,func_getsal(empno) from emp;
	
	--输出参数
	
	create or replace procedure proc_gettotalsal (vempno in number,vtotalsal out number)
	is
	
	begin
		select sal*12+nvl(comm,0) into vtotalsal from emp where empno = vempno;
	end;

触发器

当用户执行了 insert update delete 这些操作后,可以触发一系列动作

分类:
语句级触发器:不管影响多少行,都只会执行一次
行级触发器:影响多少行,就触发多少次 [for each row]
:old 代表旧的记录,更新前的记录
:new 代表更新后的记录

作用:
数据确认:插入数据,做一些校验
复杂性安全性
审计

语法:	
	create [or replace] trigger 触发器名称 
		before|after
			insert|update|delete  
				on 表名 [for each row]
	declare
				
    begin	
    	
	end;
--插入员工之后,输出一句话
	create or replace trigger tri_test1
		after
			insert
			on emp
		declare
		begin
			dbms_output.put_line('welcome');
		end;
		
--数据校验,星期六老板不在,不能办理新员工入职
	在插入数据之前,判断当前日期是否是周六,如果周六,就不能插入
	create or replace trigger tri_test2
	before
		insert
		on emp
	declare
		--声明变量:
			vday varchar2(10);
	begin
		--查询当前日期
		select to_char(sysdate,'day') into vday from dual;
		--判断当前日期:
		if vday = 'saturday' then
			dbms_output.put_line('老板不在,不能办理');
			--抛出系统异常
			raise_application_error(-20001,'老板不在,不能办理');
		end if;
	end;
	
--更新所有员工的工资
	create or replace trigger tri_test3
	after 
		update
		on emp
		for each row
	declare
		
	begin
		dbms_output.put_line('工资更新');  //输出多次
	end;
	
--判断员工涨工资后的工资大于涨工资前的工资(两个隐对象)
	触发器:before
		旧的工资
		新的工资
		如果旧工资大于新的工资,抛出异常,不让它执行
		
	create or replace trigger tri_updatesal
	before
		update
		on emp
		for each row
	declare
	begin
		if :old.sal > :new.sal then
			raise_application_error(-20002,'不执行');
		end if;
	end;

--模拟mysql中id自增长属性 auto_increment

	触发器:
	create table person(
		pid number primary key,
		pname varchar2(20)
	)
	insert into person values(null,'张三');//没有触发器,空值不能被插入
	
	--序列用途:写触发器
	create sequence seq_person_pid;
	
	--触发器
	create or replace trigger tri_add_person_pid
	before
	insert
		on person
		for each row
	declare
	begin
		dbms_output.put_line(:new.pname);
		--给新记录pid赋值
		select seq_person_pid.nextval into :new.pid from dual;
	end;

猜你喜欢

转载自blog.csdn.net/jmkmlm123456/article/details/85224467