[oracle]存储过程入门

什么是存储过程

官方解释是这样的:存储过程是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,存储在数据库中,经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来调用存储过程。
我在初学存储过程的时候给我的感觉就很像是java、C#里的方法,能够传参以及反复调用,效率较高。

演示

第一个存储过程:无参数,无返回值。

无参的存储过程带不带小括号都可以。

create or replace procedure procDemo1--不带小括号
as
begin
  dbms_output.put_line('哈喽,第一个存储过程');
end;
--或者
create or replace procedure procDemo1()--带有小括号
as
begin
  dbms_output.put_line('哈喽,第一个存储过程');
end;

这就创建好了,可以在目录Procedures里找到这个存储过程。但是创建后仅仅是编译好了,我们需要使用的话还得调用。

存储过程有两种调用方式
第一种:无参的时候带不带小括号都可以

begin
  procDemo1;
end;
--或者
begin
  procDemo1();
end;

第二种:即便是无参也不能省略小括号

call procDemo1();

output输出结果为

哈喽,第一个存储过程

一般在PL/SQL窗口用第一种方式,在应用程序里用第二种方式,比如
hibernateDao.excuteSqlUpdate("{call procDemo1()}");

第二个存储过程:声明变量和赋值

在存储过程中声明的变量属于局部变量,只能在存储过程内部使用,声明变量写在关键字as和begin之间。

create or replace procedure procDemo2
as
  myName varchar2(20);
  myPetName varchar2(20):='笨笨';--可以在声明的时候就赋初始值
begin
  myName:='李大傻';
  dbms_output.put_line('我的名字叫'||myName||',我的宠物叫'||myPetName);
end;

call procDemo2();

output输出结果为

我的名字叫李大傻,我的宠物叫笨笨

第三个存储过程:带参数

create or replace procedure procDemo3(myName varchar2,myPetName varchar2)--注意:参数不能像声明变量一样指定长度,否则会编译出错。
as
begin
  dbms_output.put_line('我的名字叫'||myName||',我的宠物叫'||myPetName);
end;

call procDemo3('王二丫','毛毛');
--传实参还可以用另一种方式,即形参名=>实参变量名,但似乎不支持call调用。
begin
  procDemo3(myName=>'王二丫',myPetName=>'毛毛');
end;
--甚至可以不按照形参顺序来,只需要名字一一对应即可。
begin
  procDemo3(myPetName=>'毛毛',myName=>'王二丫');
end;

以上3种调用效果相同,output输出结果为

我的名字叫王二丫,我的宠物叫毛毛

第四个存储过程:入参和出参

在第三个存储过程中,并没有指定是入参还是出参,那么它既是入参又是出参,比如形参写法myName varchar2实际上就是myName in out varchar2的简写。
而在第四个存储过程中,则明确定义了是出参还是入参。
入参要使用关键字in,表明该参数只能拿来使用,但不能改变值;
出参要使用关键字out,需要在存储过程内部给它重新赋值。

这个存储过程用于计算两个数相加,并返回相加后的结果

create or replace procedure procDemo4(a_num1 in number,a_num2 in number,a_result out number)
as
begin
  a_result:=a_num1+a_num2;
end;

declare
  v_num1 number(5,2);
  v_num2 number(5,2);
  v_result number(6,2);
begin
  v_num1:=101.76;
  v_num2:=298.24;
  v_result:=0;
  dbms_output.put_line('调用存储过程前,v_num1='||v_num1||',v_num2='||v_num2||',v_result='||v_result);
  procDemo4(v_num1,v_num2,v_result);
  dbms_output.put_line('调用存储过程后,v_num1='||v_num1||',v_num2='||v_num2||',v_result='||v_result);
end;

output输出结果为

调用存储过程前,v_num1=101.76,v_num2=298.24,v_result=0
调用存储过程后,v_num1=101.76,v_num2=298.24,v_result=400
关于出参的研究

经过试验发现,如果不在存储过程内部给出参赋值的话,并不会导致编译错误,但是变量从传进存储过程那一刻起,就变成了null。

create or replace procedure procDemo4_1(a_result out number)
as
begin
  dbms_output.put_line('不进行任何操作');
end;

declare
  a_result number(6,2);
begin
  a_result:=99.85;
  if a_result is null then
    dbms_output.put_line('调用存储过程前:a_result is null');
  else
    dbms_output.put_line('调用存储过程前:a_result='||a_result);
  end if;
  procDemo4_2(a_result);
  if a_result is null then
    dbms_output.put_line('调用存储过程后:a_result is null');
  else
    dbms_output.put_line('调用存储过程后:a_result='||a_result);
  end if;
end;

output输出结果为

调用存储过程前:a_result=99.85
不进行任何操作
调用存储过程后:a_result is null

可以看到,存储过程内部不给出参赋值,导致外部变量的值变成了null。

关于入参的研究

入参不能赋值,否则造成编译错误。

create or replace procedure procDemo4_2(a_num in number)
as
begin
  a_num:=101.33;
end;

这个存储过程是不能成功创建的,此时编译报错信息如下。
在这里插入图片描述

第五个存储过程:查询表信息

准备数据

create table myFriends(
       id number(5) primary key,
       name varchar2(50) not null,
       age number(3) not null,
       hobby varchar2(100)
);
insert into myfriends values(1,'大明',28,'打炮');
insert into myfriends values(2,'黑狗',22,'看AV');
insert into myfriends values(3,'小黄',25,'健身');
insert into myfriends values(4,'老王',31,'拳击');
insert into myfriends values(5,'小花',18,'刷电视剧');
commit;
select * from myfriends;

在这里插入图片描述
创建存储过程并调用

create or replace procedure procDemo5(v_id in number)
as
  v_name myfriends.name%type;
  v_age myfriends.age%type;
  v_hobby myfriends.hobby%type;
begin
  select t.name,t.age,t.hobby into v_name,v_age,v_hobby from myfriends t where t.id=v_id;
  dbms_output.put_line('我的朋友名字='||v_name||',年龄='||v_age||',爱好='||v_hobby);
  exception when no_data_found then
    dbms_output.put_line('no_data_found异常');
end;

call procDemo5(2);

output输出结果为

我的朋友名字=黑狗,年龄=22,爱好=看AV

当select into查询不到数据时,会触发no_data_found异常,如下。

call procDemo5(6);

output输出结果为

no_data_found异常
还可以使用for循环进行遍历
create or replace procedure procDemo5_1
as
begin
  for friend in (select * from myfriends) loop
    dbms_output.put_line('我的朋友id='||friend.id||',名字='||friend.name||',年龄='||friend.age||',爱好='||friend.hobby);
  end loop;
end;

call procDemo5_1();

output输出结果为

我的朋友id=1,名字=大明,年龄=28,爱好=打炮
我的朋友id=2,名字=黑狗,年龄=22,爱好=看AV
我的朋友id=3,名字=小黄,年龄=25,爱好=健身
我的朋友id=4,名字=老王,年龄=31,爱好=拳击
我的朋友id=5,名字=小花,年龄=18,爱好=刷电视剧

第六个存储过程:增删改操作

注意:一般不在存储过程内部写commit或rollback,而是外部调用完后才写,这样可以比较好统一处理事务。

新增操作

sql%found为隐式游标属性,关于隐式游标详情见我另一篇博客https://blog.youkuaiyun.com/qq_20481125/article/details/101675668

create or replace procedure procDemo6(v_id myfriends.id%type,v_name myfriends.name%type,v_age myfriends.age%type,v_hobby myfriends.hobby%type)
as
begin
  insert into myfriends values(v_id,v_name,v_age,v_hobby);
  if sql%found then
    dbms_output.put_line('新增成功');
  else
    dbms_output.put_line('新增失败');
  end if;
  exception when dup_val_on_index then
    dbms_output.put_line('插入的id重复');
  when others then
    dbms_output.put_line('其他异常');
end;

begin
  procDemo6(6,'老铁',33,'踢足球');
  commit;
end;

output输出结果为

插入成功

此时表数据如下,发现确实成功新增了id=6这一条信息。
在这里插入图片描述

修改:根据id修改其他信息
create or replace procedure procDemo6_update(v_id myfriends.id%type,new_name myfriends.name%type,new_age myfriends.age%type,new_hobby myfriends.hobby%type)
as
begin
  update myfriends set name=new_name,age=new_age,hobby=new_hobby where id=v_id;
  if sql%found then
    dbms_output.put_line('修改成功');
  else
    dbms_output.put_line('修改失败');
  end if;
end;

begin
  procDemo6_update(6,'老李',40,'打篮球');
  commit;
end;

output输出结果为

修改成功

此时表数据如下,发现id=6的信息确实更新成功了。
在这里插入图片描述

删除:根据id删除
create or replace procedure procDemo6_delete(v_id myfriends.id%type)
as
begin
  delete from myfriends where id=v_id;
  if sql%found then
    dbms_output.put_line('删除成功');
  else
    dbms_output.put_line('删除失败');
  end if;
end;

begin
  procDemo6_delete(6);
  commit;
end;

output输出结果为

删除成功

此时表数据如下,发现id=6的信息不存在了。
在这里插入图片描述
存储过程入门的东西就那么多了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值