pl/sql编程
------------------------pl/sql编程----------------------------
(procedual):oracle 在标准sql语言上的扩展
简单分类:
块(存储过程,函数,包,触发器)
declare --定义部分
begin --执行部分
exception ---异常处理部分
end; --结束
set serveroutput on --输出开关开启
1.-----------------------第一个块------------------------------------------------
declare
v_name varchar2(20);
begin
v_name:='王照陆爱编程'; -- (:= 赋值)
dbms_output.put_line(v_name);
end;
2.-------------------------------------------------------------------------------
declare
v_ename varchar2(20);
begin
select ename into v_ename from emp where empno=7788;
dbms_output.put_line(v_ename);
end;
3.------------------------------------------------------------------------------
例子:根据员工的编号,查询出姓名、工资,并把姓名和工资输出
declare
v_ename varchar2(20);
v_sal number(7,2);
begin
select ename,sal into v_ename, v_sal from emp where empno=&no; --&no:从键盘输入
dbms_output.put_line(v_ename || '------'|| v_sal);
end;
4.------------------------------------------------------------------------------
--插入一条数据,把插入的数据输出-----------------------------------------------------
----建表
create table wzl(
deptno number,
dname varchar2(20),
loc varchar2(10)
);
returning----用于语句中所影响到的数据行
into :把表中的信息赋予一个变量
--方法一:
insert into values(80,'dd','dd');
declare
v_deptno number;
v_dname varchar2(20);
v_loc varchar2(10);
begin
insert into wzl values(80,'dd','dd') returning deptno,dname,loc
into v_deptno,v_dname,v_loc;
dbms_output.put_line(v_deptno || '---'|| v_dname||'---'||v_loc);
end;
--方法二:
declare
v_info varchar2(30);
begin
insert into wzl values(80,'dd','dd') returning deptno||dname||loc into v_info;
dbms_output.put_line(v_info);
end;
--更新一条数据,把更新的数据输出----------------------------------------------------
declare
v_deptno number;
v_dname varchar2(20);
v_loc varchar2(10);
begin
update wzl set dname='王照陆' where dname='dd' returning deptno,dname,loc
into v_deptno,v_dname,v_loc;
update wzl set loc='南京' where loc='dd' returning deptno,dname,loc
into v_deptno,v_dname,v_loc;
dbms_output.put_line(v_deptno || '---'|| v_dname||'---'||v_loc);
end;
--删除一条数据,把删除的数据输出------------------------------------------------------
--复合类型、记录类型----------------------------------------------------------------
语法:
type 记录类型的名字 is record (
v1 type,
v2 type,
.....
);
--------------------------------------------------------------------------------
declare
type rec is record(
deptno number(4),
dname varchar2(20),
loc varchar2(10));
v_r rec;
begin
update wzl set deptno=80 where deptno=60 returning deptno,dname,loc
into v_r.deptno,v_r.dname,v_r.loc;
dbms_output.put_line(v_r.deptno || '---'|| v_r.dname||'---'||v_r.loc);
end;
--数组类型-----------------------------------------------------------------------
语法:
type 数组类型名 is varray (size)of date_type
declare
type array is varray(4) of varchar2(10);
v_a array;
begin
v_a:=array('dd','cc','ff','gg');--对数组的 赋值
dbms_output.put_line(v_a(1)||'--'||v_a(2)||'--'||v_a(3)||'--'||v_a(4));
dbms_output.put_line(v_a.first||'--'||v_a.last);
end;
first --取数组下标的最小值
last --取数组下标的最大值
--%type----------------------------------------------------------------
语法:
表名.字段名%type
--%rowtype-----------------------------------------------------------------------
--记录类型
用法:表%rowtype
--pl/sql的控制语句----------------------------------------------------------------
if 条件 then
elsif 条件 then
.........
else
end if;
-----------------
1.输入雇员的编号,查询雇员的工资,
如果工资小于1500,显示工资太低了
如果工资大于5000,显示工资太高了
declare
v_sal emp.sal%type;
v_comment varchar2(20);
begin
select sal into v_sal from emp where empno=&no;
if v_sal<1500 then v_comment:='工资太低了';
elsif v_sal>5000 then v_comment:='工资太高了';
end if;
dbms_output.put_line(v_comment);
end;
2.输入雇员的编号,查询出雇员的姓名和雇佣日期,
如果雇佣日期万元万余晚于1988-01-01,奖金是1600,
如果雇佣日期万元万余晚于1990-01-01,奖金是800,
其他情况,奖金是2400,请输出雇员的姓名,受雇日期和奖金
declare
v_info emp%rowtype;
v_bonus number(10);
begin
select * into v_info from emp where empno=&no;
if v_info.hiredate>to_date('1988-01-01','yyyy/mm/dd') then
v_bonus:=1600;
elsif v_info.hiredate>to_date('1990-01-01','yyyy/mm/dd') then
v_bonus:=800;
else
v_bonus:=2400;
end if;
dbms_output.put_line(v_info.ename||'--'||v_info.hiredate||'--'||v_bonus);
end;
--------------------------------------------------------------------------------
case 语句
case 条件表达式
when 结果1 then
when 结果2 then
...
else 结果
end case;
1.输入成绩,是A,输出excellent,
是B 输出verygood,
是C,输出good,
其他显示 no grade
declare
v_grade char(1):='&grade';
v_comment varchar2(10);
begin
case v_grade
when 'A' then v_comment:='excellent';
when 'B' then v_comment:='verygood';
when 'C' then v_comment:='good';
else v_comment :='no grade';
end case;
dbms_output.put_line(v_comment);
end;
--循环语句-----------------------------------------------------------------------
loop
语法:
loop .....
exit when 条件
end loop;
declare
v_int number:=1;
begin
dbms_output.put_line(v_int);
loop
v_int:=v_int+1;
dbms_output.put_line(v_int);
exit when v_int>=10;
end loop;
end;
------------------
while 循环
语法:
while 条件 loop
.........
end loop;
declare
v_int number:=1;
begin
while v_int<=10
loop
dbms_output.put_line(v_int);
v_int:=v_int+1;
end loop;
end;
------------------
for 循环
for 变量名 in [reverse] 最小值...最大值
loop
.....
end loop
变量名:名字,不需要定义,number
in:自动加1
in reverse :自动减1
begin
for v_int in reverse in 1...10
loop
dbms_output.put_line(v_int);
end loop;
end;
-----------练习题部分-------------------------------------------------------------
1、创建一张表,先向表中插入数据10,然后依次插入20到25的值2遍
create table temp_wzl(no number(3));
declare
v_num number(2):=10;
begin
insert into temp_wzl(no) values(v_num);
for v_i in 1..2 loop
for v_num in 20..25 loop
insert into temp_wzl(no) values(v_num);
end loop;
end loop;
end;
2、定义一个数组类型,并给这个数组类型赋值SALESMAN,CLERK,MANAGER,ANALYST并针对数组中的每个岗位,求出
该岗位的雇员人数,并输出岗位和人数
declare
type jobs_array is varray(4) of varchar2(20);
v_job jobs_array;
v_counter number(2);
begin
v_job:=jobs_array('SALESMAN','CLERK','MANAGER','ANALYST');
for i in v_job.first..v_job.last loop
select count(*) into v_counter from emp where job=v_job(i);
dbms_output.put_line(v_job(i)||'---'||v_counter);
end loop;
end;
3、求出100到110之间的素数
declare
v_num number(3):=100;
v_i number(3);
v_counter number(3):=0;
begin
while v_num<110 loop
v_i:=2;
loop
if mod(v_num,v_i)=0 then
v_i:=0;
exit;
end if;
v_i:=v_i+1;
exit when v_i>v_num-1;
end loop;
if v_i>0 then
v_counter:=v_counter+1;
dbms_output.put_line('第'||v_counter||'的素数'||v_num);
end if;
v_num:=v_num+1;
end loop;
end;
--块存储过程(procedure)---------------------------------------------------------
or replace --替换
create [or replace] procedure 存储过程的名字(arg1 {in|out|inout} type1,arg2 {in|out|inout} type2.....)
is|as
<变量,常量的声明>
begin
.....
exception
....
end;
模式
in:将实参的值传递给形参,进入存储过程的内部,但只能读不能写
out:会忽略调用的实参值,返回时,形参的值会赋予实参,(变量)
inout:
例:输入雇员名,返回雇员的工资
create or replace procedure sp1(spno in number,spsal out number)
is
begin
select sal into spsal from emp where empno=spno;
end;
exec 存储过程名();
call 存储过程名();
块中进行调用
declare
v1 number(7,2);
begin
sp1(7788,v1);
dbms_output.put_line(v1);
end;
---------------------------
create or replace procedure sp2(spno in number)
is
spsal emp.sal%type;
begin
select sal into spsal from emp where empno=spno;
dbms_output.put_line(spsal);
end;
--------------------------------------------------------------------------------
例:写一个过程,输入员工的编号,返回该雇员的姓名和工作
create or replace procedure sp1_wzl(spno number,spname out varchar2,spjob out varchar2) --in可以省略不写
as
begin
select ename,job into spname,spjob from emp where empno=spno;
end;
declare
v_name varchar2(10);
v_job varchar2(10);
begin
sp1_wzl(7788,v_name,v_job);
dbms_output.put_line(v_name||'---'||v_job);
end;
--函数---------------------------------------------------------------------------
create function 函数名(arg1 {in|out|inout} type1,arg2 {in|out|inout} type2.....)
is|as
<变量,常量的声明>
begin
.....
return expression;
exception
....
end;
输入雇员的编号,返回雇员的一年的总收入
create or replace function f1(spno number) return number
is
v_income emp.sal%type;
begin
select nvl2(comm,sal+comm,sal)*12 into v_income from emp where empno=spno;
return v_income;
end;
declare
v1 emp.sal%type;
begin
v1:=f1(7788);
dbms_output.put_line(v1);
end;
--------------------------------------------------------------------------------
例:写一个过程,输入员工的编号,返回该雇员的姓名
create or replace function f_name(spno number) return varchar2
as
v_name emp.ename%type;
begin
select ename into v_name from emp where empno=spno;
return v_name;
end;
declare
v1 emp.ename%type;
begin
v1:=f_name(7788);
dbms_output.put_line(v1);
end;
--游标(cursor)-----------------------------------------------------------------
分类:静态游标(显示游标、隐式游标)、动态游标
静态游标
显示游标(过程)
1、声明游标
cursor 游标名 is select 语句;
2、打开游标
open 游标名;
3、提取数据
fetch 游标名 into 变量(记录类型)
4、关闭游标
close 游标名;
游标的属性:
noutfound: 没有发现
found:发现
isopen:是否打开
rowcount:行数,访问或修改了多少条数据
用法: 游标名%属性