您的位置:首页 > 数据库 > Oracle

oracle 存储过程

2017-03-29 23:58 239 查看
1.基本结构

CREATE OR REPLACE PROCEDURE 存储过程名字

(

    参数1 IN NUMBER,

    参数2 IN NUMBER

)  AS

变量1 INTEGER :=0;

变量2 DATE;

BEGIN
END 存储过程名字

2.SELECT INTO STATEMENT

  将select查询的结果存入到变量中,可以同时将多个列存储多个变量中,必须有一条

  记录,否则抛出异常(如果没有记录抛出NO_DATA_FOUND)

  例子:

  BEGIN

  SELECT col1,col2 into 变量1,变量2 FROM typestruct where xxx;

  EXCEPTION

  WHEN NO_DATA_FOUND THEN

      xxxx;

  END;

  ...

3.IF 判断

  IF V_TEST=1 THEN

    BEGIN

       do something

    END;

  END IF;

4.while 循环

  WHILE V_TEST=1 LOOP

  BEGIN

 XXXX

  END;

  END LOOP;


5.变量赋值
  V_TEST := 123;


6.用for in 使用cursor


  ...

  IS

  CURSOR cur IS SELECT * FROM xxx;

  BEGIN

 FOR cur_result in cur LOOP

  BEGIN

   V_SUM :=cur_result.列名1+cur_result.列名2

  END;

 END LOOP;

  END;

7.带参数的cursor

  CURSOR C_USER(C_ID NUMBER) IS SELECT NAME FROM USER WHERE TYPEID=C_ID;

  OPEN C_USER(变量值);

  LOOP

 FETCH C_USER INTO V_NAME;

 EXIT FETCH C_USER%NOTFOUND;

    do something

  END LOOP;

  CLOSE C_USER;

8.用pl/sql developer debug
  连接数据库后建立一个Test WINDOW

  在窗口输入调用SP的代码,F9开始debug,CTRL+N单步调试

关于oracle存储过程的若干问题备忘

1.在oracle中,数据表别名不能加as,如:


select a.appname from appinfo a;--
正确


select a.appname from appinfo as a;--
错误

 也许,是怕和oracle中的存储过程中的关键字as冲突的问题吧

2.在存储过程中,select某一字段时,后面必须紧跟into,如果select整个记录,利用游标的话就另当别论了。


  select af.keynode into kn from APPFOUNDATION af where af.appid=aid and af.foundationid=fid;-- 有into,正确编译


  select af.keynode from APPFOUNDATION af where af.appid=aid and af.foundationid=fid;-- 没有into,编译报错,提示:Compilation 


  Error: PLS-00428: an INTO clause is expected in this SELECT statement





3.在利用select...into...语法时,必须先确保数据库中有该条记录,否则会报出"no data found"异常。

   可以在该语法之前,先利用select count(*) from 查看数据库中是否存在该记录,如果存在,再利用select...into...

4.在存储过程中,别名不能和字段名称相同,否则虽然编译可以通过,但在运行阶段会报错


 select keynode into kn from APPFOUNDATION where appid=aid and foundationid=fid;-- 正确运行


select af.keynode into kn from APPFOUNDATION af where af.appid=appid and af.foundationid=foundationid;-- 运行阶段报错,提示


ORA-01422:exact fetch returns more than requested number of rows


5.在存储过程中,关于出现null的问题

假设有一个表A,定义如下:


create table A(


id varchar2(50) primary key not null,


vcount number(8) not null,


bid varchar2(50) not null -- 外键 


);

如果在存储过程中,使用如下语句:


select sum(vcount) into fcount from A where bid='xxxxxx';

如果A表中不存在bid="xxxxxx"的记录,则fcount=null(即使fcount定义时设置了默认值,如:fcount number(8):=0依然无效,fcount还是会变成null),这样以后使用fcount时就可能有问题,所以在这里最好先判断一下:


if fcount is null then


    fcount:=0;


end if;

这样就一切ok了。

6.Hibernate调用oracle存储过程


        this.pnumberManager.getHibernateTemplate().execute(


                new HibernateCallback() {


                    public Object doInHibernate(Session session)


                            throws HibernateException, SQLException {


                        CallableStatement cs = session


                                .connection()


                                .prepareCall("{call modifyapppnumber_remain(?)}");


                        cs.setString(1, foundationid);


                        cs.execute();


                        return null;


                    }


                });

一个简单的例子~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

---创建表

create table TESTTABLE

(

  id1  VARCHAR2(12),

  name VARCHAR2(32)

)

select t.id1,t.name from TESTTABLE t

insert into TESTTABLE (ID1, NAME)

values ('1', 'zhangsan');

insert into TESTTABLE (ID1, NAME)

values ('2', 'lisi');

insert into TESTTABLE (ID1, NAME)

values ('3', 'wangwu');

insert into TESTTABLE (ID1, NAME)

values ('4', 'xiaoliu');

insert into TESTTABLE (ID1, NAME)

values ('5', 'laowu');

---创建存储过程

create or replace procedure test_count

as

v_total number(1);

begin

  select count(*) into v_total from TESTTABLE;

  DBMS_OUTPUT.put_line('总人数:'||v_total);

end;

--准备

--线对scott解锁:alter user scott account unlock; 

--应为存储过程是在scott用户下。还要给scott赋予密码

---alter user scott identified by tiger;

---去命令下执行

EXECUTE test_count;

----在ql/spl中的sql中执行

begin

  -- Call the procedure

  test_count;

end;



create or replace procedure TEST_LIST

      AS 

      ---是用游标

        CURSOR test_cursor IS select t.id1,t.name from TESTTABLE t;

      begin

        for Test_record IN test_cursor loop---遍历游标,在打印出来

           DBMS_OUTPUT.put_line(Test_record.id1||Test_record.name);

           END LOOP;

            test_count;--同时执行另外一个存储过程(TEST_LIST中包含存储过程test_count)

            end;

      -----执行存储过程TEST_LIST

      begin 

         TEST_LIST;

         END;

       ---存储过程的参数

        ---IN  定义一个输入参数变量,用于传递参数给存储过程   

        --OUT 定义一个输出参数变量,用于从存储过程获取数据   

        ---IN OUT  定义一个输入、输出参数变量,兼有以上两者的功能  

        --这三种参数只能说明类型,不需要说明具体长度 比如 varchar2(12),defaul 可以不写,但是作为一个程序员最好还是写上。

        

      ---创建有参数的存储过程

      create or replace procedure test_param(p_id1 in VARCHAR2 default '0')

        as v_name varchar2(32);

        begin

          select t.name into v_name from TESTTABLE t where t.id1=p_id1;

          DBMS_OUTPUT.put_line('name:'||v_name);

         end;

      ----执行存储过程

      begin

         test_param('1');

       end;

      

       default '0'

      ---创建有参数的存储过程

      create or replace procedure test_paramout(v_name OUT VARCHAR2 )

        as  

        begin

          select name into v_name from TESTTABLE where id1='1';

          DBMS_OUTPUT.put_line('name:'||v_name);

         end;

      ----执行存储过程

    DECLARE  

        v_name VARCHAR2(32);   

        BEGIN  

        test_paramout(v_name);

        DBMS_OUTPUT.PUT_LINE('name:'||v_name);   

        END;  

    -------IN OUT

    ---创建存储过程

    create or replace procedure test_paramINOUT(p_phonenumber in out varchar2)

    as  

    begin 

      p_phonenumber:='0571-'||p_phonenumber;

    end;

    

    ----

    DECLARE  

    p_phonenumber VARCHAR2(32);  

    BEGIN  

    p_phonenumber:='26731092';  

    test_paramINOUT(p_phonenumber);  

    DBMS_OUTPUT.PUT_LINE('新的电话号码:'||p_phonenumber);  

    END;  

    -----sql命令下,查询当前用户的存储过程或函数的源代码,

    -----可以通过对USER_SOURCE数据字典视图的查询得到。USER_SOURCE的结构如下:

    

    SQL> DESCRIBE USER_SOURCE ;

    Name Type           Nullable Default Comments                                                                                                      

    ---- -------------- -------- ------- ------------------------------------------------------------------------------------------------------------- 

    NAME VARCHAR2(30)   Y                Name of the object                                                                                            

    TYPE VARCHAR2(12)   Y                Type of the object: "TYPE", "TYPE BODY", "PROCEDURE", "FUNCTION",

    "PACKAGE", "PACKAGE BODY" or "Java
SOURCE" 

    LINE NUMBER         Y                Line number of this line of source                                                                            

    TEXT VARCHAR2(4000) Y                Source text                                                                                                   

    SQL> 

    ---查询出存储过程的定义语句

    select text from user_source WHERE NAME='TEST_COUNT';

    ----查询存储过程test_paramINOUT的参数

    SQL> DESCRIBE test_paramINOUT;

    Parameter     Type     Mode   Default? 

    ------------- -------- ------ -------- 

    P_PHONENUMBER VARCHAR2 IN OUT  

    SQL> 

    ---查看当前的存储过程的状态是否正确,

    ---VALID为正确,INVALID表示存储过程无效或需要重新编译

    SELECT STATUS FROM USER_OBJECTS WHERE OBJECT_NAME='TEST_COUNT';

    -----如果要检查存储过程或函数的依赖性,可以通过查询数据字典USER_DENPENDENCIES来确定,该表结构如下:

    SQL> DESCRIBE USER_DEPENDENCIES;

    Name                 Type          Nullable Default Comments                                                   

    -------------------- ------------- -------- ------- ---------------------------------------------------------- 

    NAME                 VARCHAR2(30)                   Name of the object                                         

    TYPE                 VARCHAR2(17)  Y                Type of the object                                         

    REFERENCED_OWNER     VARCHAR2(30)  Y                Owner of referenced object (remote owner if remote object) 

    REFERENCED_NAME      VARCHAR2(64)  Y                Name of referenced object                                  

    REFERENCED_TYPE      VARCHAR2(17)  Y                Type of referenced object                                  

    REFERENCED_LINK_NAME VARCHAR2(128) Y                Name of dblink if this is a remote object                  

    SCHEMAID             NUMBER        Y                                                                           

    DEPENDENCY_TYPE      VARCHAR2(4)   Y                                                                               

    SQL>  

    ---查询存储过程TEST_COUNT的依赖关系

    SELECT REFERENCED_NAME,REFERENCED_TYPE FROM USER_DEPENDENCIES WHERE NAME='TEST_COUNT';
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: