/*
概述--
定义:存储在数据库中供所有用户调用的子程序叫存储过程或存储函数。
两者区别:
相同点:都是能完成特定功能的程序。
不同点:存储函数必须有一个return,用于返回函数的返回值,存储过程没有。
注意:
存储过程和存储函数不能被修改,只能创建或者替换,如果需要修改,直接
使用replace procedure 过程名修改。过程和函数都可以带参数列表和不带
参数列表。
*/
/******************************* 存储过程 **********************************/
语法:
create or replace procedure 过程名(参数列表)
as
变量定义说明
begin
PLSQL子程序
end;
*/
/*
存储过程调用:
exec helloword();
begin
helloword();
helloword();
helloword();
end;
*/
create or replace procedure helloword
as
--说明部分
begin
dbms_output.put_line('HelloWord!');
end;
/*
创建带参数的存储过程
eg:给指定员工涨工资,并打印涨前和涨后的薪水
注意:
当存储函数后过程带参数时,必须指明该参数是输出参数(out)还是输入参数(in)
*/
create or replace procedure raisesalary(eno in number)
as
--定义变量保存涨前薪水
--定义变量时引用员工表emp中的sal字段的类型为变量类型
pasl emp.sal%type;
begin
--得到涨前工资
select sal into pasl from emp where empno = eno;
--给指定员工涨工资
update emp set sal = sal + 100 where empon = eno;
/*
问题:存储过程和函数中是否可以commit和rollback?
可以(容易出现事务不同步),但是一般不用。
注意:
存储过程或函数中出现更新、插入等事务操作时,一般不commit和rollback,
因为存储过程和函数是作为一个程序的子程序被调用的,事务相关的一般在
主程序中操作。
*/
--打印涨前涨后薪水
dbms_output.put_line('涨前:'||pasl||'涨后:'||(pasl+100))
end;
/******************************* 存储函数 **********************************/
/*
语法:
create or replace FUNCTION 函数名(参数列表)
return 函数返回值类型
as
变量定义说明
begin
PLSQL子程序
end;
*/
/*
创建存储函数
eg:查询某个员工的年收入
*/
create or replace function queryempincome(eno in number)
return number
as
--定义变量保存员工薪水和奖金
pasl emp.sal%type;
pcomm emp.comm%type;
begin
--得到月薪和奖金
select sal,comm into pasl,pcomm from emp where empno = eno;
--返回年收入
--nvl(a,b) 预空函数,当a为空时用b
return sal*12 + nvl(pcomm,0);
end;
/**************************************输入输出参数*************************************/
/*
存储过程和函数都可以通过out指定一个或者多个输出参数,可以利用out参数在过程或者函数中实现返回多个值
注意:
一般情况下,需要一个返回值,使用存储函数,需要多个返回值,则使用存储函数
eg:
查询某个员工的姓名,月薪,职位
*/
create or replace procedure queryempinfo(eno in number,
pname out varchar2,
psal out number,
pjob out varchar2)
as
begin
select ename,esal,ejob into pname,psal,pjob from emp where empon = eno;
end;
/**************************************java中调用过程或者函数**************************************/
Connection con = null;
CallableStatement call = null;
String sql = "{call queryempinfo(?,?,?,?)}";
try{
--//获取连接
con = JDBCUtil.getConnection();
--//通过连接创建statement
call = con.prepareCall(sql);
--//处理入参in,赋值
call.setInt(1,111);
--//处理出参out,声明其类型
call.registerOutParameter(2, OracleTypes.VARCHAR);
call.registerOutParameter(3,OracleTypes.NUMBER);
call.registerOutParameter(4,OracleTypes.VARCHAR);
--//执行过程
call.execute();
--//获取结果
String name = call.getString(2);
Float sal = call.getFloat(3);
String job = call.getString(4);
--//输出
System.out.println(name + "\t" + sal + "\t" + job );
}catch(Exception e){
e.printStackTrace();
}finally{
util.JDBCUtil.release(con,call,null);
}
/*************************************out参数中使用光标******************************************/
/*
光标:自定义参数类型
使用:
使用光标时,必须声明包结构,包结构包括包头(包声明、光标定义、函数或过程定义)和包体,
包中可包含多个过程或者函数,类似于java中的接口包含多个方法,包体类似于接口实现
*/
/*包声明*/
create or replace package mypackage as
--自定义类型(使用光标cursor类型)
type empcursor for ref cursor;
--定义过程或函数,可以多个
procedure queryEmpList(eno int number,empList out empcursor);
function getSal(eno int number,sal out number);
end mypackage;
/*包体实现*/
create or replace package body mypackage as
--定义过程或函数,可以多个
/*
queryEmpList过程实现
*/
procedure queryEmpList(eno int number,empList out empcursor)
as
begin
--打开光标,将sql查询结果存入empLise
open empList for select * from emp where empno = eno;
end queryEMpList;
/*
getSal函数实现
*/
function getSal(eno int number,sal out number)
return number
as
psal emp.sal%type;
begin
select sal into psal from emp where empno = eno;
return psal;
end getSal;
end mypackage;
/*****************************************调用包中的过程或函数********************************************/
String sql = "{call mypackage.queryEmpList(?,?)}";
Connection con = null;
CallableStatement call = null;
ResultSet rs = null;
try{
--//获取连接
con = JDBCUtil.getConnection();
--//通过连接创建statement
call = con.prepareCall(sql);
--//处理入参in,赋值
call.setInt(1,111);
--//处理出参out,声明其类型自定义的类型使用的是光标cursor类型
call.registerOutParameter(2, OracleTypes.CURSOR);
--//执行过程
call.execute();
--//获取结果
rs = ((OrcaleCallableStatement)call).getCursor(2);
while(rs.next()){
--取出员工的职位、姓名、工资
String job = rs.getString("job");
Float sal = rs.getFloat("sal");
String name = rs.getString("name");
--//输出
System.out.println(name + "\t" + sal + "\t" + job );
}
}catch(Exception e){
e.printStackTrace();
}finally{
util.JDBCUtil.release(con,call,null);
}
概述--
定义:存储在数据库中供所有用户调用的子程序叫存储过程或存储函数。
两者区别:
相同点:都是能完成特定功能的程序。
不同点:存储函数必须有一个return,用于返回函数的返回值,存储过程没有。
注意:
存储过程和存储函数不能被修改,只能创建或者替换,如果需要修改,直接
使用replace procedure 过程名修改。过程和函数都可以带参数列表和不带
参数列表。
*/
/******************************* 存储过程 **********************************/
语法:
create or replace procedure 过程名(参数列表)
as
变量定义说明
begin
PLSQL子程序
end;
*/
/*
存储过程调用:
exec helloword();
begin
helloword();
helloword();
helloword();
end;
*/
create or replace procedure helloword
as
--说明部分
begin
dbms_output.put_line('HelloWord!');
end;
/*
创建带参数的存储过程
eg:给指定员工涨工资,并打印涨前和涨后的薪水
注意:
当存储函数后过程带参数时,必须指明该参数是输出参数(out)还是输入参数(in)
*/
create or replace procedure raisesalary(eno in number)
as
--定义变量保存涨前薪水
--定义变量时引用员工表emp中的sal字段的类型为变量类型
pasl emp.sal%type;
begin
--得到涨前工资
select sal into pasl from emp where empno = eno;
--给指定员工涨工资
update emp set sal = sal + 100 where empon = eno;
/*
问题:存储过程和函数中是否可以commit和rollback?
可以(容易出现事务不同步),但是一般不用。
注意:
存储过程或函数中出现更新、插入等事务操作时,一般不commit和rollback,
因为存储过程和函数是作为一个程序的子程序被调用的,事务相关的一般在
主程序中操作。
*/
--打印涨前涨后薪水
dbms_output.put_line('涨前:'||pasl||'涨后:'||(pasl+100))
end;
/******************************* 存储函数 **********************************/
/*
语法:
create or replace FUNCTION 函数名(参数列表)
return 函数返回值类型
as
变量定义说明
begin
PLSQL子程序
end;
*/
/*
创建存储函数
eg:查询某个员工的年收入
*/
create or replace function queryempincome(eno in number)
return number
as
--定义变量保存员工薪水和奖金
pasl emp.sal%type;
pcomm emp.comm%type;
begin
--得到月薪和奖金
select sal,comm into pasl,pcomm from emp where empno = eno;
--返回年收入
--nvl(a,b) 预空函数,当a为空时用b
return sal*12 + nvl(pcomm,0);
end;
/**************************************输入输出参数*************************************/
/*
存储过程和函数都可以通过out指定一个或者多个输出参数,可以利用out参数在过程或者函数中实现返回多个值
注意:
一般情况下,需要一个返回值,使用存储函数,需要多个返回值,则使用存储函数
eg:
查询某个员工的姓名,月薪,职位
*/
create or replace procedure queryempinfo(eno in number,
pname out varchar2,
psal out number,
pjob out varchar2)
as
begin
select ename,esal,ejob into pname,psal,pjob from emp where empon = eno;
end;
/**************************************java中调用过程或者函数**************************************/
Connection con = null;
CallableStatement call = null;
String sql = "{call queryempinfo(?,?,?,?)}";
try{
--//获取连接
con = JDBCUtil.getConnection();
--//通过连接创建statement
call = con.prepareCall(sql);
--//处理入参in,赋值
call.setInt(1,111);
--//处理出参out,声明其类型
call.registerOutParameter(2, OracleTypes.VARCHAR);
call.registerOutParameter(3,OracleTypes.NUMBER);
call.registerOutParameter(4,OracleTypes.VARCHAR);
--//执行过程
call.execute();
--//获取结果
String name = call.getString(2);
Float sal = call.getFloat(3);
String job = call.getString(4);
--//输出
System.out.println(name + "\t" + sal + "\t" + job );
}catch(Exception e){
e.printStackTrace();
}finally{
util.JDBCUtil.release(con,call,null);
}
/*************************************out参数中使用光标******************************************/
/*
光标:自定义参数类型
使用:
使用光标时,必须声明包结构,包结构包括包头(包声明、光标定义、函数或过程定义)和包体,
包中可包含多个过程或者函数,类似于java中的接口包含多个方法,包体类似于接口实现
*/
/*包声明*/
create or replace package mypackage as
--自定义类型(使用光标cursor类型)
type empcursor for ref cursor;
--定义过程或函数,可以多个
procedure queryEmpList(eno int number,empList out empcursor);
function getSal(eno int number,sal out number);
end mypackage;
/*包体实现*/
create or replace package body mypackage as
--定义过程或函数,可以多个
/*
queryEmpList过程实现
*/
procedure queryEmpList(eno int number,empList out empcursor)
as
begin
--打开光标,将sql查询结果存入empLise
open empList for select * from emp where empno = eno;
end queryEMpList;
/*
getSal函数实现
*/
function getSal(eno int number,sal out number)
return number
as
psal emp.sal%type;
begin
select sal into psal from emp where empno = eno;
return psal;
end getSal;
end mypackage;
/*****************************************调用包中的过程或函数********************************************/
String sql = "{call mypackage.queryEmpList(?,?)}";
Connection con = null;
CallableStatement call = null;
ResultSet rs = null;
try{
--//获取连接
con = JDBCUtil.getConnection();
--//通过连接创建statement
call = con.prepareCall(sql);
--//处理入参in,赋值
call.setInt(1,111);
--//处理出参out,声明其类型自定义的类型使用的是光标cursor类型
call.registerOutParameter(2, OracleTypes.CURSOR);
--//执行过程
call.execute();
--//获取结果
rs = ((OrcaleCallableStatement)call).getCursor(2);
while(rs.next()){
--取出员工的职位、姓名、工资
String job = rs.getString("job");
Float sal = rs.getFloat("sal");
String name = rs.getString("name");
--//输出
System.out.println(name + "\t" + sal + "\t" + job );
}
}catch(Exception e){
e.printStackTrace();
}finally{
util.JDBCUtil.release(con,call,null);
}