plsql

plsql 高级的笔记

程序结构

declare

begin
--程序开始 可以写sql+选择结构 +循环结构
--'你好 world' system.out.print('你好 world')
--程序包       类似于     java 类
--存储过程               方法
dbms_output.put_line('你好 world');--输出语句
end;

声明变量

declare
	sname varchar2(10);
begin
--第一种方法
--java 赋值 用==   oracle 用 := 
   sname :='tom';

--第二种方法 select 列名 into 变量名 from 表名 
select s.sname into sname from student where sno=108;
dbms_output.put_line(sname);
end;

引用变量

--%type 变量的类型和制定的列的类型是一致的
sname student.sname%type;
--%rowtype
stu stuednt%rowstudent;

declare
   sname student.sname%type ;
   stu student%rowtype; 
begin
  select * into stu from student s where sno=108;
  dbms_output.put_line(stu.sno||'==》'|| stu.sname); 
end;

选择结构 if

一般写完if 一定要先写end if ; 后面很容易忘记不写

declare
	snum number:=3;
begin
	if snum>2 then 
		dbms_output.put_line(snum||'大于2');
	end if;	
end;

if else

declare
	snum number:=3;
begin
	if snum>2 then 
		dbms_output.put_line(snum||'大于2');
	else
    	dbms_output.put_line(snum||'小于2');
    end if;	
end;

if else ifelse 结构

/*
if 条件 then 代码块1;
	elsif 条件 then 代码块2;
    	elsif 条件 then 代码块3;
end if;
*/
declare 
snum number :=1; 
begin
  if snum>2then dbms_output.put_line(snum||'大于2');
    elsif snum>0 then dbms_output.put_line(snum||'大于0');
    else
         dbms_output.put_line(snum||'小于等于0');
  end if;
end;

循环

declare
	snum number :=1;
begin 
	loop
	--exit when 退出循环条件
	exit when snum>5;
	dbms_output.put_line(snum);
	snum:=snum+1;
	end loop;
end;

作业 :从1开始累加 当综合大于20 输出最后一个数

declare
	ssum number :=0;
	i number :=0;
begin
	loop
		exit when ssum>20;
		ssum:=ssum+i;--当结果在这里大于20的时候 接下来的一步会给i再加1  所以输出结果时  i就要减1
		i:=i+1
	end loop;
	dbms_output.put_line(i-1)
end

游标

1.游标:类似于集合,可以存储一组记录

  1. 语法 : cursor 游标 is 查询语句
declare
	cursor c_emp is select  tno,tname from emp;  --创建游标
	tno emp.tno%type;
	tname emp.tname%type;
begin
	--1.打开游标
	open c_emp;
	--2.循环游标取值
	loop
	fetch c_emp into tno,tname ;  ---fetch   into 取值
	exit when c_emp%notfound; ---当为true时 退出循环
	dbms_output.put_line(tno||'==>'||tname)
	end loop;
	--3.关闭游标
	close c_emp;

end;

带参数的游标

declare
     --               参数        参数类型
     cursor c_teacher(dno teacher.deptno%type) is select tno,tname,deptno from teacher where deptno=dno;
     tno teacher.tno%type;
     tname teacher.tname%type;
     deptno teacher.deptno%type;
begin
  --打开游标   传入参数 从这个部门里选择
  open c_teacher(20);
       loop
         fetch c_teacher into tno,tname,deptno;
         exit when c_teacher%notfound;
         dbms_output.put_line(tno||'==>'||tname||'==>'||deptno);
       end loop; 
   --关闭游标    
  close c_teacher;
  
end;

练习:统计scott用户下emp表每年入职的人数[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ta4Q4B0W-1593432183367)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20200628204638674.png)]

declare
  cursor c_emp is select to_char(hiredate,'yyyy') from emp;
  ccount1980 number :=0;
  ccount1981 number :=0;
  ccount1987 number :=0;
  ccount1982 number :=0;
  acount varchar2(4);
  
begin
  open c_emp;
  loop
    fetch c_emp into acount;
    exit when c_emp%notfound;
    if acount='1980' then  ccount1980:=ccount1980+1  ;
    elsif acount='1981' then ccount1981:=ccount1981+1 ;
    elsif acount='/1982' then ccount1982:=ccount1982+1;
    elsif acount='1987' then ccount1987:=ccount1987+1 ;
    end if;
  end loop;
  close c_emp;
   dbms_output.put_line('1980出生的人数' ||'==>'||ccount1980);
   dbms_output.put_line('1981出生的人数' ||'==>'||ccount1981);
    dbms_output.put_line('1982出生的人数'||'==>'||ccount1982);
    dbms_output.put_line('1987出生的人数'||'==>'||ccount1987);
end;

select *from teacher

游标属性

属性名称说明
%found用于检验游标是否成功,通常在FETCH语句前使用,当游标按照条件查询出一条记录时,返回true
%isopen判断游标是否处于打开状态,视图打开一个已经打开或者已经关闭的游标,将会出现错误
%notfound与%found的作用相反,当按照条件无法查询到记录时,返回true
%rowcount循环执行游标读取数据时,返回检索出的记录数据的行数

异常

--预定异常
declare
  i number ;
  when exception zero_divide then dbms_output.put_line('除数不能为0 ');
  --others  类似于最大的异常类型
  when others then dbms_output.put_line('未知异常 ');
begin 
  i:=1/0;
  
end;

自定义异常

declare
  cursor c_teacher is select tno,tname,deptno from teacher where deptno=60; --创建游标
  ttno teacher.tno%type;--创建变量
  ttname teacher.tname%type;
  ddeptno teacher.deptno%type;
  --变量的类型时 exception 这个变量就是异常变量
  no_deptno_date exception;  --自定义异常
begin
  open c_teacher;
       fetch c_teacher into ttno,ttnae,ddeptno;
             --throw  ==raise  都是抛异常的意思
       if c_teacher%notfound then raise  no_deptno_date;
       end if;
  
  close c_teacher;
  exception when  no_deptno_date then dbms_output.put_line('该部门编号没有老师 ');
end;

存储过程

无参存储

create or replace procedure sayHelloWorld
--  is  as  相当于 declare
is 
begin
	dbms_output.put_line('HelloWorld ');
end;

--调用存储过程

begin
sayHelloWorld();   --无参存储过程 在创建的时候不用括号  调用的时候要带上括号
end

带参存储

--带参数存储过程 根据tno输出教师的名字和薪水   参数名 参数类型 参数的数据类型
--in  输出参数 接收外界的值
--out 输出参数 将方法内的值返回到方法调用位置
create or replace procedure findTeacherBytno(
teano in teacher.tno%type
)
is
teaname teacher.tname%type;
teasal teacher.sal%type;
bgein
	select tname,sal into teaname,teasal from teacher where tno=teano;
	dbms_output.put_line('teaname||'=='||'teasal' ');
end;


--调用
declare 
bgein
	findTeacherBytno(1002);--类似Java  调用方法 传参数
end;

带两个参数

--带两个参数   
--根据tno找到教师  增加工资
create or replace procedure addsal(teatno in teacher.tno%type,money in number)
is
--teatno teacher.tno%type;
begin
  update teacher set sal=sal+money where tno=teatno;
  end;
  
--diaoyomg
declare
begin
  addsal(1002,200);
  commit;--谁调用谁提交事务
  end;

存储函数

存储函数 和存储过程语法基本是一样的

存储函数和存储过程最大的区别就是 存储函数有一个返回值

根据tno查询教师年薪

create or replace function getIncome(teatno in teacher.tno%type)
return number;
is
tsal teacher.sal%type;
tcomm teacher.comm%type;
begin
  select sal,comm,into tsal,tcomm from teacher where tno=teatno;
  return tsal*12+nvl(tcomm,0);
end;  

declare 
begin 
  getIncome(1002);
end;

触发器

​ 与一张表关联 对标执行 insert update delete

​ 1.语句级触发器 执行sql语句 触发器只执行一次 sql语句更新了多少条记录 触发器都执行一次

 create or replace trigger showInfo
 after insert  on teacher
 declare
 begin
   dbms_output.put_line('插入成功!');
 end;

​ 2.行级触发器 sql更新了多少条数据触发器就执行多少次

​ x相比语句触发器多加了 for each row

  create or replace trigger testType
 after update
 on teacher
 for each row
 declare 
 begin
   dbms_output.put_line('testType触发器执行');
 end;  
 
 update teacher set comm=1000;

案例

		**禁止在非工作时间插入新老师信息**
 create or replace trigger checkDay
 before insert --修改数据用的before
 on teacher --作用于 老师表
 declare    --去空格               得到今天是星期几
    --select rtrim(tochar(sysdate,'day')) into today from dual
    today varchar2(20);

 begin
   select rtrim(tochar(sysdate,'day')) into today from dual;--赋值给today
   if today='monday' then  raise_appliaction_error(-20005,'周一不能插入,放假'); --声明异常 
   end if;
 end;

三大范式

  1. 第一范式:确保每列的原子性
  2. 第二范式:确保表中每列都和主键相关
  3. 第三范式:确保每列都和主键直接相关,而不是间接相关

事务

事务时绑定在一个任务单元的一些sql语句,目的是为了保证这些sql语句同时运行成功,则提交事务,如果有一个不成功,则事务回滚。

事务的四大特性(acid) :

  1. 原子性 不可分割sql语句组中 的sql执行时不能分割必须同时成功同时失败
  2. 一致性 数据库必须是从一个一致性状态到另一个一致性状态
  3. 持久性 事务一旦提交 对数据就是永久的
    nto today from dual;–赋值给today
    if today=‘monday’ then raise_appliaction_error(-20005,‘周一不能插入,放假’); --声明异常
    end if;
    end;



# 三大范式 

1. 第一范式:确保每列的原子性
2. 第二范式:确保表中每列都和主键相关
3. 第三范式:确保每列都和主键直接相关,而不是间接相关

# 事务

事务时绑定在一个任务单元的一些sql语句,目的是为了保证这些sql语句同时运行成功,则提交事务,如果有一个不成功,则事务回滚。

事务的四大特性(acid) :

1. 原子性 不可分割sql语句组中 的sql执行时不能分割必须同时成功同时失败
2.  一致性 数据库必须是从一个一致性状态到另一个一致性状态
3.  持久性 事务一旦提交 对数据就是永久的
4. 隔离性 一个事务和其他事务之间不能互相干扰
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值