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 }
    callPro_addBook

  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 }
    callPro_showBook

  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 }
    callPro_showPubBook

三、分页编程

  案例:编写一个存储过程,要求可以输入表名、每页显示记录数、当前页,返回总记录数、总页数和返回的结果集。

  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(第七天)

    Oracle之PL/SQL学习笔记

    Oracle之PL/SQL学习笔记

    慕课网笔记之oracle开发利器-PL/SQL基础

    python运维开发之第七天

    Oracle学习笔记之PL/SQL编程