- 前面第一篇众中讲述了Java程序调用存储过程,这里再加以补充。
存储过程可能无返回值、有返回值(非列表)、返回结果集等几种情况,下面一一举例:
-
--建表 drop table book; create table book( bookId number(10) primary key, bookName varchar2(50), publishHouse varchar2(50), bookClass number(3) not null); /* 案例 实例16-向表book中添加书籍,并用java程序调用: */ --存储过程:in 表示输入参数, out表示输出参数, 不写默认是输入参数 create or replace procedure add_book(proBookId in number, proBookName in varchar2, proPublishHouse in varchar2, proBookClass in number) is begin insert into book values(proBookId, proBookName, proPublishHouse, proBookClass); end; /* --Java调用 public class TestProcedure { public static void main(String[] args) { Connection conn = null; CallableStatement cs = null; try { //加载驱动 Class.forName("oracle.jdbc.driver.OracleDriver"); //获得连接 conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "dog", "dog"); cs = conn.prepareCall("{call add_book(?, ?, ?)}"); //设置参数 cs.setInt(1, 1); cs.setString(2, "Thinking in Java"); cs.setString(3, "America Universe Publish"); cs.setInt(4, 1); //执行 cs.execute(); } catch (Exception e) { e.printStackTrace(); } finally { try { cs.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } */ /* 案例:有返回值的存储过程(返回值非列表) 实例17-输入书籍编号,返回书籍名、出版社 */ create or replace procedure get_book(proBookId in number, proBookName out varchar2, proPublishHouse out varchar2) is begin select bookName, publishHouse into proBookName, proPublishHouse from book where bookId = proBookId; end; /* --Java调用 public class TestProcedure { public static void main(String[] args) { Connection conn = null; CallableStatement cs = null; try { //加载驱动 Class.forName("oracle.jdbc.driver.OracleDriver"); //获得连接 conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "dog", "dog"); cs = conn.prepareCall("{call get_book(?, ?, ?)"); //设置输入参数 cs.setInt(1, 1); //设置输出参数 cs.registerOutParameter(2, oracle.jdbc.OracleTypes.VARCHAR); cs.registerOutParameter(3, oracle.jdbc.OracleTypes.VARCHAR); //执行 cs.execute(); //输出返回值 String bookName = cs.getString(2); String publishHouse = cs.getString(3); System.out.println("书名:" + bookName + " ---出版社:" + publishHouse); } catch (Exception e) { e.printStackTrace(); } finally { try { cs.close(); conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } */ /* 案例:有返回值的存储过程(返回值是列表(结果集)) 由于返回的是结果集,不能使用一般的out参数,必须使用package。 实例18-输入书籍类别,返回书籍信息 */ --再向book表中插入几条数据 --insert into book values(1, ‘Thinking in Java‘, ‘America Universe Publish‘, ‘001‘); insert into book values(2, ‘Harry Potter‘, ‘Titan Books Ltd‘, ‘001‘); insert into book values(3, ‘The Accident‘, ‘Orion Publishing Co‘, ‘001‘); --第一步:创建一个包 --定义一个游标类型 create or replace package pak_ResultSet is type pak_cursor_type is ref cursor; end; --第二部:创建存储过程 create or replace procedure pro_ResultSet(proBookClass in number, pak_cursor out pak_ResultSet.pak_cursor_type) is begin --打开游标 open pak_cursor for select * from book where bookClass = proBookClass; end; /*Java调用 public class TestProcedure { public static void main(String[] args) { Connection conn = null; CallableStatement cs = null; ResultSet rs = null; try { //加载驱动 Class.forName("oracle.jdbc.driver.OracleDriver"); //获得连接 conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "dog", "dog"); //有输入参数 和 输出参数,输出参数 是 结果集 cs = conn.prepareCall("{call pro_ResultSet(?, ?)}"); cs.setInt(1, 1); //结果集参数设置 cs.registerOutParameter(2, oracle.jdbc.OracleTypes.CURSOR); cs.execute(); //得到结果 rs = (ResultSet) cs.getObject(2); while (rs.next()) { System.out.println("书编号:" + rs.getInt(1) + " ---书名:" + rs.getString(2) + " ---出版社:" + rs.getString(3) + " ---类别:" + rs.getString(4)); } } catch (Exception e) { e.printStackTrace(); } finally { try { cs.close(); conn.close(); rs.close(); } catch (SQLException e) { e.printStackTrace(); } } } } */
- PL/SQL的例外处理:
oracle 将例外分为:预定义例外、非预定义例外和自定义例外 三种。前两者用来处理与oracle错误相关的,并且出现的oracle错误会隐含触发相应的例外;而自定义例外与oracle的错误没有任何关联,它是由开发人员为特定情况所定义的例外。
a. 预定义例外:用于处理常见的oracle错误;非预定义例外用于处理预定义例外不能处理的例外;自定义例外用于处理 与oraccle错误无关的其他情况。
oracle预定义例外大概有20多个,下面介绍一些常见的预定义例外:
-
/* 预定义例外: no_data_found, 之前在第一篇中出现过,不再赘述 */ /* 预定义例外: case_not_found */ create or replace procedure pro_caseException(EmployNum number) is v_sal emp.sal%type; begin select sal into v_sal from emp where empno = EmployNum; case when v_sal < 1000 then update emp set sal = sal + 200 where empno = EmployNum; when v_sal < 2000 then update emp set sal = sal + 100 where empno = EmployNum; --这里如果没有指定default情况,而又不符合上面两个case,可能会报错,可以在下面指定exception end case; exception when case_not_found then dbms_output.put_line(‘case not matched‘); end; /* 预定义例外: cursor_already_open */ declare cursor emp_cursor is select ename, sal from emp; begin open emp_cursor; for emp_record1 in emp_cursor loop dbms_output.put_line(emp_record1.ename); end loop; exception when cursor_already_open then dbms_output.put_line(‘Cursor has been opened!‘); end; /* 预定义例外: dup_val_on_index 在唯一索引对应的列上插入重复的值时,会隐含的触发该例外 */ begin insert into dept values(10, ‘技术部‘, ‘shanghai‘); exception when dup_val_on_index then dbms_output.put_line(‘Duplicated Deptno!‘); end; /* 预定义例外: invalid_cursor 当试图在不合法的游标上执行操作时,会触发该例外(游标没有打开或是关闭没有打开的游标) */ declare cursor emp_cursor is select ename, sal from emp; emp_record emp_cursor%rowtype; begin --open emp_cursor; fetch emp_cursor into emp_record; dbms_output.put_line(emp_record.ename); close emp_cursor; exception when invalid_cursor then dbms_output.put_line(‘Cursor has been closed!‘); end; /* 预定义例外: invalid_number 当输入的数据有误时,会触发该例外 */ begin update emp set sal=sal + ‘abc‘; exception when invalid_number then dbms_output.put_line(‘Number error!‘); end; /* 预定义例外: too_many_rows 当执行select into 语句时,如果返回超过了一行,则会触发该例外 */ declare v_ename emp.ename%type; begin select ename into v_ename from emp; exception when too_many_rows then dbms_output.put_line(‘Return too many rows!‘); end; /* 预定义例外: zero_divide 当执行2/0 语句时,则会触发该例外 */ declare c_num number := 2; begin c_num := c_num/0; exception when zero_divide then dbms_output.put_line(‘Zero cannot be divide!‘); end; /* 预定义例外: value_error 当在执行赋值操作时,如果变量的长度不足以容纳实际数据,则会触发该例外 */ declare v_ename varchar2(5); begin select ename into v_ename from emp where empno = 7654; exception when value_error then dbms_output.put_line(‘Value is too large for v_ename!‘); end; /* 其他预定义例外: login_denide --- 用户非法登陆时,会触发该例外 not_logged_on --- 用户没有登陆就执行dml操作,,会触发该例外 storage_error --- 超出了内存空间或者内存被损坏,,会触发该例外 timeout_on_resource --- 如果oracle在等待资源时出现超时,,会触发该例外 */
b. 自定义例外:与oracle的错误没有任何关联,它是由开发人员为特定情况所定义的例外。
-
/* 自定义例外: */ create or replace procedure test_ModifiedException(EmployeeNo number) is --定义一个例外 myex exception; begin update emp set sal = sal + 1000 where empno = EmployeeNo; --sql%notfound 表示没有update --raise myex; 触发myex 例外 if sql%notfound then raise myex; end if; exception when myex then dbms_output.put_line(‘Myex has been occured!‘); end;
- 视图(View):视图是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含 带有名称的列和行数据。但是视图并不在数据库中以存储的数据值集形式存在。行和列数据来自 由自定义视图的查询所引用的表,并且在引用视图时动态生成。视图和视图可以联合查询。
视图和表的区别:
- 表需要占用磁盘空间,而视图不需要
- 视图不能添加索引,所以查询速度会比表慢一些
- 使用试图可以简化复杂查询
- 视图有利于提高安全性(不同用户查询不同内容的视图,分隔权限)
语法:
创建视图:create or replace view viewName as select ... [with read only]
删除视图:drop view viewName
时间: 2024-10-17 13:51:00