oralce实战第七天--pl/sql的进阶、分页存储过程、例外和视图
2012-05-07 13:58
429 查看
内容介绍
1.pl/sql的进阶
2.oracle的视图
3.oracle的触发器
期望目标
1.掌握pl/sql的高级用法(能编写分页过程模块,下订单过程模块…)。
2.会处理oracle常见的例外。
3.会编写oracle各种触发器。
4.理解视图的概念并能灵活使用视图。
pl/sql的进阶
控制结构
在任何计算机语言(c,java,pascal)都有各种控制语句(条件语句,循环语句,顺序控制结构…)在pl/sql中也存在这样的控制结构。
条件分支语句
Plsql中提供了三种条件分支语句
If…then
If…then….else
If…then…elsif…else
简单的条件判断If…then
编写一个过程,可以输入一个雇员名,如果该雇员的工资低于2000,就给雇员工资增加10%。
二重条件分支If…then….else
编写一个过程,可以输入一个雇员名,如果该雇员的补助不是0就在原来的基础上增加100;如果补助为0就把补助设为200。
多重条件分支If…then…elsif…else
编写一个过程,可以输入一个雇员的编号,如果该雇员的职位是president就给他的工资增加1000,如果该雇员的职位是MANAGER就给他的工资增加500,其它职位的雇员工资增加200.
循环语句
loop
是pl/sql中最简单的循环语句,这种循环语句以loop开头,以end loop结尾,这种循环至少会被执行一次。
案例:现有一张表users,表结构如下
用户id 用户名
1 zhangsan
请编写一个过程,可输入用户名,并循环添加10个用户到users表中,用户编号从1开始增加。
while
基本循环至少要执行循环体一次,而对于while循环来说,只有条件为true时,才会执行循环体语句,while循环以while…loop开始,以end loop结束。
案例:现有一张表users,表结构如下
用户id 用户名
1 zhangsan
请编写一个过程,可输入用户名,并循环添加10个用到users表中,用户编号从11开始增加。
For
for循环的基本结构如下:
我们可以看到控制变量I, 在隐含中就在不停的增加。
顺序控制语句
Goto语句
Goto语句用于跳转到特定标号去执行语句。注意由于使用goto语句会增加程序的复杂性,并使得应用程序可读性变差,所以在做一般应用开发时,建议不要使用goto语句。
基本语法如下goto lable是已经定义好的标号名。
null
null语句不会执行任何操作,并且直接将控制传递到下一条语句。使用null语句的主要好处是可以提高pl/sql的可读性。
编写分页过程
分页是任何一个网站(bbs,网上商城,blog)都会使用到的技术,因此学习pl/sql编程开发就一定要掌握该技术。
无返回值的存储过程
古人云:欲速则不达。为了让大家比较容易接受分页过程编写,我们还是从简单到复杂,循序渐进的给大家讲解。首先是掌握最简单的过程,无返回值的存储过程:
案例:现有一张表,表结构如下:
请编写一个过程,可以向book表添加书,要求通过java程序调用该过程。
在java中调用:
有返回值的存储过程(非列表)
再看如何处理有返回值的存储过程:
案例:编写一个过程,可以输入雇员的编号,返回该雇员的姓名。
在java中调用
案例扩张:编写一个过程,可以输入雇员的编号,返回该雇员的姓名,工资和岗位。
在java中调用
有返回值的存储过程(列表[结果集])
案例:编写一个过程,输入部门号,返回该部门所有雇员信息。
对该题分析如下:
由于oracle存储过程没有返回值,它的所有返回值都是通过out参数来替代的,列表同样也不例外,但由于是集合,所以不能用一般的参数,必须要用package了,所以要分两部分:
1)建一个包,如下:
2)建立存储过程
3)在java中调用
编写存储过程
有了上面的基础,相信大家可以完成分页存储过程了。
要求,请编写一个存储过程,要求可以输入表名,每页显示记录数,当前页。返回总记录数,总页数和返回的结果集。
分页的写法:
可以当成一个模板来使用。
分页的存储过程
分页的算法请参考第三天的内容。
在java中调用
例外处理
例外的分类
Oracle将例外分为预定义例外,非预定义例外和自定义例外三种。
预定义例外用于处理常见的oracle错误。
非预定义例外用于处理预定义例外不能处理的例外。
自定义例外用于处理与oracle错误无关的其它情况。
例外处理
例外传递
如果不处理例外我们看看会出现什么情况:
案例:编写一个过程,可接收雇员的编号,并显示该雇员的姓名。
问题是,如果输入的雇员的编号不存在,怎样去处理呢?
处理预定义例外
预定义例外是由pl/sql所提供的系统例外。当pl/sql应用程序违反了oracle规定的限制时,则会隐含的触发一个内部例外。Pl/sql为开发人员提供了二十多个预定义例外。我们给大家介绍常用 的例外。
Case_not_found
在开发pl/sql块中编写case语句时,如果when子句中没有包含必须的条件分支,就会触发case_not_found的例外:
Cursor_already_open
当重新打开已经打开的游标时,会隐含的触发例外cursor_already_open
Dup_val_on_index
在唯一索引所对应的列上插入重复的值时,会隐含的触发例外dup_val_on_index例外
Invalid_cursor
当试图在不合法的游标上执行操作时,会触发该例外
例如:试图从没有打开的游标提取数据,或是关闭没有打开的游标。则会触发访例外
Invalid_number
当输入的数据有误时,会触发该例外
比如:数字100写成了1oo就会触发该例外。
No_data_found
下面是一个pl/sql块,当执行select into没有返回行,就会触发该例外。
Too_many_rows
当执行select into语句时,如果返回超过了一行,就会该例外。
Zero_divide
当执行2/0语句时,则会触发该例外。
Value_error
当执行赋值操作时,如果变量的长度不足以容纳实际数据,则会触发该例外value_error,
比如:
其它预定义例外:
1)login_denide
当用户非法登陆时,会触发该例外。
1) Not_logged_on
如果用户没有登陆就执行dml操作,就会触发该例外。
2) Storage_error
如果超出了内存空间或是内存被损坏,就会触发该例外。
3) Timeout_on_resource
如果oracle在等待资源时,出现了超时就会触发该例外。
非预定义例外
非预定义例外用于处理与预定义例外无关的oracle错误。使用预定义例外只能处理21个oracle错误,而当使用pl/sql开发应用程序时,可能会遇到其他的一些oracle错误。比如在pl/sql块中执行dml语句时,违反了约束规定等等,在这样的情况下,也可以处理oracle的各种例外,因为非预定义例外的不多,这里就不举例了。
处理自定义例外
预定义例外和自定义例外都是oracle错误相关的,并且出现的oracle错误会隐含的触发相应的例外;而自定义例外与oracle错误没有任何关联,它是由开发人员为特定情况所定义的例外。
请编写一个pl/sql块,接收一个雇员的编号,并给雇员工资增加1000元,如果该雇员不存在,请提示。
Oracle视图
视图是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据。但是,视图并不在数据库中以存储的数据值集形式存在。行和列数据来自由定义视图的查询所引用的表,并且在引用视图时动态生成。
假设以下情境:
1.如果要显示各个雇员的名字他所有部门的名称,必须用两张表。
2.假设管理员创建了一个用户,xiaohong,现在就希望xiaohong只可以查询sal<1000的哪些雇员。
这时我们就可以用视图来解决。
视图与表的区别:
1.表需要占用磁盘空间,视图不需要。
2.视图不能添加索引。
3.使用视图可以简化复杂查询。比如:学生选课系统。
4.视图利于提高安全性。
比如:不同用户查看不同视图。
创建视图
创建或修改视图
删除视图
1.pl/sql的进阶
2.oracle的视图
3.oracle的触发器
期望目标
1.掌握pl/sql的高级用法(能编写分页过程模块,下订单过程模块…)。
2.会处理oracle常见的例外。
3.会编写oracle各种触发器。
4.理解视图的概念并能灵活使用视图。
pl/sql的进阶
控制结构
在任何计算机语言(c,java,pascal)都有各种控制语句(条件语句,循环语句,顺序控制结构…)在pl/sql中也存在这样的控制结构。
条件分支语句
Plsql中提供了三种条件分支语句
If…then
If…then….else
If…then…elsif…else
简单的条件判断If…then
编写一个过程,可以输入一个雇员名,如果该雇员的工资低于2000,就给雇员工资增加10%。
create or replace procedure p_updateEmpSal (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 * 1.1 where ename = v_ename; end if; end; exec p_updateEmpSal('SCOTT'); |
编写一个过程,可以输入一个雇员名,如果该雇员的补助不是0就在原来的基础上增加100;如果补助为0就把补助设为200。
create or replace procedure p_updateEmpSalAndComm (v_ename varchar2) is v_comm emp.comm%type; begin select comm into v_comm from emp where ename= v_ename; if v_comm <> 0 then update emp set comm = comm + 100 where ename = v_ename; else update emp set comm = comm + 200 where ename = v_ename; end if; end; |
编写一个过程,可以输入一个雇员的编号,如果该雇员的职位是president就给他的工资增加1000,如果该雇员的职位是MANAGER就给他的工资增加500,其它职位的雇员工资增加200.
create or replace procedure p_updateSalBaseTitle (v_empno number) is v_job emp.job%type; begin select job into v_job from emp where empno = v_empno; if v_job = 'PRESIDENT' then update emp set sal=sal + 1000 where empno = v_empno; elsif v_job = 'MANAGER' then update emp set sal=sal + 500 where empno = v_empno; else update emp set sal=sal + 200 where empno = v_empno; end if; end; |
loop
是pl/sql中最简单的循环语句,这种循环语句以loop开头,以end loop结尾,这种循环至少会被执行一次。
案例:现有一张表users,表结构如下
用户id 用户名
1 zhangsan
请编写一个过程,可输入用户名,并循环添加10个用户到users表中,用户编号从1开始增加。
create or replace procedure p_addUsers (v_name varchar2) is v_num number := 1; begin loop insert into users values(v_num,v_name); exit when v_num = 10; v_num := v_num + 1; end loop; end; |
基本循环至少要执行循环体一次,而对于while循环来说,只有条件为true时,才会执行循环体语句,while循环以while…loop开始,以end loop结束。
案例:现有一张表users,表结构如下
用户id 用户名
1 zhangsan
请编写一个过程,可输入用户名,并循环添加10个用到users表中,用户编号从11开始增加。
create or replace procedure p_addUsers2 (v_name varchar2) is v_num number := 11; begin while v_num <= 20 loop insert into users values(v_num,v_name); v_num := v_num + 1; end loop; end; |
for循环的基本结构如下:
create or replace procedure p_addUsers3 (v_name varchar2) is begin for i in reverse 1..10 loop insert into users values(i,v_name); end loop; end; |
顺序控制语句
Goto语句
Goto语句用于跳转到特定标号去执行语句。注意由于使用goto语句会增加程序的复杂性,并使得应用程序可读性变差,所以在做一般应用开发时,建议不要使用goto语句。
基本语法如下goto lable是已经定义好的标号名。
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('loop end'); end; |
null语句不会执行任何操作,并且直接将控制传递到下一条语句。使用null语句的主要好处是可以提高pl/sql的可读性。
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; |
分页是任何一个网站(bbs,网上商城,blog)都会使用到的技术,因此学习pl/sql编程开发就一定要掌握该技术。
无返回值的存储过程
古人云:欲速则不达。为了让大家比较容易接受分页过程编写,我们还是从简单到复杂,循序渐进的给大家讲解。首先是掌握最简单的过程,无返回值的存储过程:
案例:现有一张表,表结构如下:
书号 | 书名 | 出版社 |
create table book( bookId number, bookName varchar2(50), pulishHouse varchar2(50) ); create or replace procedure p_addBook ( vBookId in number, vBookName in varchar2, vPublishHouse in varchar2 ) is begin insert into book values ( vBookId, vBookName, vPublishHouse ); end; |
package com.anllin.jdbc.oracle; import java.sql.*; public class NoReturnValProc { public static void main(String[] args) { Connection conn = null; CallableStatement stmt = null; try { Class.forName("oracle.jdbc.driver.OracleDriver"); conn = DriverManager .getConnection("jdbc:oracle:thin:@127.0.0.1:1521:myorcl", "scott", "tiger"); stmt = conn.prepareCall("{call p_addBook(?,?,?)}"); stmt.setInt(1, 1); stmt.setString(2, "水是最好的药"); stmt.setString(3, "人民出版社"); stmt.execute(); } catch (Exception e) { throw new RuntimeException(e); } finally { try { if (null != stmt) stmt.close(); if (null != conn) conn.close(); } catch (Exception ex) { throw new RuntimeException(ex); } } } } |
再看如何处理有返回值的存储过程:
案例:编写一个过程,可以输入雇员的编号,返回该雇员的姓名。
create or replace procedure sp_getEnameByEmpno (spno in number,spName out varchar2) is begin select ename into spName from emp where empno = spno; end; |
package com.anllin.jdbc.oracle; import java.sql.*; public class HaveReturnValProc { public static void main(String[] args) { Connection conn = null; CallableStatement stmt = null; try { Class.forName("oracle.jdbc.driver.OracleDriver"); conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:myorcl","scott","tiger"); stmt = conn.prepareCall("{call sp_getEnameByEmpno(?,?)}"); stmt.setInt(1,7788); stmt.registerOutParameter(2,oracle.jdbc.OracleTypes.VARCHAR); stmt.execute(); String name = stmt.getString(2); System.out.println("7788的名字是:"+ name); } catch (Exception e) { throw new RuntimeException(e); } finally { try { if(null != stmt) stmt.close(); if(null != conn) conn.close(); } catch (Exception e) { throw new RuntimeException(e); } } } } |
create or replace procedure sp_getEmpMsgByEmpno ( vNo in number, vName out varchar2, vSal out number, vJob out varchar2 ) is begin select ename,sal,job into vName,vSal,vJob from emp where empno = spno; end; |
package com.anllin.jdbc.oracle; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DriverManager; public class HaveReturnValProc2 { public static void main(String[] args) { Connection conn = null; CallableStatement stmt = null; try { Class.forName("oracle.jdbc.driver.OracleDriver"); conn = DriverManager .getConnection("jdbc:oracle:thin:@127.0.0.1:1521:myorcl", "scott", "tiger"); stmt = conn.prepareCall("{call sp_getEmpMsgByEmpno(?,?,?,?)}"); stmt.setInt(1, 7788); stmt.registerOutParameter(2, oracle.jdbc.OracleTypes.VARCHAR); stmt.registerOutParameter(3, oracle.jdbc.OracleTypes.DOUBLE); stmt.registerOutParameter(4, oracle.jdbc.OracleTypes.VARCHAR); stmt.execute(); String name = stmt.getString(2); double sal = stmt.getDouble(3); String job = stmt.getString(4); System.out.println("7788的名字是:" + name + ",工资是:" + sal + ",职位是:" + job); } catch (Exception e) { throw new RuntimeException(e); } finally { try { if (null != stmt) stmt.close(); if (null != conn) conn.close(); } catch (Exception e) { throw new RuntimeException(e); } } } } |
案例:编写一个过程,输入部门号,返回该部门所有雇员信息。
对该题分析如下:
由于oracle存储过程没有返回值,它的所有返回值都是通过out参数来替代的,列表同样也不例外,但由于是集合,所以不能用一般的参数,必须要用package了,所以要分两部分:
1)建一个包,如下:
create or replace package testpackage as type test_cursor is ref cursor; end testpackage; |
create or replace procedure p_getEmpsByDeptno ( vNO in number, p_cursor out testpackage.test_cursor ) is begin open p_cursor for select * from emp where deptno = vNO; end; |
package com.anllin.jdbc.oracle; import java.sql.*; public class HaveReturnValProc3 { public static void main(String[] args) { Connection conn = null; CallableStatement stmt = null; try { Class.forName("oracle.jdbc.driver.OracleDriver"); conn = DriverManager .getConnection("jdbc:oracle:thin:@127.0.0.1:1521:myorcl", "scott", "tiger"); stmt = conn.prepareCall("{call sp_getEmpsByDeptno(?,?)}"); stmt.setInt(1, 20); stmt.registerOutParameter(2, oracle.jdbc.OracleTypes.CURSOR); stmt.execute(); ResultSet rs = (ResultSet) stmt.getObject(2); while (rs.next()) { System.out.println(rs.getInt(1) + " " + rs.getString(2)); } } catch (Exception e) { throw new RuntimeException(e); } finally { try { if (null != stmt) stmt.close(); if (null != conn) conn.close(); } catch (Exception e) { throw new RuntimeException(e); } } } } |
有了上面的基础,相信大家可以完成分页存储过程了。
要求,请编写一个存储过程,要求可以输入表名,每页显示记录数,当前页。返回总记录数,总页数和返回的结果集。
分页的写法:
select * from ( select t.*,rownum rn from (select * from emp) t where rownum <= 10 ) where rn >= 6; |
分页的存储过程
create or replace package pagingPackage as type paging_cursor is ref cursor; end pagingPackage; create or replace procedure pagingProcedure ( tableName in varchar2, pageSize in number, pageNow in number, rowsCount out number, pageCount out number, p_cursor out pagingPackage.paging_cursor ) is v_sql varchar2(1000); v_begin number := (pageNow - 1) * pageSize + 1; v_end number := pageNow * pageSize; begin v_sql := 'select * from ( select t.*,rownum rn from (select * from '||tableName||') t where rownum <= '|| v_end ||') where rn >= '|| v_begin; open p_cursor for v_sql; v_sql := 'select count(*) from '||tableName; execute immediate v_sql into rowsCount; if mod(rowsCount,pageSize) = 0 then pageCount := rowsCount/pageSize; else pageCount := rowsCount/pageSize + 1; end if; close p_cursor; end; |
在java中调用
package com.anllin.jdbc.oracle; import java.sql.*; import oracle.jdbc.*; public class Paging { public static void main(String[] args) { Connection conn = null; CallableStatement stmt = null; try { Class.forName("oracle.jdbc.driver.OracleDriver"); conn = DriverManager .getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "tiger"); stmt = conn.prepareCall("{call pagingProcedure(?,?,?,?,?,?)}"); stmt.setString(1, "emp"); stmt.setInt(2, 5); stmt.setInt(3, 1); stmt.registerOutParameter(4, OracleTypes.INTEGER); stmt.registerOutParameter(5, OracleTypes.INTEGER); stmt.registerOutParameter(6, OracleTypes.CURSOR); stmt.execute(); int rowCount = stmt.getInt(4); int pageCount = stmt.getInt(5); ResultSet rs = (ResultSet) stmt.getObject(6); System.out.println("总记录数为:" + rowCount); System.out.println("总页数为:" + pageCount); while (rs.next()) { System.out.println("员工编号:" + rs.getInt(1) + " 姓名:" + rs.getString(2) + " 工资:" + rs.getFloat(6)); } } catch (Exception e) { throw new RuntimeException(e); } finally { try { if (null != stmt) stmt.close(); if (null != conn) conn.close(); } catch (Exception ex) { throw new RuntimeException(ex); } } } } |
例外的分类
Oracle将例外分为预定义例外,非预定义例外和自定义例外三种。
预定义例外用于处理常见的oracle错误。
非预定义例外用于处理预定义例外不能处理的例外。
自定义例外用于处理与oracle错误无关的其它情况。
例外处理
例外传递
如果不处理例外我们看看会出现什么情况:
案例:编写一个过程,可接收雇员的编号,并显示该雇员的姓名。
问题是,如果输入的雇员的编号不存在,怎样去处理呢?
declare v_ename emp.ename%type; begin select ename into v_ename from emp where empno=&no; dbms_output.put_line('emp name : '|| v_ename); exception when no_data_found then dbms_output.put_line('empno not exist.'); end; |
预定义例外是由pl/sql所提供的系统例外。当pl/sql应用程序违反了oracle规定的限制时,则会隐含的触发一个内部例外。Pl/sql为开发人员提供了二十多个预定义例外。我们给大家介绍常用 的例外。
Case_not_found
在开发pl/sql块中编写case语句时,如果when子句中没有包含必须的条件分支,就会触发case_not_found的例外:
create or replace procedure p_proc6(vno number) is v_sal emp.sal%type; begin select sal into v_sal from emp where empno= vno; case when v_sal < 1000 then update emp set sal = sal + 100 where empno = vno; when v_sal < 2000 then update emp set sal = sal + 200 where empno = vno; end case; exception when case_not_found then dbms_output.put_line('case statement no match condition for '||v_sal); end; |
当重新打开已经打开的游标时,会隐含的触发例外cursor_already_open
DECLARE CURSOR emp_cursor IS SELECT ename, sal FROM emp; emp_record emp_cursor%ROWTYPE; BEGIN OPEN emp_cursor; FOR emp_record IN emp_cursor LOOP dbms_output.put_line(emp_record.ename); END LOOP; EXCEPTION WHEN cursor_already_open THEN dbms_output.put_line('cursor already open'); END; |
在唯一索引所对应的列上插入重复的值时,会隐含的触发例外dup_val_on_index例外
BEGIN INSERT info dept VALUES (10, 'PublicRelations', 'beijing'); EXCEPTION WHEN dup_val_on_index THEN dbms_output.put_line('the column of deptno can not appear repeat value'); END; |
当试图在不合法的游标上执行操作时,会触发该例外
例如:试图从没有打开的游标提取数据,或是关闭没有打开的游标。则会触发访例外
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('please check cursor is already open?'); END; |
当输入的数据有误时,会触发该例外
比如:数字100写成了1oo就会触发该例外。
BEGIN UPDATE emp SET sal = sal + '1oo'; EXCEPTION WHEN invalid_number THEN dbms_output.put_line('input number is invalid.'); END; |
下面是一个pl/sql块,当执行select into没有返回行,就会触发该例外。
DECLARE v_sal emp.sal%TYPE; BEGIN SELECT sal INTO v_sal FROM emp WHERE ename = '&name'; EXCEPTION WHEN no_data_found THEN dbms_output.put_line('the emp no exist.'); END; |
当执行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; |
当执行2/0语句时,则会触发该例外。
DECLARE v_num NUMBER; BEGIN v_num := 2 / 0; EXCEPTION WHEN zero_divide THEN dbms_output.put_line('can not divide zero'); END; |
当执行赋值操作时,如果变量的长度不足以容纳实际数据,则会触发该例外value_error,
比如:
DECLARE v_ename VARCHAR2(5); BEGIN SELECT ename INTO v_ename FROM emp WHERE empno = &no; EXCEPTION WHEN value_error THEN dbms_output.put_line('variable is not enough size to store value'); END; |
1)login_denide
当用户非法登陆时,会触发该例外。
1) Not_logged_on
如果用户没有登陆就执行dml操作,就会触发该例外。
2) Storage_error
如果超出了内存空间或是内存被损坏,就会触发该例外。
3) Timeout_on_resource
如果oracle在等待资源时,出现了超时就会触发该例外。
非预定义例外
非预定义例外用于处理与预定义例外无关的oracle错误。使用预定义例外只能处理21个oracle错误,而当使用pl/sql开发应用程序时,可能会遇到其他的一些oracle错误。比如在pl/sql块中执行dml语句时,违反了约束规定等等,在这样的情况下,也可以处理oracle的各种例外,因为非预定义例外的不多,这里就不举例了。
处理自定义例外
预定义例外和自定义例外都是oracle错误相关的,并且出现的oracle错误会隐含的触发相应的例外;而自定义例外与oracle错误没有任何关联,它是由开发人员为特定情况所定义的例外。
请编写一个pl/sql块,接收一个雇员的编号,并给雇员工资增加1000元,如果该雇员不存在,请提示。
CREATE OR REPLACE PROCEDURE ex_test(vno NUMBER) IS --definition exception myex EXCEPTION; BEGIN UPDATE emp SET sal = sal + 100 WHERE empno = vno; --sql%notfound -- denotation not update IF SQL%NOTFOUND THEN RAISE myex; END IF; EXCEPTION WHEN myex THEN dbms_output.put_line('no emp to update'); END; |
视图是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据。但是,视图并不在数据库中以存储的数据值集形式存在。行和列数据来自由定义视图的查询所引用的表,并且在引用视图时动态生成。
假设以下情境:
1.如果要显示各个雇员的名字他所有部门的名称,必须用两张表。
2.假设管理员创建了一个用户,xiaohong,现在就希望xiaohong只可以查询sal<1000的哪些雇员。
create view myview1 as select * from emp where sal < 1000; |
视图与表的区别:
1.表需要占用磁盘空间,视图不需要。
2.视图不能添加索引。
3.使用视图可以简化复杂查询。比如:学生选课系统。
4.视图利于提高安全性。
比如:不同用户查看不同视图。
创建视图
create view myview as select emp.ename,emp.job,dept.deptno from emp,dept where emp.deptno = dept.deptno with read only; |
create or replace view myview as select emp.ename,emp.job,dept.deptno from emp,dept where emp.deptno = dept.deptno with read only; |
drop view myview; |
相关文章推荐
- oralce实战第七天--pl/sql的进阶、分页存储过程、例外和视图
- PL/SQL中编写Oracle数据库分页的存储过程
- pl/sql 编写 Oracle分页的存储过程 Java调用该过程
- PL/SQL的进阶----编写分页过程
- PL/SQL中编写Oracle数据库分页的存储过程
- oracle笔记——第七天:oracle视图、触发器,编写分页存储过程
- Oracle学习笔记(二十九)——pl/sql的进阶之编写分页过程
- Oracle基础(五)pl/sql进阶(分页过程)
- Oracle基础(五)pl/sql进阶(分页过程)
- Delphi调用SQL分页存储过程实例 [转]
- SQL 高效通用分页存储过程(双向检索)
- Oralce 写一个分页的存储过程
- 手动 重编译存储过程、SQL语句、函数、触发器、视图
- SQL 根据分类表实现的分页存储过程
- PL/SQL的存储过程和函数
- sql分页存储过程大比拼
- 成熟sql 分页存储过程(UP_Common_GetPage)
- 针对SQL 2000 的分页存储过程代码分享
- 折腾Oracle问题小菜记[分页存储过程/查询所有表、视图、存储过程/查询表、视图、存储过程字段结构与参数](三)