Oracle存储过程详解(二)

参考资料:
Oracle存储过程及参数理解

无参存储过程:

create or replace procedure sayhello as --说明部分 begin dbms_output.put_line('hello world');
end;

命令窗口的两种调用方法

    1.
SQL> set serveroutput on;   --第一次一定要开
SQL> exec sayhello
hello world
PL/SQL procedure successfully completed
    2.
SQL> begin
  2  sayhello();
  3  sayhello();
  4  end;
  5  /
hello world
hello world
PL/SQL procedure successfully completed

pl/sql块 调试

BEGIN SAYHELLO();
--rollback; 
END;

SQL窗口调用(不会输出dbms_output的内容)

exec是sqlplus的命令,只能在sqlplus中使用(PLSQL Developer的命令窗口也是这种)。
call是sql命令,任何工具都可以使用。如果想返回结果就用 传递参数

call sayhello();

有参存储过程

案例:给员工涨薪水

create or replace procedure raisesalary(eno in number) as --定义一个变量用来保存涨薪前的薪水 psal emp.sal%TYPE;
begin
 --涨薪前
 select sal into psal from emp where empno = eno;

 --涨薪
 update emp set sal = sal + 100 where empno = eno;

 DBMS_OUTPUT.PUT_LINE('涨薪前:' ||psal|| '涨薪后:' || (psal+100));
 end;

PL/SQL块调试

DECLARE
  ENO NUMBER;
BEGIN
  ENO := 7499;

  RAISESALARY(
    ENO => ENO
  );
--rollback; 
END;

案例:查询员工信息

create or replace procedure queryempinfo ( eno in number, pname out varchar2, psal out number, pjob out varchar2 ) as begin select ename,sal,job into pname,psal,pjob from emp where empno = eno;
end; 

PL/SQL块调试

DECLARE
  ENO NUMBER;
  PNAME VARCHAR2(200);
  PSAL NUMBER;
  PJOB VARCHAR2(200);
BEGIN
  ENO := 7521;

  QUERYEMPINFO(
    ENO => ENO,
    PNAME => PNAME,
    PSAL => PSAL,
    PJOB => PJOB
  );

DBMS_OUTPUT.PUT_LINE('PNAME = ' || PNAME);

  :PNAME := PNAME;

DBMS_OUTPUT.PUT_LINE('PSAL = ' || PSAL);

  :PSAL := PSAL;

DBMS_OUTPUT.PUT_LINE('PJOB = ' || PJOB);

  :PJOB := PJOB;
--rollback; 
END;

有参存储函数

案例:查询员工的年收入

create or replace function queryempincome(eno in number) return number as psal emp.sal%TYPE;
pcomm emp.comm%TYPE;
BEGIN SELECT SAL,COMM INTO PSAL,PCOMM FROM EMP WHERE EMPNO = ENO;

  --返回年收入(这里一定要注意空值的情况)
  return psal*12+nvl(pcomm,0);
END;

–PL/SQL块调试

DECLARE
  ENO NUMBER;
  v_Return NUMBER;
BEGIN
  ENO := 7839;

  v_Return := QUERYEMPINCOME(
    ENO => ENO
  );

DBMS_OUTPUT.PUT_LINE('v_Return = ' || v_Return);

  :v_Return := v_Return;
--rollback; 
END;

查看存储过程的属性是输入还是输出的

SQL> DESC DBMS_OUTPUT;
Element   Type      
--------- --------- 
ENABLE    PROCEDURE DISABLE PROCEDURE PUT PROCEDURE PUT_LINE PROCEDURE NEW_LINE PROCEDURE GET_LINE PROCEDURE CHARARR TYPE GET_LINES PROCEDURE SQL> DESC DBMS_OUTPUT.put_line;
Parameter Type     Mode Default? 
--------- -------- ---- -------- 
A         VARCHAR2 IN   

out 集合(使用光标)

--包头
create or replace package mypackage as
 type empcursor is ref cursor; --声明一个光标类型
 procedure queryEmpList(dno in number,empList out empcursor);
end;

--包体
create or replace package body mypackage as

 procedure queryEmpList(dno in number,empList out empcursor) as begin --打开光标 open empList for select * from emp where deptno=dno;
   end;
end;

命令窗口(查看程序包的结构)

SQL> desc mypackage
Element      Type      
------------ --------- 
EMPCURSOR    TYPE      
QUERYEMPLIST PROCEDURE SQL> desc mypackage.queryEmpList Parameter Type Mode Default? --------- ---------- ---- -------- DNO NUMBER IN EMPLIST REF CURSOR OUT 

应用程序中访问存储过程和存储函数

访问存储过程

//获取数据库的连接
略
//sql语句
String sql = "{call queryEmpinfo(?,?,?,?)}";
//通过连接创建statment
CallableStatement call = conn.prepareCall(sql);

//对于IN参数需要赋值
call.setInt(1,7839);

//对于OUT参数需要先申明
call.registerOutParameter(2,OracleTypes.VARCHAR);
call.registerOutParameter(3,OracleTypes.NUMBER);
call.registerOutParameter(4,OracleTypes.VARCHAR);

//执行调用
call.execute();

//取出结果
String name = call.getString(2);
double sal = call.getDouble(3);
String job = call.getString(4);

访问存储函数

//获取数据库的连接
略
//sql语句
String sql = "{?=call queryempincome(?)}";
//通过连接创建statment
CallableStatement call = conn.prepareCall(sql);

//对于输出参数需要声明
call.setInt(1,OracleTypes.NUMBER);

//对于输入参数需要赋值
call.registOutParameterr(2,7839);

//执行调用
call.execute();

//取出年收入
double income = call.getDouble(1);

访问有光标的存储过程

//获取数据库的连接
略
//sql语句 (一定要写上包名)
String sql = "{call mypackage.queryEmpList(?,?)}";
//通过连接创建statment
CallableStatement call = conn.prepareCall(sql);

//对于IN参数需要赋值
call.setInt(1,10);

//对于OUT参数需要先申明
call.registerOutParameter(2,OracleTypes.CURSOR);

//执行调用
call.execute();

//取出该部门中所有员工信息(注意这里)
ResultSet rs = ((OracleCallableStatement)call).getCursor(2);

while(rs.next()){
    //可以取出sql语句中查询的所有字段(这里只取几个演示下)
    int empno = rs.getInt("empno");
    String ename = rs.getString("ename");
    double sal = rs.getDouble("sal");
}

公司用的最基本的两个存储过程:

删除表

create or replace procedure drop_table(tablename in VARCHAR2) is vn_ctn number(2);
  Begin

  select count(*) into vn_ctn from user_all_tables a where a.table_name = upper(tablename); if vn_ctn > 0 then --execute immediate不管表在与不成都通过编译或执行 execute immediate 'drop table ' || tablename; end if; EXCEPTION WHEN OTHERS THEN dbms_output.put_line(SQLCODE || '::'||SUBSTR(SQLERRM, 1, 400)); End drop_table;

删除序列

create or replace procedure drop_sequence(sequenceName in VARCHAR2) is vn_ctn number(2);
  Begin

  select count(*) into vn_ctn from user_sequences a where a.sequence_name = upper(sequenceName); if vn_ctn > 0 then execute immediate 'drop sequence ' || sequenceName; end if; EXCEPTION WHEN OTHERS THEN dbms_output.put_line(SQLCODE || '::'||SUBSTR(SQLERRM, 1, 400)); End drop_sequence;

你可能感兴趣的:(oracle,plsql,存储)