无参存储过程:
create or replace procedure sayhello
as
--说明部分
begin
dbms_output.put_line('hello world');
end;
- 1
- 2
- 3
- 4
- 5
- 6
命令窗口的两种调用方法
- 1.
SQL> set serveroutput on; --第一次一定要开
SQL> exec sayhello
hello world
PL/SQL procedure successfully completed
- 1
- 2
- 3
- 4
- 2.
SQL> begin
2 sayhello();
3 sayhello();
4 end;
5 /
hello world
hello world
PL/SQL procedure successfully completed
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
pl/sql块 调试
BEGIN
SAYHELLO();
--rollback;
END;
- 1
- 2
- 3
- 4
SQL窗口调用(不会输出dbms_output的内容)
exec是sqlplus的命令,只能在sqlplus中使用(PLSQL Developer的命令窗口也是这种)。
call是sql命令,任何工具都可以使用。如果想返回结果就用 传递参数
call sayhello();
- 1
有参存储过程
案例:给员工涨薪水
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;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
PL/SQL块调试
DECLARE
ENO NUMBER;
BEGIN
ENO := 7499;
RAISESALARY(
ENO => ENO
);
--rollback;
END;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
案例:查询员工信息
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;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
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;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
有参存储函数
案例:查询员工的年收入
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;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
–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;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
查看存储过程的属性是输入还是输出的
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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
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;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
命令窗口(查看程序包的结构)
SQL> desc mypackage
Element Type
------------ ---------
EMPCURSOR TYPE
QUERYEMPLIST PROCEDURE
SQL> desc mypackage.queryEmpList
Parameter Type Mode Default?
--------- ---------- ---- --------
DNO NUMBER IN
EMPLIST REF CURSOR OUT
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
应用程序中访问存储过程和存储函数
访问存储过程
//获取数据库的连接
略
//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);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
访问存储函数
//获取数据库的连接
略
//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);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
访问有光标的存储过程
//获取数据库的连接
略
//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");
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
公司用的最基本的两个存储过程:
删除表
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;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
删除序列
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;