oracle_学习笔记04

一:PLSQL

/*
		PLSQL编程:procedure Language   过程语言  Oracle于SQL的一个扩展
		
		declare
		--声明变量
		变量名  变量类型:=初始值
		vsal    emp.sal%type  --因为不知道表中的变量类型,所以使用引用型变量
		vrow    emp%rowtype  --声明记录型变量
		begin 
			业务逻辑
		end;
		
		--输出语句:dbms_output.put_line(); 
*/

--test1
declare
  i varchar2(10):='zhugeliang';
begin
  dbms_output.put_line(i);
end;


--test2:查询员工编号为7369的员工工资,并且打印出来
declare 
    vsal emp.sal%type;
begin
    --select sal from emp where empno='7369'; 正常查询结果,下面的语句用into  赋值给变量
    select sal into  vsal from emp where empno='7369';
    dbms_output.put_line(vsal);

end;


--test3 查询员工7369的信息,并打印出来
declare 
       vrow emp%rowtype;
begin
       select * into vrow from emp where empno='7369';
       dbms_output.put_line('姓名:'||vrow.ename ||'--' ||'工资:'||vrow.sal); --不能用,分隔

end;
--end;结尾

二:条件判断

/*
PL条件判断
if then 
	业务逻辑;
elsif then
	业务逻辑;
elsif then
	业务逻辑;
else
	业务逻辑;
end if;

*/


--根据不同的年龄,输出相关内容

declare
       age number:=20;       
begin
  if age < 18 then
    dbms_output.put_line('小孩子');
    
  elsif age > 18  and age <=24 then
    dbms_output.put_line('青年人');
    
  elsif age > 24 and age < 40 then
    dbms_output.put_line('中年人');
       
  else
    dbms_output.put_line('老年人'); 
  end if;
  
end;

三:循环操作

/*
语法1:
	while 条件 loop
	...
	end loop;
	
语法二:
	for 变量  in 起始值..结束值 loop
	...
	end loop;
	
语法三:
	loop
		exit when 条件
			...
	end loop;

*/

--输出1-10 while循环
declare
  i number:=1;
begin
  while i  <=10 loop
    dbms_output.put_line(i);
    i := i + 1;
  end loop;
end;
--条件loop后面不要;,end loop;不要忘记
--i := i + 1;  不支持缩写


--输出1-10  for循环
declare

begin
  for i in 1..10 loop
    dbms_output.put_line(i);
    end loop;
end;
--for循环中  i 不需要声明

--loop循环
declare
       i number := 1;
begin
       loop 
         exit when i>10;
         dbms_output.put_line(i);
         i := i+1;
       end loop;
end;

--输出棱形
/*
输出m
	x:[-m,m]
	y:[-m,m]
	输出所有棱形满足条件: asb(x)+abs(y)<=m
	m取任意大于零值
	
  *  
 *** 
*****
 *** 
  *
	
*/

--输出棱形

declare
    m number := 2;
begin
    for x in -m..m loop
        for y in -m..m  loop
            if abs(x)+abs(y) <=m then
              dbms_output.put('*');
            else
              dbms_output.put(' ');
            end if;
        end loop;
            dbms_output.new_line();  --输出新行
    end loop;

end;

--输出倒三角
declare
    m number := 2;
begin
    for x in -m..m loop
        for y in -m..m  loop
            if abs(x)+abs(y) <=m and x>=0 then  --注意这里的条件1
              dbms_output.put('*');
            else
              dbms_output.put(' ');
            end if;
        end loop;
            dbms_output.new_line();  --输出新行
    end loop;

end;

--输出正三角
declare
    m number := 2;
begin
    for x in reverse -m..m loop         --注意这的条件2
        for y in -m..m  loop
            if abs(x)+abs(y) <=m and x>=0 then   --注意这里的条件1
              dbms_output.put('*');
            else
              dbms_output.put(' ');
            end if;
        end loop;
            dbms_output.new_line();  --输出新行
    end loop;

end;



四:游标

/*
	游标:用来查询结果集:
	
	语法:cursor 游标名[(参数名 参数类型)] is 查询结果集
	
	开发步骤:
		1:声明游标
		2:打开游标    open  游标名
		3:从游标中取数据  fetch   游标名 into  变量
						游标名%found:找到数据
						游标名%notfound:没有找到数据
		4:关闭游标   close 游标名
*/
--test1:输出员工表中所有的员工姓名和工资
declare 
  --声明一个游标
  cursor vrows is select * from emp;
  --声明变量
  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;
 
  --3:关闭游标
   close vrows;
end;

--output
姓名SMITH2工资:800
姓名ALLEN工资:1600
姓名WARD工资:1250
姓名JONES工资:2975
姓名MARTIN工资:1250
姓名BLAKE工资:2850
姓名CLARK工资:2450
姓名SCOTT工资:3000
姓名KING工资:5000
姓名TURNER工资:1500
姓名ADAMS工资:1100
姓名JAMES工资:950
姓名FORD工资:3000
姓名MILLER工资:1300


--test2:指定部门的所有员工信息
--声明一个变量记录一行数据
declare 
  --游标
  cursor vrows(dno number ) is  select * from emp where deptno = dno;
  --声明变量
  vrow emp%rowtype;
begin
  --1;打开游标,指定10号部门
  open vrows(10);
  --业务逻辑 2;从游标中提取数据
  --遍历循环获取数据
  loop
         fetch vrows into vrow;
         exit when vrows%notfound;
         
        dbms_output.put_line('姓名'||vrow.ename || '工资:' || vrow.sal); --注意语法
  
  end loop;
 
  --3:关闭游标
   close vrows;
end;

--output
姓名CLARK工资:2450
姓名KING工资:5000
姓名MILLER工资:1300

/*系统引用游标
1:声明游标:游标名 sys_refcursor 
2:打开游标: open  游标名 for  结果集
3:从游标中取数据
4: 关闭游标



*/
--输出员工表中所有员工姓名和工资
declare
  --声明系统引用游标
  vrows  sys_refcursor;
  --声明一个变量
  vrow emp%rowtype;

begin
  --1:打开游标
  open vrows  for select * from emp;
  --2:取数据
  loop
       fetch vrows into  vrow;
       exit when vrows%notfound;
       dbms_output.put_line('姓名'||vrow.ename || '工资:' || vrow.sal);
  end loop;
  --3:关闭游标
      close vrows;
  
end;


/*for循环遍历游标
不需要声明变量
不需要打开游标
不需要关闭游标
*/

--使用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 
   --1:打开游标
    open vrows;
   --2:循环取数据
    loop
    --获取数据
          fetch vrows into vrow;
          --退出条件
          exit when vrows%notfound;
          
          --3:根据不同的职位,涨工资:总裁涨1000,经理涨800,其它涨400
          if vrow.job ='PRESIDENT' then
             update emp set sal = sal + 1000 where empno = vrow.empno;  --注意这里使用empno来更新
          
          elsif  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;
   
   --4:关闭游标
   close vrows;
   --5:提交事务
   commit;

end;

select *from emp;  --查看是否更新

五: 存储过程

/*存储过程:实际上是封装在服务器上的一段PLSQL代码,已经编译好了的代码。
客户端调用存储过程,执行效率会非常高.

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

--声明一个变量:存储涨工资前的工资
--查询出当前的工资是多少
--打印张薪前的工资
--更新工资
--打印涨薪后的工资


create or replace procedure proc_updatesal(vempno in number,vnum in number)
is
--声明一个变量
       vsal number;
begin
       --查询当前的工资
       select sal into vsal from emp e  where e.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,1000);

--调用方式2:
declare

begin
  proc_updatesal(7788,-1000);

end;

-----------------------------------------------------------------------------------------------------

--指定员工的年薪
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;


--调用

declare
    vtotal number;   --声明一个变量保存年薪
begin
    proc_gettotalsal(7788,vtotal);   --传到存储过程的输出参数上
    dbms_output.put_line('年薪'||vtotal);
end;


六:存储函数

/*存储函数:实际上是封装在服务器上的一段PLSQL代码,已经编译好了的代码。
语法:
	create  [or replace ]  function  存储函数的名称(参数名  in|out 参数类型,参数名  in|out 参数类型,)
	return 参数类型
	is | as 
	--声明部分
	begin
		业务逻辑;
	end;


默认是in,必须要有return
存储过程和存储函数本质上没有任何区别
存储函数存在的意义是给存储过程调用
存储函数可以在SQL语句中直接调用

*/

--查询指定员工的年薪
--参数:员工的编号
--返回值:年薪


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;


select * from emp;

--调用存储函数
declare
       vsal number;
begin
       vsal:=func_getsal(7788);
       dbms_output.put_line(vsal);

end;

--调用存储函数
--查询员工姓名和他的年薪
select ename,func_getsal(EMPNO)  from emp;



七:触发器

/*
触发器:当用户执行了  insert|update|delete 这些操作之后,可以触发一系列其它的动作|业务逻辑
作用:在动作执行之前或者之后,触发业务处理逻辑
语法:
	create [or replace] trigger 触发器的名字
	before | after
	insert | update | delete
	on 表名
	[for each row]
	declare
	begin
	end;
*/
--插入新员工之后,出出一句话:welcome!
create or replace trigger tri_test1
after
insert
on emp
declare
begin
  dbms_output.put_line('Welcome!');
  
end;

insert into emp(empno,ename)  values(9528,'huaan');


/*触发器的分类:
  语句级触发器:不管影响多少行,都只会执行一次
  行级触发器:  影响多少行,就触发多少次  [for each row]  
  	:old 代表旧的记录,更新前的记录
    :new 代表新的记录,更新后的记录
  
  */
  
--判断员工涨工资后的工资一定大于涨工资前的工资
--触发器: before
--200->100
--旧的工资大于新的工资,爆出异常,不让它执行


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; 

update emp set sal= sal + 10;  --注意commit
select *from emp;

posted @ 2019-12-24 22:49  Noob52037  阅读(172)  评论(0编辑  收藏  举报