存储过程基本语法

来源:互联网 发布:网络电影赵奕欢 编辑:程序博客网 时间:2024/05/27 19:27
存储过程

    存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。

详见 http://baike.baidu.com/view/68525.htm

    CREATE OR REPLACE PROCEDURE 存储过程名

   IS

   BEGIN

  4  NULL;

   END;

行1:

  CREATE OR REPLACE PROCEDURE 是一个SQL语句通知Oracle数据库去创建一个叫做skeleton存储过程, 如果存在就覆盖它;

行2:

  IS关键词表明后面将跟随一个PL/SQL体。

行3:

  BEGIN关键词表明PL/SQL体的开始。

行4:

  NULL PL/SQL语句表明什么事都不做,这句不能删去,因为PL/SQL体中至少需要有一句;

行5:

  END关键词表明PL/SQL体的结束

存储过程创建语法:

存储过程
语法:
create [or replace] procedure pro_name[(par list)]
as|is
    声明存储过程的变量;
begin
    存储过程执行语句;
end [pro_name];

注意事项:

1, 存储过程参数不带取值范围,in表示传入,out表示输出

类型可以使用任意Oracle中的合法类型。

2,  变量带取值范围,后面接分号

3,  在判断语句前最好先用count(*)函数判断是否存在该条操作记录

4,  用select 。。。into。。。给变量赋值

5,  在代码中抛异常用 raise+异常名

 

例如:为员工编号为7369员工的工资添加200

----1.不带参数的存储过程
create or replace procedure pro_addsal
is
begin
     update emp set sal=sal+200 where empno=7369;
     dbms_output.put_line('add ok!'); 
end pro_addsal;


---调用存储过程
1.PL/SQL---如果带有参数,无效
  call pro_addsal();
2.PL/SQL块中调用
begin
   pro_addsal();
end;
3.在SQL/PLUS中调用
 execute pro_addsal();

 

----2.带参数的存储过程
create or replace procedure pro_addsal(myempno emp.empno%type)
is
begin
   update emp set sal=sal+300 where empno=myempno;
   dbms_output.put_line('add2 ok!');
end;
--测试
declare
   myempno emp.empno%type;
begin
   ---实际参数
   myempno := &请输入员工编号;
   pro_addsal(myempno);
end;

 

----根据输入员工编号获得对应员工姓名
create or replace procedure pro_getName(myempno in emp.empno%type,myename out emp.ename%type)
is
begin
       select ename into myename from emp where empno=myempno;
       dbms_output.put_line('员工姓名--'|| myename);
end;

---测试
declare
   myename emp.ename%type;
begin
   pro_getName(7369,myename);
   dbms_output.put_line('姓名--' || myename);
end;

 

----根据输入部门编号,显示对应部门员工信息
create or replace procedure pro_getEmp
is
---定义游标
cursor mycur is select * from emp where deptno=20;
myemprow emp%rowtype;
begin
     ---打开游标   
     open mycur;
     loop
         ---读取数据
         fetch mycur into myemprow;
         exit when mycur%notfound;
         dbms_output.put_line('编号--'||myemprow.empno||'姓名--'||myemprow.ename);
     end loop;   
     --关闭游标
     close mycur;
end;

---测试
begin
    pro_getEmp();
end;

 

函数

语法:

create or replace function fun_name[(参数列表)] return 数据类型
is|as
本地变量声明
begin
   执行语句;
end;
注意:
1.函数的参数只能输入参数 in
2.函数必须有返回值

create or replace function fun_addNum(a int,b int) return int
is
  nresult int;
begin
  nresult := a + b;
  return nresult;
end fun_addNum;

---函数调用(1.可以通过select 语句调用)
select fun_addNum(1,1) from dual;
---2.在PL/SQL中调用
declare
   nsum int ;
begin
   nsum := fun_addNum(23,12);
   dbms_output.put_line('nsum='||nsum);
end;

 

程序包

语法:

程序包:包头和包体组成
包头:声明部分
包体:实现部分
创建包头语法:
create or replace package 包头的名称
is|as
   存储过程和函数等对象的声明部分
end ;
创建包体语法:
create or replace package body 包头的名称
is|as
   存储过程的实现和函数的实现部分
end;

---创建包头
create or replace package pak_xiaoyi
is
  ---定义变量(在整个包是全局的)
  ncount int :=0;
  ---定义存储过程
  procedure pro_add(a int,b int);
  procedure pro_setCount(mycount int);
  ---定义函数
  function fun_add(a int,b int) return int;
  function fun_add(a int,b int,c int) return int;
  function fun_getCount return int;
end;


---创建包体
create or replace package body pak_xiaoyi
is
   ---存储过程实现      
   procedure pro_add(a int,b int)
   as
   ---定义存储过程中局部变量
   nsum int;
   begin
       nsum := a + b;
       dbms_output.put_line('nsum='|| nsum);      
   end pro_add;
   ---访问ncount存储过程
   procedure pro_setCount(mycount int)
   as
   begin
        ncount := mycount;    
   end pro_setCount;
  
   ---函数的实现
    function fun_add(a int,b int) return int
    as
    begin
       return a+b;
    end fun_add;  
    ---函数2的实现
    function fun_add(a int,b int,c int) return int
    as
    begin
      return a+b+c;
    end fun_add;
    ---访问ncount对应函数
    function fun_getCount return int
    as     
    begin
     return ncount;
    end fun_getCount;
   
end;


---测试  
begin
   ---调用包中存储过程(包.存储过程名称)
  pak_xiaoyi.pro_add(12,23);
end;

declare
   nsum int;
   ncount int := 10;
   ncount2 int;
begin
   nsum := pak_xiaoyi.fun_add(199,200,100);
   dbms_output.put_line(nsum);
   pak_xiaoyi.pro_setCount(ncount);
   ncount2 := pak_xiaoyi.fun_getCount;
   dbms_output.put_line(ncount2);
end;

 

自主事务

----显示编号为7369员工的工资
create or replace procedure pro_sub
is
 mysal emp.sal%type;
 ----子程序中事务自我独立
 PRAGMA AUTONOMOUS_TRANSACTION;
begin
    select sal into mysal from emp where empno=7369;
    dbms_output.put_line('子存储过程:' || mysal);
    ---事务回滚
    rollback; ---如果没有采用自主事务机制,子存储过程的事务会影响父程序中的事务
end pro_sub;

---父存储过程
create or replace procedure pro_parent
is
  mysal emp.sal%type;     
begin
   select sal into mysal from emp where empno=7369;
   dbms_output.put_line('修改之前:'|| mysal);
   update emp set sal=8888 where empno=7369;
   ---调用子存储过程
   pro_sub();
   select sal into mysal from emp where empno=7369;
   dbms_output.put_line('修改之后:'|| mysal);
end pro_parent;


---测试
begin
   pro_parent();
end;

 

 

oracle存储过程语法

、判断语句: 

if 比较式 then begin end; end if; 

create or replace procedure test(x in number) is 

begin 

        if >0 then 

         begin 

        := x; 

        end; 

    end if; 

    if then 

       begin 

        x: 1; 

    end; 

    end if; 

end test; 

For 循环 

For ... in ... LOOP 

-- 执行语句 

end LOOP; 

(1) 循环遍历游标 

create or replace procedure test() as 

Cursor cursor is select name from student; name varchar(20); 

begin 

for name in cursor LOOP 

begin 

 dbms_output.putline(name);  

end; 

end LOOP; 

end test; 

(2) 循环遍历数组 

 create or replace procedure test(varArray in myPackage.TestArray) as 

--( 输入参数varArray 是自定义的数组类型,定义方式见标题6) 

number; 

begin 

:= 1;  -- 存储过程数组是起始位置是从开始的,与java C++ 等语言不同。因为在Oracle 中本是没有数组的概念的,数组其实就是一张 

-- (Table), 每个数组元素就是表中的一个记录,所以遍历数组时就相当于从表中的第一条记录开始遍历 

for in 1..varArray.count LOOP      

dbms_output.putline('The No.'|| || 'record in varArray is:'||varArray(i));    

 end LOOP; 

end test; 

While 循环 

while 条件语句 LOOP 

begin 

end; 

end LOOP; 

E.g 

create or replace procedure test(i in number) as 

begin 

while 10 LOOP 

begin     

 i:= 1; 

end; 

end LOOP; 

 end test; 

、数组 

首先明确一个概念:Oracle 中本是没有数组的概念的,数组其实就是一张表(Table), 每个数组元素就是表中的一个记录。 

使用数组时,用户可以使用Oracle 已经定义好的数组类型,或可根据自己的需要定义数组类型。 

(1) 使用Oracle 自带的数组类型 

array; -- 使用时需要需要进行初始化 

e.g: 

create or replace procedure test(y out array) is 

 array;   

 begin 

:= new array(); 

:= x; 

end test; 

(2) 自定义的数组类型 自定义数据类型时,建议通过创建Package 的方式实现,以便于管理

create or replace package myPackage is 

   Public type declarations   type info is record(     name varchar(20),     number); 

  type TestArray is table of info index by binary_integer;   

-- 此处声明了一个TestArray 的类型数据,其实其为一张存储Info 数据类型的Table 而已,及TestArray 就是一张表,有两个字段,一个是name ,一个是。需要注意的是此处使用了Index by binary_integer 编制该Table 的索引项,也可以不写,直接写成:type TestArray is 

table of info ,如果不写的话使用数组时就需要进行初始化:varArray myPackage.TestArray; varArray := new myPackage.TestArray(); 

end TestArray; 

5. 游标的使用 Oracle Cursor 是非常有用的,用于遍历临时表中的查询结果。其相关方法和属性也很多,现仅就常用的用法做一二介绍: 

(1)Cursor 型游标不能用于参数传递) 

create or replace procedure test() is   

cusor_1 Cursor is select std_name from student where  ...;  --Cursor 的使用方式  cursor_2 Cursor; 

begin 

select class_name into cursor_2 from class where ...;  --Cursor 的使用方式

可使用For in cursor LOOP .... end LOOP; 来实现对Cursor 的遍历 

end test; 

(2)SYS_REFCURSOR 型游标,该游标是Oracle 以预先定义的游标,可作出参数进行传递 

create or replace procedure test(rsCursor out SYS_REFCURSOR) is 

cursor SYS_REFCURSOR; 

name varhcar(20); 

begin 

OPEN cursor FOR select name from student where ... --SYS_REFCURSOR 只能通过OPEN 方法来打开和赋值 

LOOP 

 fetch cursor into name   --SYS_REFCURSOR 只能通过fetch into 来打开和遍历 exit when cursor%NOTFOUND;              --SYS_REFCURSOR 中可使用三个状态属性:                                         ---%NOTFOUND( 未找到记录信息%FOUND( 找到记录信息                                        ---%ROWCOUNT( 然后当前游标所指向的行位置

 dbms_output.putline(name); 

end LOOP; 

rsCursor := cursor; 

end test; 

 

 

 

实例

下面写一个简单的例子来对以上所说的存储过程的用法做一个应用: 

现假设存在两张表,一张是学生成绩表(studnet) ,字段为:stdId,math,article,language,music,sport,total,average,step               

一张是学生课外成绩表(out_school), 字段为:stdId,parctice,comment 

通过存储过程自动计算出每位学生的总成绩和平均成绩,同时,如果学生在课外课程中获得的评价为,就在总成绩上加20 分。 

create or replace procedure autocomputer(step in number) is 

rsCursor SYS_REFCURSOR; 

commentArray myPackage.myArray; 

math number; 

article number; 

language number; 

music number; 

sport number; 

total number; 

average number; 

stdId varchar(30); 

record myPackage.stdInfo; 

number; 

begin 

:= 1; 

get_comment(commentArray); -- 调用名为get_comment() 的存储过程获取学生课外评分信息 

OPEN rsCursor for select stdId,math,article,language,music,sport from student where t.step step; 

LOOP 

fetch rsCursor into stdId,math,article,language,music,sport; exit when rsCursor%NOTFOUND; 

total := math article language music sport; 

for in 1..commentArray.count LOOP  

 record := commentArray(i);     

if stdId record.stdId then   

 begin      

 if record.comment 'A' then      

  begin          

 total := total 20;    

   go to next; -- 使用go to 跳出for 循环        

  end;     

end if;   

end;   

end if; 

end LOOP; 

<<continue>>  average := total 5; 

 update student set t.total=total and t.average average where t.stdId stdId; 

end LOOP; 

end; 

end autocomputer; 

-- 取得学生评论信息的存储过程 

create or replace procedure get_comment(commentArray out myPackage.myArray) is 

rs SYS_REFCURSOR ; 

record myPackage.stdInfo; 

stdId varchar(30); 

comment varchar(1); 

number; 

begin 

open rs for select stdId,comment from out_school 

:= 1; 

LOOP 

 fetch rs into stdId,comment; exit when rs%NOTFOUND; 

record.stdId := stdId; 

 record.comment := comment; 

recommentArray(i) := record; 

i:=i 1; 

end LOOP; 

end get_comment; 

-- 定义数组类型myArray 

create or replace package myPackage is begin 

type stdInfo is record(stdId varchar(30),comment varchar(1)); 

type myArray is table of stdInfo index by binary_integer; 

end myPackage;

 

转载:http://blog.sina.com.cn/s/blog_c045da510101fotv.html

0 0
原创粉丝点击