Oracle PL/SQL (10) - 存储过程的创建和调用

子程序包括存储过程和函数。
子程序包括:
  1、声明部分:声明部分包括类型、游标、常量、变量、异常和嵌套子程序的声明。这些项都是局部的,在退出后就不复存在。
  2、可执行部分:可执行部分包括赋值、控制执行过程以及操纵ORacle数据的语句。
  3、异常处理部分:  异常处理部分包括异常处理程序,负责处理执行存储过程中出现的异常。

存储过程是执行某些操作的子程序,是执行特定任务的模块。从根本上讲,存储过程就是PLSQL块,它可以被赋予参数,存储在数据库中,然后由一个应用程序或其他PLSQL程序调用。

存储过程存放在数据库服务器中,而且是已经编译好的,且在服务器端执行,因此执行效率高;
存储过程把商业逻辑固化在存储过程中,还隐藏了数据,因此增强了数据安全性;
存储过程增加了程序开发的灵活性和模块化;
存储过程是存储在服务器端,且在服务器端执行,减少了网络通信量。

create or replace procedure 存储过程名称
(
--定义输入、输出参数--
参数名1 in 参数类型,
参数名2 in 参数类型,
参数名3 in 参数类型,
参数名4 out 参数类型
)
as
--定义变量--
--变量名 变量数据类型;如:
-- numCount integer; 
begin   
    --处理方法-
end;
CREATE OR REPLACE PROCEDURE 存储过程名(param1 in type,param2 out type)
 IS
 变量1 类型(值范围);
 变量2 类型(值范围);  
 BEGIN
   select count(*) into 变量1 from 表名 where 列名=param1;
   if (判断条件) then
     select 列名 into 变量2 from 表名 where 列名=param1;
     DBMS_OUTPUT.put_line('打印信息');
   Elsif (判断条件) then
     dbms_output.put_line('打印信息');
   Else
     Raise 异常名 (NO_DATA_FOUND);
   End if;
 Exception
     When others then
       Rollback;   
 END;

创建一个最简单的存储过程。

create or replace procedure pro_1(id varchar2)
is
   name varchar2(20); -- 声明一个变量
begin
   -- 以下就是存储过程的主体部分
   dbms_output.put_line('id:' || id || ' name:' || name);
end;

1、create or replace表示如果这个存储过程不存在就创建一个新的存储过程,而如果这个存储过程存在了,就覆盖这个存储过程;
2、id varchar2是传递的一个参数,默认是IN类型。
3、在存储过程(PROCEDURE)和函数(FUNCTION)中使用IS和AS并没有太大区别,在视图(VIEW)中只能用AS不能用IS,在游标(CURSOR)中只能用IS不能用AS。后面一般跟变量声明。
4、begin和end之间是PL/SQL程序体,其中exception来指定失败处理流程。
调用存储过程。
一般使用的比较多的是在PL/SQL中调用存储过程,在PL/SQL调用存储过程就好比调用一个函数一样,例如:

begin
   pro_1(00813045);
end;

查询存储过程

select * from user_source where name='pro_1';

查看存储过程的状态

select * from user_objects where object_name = 'pro_1';

删除存储过程

drop procedure pro_1;

对于参数的模式有以下三种:
IN参数
语法:参数名 IN 数据类型 DEFAULT 值;
定义一个输入参数变量,用于传递参数给存储过程。在调用存储过程时,主程序的实际参数可以是常量、有值变量或表达式等。DEFAULT 关键字为可选项,用来设定参数的默认值。如果在调用存储过程时不指明参数,则参数变量取默认值。在存储过程中,输入变量接收主程序传递的值,但不能对其进行赋值。

OUT参数
语法:参数名 OUT 数据类型;
定义一个输出参数变量,用于从存储过程获取数据,即变量从存储过程中返回值给主程序。
在调用存储过程时,主程序的实际参数只能是一个变量,而不能是常量或表达式。在存储过程中,参数变量只能被赋值而不能将其用于赋值,在存储过程中必须给输出变量至少赋值一次。

IN OUT参数
语法:参数名 IN OUT 数据类型 DEFAULT 值;
定义一个输入、输出参数变量,兼有以上两者的功能。在调用存储过程时,主程序的实际参数只能是一个变量,而不能是常量或表达式。DEFAULT 关键字为可选项,用来设定参数的默认值。在存储过程中,变量接收主程序传递的值,同时可以参加赋值运算,也可以对其进行赋值。在存储过程中必须给变量至少赋值一次。

实例1,没有参数的存储过程
根据不同的厂牌 把对应的车系数据输出

create or replace procedure series_cur_prc
 as
  v_sql long;
  v_vehicle_make_name   t_md_vehicle_make.vehicle_manuf_make_name%type;

 cursor cur_make is 
 select distinct s.vehicle_make_id  from t_md_vehicle_series s ;
 
 cursor cur_seriesinfo(v_make_id varchar2) is 
    select s.vehicle_series_name 
    from t_md_vehicle_series s where s.vehicle_make_id=v_make_id ;

begin
      for  M_CUR IN cur_make LOOP
        v_sql:='select m.vehicle_manuf_make_name  from t_md_vehicle_make m where m.vehicle_make_id='''||M_CUR.vehicle_make_id||'''';
        EXECUTE IMMEDIATE v_sql into  v_vehicle_make_name;
        DBMS_OUTPUT.PUT_LINE('--------------------------------------');
        DBMS_OUTPUT.PUT_LINE(v_vehicle_make_name || ':');
        for P_CUR IN cur_seriesinfo(M_CUR.vehicle_make_id) LOOP
              DBMS_OUTPUT.PUT_LINE('车系名称: ' || P_CUR.vehicle_series_name );
        end loop; 
      END LOOP;
end ;
--存储过程调用(下面只是调用存储过程语法)
BEGIN 
   series_cur_prc;
END;
image.png

输出结果:


image.png

实例2,仅带传入参数的过程
根据输入的车辆品牌 从表车系表中搜索符合要求的数据,并将其输出

create or replace procedure series_intype_pro(parm_make_name in t_md_vehicle_make.vehicle_manuf_make_name%type)
 as
  v_vehicle_make_name   t_md_vehicle_make.vehicle_manuf_make_name%type;

 cursor cur_make is 
 select  m.vehicle_make_id  from t_md_vehicle_make m where m.vehicle_manuf_make_name=parm_make_name;
 
 cursor cur_seriesinfo(v_make_id varchar2) is 
    select s.vehicle_series_id,s.vehicle_series_name 
    from t_md_vehicle_series s where s.vehicle_make_id=v_make_id ;

begin
      for  M_CUR IN cur_make LOOP
       
        DBMS_OUTPUT.PUT_LINE('--------------------------------------');
        DBMS_OUTPUT.PUT_LINE(parm_make_name || ':');
        for P_CUR IN cur_seriesinfo(M_CUR.vehicle_make_id) LOOP
              DBMS_OUTPUT.PUT_LINE('车系名称: ' || P_CUR.vehicle_series_name||'车系id: ' || P_CUR.vehicle_series_id);
        end loop; 
      END LOOP;
end ;

存储过程调用

declare
 v_vehicle_make_name   t_md_vehicle_make.vehicle_manuf_make_name%type; 
begin
 v_vehicle_make_name:='一汽大众';
 series_intype_pro(v_vehicle_make_name);
end;
image.png

输出结果:


image.png

代码解析:
第1~2行表示创建存储过程。存储过程包括IN类型的参数,表示该参数为输入类型的参数。此时可以省略关键字IN。
第3行表示声明存储过程的内部变量。其中,v_vehicle_make_name表示品牌名称。
第5~6行表示创建cur_make游标,通过品牌名称查询品牌ID。
第8~10行表示创建cur_seriesinfo游标,带参游标,通过传入的品牌ID查询车系表中对应的车系ID,名称
第12~16行表示循环cur_make游标,并输出品牌名称。
第17~19行表示cur_seriesinfo游标,并将品牌ID传入,根据品牌ID从车系表中中查询数据,并把得到的数据输出到屏幕。

实例3,带输入,输出参数的存储过程
根据输入的车辆品牌查询出对应的车辆品牌id,并将得到车辆品牌id放到输出参数中

create or replace procedure make_outype_pro
(
  parm_make_name in t_md_vehicle_make.vehicle_manuf_make_name%type,
  parm_make_id out t_md_vehicle_make.vehicle_make_id%type
)
 as
begin
        select  m.vehicle_make_id into parm_make_id from t_md_vehicle_make m where m.vehicle_manuf_make_name=parm_make_name; 
        DBMS_OUTPUT.PUT_LINE('车辆品牌: ' ||parm_make_name||'车辆品牌id: ' ||parm_make_id);
end ;

存储过程调用
根据输入的车辆品牌以及 车系id的部分 从表车系表 中查询符合要求的数据并输出到屏幕

create or replace procedure serise_clouttype_pro(
    parm_make_name in t_md_vehicle_make.vehicle_manuf_make_name%type,
    parm_series  varchar2
)
as  
  cursor cur_series(v_series_id t_md_vehicle_series.vehicle_series_id%type) is
    select s.vehicle_series_name from t_md_vehicle_series s where s.vehicle_series_id like v_series_id||'%';
  parm_make_id    t_md_vehicle_make.vehicle_make_id%type;
begin
   make_outype_pro(parm_make_name,parm_make_id);

   DBMS_OUTPUT.PUT_LINE('---------------------------------------------------------------');
  for S_CUR in cur_series(parm_series) loop
      DBMS_OUTPUT.PUT_LINE('车系名称: ' ||S_CUR.vehicle_series_name);
  end loop;

end;

测试调用


image.png

输出结果:


image.png

实例4,在存储过程调用函数
创建加、减、乘、除计算的存储过程
输入参数: 数字1,数字2,计算类型
输出参数: 数字3

create or replace function fun_Test(num_1  in number, num_2 in number, num_3 in number)
return number
as
 num_A   number:=num_1;
 num_B   number:=num_2;
 numType number:=num_3;
 num_C   number;
begin
if numType=1 then
      return num_C := num_A + num_B;
    elsif numType=2 then
      return num_C := num_A - num_B;
    elsif numType=3 then
     return  num_C := num_A * num_B; 
    elsif numType=4 then
     return  num_C := num_A / num_B; 
    end if;
END fun_Test;

create or replace procedure Proc_Test1
(
--定义输入、输出参数--
num_A in integer,
num_B in integer,
numType in integer,
num_C out integer
)
as
--定义变量--
-- numStr varchar(20);  
begin   
    --调用函数 并赋值到num_C
    num_C:=fun_Test(num_A,num_B,numType);
end;

--调用存储过程---
declare 
  num_C integer;
begin
  Proc_Test1(12,2,4,num_C);
  dbms_output.put_line('输出结果:'|| num_C);
end;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,045评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,114评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,120评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,902评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,828评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,132评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,590评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,258评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,408评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,335评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,385评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,068评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,660评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,747评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,967评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,406评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,970评论 2 341

推荐阅读更多精彩内容