一存储过程
1.什么是存储过程,为什么使用存储过程
存储过程是存储在数据库中供用户调用的子程序,由于存储过程是存储在数据库中已经编译好的程序,在调用的时候,不必再次进行编译,从而提高了程序的运行效率.
2.存储过程的语法
创建存储过程的语法
create [or replace] procedure procedure_name ([{in| out}] data_type,parameter [{in| out}] data_type..)
(is|as)
pl/sql子程序;
in:表示输入参数 out:输出参数
调用存储过程有两种方法:
第一种:execute(exec) procedure_name(参数列表)
第二种:begin
procedure_name(参数列表)
end;
3.无参数的存储过程
create or replace
PROCEDURE empename as
emp_ename emp.ename%type;
emp_sal emp.sal%type;
begin
select ename ,sal into emp_ename,emp_sal from emp where empno=7934;
dbms_output.put_line(emp_ename||'的工资是'|| emp_sal);
end;
注意:声明变量不需要写declare
调用存储过程
set serveroutput on;
begin
empename;
end;
4.带参数的存储过程
create or replace
PROCEDURE empename(enum in number,emp_ename out emp.ename%type,emp_sal out emp.sal%type)
as
begin
select ename ,sal into emp_ename,emp_sal from emp where empno=enum;
end;
调用存储过程:
set serveroutput on;
declare
emp_ename emp.ename%type;
emp_sal emp.sal%type;
begin
empename(7369, emp_ename, emp_sal);
dbms_output.put_line(emp_ename||'的工资是'|| emp_sal);
end;
二存储函数
函数为一命名的存储程序,可带参数,并返回一计算值
1.存储函数的语法
create oy replace function function_name([{in| out}] data_type,parameter [{in| out}] data_type..)
return 返回值的数据类型
begin
函数要做的操作
end;
in:表示输入参数 out:输出参数
create or replace
function emp_function(eno in number) RETURN NUMBER
as
esal NUMBER;
ecommon NUMBER;
BEGIN
select sal ,comm into esal, ecommon from emp where empno=eno;
return esal+nvl(ecommon,0);
end;
调用函数
set serveroutput on;
declare
sal_sum NUMBER;
begin
sal_sum:=emp_function(7369);
dbms_output.put_line('7369的年薪是'||sal_sum);
end;
三.使用jdbc怎么调用存储函数和存储过程
jdbc调用存储函数和存储过程使用CallableStatement接口,sql语句如下;
{?= call <procedure-name>[(<arg1>,<arg2>, ...)]}------------------------------------->存储函数
{call <procedure-name>[(<arg1>,<arg2>, ...)]}----------------------------------->存储过程
调用存储过程
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import oracle.jdbc.OracleTypes;
import com.hotelmanagersystem.util.JdbcUtil;
public class maintest {
public static void main(String[] args) {
Connection conn=null;
CallableStatement sts=null;
ResultSet rs=null;
try {
conn=JdbcUtil.getConnection();
sts=conn.prepareCall("call empename(?,?,?)");
//设置输入参数
sts.setInt(1,7369);
//注册输出参数
sts.registerOutParameter(2,OracleTypes.VARCHAR);
sts.registerOutParameter(3,OracleTypes.NUMBER);
sts.execute();
System.out.println(sts.getString(2)+"的工资是"+sts.getInt(3));
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
JdbcUtil.closeAll(rs, sts, conn);
}
}
}
调用存储函数;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import oracle.jdbc.OracleTypes;
import com.hotelmanagersystem.util.JdbcUtil;
public class maintest {
public static void main(String[] args) {
Connection conn=null;
CallableStatement sts=null;
ResultSet rs=null;
try {
conn=JdbcUtil.getConnection();
sts=conn.prepareCall("{?=call emp_function(?)}");
//设置输入参数
sts.setInt(2,7369);
//注册输出参数
sts.registerOutParameter(1,OracleTypes.NUMBER);
sts.execute();
System.out.println("年薪是"+sts.getInt(1));
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
JdbcUtil.closeAll(rs, sts, conn);
}
}
}
注意:调用函数的大括号不能省略,调用存储过程可以省略。
四.包和包体
1.包和包体
前面我们看到的都是返回一行数据,如果返回多行数据怎么处理了,我们就可以使用游标,但是在存储过程和函数中使用游标只能在包中,现在来看包是什么
包就是一组相关的过程,函数,变量,常量和游标等PL/SQL 程序设计元素的组合,包分为包头和包体,
包头里面定义了包里面应该包含的 变量,过程,函数 等
在包头里面需要定义包里面的函数,存储过程等
包体里面对包头中定义的函数存储过程等进行实现
包头的定义语法:
CREATE OR REPLACE PACKAGE package_name IS
//游标,变量,过程,函数等
TYPE mycursor IS REF CURSOR;
PROCEDURE myproc(outcursor IN OUT mycursor);
END package_name;
包体:
CREATE OR REPLACE PACKAGE BODY mypack IS
PROCEDURE myproc(
outcursor IN OUT mycursor
)
IS
BEGIN
OPEN outcursor FOR
SELECT*FROM Student WHERE ROWNUM<10;
RETURN;
END myproc;
END;
包头代码:
CREATE OR REPLACE
PACKAGE MYPACKAGE AS
type empcursor is ref cursor;
PROCEDURE queryempList(dno in NUMBER,empList out empcursor);
/* TODO 在此输入程序包声明 (类型, 异常错误, 方法等) */
END MYPACKAGE;
包体代码;
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 queryempList ;
End;
2.JDBC调用包和包体
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import oracle.jdbc.OracleTypes;
import oracle.jdbc.internal.OracleCallableStatement;
import com.hotelmanagersystem.util.JdbcUtil;
public class maintest {
public static void main(String[] args) {
Connection conn=null;
CallableStatement sts=null;
ResultSet rs=null;
try {
conn=JdbcUtil.getConnection();
//注意sql语句的写法
sts=conn.prepareCall("{call MYPACKAGE.queryempList(?,?)}");
//设置输入参数
sts.setInt(1,10);
//注册输出参数,参数是游标型的
sts.registerOutParameter(2,OracleTypes.CURSOR);
sts.execute();
//转换成oracle的statement类型,就会有cursor方法
rs=((OracleCallableStatement)sts).getCursor(2);
while(rs.next()){
String name =rs.getString("ename");
int sal = rs.getInt("sal");
System.out.println(name+"的薪水是"+sal);
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
JdbcUtil.closeAll(rs, sts, conn);
}
}
}
五:触发器
pl/sql是一个与表相关的存储的pl/sql程序,每当一个特定的数据库操作语句(update,insert,delete)在指定的表上发出时,oracle自动的执行触发器中定义的语句序列。
创建触发器的语法格式:
create [or replace] trigger 触发器名
{before|after}
{delate | insert | updsate [of]列名 }
on 表名
[for each row [where( 条件)]]
pl/sql块
触发语句与伪列记录变量的值
触发语句 | :old | :new |
Insert | 所有字段都是空(null) | 将要插入的数据 |
Update | 更新以前该行的值 | 更新后的值 |
delete | 删除以前该行的值 | 所有字段都是空(null) |