Oracle实战笔记(第七天)之PL/SQL进阶
Posted 风之之
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Oracle实战笔记(第七天)之PL/SQL进阶相关的知识,希望对你有一定的参考价值。
一、控制结构
控制结构包括:判断语句(条件分支语句)、循环语句、顺序控制语句三种。
1、条件分支语句
- if--then:简单条件判断
--编写一个过程,可以输入一个雇员名,如果该雇员名的工资低于2000,就给该雇员工资增加10% create or replace procedure pro_addSal(v_ename varchar2) is --定义变量 v_sal emp.sal%type; begin select sal into v_sal from emp where ename=v_ename; --判断 if v_sal<2000 then update emp set sal=sal+sal*0.1 where ename=v_ename; end if; end; /
- if--then--else:二重条件分支
--编写一个过程,可以输入一个雇员名,如果该雇员名的工资低于2000,就给该雇员工资增加10%,否则减少10% create or replace procedure pro_addSal(v_ename varchar2) is --定义变量 v_sal emp.sal%type; begin select sal into v_sal from emp where ename=v_ename; --判断 if v_sal<2000 then update emp set sal=sal+sal*0.1 where ename=v_ename; else update emp set sal=sal-sal*0.1 where ename=v_ename; end if; end; /
- if--then--elsif--else:多重条件分支
create or replace procedure pro_addSal(eNo number) is v_job emp.job%type; begin select job into v_job from emp where empno=eNo; if v_job=\'PRESIDENT\' then update emp set sal=sal+1000 where empno=eNo; elsif v_job=\'MANAGER\' then update emp set sal=sal+500 where empno=eNo; else update emp set sal=sal+200 where empno=eNo; end if; end; /
2、循环语句
- loop循环:pl/sql中最简单的循环语句,以loop开头,以exit()作为结束判断语句,以end loop结尾。(至少循环一次)
--编写一个过程,输入用户名,并循环添加10个用户到users表中 create table users(userId number(5),userName varchar(20));--为了后面操作先创建一个users表 create or replace procedure pro_addUser(eName varchar2) is --定义变量 v_num number:=1; begin loop insert into users values(v_num,eName); exit when v_num=10;--判断退出条件 v_num:=v_num+1;--自增 end loop; end; /
- while循环:其实就是使用while语句来代替loop循环的exit语句。
--编写一个过程,删除users表中的编号1—10的个用户 --用户编号从1开始增加。 create or replace procedure pro_delUser is --定义变量 v_num number:=1; begin while v_num<=10 loop delete from users where userId=v_num; v_num:=v_num+1;--自增 end loop; end; /
- for循环:自带变量和循环退出条件
create or replace procedure pro_addUser is begin for i in 1..10 loop insert into users values(i,\'lucy\'); end loop; end; /
3、顺序控制语句
- goto语句:用于跳转到特定标号去执行语句。注:由于使用gogo语句会增加程序的复杂性,并使得应用程序可读性变差,因此建议不要使用goto语句。
语法:goto lable,其中lable是已经定义好的标号名,如<<标记名>>,<<>>是标记符号,常用来跳出循环。
--循环输出i=1..10,最后跳出循环后打印“循环结束” declare i int:=1; begin loop dbms_output.put_line(\'i=\'||i); if i=10 then goto end_loop; end if; i:=i+1; end loop; <<end_loop>> dbms_output.put_line(\'循环结束\'); end; /
- null语句:null语句不会执行任何操作,并且会直接将控制传递到下一条语句。(类似Java中的continue的用法)
declare v_sal emp.sal%type; v_ename emp.ename%type; begin select ename,sal into v_ename,v_sal from emp where empno=&no; if v_sal<3000 then update emp set comm=sal*0.1 where ename=v_ename; else null; end if; end; /
二、使用Java程序调用存储过程
1、无返回值的存储过程
创建一个表book,表结构如下:
-
create table book(bId number(4) primary key,bName varchar(30) not null,publisher varchar(30));
编写一个过程,向book表添加书籍信息,要求可以通过java程序调用该过程:
- 使用命令行创建:
create or replace procedure pro_addBook(bookId number,bookName varchar2,pub varchar2) is begin insert into book values(bookId,bookName,pub); end; /
- 使用Java调用无返回值的过程:
1 package test; 2 import java.sql.CallableStatement; 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.SQLException; 6 7 import org.junit.Test; 8 9 /** 10 * 使用java调用Oracle创建的过程pro_addBook 11 */ 12 public class callPro_addBook { 13 @Test 14 public void test(){ 15 Connection conn = null; 16 CallableStatement cs = null; 17 try{ 18 //连接数据库 19 Class.forName("oracle.jdbc.driver.OracleDriver"); 20 conn = DriverManager.getConnection( 21 "jdbc:oracle:thin:@192.168.183.1:1521:orcl","scott","tiger"); 22 //获得执行对象 23 cs = conn.prepareCall("{call pro_addBook(?,?,?)}"); 24 //传参 25 cs.setInt(1, 1001); 26 cs.setString(2, "五年模拟三年高考"); 27 cs.setString(3, "教育出版社"); 28 //执行 29 cs.execute(); 30 }catch(Exception e){ 31 e.printStackTrace(); 32 }finally{ 33 try { 34 cs.close(); 35 conn.close(); 36 } catch (SQLException e) { 37 e.printStackTrace(); 38 } 39 } 40 } 41 }
2、有返回值的存储过程(返回若干值)
编写一个过程,要求输入book表的书号就返回书籍信息:书名和出版社
- 使用命令行创建过程:
create or replace procedure pro_showBook (bookId in number,bookName out varchar2,pub out varchar2) is begin select bName,publisher into bookName,pub from book where bId=bookId; end; /
- 使用Java调用返回值是若干数据的过程
1 package test; 2 import java.sql.CallableStatement; 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.SQLException; 6 7 import org.junit.Test; 8 9 /** 10 * 使用java调用Oracle创建的过程pro_addBook 11 */ 12 public class callPro_showBook { 13 @Test 14 public void test(){ 15 Connection conn = null; 16 CallableStatement cs = null; 17 try{ 18 //连接数据库 19 Class.forName("oracle.jdbc.driver.OracleDriver"); 20 conn = DriverManager.getConnection( 21 "jdbc:oracle:thin:@192.168.183.1:1521:orcl","scott","tiger"); 22 //获得执行对象 23 cs = conn.prepareCall("{call pro_showBook(?,?,?)}"); 24 //传入参数 25 cs.setInt(1, 1001); 26 cs.registerOutParameter(2, oracle.jdbc.OracleTypes.VARCHAR ); 27 cs.registerOutParameter(3, oracle.jdbc.OracleTypes.VARCHAR ); 28 //执行 29 cs.execute(); 30 //获取out参数 31 String bookName = cs.getString(2); 32 String pub = cs.getString(3); 33 System.out.println("书名:"+bookName); 34 System.out.println("出版社:"+pub); 35 }catch(Exception e){ 36 e.printStackTrace(); 37 }finally{ 38 try { 39 cs.close(); 40 conn.close(); 41 } catch (SQLException e) { 42 e.printStackTrace(); 43 } 44 } 45 } 46 }
3、有返回值的存储过程(返回一个列表)
为了方便说明,我们再往book表中添加几条数据:
现在的需求是:创建一个过程,要求返回指定出版社如“知乎周刊”出版的书籍信息。
如表所示,返回结果是三本书,而这种查询结果集我们一般放在一个list即列表中,而在oracle在接受返回值时需要使用包package,并用游标来进行参数输出:
-
--建立包,在该包中,定义一个游标类型test_cursor create or replace package testpackage as type test_cursor is ref cursor; end; /
- 使用命令行创建过程:
create or replace procedure pro_showPubBook (pub in varchar2,my_cursor out testpackage.test_cursor) is begin open my_cursor for select * from book where publisher=pub; end; /
- 使用Java调用返回值是列表的过程:
1 package test; 2 import java.sql.CallableStatement; 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.ResultSet; 6 import java.sql.SQLException; 7 8 import org.junit.Test; 9 10 /** 11 * 使用java调用Oracle创建的过程pro_addBook 12 */ 13 public class callPro_showPubBook { 14 @Test 15 public void test(){ 16 Connection conn = null; 17 CallableStatement cs = null; 18 try{ 19 //连接数据库 20 Class.forName("oracle.jdbc.driver.OracleDriver"); 21 conn = DriverManager.getConnection( 22 "jdbc:oracle:thin:@192.168.183.1:1521:orcl","scott","tiger"); 23 //获得执行对象 24 cs = conn.prepareCall("{call pro_showPubBook(?,?)}"); 25 //传入参数 26 cs.setString(1, "知乎周刊"); 27 cs.registerOutParameter(2,oracle.jdbc.OracleTypes.CURSOR );//游标类型 28 //执行 29 cs.execute(); 30 //获得结果集 31 ResultSet rs = (ResultSet) cs.getObject(2); 32 System.out.println("知乎周刊出版社书籍:"); 33 if(rs!=null) 34 while(rs.next()){ 35 System.out.println("书号:"+rs.getInt(1)+" "+"书名:《"+rs.getString(2)+"》"); 36 } 37 else 38 System.out.println("暂无书籍"); 39 }catch(Exception e){ 40 e.printStackTrace(); 41 }finally{ 42 try { 43 cs.close(); 44 conn.close(); 45 } catch (SQLException e) { 46 e.printStackTrace(); 47 } 48 } 49 } 50 }
三、分页编程
案例:编写一个存储过程,要求可以输入表名、每页显示记录数、当前页,返回总记录数、总页数和返回的结果集。
1、使用rownum分页查询
-
select * from emp; select t1.*,rownum rn from (select * from emp) t1; select t1.*,rownum rn from (select * from emp) t1 where rownum<=10; select * from (select t1.*,rownum rn from (select * from emp) t1 where rownum<=10) where rownum>=6;
2、编写分页的存储过程
-
--编写分页的存储过程 create or replace procedure fenye (tableName in varchar2,--in表名 myPageSize in number,--in记录数 pageNow in number,--in当前页 myRows out number,--out总记录数 myPageCount out number,--out总页数 p_cursor out testpackage.test_cursor--out结果集 )is v_sql varchar2(500);--定义sql语句 v_begin number:=(pageNow-1)*myPageSize+1;--定义起始页 v_end number:=pageNow*myPageSize;--定义尾页 begin --执行分页查询语句 v_sql:=\'select * from (select t1.*,rownum rn from (select * from \'||tableName||
\') t1 where rownum<=\'||v_end||\') where rn>=\'||v_begin; --把游标和sql语句关联 open p_cursor for v_sql; --计算myRows v_sql:=\'select count(*) from \'||tableName; execute immediate v_sql into myRows; --计算myPageCount if mod(myRows,myPageSize)=0 then myPageCount:=myRows/myPageSize; else myPageCount:=myRows/myPageSize+1; end if;end; /
3、使用Java调用分页过程
-
1 import java.sql.CallableStatement; 2 import java.sql.Connection; 3 import java.sql.DriverManager; 4 import java.sql.ResultSet; 5 6 public class Test { 7 public static void main(String[] args) { 8 // TODO Auto-generated method stub 9 Connection ct = null; 10 CallableStatement cs = null; 11 try { 12 Class. forName("oracle.jdbc.driver.OracleDriver"); 13 ct = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "***" ); 14 15 cs = ct.prepareCall( "{call fenye(?,?,?,?,?,?)}"); 16 17 // 赋值 18 cs.setString(1, "emp"); 19 cs.setInt(2, 5); 20 cs.setInt(3, 1); 21 22 // 注册总记录数 23 cs.registerOutParameter(4, oracle.jdbc.OracleTypes.INTEGER ); 24 // 注册总页数 25 cs.registerOutParameter(5, oracle.jdbc.OracleTypes.INTEGER ); 26 // 注册返回的结果集 27 cs.registerOutParameter(6, oracle.jdbc.OracleTypes.CURSOR ); 28 29 cs.execute(); 30 // 取出总记录数 31 int rowNum = cs.getInt(4); 32 // 取出总页数 33 int pageCount = cs.getInt(5); 34 ResultSet rs = (ResultSet) cs.getObject(6); 35 36 // 显示 37 System. out.println( "rowNum=" + rowNum); 38 System. out.println( "pageCount=" +python学习笔记之socket(第七天)