oracle存储过程参考资料(网上转载)

网址一:http://www.cnblogs.com/hero4china/articles/base_rule_oracle_procedure.html

  

给朋友讲解oracle proc的记录:

--准备环境
--表1
CREATE TABLE itemfile
(
  itemcode varchar2(4),
  itemdesc varchar2(20),
  p_category varchar2(20),
  qty_hand number(5),
  re_level number(5),
  max_level number(5),
  itemrate number(7,2)
);

INSERT INTO itemfile VALUES('i201','nuts','spares',100,50,250,20);
INSERT INTO itemfile VALUES('i202','bolts','spares',95,125,300,16.5);
INSERT INTO itemfile VALUES('i204','holders','spares',18,30,75,112);
INSERT INTO itemfile VALUES('i205','covers','accessories',30,15,50,400);
INSERT INTO itemfile VALUES('i203','panels','accessories',75,30,150,4000);
INSERT INTO itemfile VALUES('i206','brackets','spares',150,73,200,132);

COMMIT;

--表2
CREATE TABLE order_master
(
  orderno VARCHAR2(5),
  odate DATE,
  vencode VARCHAR2(5),
  ostatus CHAR(1),
  del_date DATE
);
alter session set nls_date_language = 'AMERICAN';
INSERT INTO order_master VALUES('o001','12-MAY-05', 'V002','c', '15-MAY-05');
INSERT INTO order_master VALUES('o002','14-MAY-05', 'V001','p', '15-MAY-05');
INSERT INTO order_master VALUES('o003','14-MAY-05', 'V001','p', '15-FEB-05');
INSERT INTO order_master VALUES('o004','14-MAY-05', 'V003','p', '15-FEB-05');
INSERT INTO order_master VALUES('o005','14-MAY-05', 'V001','p', '15-FEB-05');
INSERT INTO order_master VALUES('o006','14-APR-03', 'V004','p', '18-MAY-05');
INSERT INTO order_master VALUES('o007','14-MAY-04', 'V003','p', '10-FEB-05');
INSERT INTO order_master VALUES('o008','11-MAY-05', 'V001','p', '12-JUN-05');
INSERT INTO order_master VALUES('o009','14-JAN-05', 'V002','c', '16-FEB-05');
INSERT INTO order_master VALUES('o011','14-JAN-05', 'V001','p', '10-FEB-05');
INSERT INTO order_master VALUES('o012','14-FEB-05', 'V003','p', '15-MAY-05');
INSERT INTO order_master VALUES('o013','14-MAR-05', 'V001','p', '15-MAY-05');
INSERT INTO order_master VALUES('o014','14-FEB-05', 'V002','c', '12-MAY-05');
INSERT INTO order_master VALUES('o015','14-APR-03', 'V004','p', '17-APR-05');
COMMIT;

alter session set nls_date_language = 'SIMPLIFIED CHINESE';

--表3
CREATE TABLE ORDER_DETAIL
(
  ORDERNO     VARCHAR2(5) PRIMARY KEY,
  ODATE       DATE,
  VENCODE     VARCHAR2(5),
  itemcode    VARCHAR2(10),
  qty_ord     NUMBER,
  qty_deld    NUMBER,
  OSTATUS     CHAR(1),
  DEL_DATE    DATE,
  ORDER_COST  NUMBER
);


--表4
create table student
(
stuid int,
stuname varchar2(10),
sex  varchar2(2)
);

insert into student values (101, '刘德华', '男');
insert into student values (102, '张学友', '男');
insert into student values (103, '周润发', '男');
insert into student values (104, 'wind', '女');
insert into student values (105, '林青霞', '女');

--表5
create table subject
(
subid varchar2(10) primary key,
subname varchar2(30) not null
);
insert into subject values ('s001', 'oracle');
insert into subject values ('s002', 'java');


----------------------------------------------------------------
****************************************************************
第一部分:开发存储过程
****************************************************************
----------------------------------------------------------------

----------------------------------------------------------------
***************************************************************
1.建立过程:不带任何参数
---------------------------------------------------------------
--案例01:建立一个输出当前系统日期和时间的过程
create or replace procedure system_out_time
is
begin
dbms_output.put_line(systimestamp);
end;


调用过程方法01:
SQL> exec system_out_time;


调用过程方法02:
SQL> call system_out_time();

 

--案例01:打印乘法小九九
create or replace procedure xjj
as
i integer;
j integer;
begin
    dbms_output.put_line(' 打印小九九   ');
     for i in 1..9 loop
     for j in 1..9 loop
  if i>=j then
    dbms_output.put_line(to_char(j) ||'*'||to_char(i) || '='||to_char(i*j)||'  ');
    end if;
    end loop;
dbms_output.put_line('    ');
end loop;
end;


----------------------------------------------------------------
***************************************************************
2.建立过程:带输入IN参数
---------------------------------------------------------------


--案例01:使用输入参数查询用户信息
create or replace procedure  find_emp(emp_no number)
as
empname emp.ename%type;
begin
select ename into empname from emp where empno=emp_no;
dbms_output.put_line('  雇员的姓名是:  '|| empname);
exception
when no_data_found then
dbms_output.put_line ( '  雇员编号未找到:     ');
end;

 


----案例02:根据已知的编号显示出对应职工的姓名
create or replace procedure queryempname
(sfindno emp.empno%type )
as
sname emp.ename%type;
sjob  emp.job%type;
begin
select ename, job into sname, sjob from emp where empno=sfindno;
dbms_output.put_line(' 编号为  '||sfindno|| '   的职工姓名为  '||sname || '  工作为   :' ||sjob);
exception
when no_data_found then
dbms_output.put_line('没有符合条件的记录!');
when too_many_rows then
dbms_output.put_line('返回的行数太多!');
when others then
dbms_output.put_line('发生以外错误!');
end;

 

--案例03:新建一个带有输入参数的存储过程

create or replace procedure add_empoyee
(
eno number,
name varchar2,
sal number,
job varchar2 default 'CLERK',
dno number
)
is
e_inte  exception;
pragma exception_init(e_inte, -2291);  --关联例外和错误号,相当于raise
begin
insert into emp (empno, ename, sal, job,deptno) values (eno, name, sal, job, dno);
exception
when dup_val_on_index then    --dup_val_on_index是oracle预定义错误
raise_application_error(-20000,'雇员信息不能重复!');   --raise_application_error显示触发例外
when e_inte then
raise_application_error(-20001, '部门号不存在!');
end;

 

---如该改写为,注意运行结果的异同:
create or replace procedure add_empoyee
(
eno number,
name varchar2,
sal number,
job varchar2 default 'CLERK',
dno number
)
is
e_inte  exception;
begin
insert into emp (empno, ename, sal, job,deptno) values (eno, name, sal, job, dno);
exception
when dup_val_on_index then    --dup_val_on_index是oracle预定义错误
dbms_output.put_line('雇员信息不能重复!');  
when e_inte then
dbms_output.put_line('部门号不存在!');
end;

 

--调用方法
exec add_empoyee(&no,'&name', &sal,'&job',&dno);

exec add_empoyee(1113,'CLERK',2000,'MANAGER',15);

如果使用job的默认值则:
exec add_empoyee(1113,'CLERK',2000,null,10);

 

----------------------------------------------------------------
***************************************************************
3.建立过程:带输入out参数
---------------------------------------------------------------

 

 

--案例01:带有输出out参数的存储过程

--新建存储过程
create or replace procedure test001
(epno in number,
v02 out varchar2)
as
salary number;
begin
 select sal into salary from emp
where empno=epno;
if salary <1000 then
  v02:='这样的工资太低!';
elsif salary  between 1000 and 2000 then
  v02:='这样的工资还可以接受!';
else
v02:='这样的待遇是我们不离开的原因!';
end if;
end;


--调用存储过程方法01 (这样的值是固定的):
declare
 v2 varchar2(200);  --声明变量时需要和输入参数的类型一致
 begin
 test001 (&no, v2);
 dbms_output.put_line('v02的值为:'||v2);
end;

 

--调用存储过程方法02(用户交互):
declare
 empno number:=&empno;
 v2 varchar(200);  --声明变量时需要和输入参数的类型一致
 begin
 test001 (empno, v2);
 dbms_output.put_line('v02的值为:'||v2);
end;

------也可以写成
declare
 empno number;
 v2 varchar(200);  --声明变量时需要和输入参数的类型一致
 begin
 empno:=&empno;
 test001 (empno, v2);
 dbms_output.put_line('v02的值为:'||v2);
end;

 

--案例02:新建一个用于输出雇员名以及工资的过程
create or replace procedure query_emp
(
eno number,
name  out varchar2,
salary out number
)
is
begin
select ename, sal into name, salary from emp where empno=eno;
exception
when no_data_found then
raise_application_error(-20000, '这个员工不存在!');
end;

 

--调用过程方法01:(使用固定的变量)
declare
nae varchar2(10);  --这里的变量和过程中输入参数的类型需要对应
sala number;
begin
query_emp(7788,nae,sala);
dbms_output.put_line('the employee name is : '||nae);
dbms_output.put_line('the employee sal is : '||sala);
end;

--调用过程方法02:(使用交互的变量)
declare
nae varchar2(10);  --这里的变量和过程中输入参数的类型需要对应
sala number;
begin
query_emp(&empno,nae,sala);
dbms_output.put_line('the employee name is : '||nae);
dbms_output.put_line('the employee sal is : '||sala);
end;

----------------------------------------------------------------
在存储过程中使用dbms_output.put_line
----------------------------------------------------------------

--案例02的另外一种写法:
create or replace procedure query_emp
(
eno number,
name  out varchar2,
salary out number
)
is
begin
select ename, sal into name, salary from emp where empno=eno;
dbms_output.put_line('the employee name is : '||name);
dbms_output.put_line('the employee sal is : '||salary);
exception
when no_data_found then
raise_application_error(-20000, '这个员工不存在!');
end;

 

--调用过程方法01:(使用固定的变量)
declare
nae varchar2(10);  --这里的变量和过程中输入参数的类型需要对应
sala number;
begin
query_emp(7788,nae,sala);
end;


--调用过程方法02:(使用交互式变量)

declare
nae varchar2(10);  --这里的变量和过程中输入参数的类型需要对应
sala number;
begin
query_emp(&empno,nae,sala);
end;

 

 

 


----------------------------------------------------------------
***************************************************************
4.建立过程:带输入 IN out参数
---------------------------------------------------------------

--案例01:新建带 IN OUT参数的过程
--新建代码
create or replace procedure swap
(
p1 in out number,
p2 in out number
)
as
v_temp number;
begin
v_temp:=p1;
p1:=p2;
p2:=v_temp;
end;

--调用带IN OUT参数的存储过程方法01:
/*由于参数即是输入又是输出参数,所以需要声明变量并输入值*/
declare
n01 number:=100;
n02 number:=200;
begin
swap(n01, n02);
dbms_output.put_line ('n01=' ||n01);
dbms_output.put_line ('n02=' ||n02);
end;

--调用带IN OUT参数的存储过程方法02:
declare
n01 number;
n02 number;
begin
n01:=100;
n02:=200;
swap(n01, n02);
dbms_output.put_line ('n01=' ||n01);
dbms_output.put_line ('n02=' ||n02);
end;


--案例02:新建一个带有in out参数的过程

create or replace procedure comp
(
nm01 in out number,
nm02 in out number
)
is
v1 number;
v2 number;
begin
v1:=nm01/nm02;
v2:=mod(nm01,nm02);
nm01:=v1;
nm02:=v2;
end;


--调用
declare
n1 number;
n2 number;
begin
n1:=100;
n2:=30;
comp(n1,n2);
dbms_output.put_line(n1);
dbms_output.put_line(n2);
end;

 

----------------------------------------------------------------
***************************************************************
5.建立过程:为参数传递变量和数据
---------------------------------------------------------------

exec queryempname(sfindno=>7788);


exec queryempname(sfindno=>&no);

网址二:http://blog.csdn.net/yangzhawen/article/details/7309535

Oracle存储过程基本语法

 

存储过程

  1  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 存储过程名(param1 in typeparam2 out type) 

as 

变量1 类型(值范围); --vs_msg   VARCHAR2(4000); 

变量2 类型(值范围);

Begin

Select count(*) into 变量1 from 表A where列名=param1

 

    If (判断条件) then

       Select 列名 into 变量2 from 表A where列名=param1

       Dbms_outputPut_line(‘打印信息’);

    Elsif (判断条件) then

       Dbms_outputPut_line(‘打印信息’);

    Else

       Raise 异常名(NO_DATA_FOUND;

    End if;

Exception

    When others then

       Rollback;

End;

 

 

 

注意事项:

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

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

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

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

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

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

 

CREATE OR REPLACE PROCEDURE存储过程名
(

--定义参数
 is_ym  IN CHAR(6) ,

the_count OUT NUMBER,

AS 
--定义变量 
vs_msg   VARCHAR2(4000);   --错误信息变量
vs_ym_beg  CHAR(6);      --起始月份
vs_ym_end  CHAR(6);      --终止月份
vs_ym_sn_beg CHAR(6);     --同期起始月份
vs_ym_sn_end CHAR(6);     --同期终止月份

--定义游标(简单的说就是一个可以遍历的结果集) 


CURSOR cur_1 IS 
  SELECT 。。。 
  FROM 。。。 
    WHERE 。。。
   GROUP BY 。。。; 

BEGIN 


--用输入参数给变量赋初值,用到了OralceSUBSTR TO_CHAR ADD_MONTHS 

 

TO_DATE 等很常用的函数。 
vs_ym_beg := SUBSTR(is_ym,1,6); 
vs_ym_end := SUBSTR(is_ym,7,6); 
vs_ym_sn_beg := TO_CHAR(ADD_MONTHS(TO_DATE(vs_ym_beg,'yyyymm'), -12),'yyyymm'); 
vs_ym_sn_end := TO_CHAR(ADD_MONTHS(TO_DATE(vs_ym_end,'yyyymm'), -12),'yyyymm'); 


--先删除表中特定条件的数据。 


DELETE FROM 表名 WHERE ym = is_ym; 


  --然后用内置的DBMS_OUTPUT对象的put_line方法打印出影响的记录行数,其中用到一个系统变量SQL%rowcount 


DBMS_OUTPUT.put_line('del上月记录='||SQL%rowcount||''); 

INSERT INTO表名(area_code,ym,CMCODE,rmb_amt,usd_amt) 
SELECT area_code,is_ym,CMCODE,SUM(rmb_amt)/10000,SUM(usd_amt)/10000 
FROM BGD_AREA_CM_M_BASE_T 
  WHERE ym >= vs_ym_beg 
  AND ym <= vs_ym_end 
GROUP BY area_code,CMCODE; 

DBMS_OUTPUT.put_line('ins当月记录='||SQL%rowcount||''); 
--遍历游标处理后更新到表。遍历游标有几种方法,用for语句是其中比较直观的一种

 
FOR rec IN cur_1 LOOP 
  UPDATE 表名
  SET rmb_amt_sn = rec.rmb_amt_sn,usd_amt_sn = rec.usd_amt_sn 
   WHERE area_code = rec.area_code 
   AND CMCODE = rec.CMCODE 
   AND ym = is_ym; 
END LOOP; 

COMMIT; 


--错误处理部分。OTHERS表示除了声明外的任意错误。SQLERRM是系统内置变量保存了当前错误的详细信息。 


EXCEPTION 


   WHEN OTHERS THEN 
      vs_msg := 'ERROR IN xxxxxxxxxxx_p('||is_ym||'):'||SUBSTR(SQLERRM,1,500);

 
   ROLLBACK; 


   --把当前错误记录进日志表。 


   INSERT INTO LOG_INFO(proc_name,error_info,op_date) 
   VALUES('xxxxxxxxxxx_p',vs_msg,SYSDATE); 
   COMMIT; 
   RETURN; 


END;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

oracle存储过程语法

1 、判断语句: 

if 比较式 then begin end; end if; 

create or replace procedure test(x in number) is 

begin 

        if x >0 then 

         begin 

        x := 0 - x; 

        end; 

    end if; 

    if x = 0 then 

       begin 

        x: = 1; 

    end; 

    end if; 

end test; 

2 、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) 

i number; 

begin 

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

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

for i in 1..varArray.count LOOP      

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

 end LOOP; 

end test; 

3 、While 循环 

while 条件语句 LOOP 

begin 

end; 

end LOOP; 

E.g 

create or replace procedure test(i in number) as 

begin 

while i < 10 LOOP 

begin     

 i:= i + 1; 

end; 

end LOOP; 

 end test; 

4 、数组 

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

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

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

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

e.g: 

create or replace procedure test(y out array) is 

 x array;   

 begin 

x := new array(); 

y := x; 

end test; 

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

create or replace package myPackage is 

   Public type declarations   type info is record(     name varchar(20),     y 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 的使用方式1   cursor_2 Cursor; 

begin 

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

可使用For x 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; 

i number; 

begin 

i := 1; 

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

OPEN rsCursor for select stdId,math,article,language,music,sport from student t 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 i 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 t 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); 

i number; 

begin 

open rs for select stdId,comment from out_school 

i := 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;

 

byebye

转载于:https://www.cnblogs.com/zhfhdm/archive/2012/10/29/2744883.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值