--定义
create or replace procedure my_procedure
as
begin
dbms_output.put_line('这是第一个存储过程');
end my_procedure;
--调用
begin
my_procedure();
end;
--带输入参数的存储过程(插入数据的存储过程)
create or replace procedure my_procedure2
(
v_empno in number,
v_ename in varchar2,
v_job in varchar2,
v_deptno in number
)
as
begin
--执行一个插入语句
insert into emp (empno,ename,job,deptno) values (v_empno,v_ename,v_job,v_deptno);
end my_procedure2;
--调用
begin
my_procedure2(7944,'老梅','teacher',10);
end;
select * from emp;
--带输入输出参数的存储过程,根据输出工资查询出大于该工资的员工人数
create or replace procedure my_procedure3
(
v_sal in number,
v_count out number
)
as
begin
select count(1) into v_count from emp where sal > v_sal;
end my_procedure3;
--调用
declare
v_count number;
v_sal number := 7000;
begin
my_procedure3(v_sal, v_count);
dbms_output.put_line('工资高于'||v_sal||'的人数为'||v_count);
end;
--cursor test is select * from emp
--分页的存储过程,输入参数必须要: 当前页(number)以及一页显示条数(number) 输出参数:总页数(number)和分页数据
create or replace procedure page_handler
(
page_number in number,
page_size in number
)
as
--声明变量
total_rows number;
total_page number;
copy_page_number number := page_number;
--声明一个弱类型游标类型
type page_cursor_type is ref cursor;
--声明游标变量
page_cursor page_cursor_type;
--定义一个记录类型
type v_emp_type is record(
rn number,
empno emp.empno%type,
ename emp.ename%type,
job emp.job%type,
mgr emp.mgr%type,
hiredate emp.hiredate%type,
sal emp.sal%type,
comm emp.comm%type,
deptno emp.deptno%type
);
v_emp v_emp_type;
begin
--查询数据总条数
select count(1) into total_rows from emp;
dbms_output.put_line('数据总条数:'||total_rows);
--通过数据总数和一页显示行数计算总页数
--使用向上取整的函数 ceil
total_page := ceil(total_rows/page_size);
--对page_number进行合法校验
--输入参数的值时不能改变的
if copy_page_number < 1 then
copy_page_number := 1;
elsif copy_page_number > total_page then
copy_page_number := total_page;
end if;
dbms_output.put_line('当前页码:'||copy_page_number);
--进行分页查询,打开一个动态游标
open page_cursor for 'select * from (select rownum rn, emp.* from emp where rownum <= '|| (copy_page_number*page_size) ||') e where e.rn > '|| (copy_page_number-1)*page_size ||'';
loop
fetch page_cursor into v_emp;
exit when page_cursor%notfound;
dbms_output.put_line(v_emp.empno||' '||v_emp.ename);
end loop;
close page_cursor;
end page_handler;
--子查询
select * from (select rownum rn, emp.* from emp where rownum < 10) e where e.rn > 0;
--执行
begin
page_handler(-1, 5);
end;
select * from emp;
select ceil(5/3) from dual;
--包的使用,在包中定义一个存储过程,输入参数为薪资,输出输出为游标变量
create or replace package my_package
as
--定义游标、存储过程、函数等
--定义一个游标类型
type emp_cursor_type is ref cursor;
procedure getEmp(v_sal in number, emp_cursor out emp_cursor_type);
end my_package;
--定义包体部分
create or replace package body my_package
as
--实现存储过程
procedure getEmp(v_sal in number, emp_cursor out emp_cursor_type)
as
begin
open emp_cursor for select * from emp where sal > v_sal;
end getEmp;
end my_package;
--调用程序包
declare
--声明游标变量
emp_cursor my_package.emp_cursor_type;
v_emp emp%rowtype;
begin
my_package.getEmp(9999, emp_cursor);
loop
fetch emp_cursor into v_emp;
exit when emp_cursor%notfound;
dbms_output.put_line(v_emp.empno||' '||v_emp.ename);
end loop;
end;
select * from emp;
create or replace procedure page_handler2
(
page_number in number,
page_size in number,
total_page out number,
data_list out my_package.emp_cursor_type
)
as
total_rows number;
copy_page_number number := page_number;
begin
--查询总条数
select count(1) into total_rows from emp;
--计算总页数
total_page := ceil(total_rows/page_size);
--校验当前页码
if copy_page_number < 1 then
copy_page_number := 1;
elsif copy_page_number > total_page then
copy_page_number := total_page;
end if;
--分页查询
open data_list for 'select * from (select rownum rn, emp.* from emp where rownum<='||(copy_page_number*page_size)||') e where e.rn>'||(copy_page_number-1)*page_size||'';
end page_handler2;
--调用
declare
total_page number;
data_list my_package.emp_cursor_type;
--定义一个记录类型
type v_emp_type is record(
rn number,
empno emp.empno%type,
ename emp.ename%type,
job emp.job%type,
mgr emp.mgr%type,
hiredate emp.hiredate%type,
sal emp.sal%type,
comm emp.comm%type,
deptno emp.deptno%type
);
v_emp v_emp_type;
begin
page_handler2(4,5,total_page,data_list);
dbms_output.put_line('总页数:'||total_page);
loop
fetch data_list into v_emp;
exit when data_list%notfound;
dbms_output.put_line('员工姓名:'||v_emp.ename||',员工职位:'||v_emp.job);
end loop;
end;
call my_procedure();
select * from emp;
drop table emp_history;
create table emp_history as select * from emp where 1=2;
--删除员工信息时将删除的员工保存到历史记录表中
create or replace trigger del_emp_tr
after delete on emp for each row
begin
--触发器有两个伪属性,:old :new
insert into emp_history values (:old.empno,:old.ename,:old.job,:old.mgr,:old.hiredate,:old.sal,:old.comm,:old.deptno);
end;
--执行删除触发触发器
delete from emp where empno=7944;
--oracle没有主键自增,可以使用序列代替
create sequence emp_seq
increment by 1
start with 1
nomaxvalue
nocycle
nocache;
create or replace trigger add_emp_tr
before insert on emp for each row
begin
select emp_seq.nextval into :new.empno from dual;
end;
insert into emp (ename,job) values ('admin', 'DBA');
--创建一个索引
create index ename_index on emp (ename);
--删除
drop index ename_index;
--赋予用户创建视图的权限
grant create view to meijiajie;
--创建一个视图
create or replace view vw_emp as select ename,job from emp;
select * from vw_emp;
create user meijiajie2 identified by meijiajie2;
grant create session to meijiajie2;
grant select on meijiajie.vw_emp to meijiajie2;
public class TestProcedure {
private Connection conn;
@Before
public void beforeMethod() throws ClassNotFoundException, SQLException {
//加载驱动
Class.forName("oracle.jdbc.driver.OracleDriver");
//获取连接
//oracle的连接(瘦连接):jdbc:oracle:thin:@192.168.10.254:1521:orcl
conn = DriverManager.getConnection("jdbc:oracle:thin:@192.168.10.254:1521:orcl", "meijiajie", "meijiajie");
}
@After
public void afterMethod() throws SQLException {
//关闭连接
if (conn != null) {
conn.close();
}
}
@Test
public void test1() throws SQLException {
//获取语句执行对象
CallableStatement cs = conn.prepareCall("call my_procedure()");
//执行存储过程
cs.execute();
//关闭资源
cs.close();
}
@Test
public void test2() throws SQLException {
CallableStatement cs = conn.prepareCall("call my_procedure2(?,?,?,?)");
//设置参数
cs.setInt(1, 2);
cs.setString(2, "金三胖");
cs.setString(3, "高丽棒子");
cs.setInt(4, 10);
//执行
cs.executeUpdate();
//关闭资源
cs.close();
}
@Test
public void test3() throws SQLException {
CallableStatement cs = conn.prepareCall("call my_procedure3(?,?)");
cs.setInt(1, 9999);
//如何去传入一个输出参数,
//输出参数需要注册
cs.registerOutParameter(2, Types.INTEGER);
//执行
cs.execute();
//获取输出参数
int count = cs.getInt(2);
System.out.println(count);
}
@Test
public void test4() throws SQLException {
CallableStatement cs = conn.prepareCall("call page_handler2(?,?,?,?)");
//设置参数
cs.setInt(1, 4);
cs.setInt(2, 5);
cs.registerOutParameter(3, Types.INTEGER);
//Oracle的游标类型需要使用OracleTypes中的常量
cs.registerOutParameter(4, OracleTypes.CURSOR);
//执行
cs.execute();
//获取输出结果
int totalPage = cs.getInt(3);
System.out.println("总页数:" + totalPage);
//获取返回的游标
ResultSet rs = (ResultSet) cs.getObject(4);
while (rs.next()) {
System.out.println(rs.getString("ename") + "\t" + rs.getString("job"));
}
}
}