PL/SQL 编程(二)

  1. 前面第一篇众中讲述了Java程序调用存储过程,这里再加以补充。

    存储过程可能无返回值、有返回值(非列表)、返回结果集等几种情况,下面一一举例:

  2. --建表
    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();
    			}
    		}
    	}
    }
    */
  3. PL/SQL的例外处理:

    oracle 将例外分为:预定义例外、非预定义例外和自定义例外 三种。前两者用来处理与oracle错误相关的,并且出现的oracle错误会隐含触发相应的例外;而自定义例外与oracle的错误没有任何关联,它是由开发人员为特定情况所定义的例外。

    a. 预定义例外:用于处理常见的oracle错误;非预定义例外用于处理预定义例外不能处理的例外;自定义例外用于处理     与oraccle错误无关的其他情况。

    oracle预定义例外大概有20多个,下面介绍一些常见的预定义例外:

  4. /*
    预定义例外: 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的错误没有任何关联,它是由开发人员为特定情况所定义的例外。

  5. /*
    自定义例外:
    */
    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;
  6. 视图(View):视图是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含 带有名称的列和行数据。但是视图并不在数据库中以存储的数据值集形式存在。行和列数据来自 由自定义视图的查询所引用的表,并且在引用视图时动态生成。视图和视图可以联合查询。

    视图和表的区别:

    1. 表需要占用磁盘空间,而视图不需要
    2. 视图不能添加索引,所以查询速度会比表慢一些
    3. 使用试图可以简化复杂查询
    4. 视图有利于提高安全性(不同用户查询不同内容的视图,分隔权限)

    语法:

    创建视图:create or replace view viewName as select ...  [with read only]

    删除视图:drop view viewName

时间: 2024-10-17 13:51:00

PL/SQL 编程(二)的相关文章

PL/SQL 编程(二)

1    For循环 语法:begin for i in reverse 1..10 loop insert into users values(i,'奥巴马'): end loop: end; 注意:循环变量 i 是隐含增加的,所以无法看到 2    goto语句 goto 语句用于跳转到特定的位置去执行语句.由于goto语句会减少程序的可读性,所以一般情况下 不建议使用goto语句 3    null语句 null语句不会执行任何操作,但是可以增加程序的可读性 4    创建返回值是一个结果

[顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之功)

原文:[顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之功) [顶]ORACLE PL/SQL编程详解之二: PL/SQL块结构和组成元素(为山九仞,岂一日之功) 继上四篇:ORACLE PL/SQL编程之八:把触发器说透                ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!)                [推荐]ORACLE PL/SQL编程之四:把游标说透(不怕做不到,只怕想不到) [推荐]

ORACLE PL/SQL编程之八(二): 把触发器说透

例2:创建DML语句行级触发器.当对emp表执行INSERT, UPDATE, DELETE 操作时,它自动更新dept_summary 表中的数据.由于在PL/SQL块中不能直接调用DDL语句,所以,利用ORACLE内置包DBMS_UTILITY中的EXEC_DDL_STATEMENT过程,由它执行DDL语句创建触发器. BEGIN  DBMS_OUTPUT.PUT_LINE('插入前');  Disp_dept_summary();  DBMS_UTILITY.EXEC_DDL_STATEM

ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!)

原文:ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!) ORACLE PL/SQL编程之六: 把过程与函数说透(穷追猛打,把根儿都拔起!)   继上篇:ORACLE PL/SQL编程之八:把触发器说透 得到了大家的强力支持,感谢.接下来再下猛药,介绍下一篇,大家一定要支持与推荐呀~!我也才有动力写后面的.   本篇主要内容如下: 6.1 引言 6.2 创建函数 6.3 存储过程 6.3.1 创建过程 6.3.2 调用存储过程 6.3.3 AUTHID 6.3.4 

【强烈强烈推荐】《ORACLE PL/SQL编程详解》全原创(共八篇)--系列文章导航

原文:[强烈强烈推荐]<ORACLE PL/SQL编程详解>全原创(共八篇)--系列文章导航 <ORACLE PL/SQL编程详解> 系列文章目录导航 ——通过知识共享树立个人品牌. 本是成书的,但后来做其他事了,就无偿的贡献出来,被读者夸其目前为止最“实在.经典”的写ORACLE PL/SQL编程的文章-! 觉得对你有帮助,请留言与猛点推荐,谢谢. [推荐]ORACLE PL/SQL编程详解之一:PL/SQL 程序设计简介(千里之行,始于足下) 本篇主要内容如下:第一章 PL/S

[推荐]ORACLE PL/SQL编程之四:把游标说透(不怕做不到,只怕想不到)

原文:[推荐]ORACLE PL/SQL编程之四:把游标说透(不怕做不到,只怕想不到) [推荐]ORACLE PL/SQL编程之四: 把游标说透(不怕做不到,只怕想不到) 继上两篇:ORACLE PL/SQL编程之八:把触发器说透 ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!) 得到了大家的强力支持,感谢.接下来再下猛药,介绍下一篇,大家一定要支持与推荐呀~!我也才有动力写后面的. 本篇主要内容如下: 4.1 游标概念 4.1.1 处理显式游标 4.1.2 处理

[推荐]ORACLE PL/SQL编程详解之三:PL/SQL流程控制语句(不给规则,不成方圆)

原文:[推荐]ORACLE PL/SQL编程详解之三:PL/SQL流程控制语句(不给规则,不成方圆) [推荐]ORACLE PL/SQL编程详解之三: PL/SQL流程控制语句(不给规则,不成方圆) ——通过知识共享树立个人品牌. 继上五篇: [顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之功) [推荐]ORACLE PL/SQL编程之四:把游标说透(不怕做不到,只怕想不到) [推荐]ORACLE PL/SQL编程之五:异常错误处理(知已知彼.百战不

[推荐]ORACLE PL/SQL编程详解之一:PL/SQL 程序设计简介(千里之行,始于足下)

原文:[推荐]ORACLE PL/SQL编程详解之一:PL/SQL 程序设计简介(千里之行,始于足下) [推荐]ORACLE PL/SQL编程详解之一: PL/SQL 程序设计简介(千里之行,始于足下) ——通过知识共享树立个人品牌. 继上六篇: [顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之功) [推荐]ORACLE PL/SQL编程详解之三:PL/SQL流程控制语句(不给规则,不成方圆) [推荐]ORACLE PL/SQL编程之四:把游标说透(

[强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!)

原文:[强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!) [强烈推荐]ORACLE PL/SQL编程详解之七: 程序包的创建与应用(聪明在于学习,天才在于积累!) ——通过知识共享树立个人品牌.   继上七篇:            [推荐]ORACLE PL/SQL编程详解之一:PL/SQL 程序设计简介(千里之行,始于足下)            [顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之

ORACLE PL/SQL编程总结(一)

----------PL/SQL 程序设计简介----------- 1.1   SQL与PL/SQL 1.1.1   什么是PL/SQL? PL/SQL是 Procedure Language & Structured Query Language 的缩写.PL/SQL是对SQL语言存储过程语言的扩展.从ORACLE6以后,ORACLE的RDBMS附带了PL/SQL.它现在已经成为一种过程处理语言,简称PL/SQL.目前的PL/SQL包括两部分,一部分是数据库引擎部分:另一部分是可嵌入到许多产