oracle学习存储过程

1, create or replace procedure  sp_pro is

begin 

insert   into  mytest values('123','wangwu');

end;;

查看错误: show error;

执行: /

2,调用;

exec  过程名(参数,参数);

call  过程名(参数,参数,....);

扫描二维码关注公众号,回复: 4118350 查看本文章

3,块(编程)-->过程,函数,包,触发器

命名规范: 变量v_前缀v_sal ,  常量c_前缀c_rate;  游标_cursor后缀emp_cursor; 异常e_前缀e_error;

declear 定义常量、变量、游标、例外异常、复杂数据类型,

 begin执行sql语句, exception 异常处理, end;

set serveroutput  on --打开输出选项;

declare --定义变量

v_ename varchar2(5);

v_sal  number(7,2);

begin

        select ename,sal  into v_ename, v_sal from emp where empno=&no; --将查询出来的ename放入到参数v_ename中,&表示从控制台接受输入的变量; 参数顺序要一致

        dbms_output.put_line('雇员名:'||v_ename); --控制台输出

        dbms_output.put_line('hello');

exception --异常处理

when no_data_found then

        dbms_output.put_line('数据输入错误');

end;

4,异常例外: no_data_found 数据不存在

create procedure sp_pro3(spName varchar2,  newSal  number) is  ---参数只指定类型不指定大小

begin

update  emp set sal=newSal   where ename=spName; --根据用户名修改工资

end;

exec sp_pro3('scott', 4678); --调用过程

java调用:

CallableStatement  cs=conn.prepareCall("{call  sp_pro3(?,?)}");

cs.setString(1,"Tom");//给? 赋值

cs.setInt(2,1000);

cs.execute(); //执行

java调用有返回值的存储过程:

CallableStatement  cs=conn.prepareCall("{call  sp_pro8(?,?)}");//第一个参数是入参数,第二个是出参数

cs.setString(1,"Tom");//给第一个? 赋值

//给第二个?赋值

cs.registerOutParameter(2,oracle.jdbc.oracleTypes.VARCHAR); //过程的第二个参数为输出参数,类型要一致

cs.execute(); //执行

//取出返回值,要注意?顺序

String  name=cs.getString(2);  //得到过程的返回值

5 创建函数:

crete function sp_fun2(spName varchar2) --参数不定义大小

 return number is  yearSal number(7,2);

begin

select  sal*12+nvl(comm,0)*12  into  yearSal  from emp where ename=spName;

return yearSal;

end;

函数调用:

var  abc  number;

call  sp_fun2('scott') into :abc; 

print abc

java程序中调用函数:

select  sp_fun('scott')  from dual;//通过rs.get(1)得到返回的结果。

6 包: 用于逻辑上组合过程和函数,它有包规范和包体两部分组成;

create package  sp_package is

        procedure  update_sal(name varchar2, newsal  number);

        function  annual_income(name  varchar2) return number;

end;

包规范只包含了过程和函数的说明,但是没有过程和函数的实现代码。包体用于实现包规范中的过程和函数。

建立包体: create package  body  sp_package is 

procedure update_sal(name varchar2, newsal  number)

is

begin

update emp set sal=newsal where ename=name;

end;

function  annual_income(name varchar2)

return  unmber  is

annual_salary  number;

begin

select  sal*12+nvl(comm,0)  into annual_salary  from emp where ename=name;

return  annual_salary;

end;

end;

调用执行: call  sp_package.update_sal('tom',120);

7 定义变量:

1),定义一个变长字符串 v_ename   varchar2(10);

2), 定义一个小数范围 -9999.99 ~ 9999.99

 v_sal  number(6.2);

3),定义一个小数并初始值为5.4 ,:=是赋值号

v_sal2  number:=5.4;

4) 定义一个日期类型的数据

v_brithdate  date;

5) 定义一个布尔变量,不能为空,初始值为false

v_valid  boolean  not  null  default false;

8,复合变量:记录类型,表类型

declare

type emp_record is record( name emp.ename%type, sal emp.sal%type); --定义一个记录类型

sp_record  emp_record; --定义一个记录变量

begin

select ename,sal into sp_record  from emp where empno=7788; --赋值

dbms_output.put_line('员工名: '|| sp_record.name); --获取

end;

------------表类型相当于数组------------------------

declare 

type sp_table_type  is table of emp.ename%type  index by binary_integer; --下标为整数可以为负数

sp_table  sp_table_type;  --定义一个表类型的变量

begin

select ename intosp_table(0) from emp where  empno=7788;  --赋值,下标为0,只能接受一行的记录

dbms_output.put_line('员工名: '||sp_table(0)); --获取

end;

9,参照表里:游标cursor

declare 

type sp_emp_cursor is ref cursor; --定义一个游标类型

sp_cursor  sp_emp_cursor; --定义一个游标变量

v_ename emp.ename%type;

v_sal  emp.sal%type;

begin

open sp_currsor  for  select   ename,sal  from emp where deptno=10; --游标与一个select结合

loop

fetch  sp_currsor into v_ename,v_sal;--从游标获取数据赋值给变量

exit  when sp_curror%notfound; --判断是否为空

dbms_output.put_line('名字: '||v_ename||'工资: '||v_sal);

end  loop;

end;

带参数的游标:

declare

  cursor  c_emp(p_deptno  employees.department_id%type)is 

  select *  from  hr.employees where department_id=p_deptno;

  v_emp c_emp%ROWTYPE;

begin

  open c_emp(10);

loop

fetch   c_emp  into  v_emp;

exit when c_emp%NOTFOUND;

DBMS_OUTPUT.PUT_LINE(v_emp.employ_id||v_emp.last_name);

end  loop;

close  .c_emp;

10, 返回结果集的存储过程

--1,创建一个包,在该包中,定义类型test_sursor, 是个游标

create  or  replace  package  testpackage  as

type  test_cursor   is  ref  cursor;

end  tespackage;

--2 创建过程

create  or  replace  procedure  sp_pro9(spNo  in  number, p_cursor  out  tespackage.test_cursor)

is

begin

open  p_cursor  for  select  * from emp  where deptno =spno;

end;

java调用返回的是结果集:

CallableStatement  cs=conn.prepareCall("{call  sp_pro9(?,?)}");//第一个参数是入参数,第二个是游标出参数

cs.setString(1,10);//给第一个? 赋值

//给第二个?赋值

cs.registerOutParameter(2,oracle.jdbc.oracleTypes.CURSOR); //过程的第二个参数为游标输出参数,类型要一致

cs.execute(); //执行

ResultSet   rs=(ResultSet)cs.getobject(2); //得到结果集

while(rs.next()){

        syso(rs.getInt(1)+' '+rs.getString(2)  ); //迭代取出数据,第一列和第二列

}

10,if控制

if v_job='pro'  then

update emp set sal=sal+1000 where empno=spNo;

elsif  v_job='MAN'  then 

update emp set sal=sal+500  where empno=spNo;

else

update emp  set sal=sal+200 where empno=spNo;

end if;

触发器:create trigger 

11.循环:

方式一:

loop

insert into  users  values(v_num, spname);

exit  when  v_num=10;--判断是否退出循环,符合条件退出

end loop;

方式二:

while v_num<=20  loop --符合条件才执行

insert into  users  values(v_num, spname);

v_num:=v_num+1;

end  loop;

方式三:

for  i  in   1..10 loop

insert into  users  values(v_num, spname);

end loop;

12, goto语句

declare

i  int :=-1;

begin

    loop

    dbms_output.put_line('输出i='||i);

    if i=10 then

    goto  end_loop;  --跳转到特定标号处

    end if;

    i:=i+1;

    end  loop;

<<end_loop>>

dbms_output.put_line('循环结束');

end;

13, null语句不会执行任何操作,

14,分页算法

--1,创建一个包,在该包中,定义类型test_sursor, 是个游标

create  or  replace  package  testpackage  as

type  test_cursor   is  ref  cursor;

end  tespackage;

--2 创建过程

create  or  replace  procedure  fenye (

tableName  in varchar2, --表名

 pagesize  in number,  --每页显示记录数

  pageNow  in number,  --显示第几页

 myrows  out  number, --总记录数

mypagecount   out  number,总页数

p_cursor  out  testpackage.test_cursor --返回的结果集

) is

---定义变量

v_sql  varchar2(1000);

v_begin  number:=(pageNow-1)*pagesize+1; --计算显示页的第一条记录

v_end  number:=pageNow*pagesize; --计算显示页的第二条记录

begin

v_sql:='select * from (select t.* , rownum  rn  from(select  * from '|| tableName||') t  where  rownum<='|| v_end||' ) where  rn >='||v_begin;

open p_cursor   for v_sql;

v_sql:='select  count(*) from '||tablesName;

execute  immediate  v_sql  into  myrows;  --表的总记录数

if  mod(myrows, pagesize)=0  then --计算总页数

mypageCount   := myrows/Pagesize;

else

myPageCount :=myrows/Pagesize+1;

end if;

close  p_cursor; --关闭游标

end;

15,case语句

create or replace procedure  sp_pro6(spno  number) is

v_sal   emp.sal%type;

begin

select sal  into v_sal  from emp where  empno=spno;

case

when v_sal <1000  then 

update emp set sal=sal+100  where empno=spno;

when  v_sal <2000  then

update  emp set sal=sal+200  where  empno=spno;

end  case;

exception

when case_not_found  then

dbms_output.put_line('case没有相匹配的');

end;

16例外:

case_not_found  case中没有相对应的条件

cursor_already_open  游标已经打开

dup_val_on_index  唯一索引重复插入inser语句

invaild_cursor  从未打开的游标中提取数据,关闭没有打开的游标

invalid_number  输入的数据有误比如100输成LOO

no_data_found  当select中没有返回行

too_many_rows  当select返回超过了一行,返回了多行

zero_divide  当执行3/0会触发该例外,分母不能为0

value_error  赋值操作变量的长度不足以容纳实际数据

自定义例外

create  or replace  procedure   ex_test(spNo number)

is

myex  exception;  --定义一个自定义例外

begin

update emp set sal=sal+1000 where empno=spNo;

if sql%notfound  then  --这是表示没有更新成功

raise  myex;   --触发myex

end  if;

exception

when myex then

dbms_output.put_line('没有更新任何用户');

end;

调用:exec  ex_test(56);

17,视图view

create  or  replace  view  视图名 as  select 语句 [ with  read  only]只可读不可改

删除视图 : drop  view  视图名

eg: create view myview as  select * from emp where  sal<1000; 

18,当语句中包含单引号使用q加分割符号

v_event := q'!Father's day!'; 前面加q其中!为分割符号

v_event :=q'[Mother's day]';  前面加q其中[]为分割符号

v_event :='Father''s day';   双单引号

19:存储过程循环

存储过程for循环:

create or replace package body update_payend_status is

procedure updatestatus(mkey varchar2,accountid number)is

v_sumUnits float :=0;

v_flag pglumpsum.flag%type;

v_mkey pglumpsum.mkey%type;

begin

open getPenFlag(mkey);

fetch getPenFlag into v_flag;

close getPenFlag;

open getAllPayendMembers;

loop

fetch getAllPayendMembers into v_mkey,v_accountid;

exit when getAllPayendMembers%NOTFOUND;

addCalc(v_mkey,v_accoutid);

end loop;

close getAllPayendMembers;

end;

END;

20, -----先创建序列,再创建触发器

create sequence SEQ_FIXED_TRADEDATE

minvalue 1

maxvalue 9999999

start with 3

increment by 1

nocache;

--创建触发器

create or replace trigger tg_fixed_Tradedate

before insert on fixed_Tradedate for each row --定义before触发器,监测表fixed_tradedate的插入操作,行级别的触发器

when (new.ID is null)

begin

select SEQ_FIXED_TRADEDATE.nextval into:new.ID from dual;

end;

---删除序列

drop sequence SEQ_FIXED_TRADEDATE;

--创建同义词

create sysnonym client_54,user for fe.user;

--删除同义词

drop sysnonym user;

--授权

grant select ,insert,update,execute on payment_batch_proc to client_54;

--增加对表空间的权限

alter user client_54 quota unlimited on users;

猜你喜欢

转载自blog.csdn.net/wang_zhij/article/details/84184223