一、PL/SQL编程语言
- pl/编程语言是对sql语言的扩展,使得sql语言具有过程化编译的特性。
- pl/编程语言比一般的过程化编程语言,更加灵活高效。
- pl/编程语言主要用来编写存储过程和存储函数
1、声明方法
赋值操作 : (:=)或者(into查询语句)两种方式赋值。
例:引用型变量(type)和记录型变量(rowtype)的使用
set serveroutput on
declare
i number(2) :=10;
s varchar2(10) :='小明';
ena emp.ename%type;-- 引用型变量
emprow emp%rowtype;--记录型变量
begin
dbms_output.put_line(i);
dbms_output.put_line(s);
select ename into ena from emp where empno=7499;
dbms_output.put_line(ena);
select * into emprow from emp where empno=7499;
dbms_output.put_line(emprow.ename||'的工作为:' ||emprow.job);
end;
2、pl/sql中的if判断语句
通用句式:(条件语句中必须要以end if结束,并且只有这里加分号、可以省去elsif和else,类似于java)
declare
begin
if then
elsif then
else
end if;
end;
例:
输入小于18的数字,输出未成年
输入小于40大于18的数字,输出中年人
输入大于40的数字,输出老年人
set serveroutput on
declare
x number(3):=&xx;
begin
if x<18 then
dbms_output.put_line('未成年');
elsif x<40 then
dbms_output.put_line('中年人');
else
dbms_output.put_line('老年人');
end if;
end;
3、pl/sql中的loop循环
三种循环方式输出1-10
1、while循环
set serveroutput on
declare
i number(2):=1;
begin
while i<11 loop
dbms_output.put_line(i);
i :=i+1;
end loop;
end;
2、exit循环(重点掌握)
set serveroutput on
declare
i number(2):=1;
begin
loop
exit when i>10;
dbms_output.put_line(i);
i:=i+1;
end loop;
end;
3、for循环
set serveroutput on
declare
i number(2):=1;
begin
for i in 1..10 loop
dbms_output.put_line(i);
end loop;
end;
三种循环输出结果相同:
3、游标
游标:可以存放多个对象,多行记录。
例:输出emp表中所有员工的姓名。
set serveroutput on
declare
cursor c1 is select * from emp;
emprow emp%rowtype;
begin
open c1;
loop
fetch c1 into emprow;
exit when c1%notfound;
dbms_output.put_line(emprow.ename);
end loop;
close c1;
end;
例:给制定部门员工涨工资
set serveroutput on
declare
cursor c2(eno emp.deptno%type) is select empno from emp where deptno=eno;
en emp.empno%type;
begin
open c2(10);
loop
fetch c2 into en;
exit when c2%notfound;
update emp set sal=sal+100 where empno=en;
commit;
end loop;
close c2;
end;
查询emp表中部门号为10的员工信息
再一次查询emp表就会发现给部门号为10的涨了100工资。
4、存储过程
存储过程:提前已经编译好的一段pl/sql语言,放置在数据库端,可以直接被调用。(这一段pl/sql一般都是固定步骤的业务)
例:给指定员工涨100工资
create or replace procedure p1(eno emp.empno%type)
is
begin
update emp set sal=sal+500 where empno=eno;
commit;
end;
or replace作用:没有时 --> 创建这个过程。有重名时 --> 替换为现在的。(保证能够每次都创建、使用or replace时,其它用户在该函数上的权限不会丢失和变化)
测试p1:
declare
begin
p1(7499);
end;
out类型参数使用方法:
例:使用存储过程来计算年薪
create or replace procedure p_yearsal(eno emp.empno%type,yealsal out number)
is
s number(10);
c emp.comm%type;
begin
select sal*12,nvl(comm,0) into s,c from emp where empno=eno;
yealsal := s+c;
end;
测试P_YEARSAL:
declare
yealsal number(10);
begin
p_yearsal(7499,yealsal);
dbms_output.put_line(yealsal);
end;
in 和 out 类型参数的区别是什么?
凡是涉及到into查询语句赋值、:= 操作的参数,都必须使用out来修饰。
5、存储函数
存储过程和存储函数的参数都不能带长度
存储函数的返回值类型不能带长度
例:通过存储函数实现计算指定员工的年薪
在oracle中,null与数字相加减,结果为null。所以需要nvl()函数将comm去除null值。
create or replace function f_yearsal(eno emp.empno%type) return number
is
s number(10);
begin
select sal*12+nvl(comm,0) into s from emp where empno =eno;
return s;
end;
测试函数(F_YEARSAL):
函数在调用的时候,返回值需要接收
declare
s number(10);
begin
s:=f_yearsal(7499);
dbms_output.put_line(s);
end;
存储过程和存储函数的区别:
- 语法区别:
关键字不一样(存储函数比存储过程多了两个return) - 本质区别:
存储函数有返回值,存储过程没有返回值。
如果存储过程想实现有返回值的业务,我么就必须用out类型的参数。
即便是存储过程使用了out类型的参数,本质也不是真的有了返回值。
而是在存储过程内部给out类型参数赋值,再执行完毕后,我们直接拿到输出类型的值。
案例需求:查询出员工姓名,员工所在部门名称。(我们可以使用存储函数有返回值的特性,来自定义函数.存储过程不能用来自定义函数。)
1、传统方式来实现:
select e.ename,d.dname
from emp e,dept d
where e.deptno=d.deptno;
2、使用存储函数来实现提供一个部门编号,输出一个部门名称。
create or replace function fdna(dno dept.deptno%type) return dept.dname%type
is
dna dept.dname%type;
begin
select dname into dna from dept where deptno=dno;
return dna;
end;
测试(fdna存储函数来实现案例需求):
select e.ename,fdna(e.deptno)
from emp e;