一: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;