您的位置:首页 > 数据库 > Oracle

Oracle的学习七:控制语句、异常、视图

2011-12-26 15:12 274 查看
1.控制结构

条件分支语句

在pl/sql中提供了三种条件分支语句:if - then, if - then - else, if - then - elseif - then

if - then - end if;

问题:编写一个过程,可以输入一个雇员名,如果该雇员的工资低于2000,就给该员工工资增加10%。

Sql 代码

1. create or replace procedure sp_pro6(spName varchar2) is

2. --定义

3. v_sal emp.sal%type;

4. begin

5. --执行

6. select sal into v_sal from emp where ename=spName;

7. --判断

8. if v_sal<2000 then

9. update emp set sal=sal+sal*10% where ename=spName;

10. end if;

11.end;

12./

if - then - else - end if;

问题:编写一个过程,可以输入一个雇员名,如果该雇员的补助不是0 就在原来的基础上增加100;如果补助为0 就把补助设为200;

Sql 代码

1. create or replace procedure sp_pro6(spName varchar2) is

2. --定义

3. v_comm emp.comm%type;

4. begin

5. --执行

6. select comm into v_comm from emp where ename=spName;

7. --判断

8. if v_comm<>0 then

9. update emp set comm=comm+100 where ename=spName;

10. else

11. update emp set comm=comm+200 where ename=spName;

12. end if;

13.end;

14./

if - then - else if - then- ... - else - end if;

问题:编写一个过程,可以输入一个雇员编号,如果该雇员的职位是PRESIDENT就给他的工资增加1000,如果该雇员的职位是MANAGER 就给他的工资增加500,其它职位的雇员工资增加200。

Sql 代码

1. create or replace procedure sp_pro6(spNo number) is

2. --定义

3. v_job emp.job%type;

4. begin

5. --执行

6. select job into v_job from emp where empno=spNo;

7. if v_job='PRESIDENT' then

8. update emp set sal=sal+1000 where empno=spNo;

9. elsif v_job='MANAGER' then

10. update emp set sal=sal+500 where empno=spNo;

11. else

12. update emp set sal=sal+200 where empno=spNo;

13. end if;

14.end;

15./

CASE结构

结构一:

CASE

WHEN 条件表达式1 THEN

语句段1;

WHEN 条件表达式2 THEN

语句段2;

...

ELSE

语句段n;

END CASE;

============================================================

结构二:

CASE 条件表达式/变量

WHEN 条件表达式结果1 THEN

语句段1;

WHEN 条件表达式结果2 THEN

语句段2;

...

ELSE

语句段n;

END CASE;

循环语句

循环语句 --loop ... end loop结构?

是pl/sql 中最简单的循环语句,这种循环语句以loop 开头,以end loop 结尾,这种循环至少会被执行一次。

=================================================================

语法格式:

[<<循环标签>>]

LOOP

语句段

EXIT 语句

END LOOP [循环标签];

..............................................

EXIT语句:

EXIT [循环标签]; 立即跳出循环体,一般和条件语句配合

EXIT [循环标签] WHEN 条件表达式; 只有WHEN为TRUE时,才退出。

注意:EXIT跳出循环体;RETURN跳出PL/SQL块。

=======================================================================

案例:现有一张表users,表结构如下: 用户id | 用户名

请编写一个过程,可以输入用户名,并循环添加10 个用户到users 表中,用户编号从1 开始增加。

Sql 代码

1. create or replace procedure sp_pro6(spName varchar2) is

2. --定义 :=表示赋值

3. v_num number:=1;

4. begin

5. loop

6. insert into users values(v_num,spName);

7. --判断是否要退出循环

8. exit when v_num=10;

9. --自增

10. v_num:=v_num+1;

11. end loop;

12.end;

13./

循环语句 –while 循环?

基本循环至少要执行循环体一次,而对于while 循环来说,只有条件为true时,才会执行循环体语句,while 循环以while...loop 开始,以end loop 结束。

=================================================================

语法格式:

[<<循环标签>>]

WHILE 条件表达式 LOOP

语句段

EXIT 语句

END LOOP [循环标签];

==================================================================

案例:现有一张表users,表结构如下:用户id| 用户名

问题:请编写一个过程,可以输入用户名,并循环添加10 个用户到users 表中,用户编号从11 开始增加。

Sql 代码

1. create or replace procedure sp_pro6(spName varchar2) is

2. --定义 :=表示赋值

3. v_num number:=11;

4. begin

5. while v_num<=20 loop

6. --执行

7. insert into users values(v_num,spName);

8. v_num:=v_num+1;

9. end loop;

10.end;

11./

循环语句 –for 循环?

基本for 循环的基本结构如下:

=================================================================

语法格式:

[<<循环标签>>]

FOR 循环变量 IN [REVERSE] 初值表达式...终值表达式 LOOP

语句段

EXIT 语句

END LOOP [循环标签];

================================================================

Sql 代码

1. begin

2. for i in reverse 1..10 loop

3. insert into users values (i, 'shunping');

4. end loop;

5. end;

我们可以看到控制变量i,在隐含中就在不停地增加。

顺序控制语句 –goto,null?

goto 语句

goto 语句用于跳转到特定符号去执行语句。注意由于使用goto 语句会增加程序的复杂性,并使得应用程序可读性变差,所以在做一般应用开发时,建议大家不要使用goto 语句。

基本语法如下 goto lable,其中lable 是已经定义好的标号名,

Sql 代码

1. declare

2. i int := 1;

3. begin

4. loop

5. dbms_output.put_line('输出i=' || i);

6. if i = 1 then

7. goto end_loop;

8. end if;

9. i := i + 1;

10. end loop;

11. <<end_loop>>

12. dbms_output.put_line('循环结束');

13.end;

null

null 语句不会执行任何操作,并且会直接将控制传递到下一条语句。使用null语句的主要好处是可以提高pl/sql 的可读性。

Sql 代码

1. declare

2. v_sal emp.sal%type;

3. v_ename emp.ename%type;

4. begin

5. select ename, sal into v_ename, v_sal from emp where empno =&no;

6. if v_sal < 3000 then

7. update emp set comm = sal * 0.1 where ename = v_ename;

8. else

9. null;

10. end if;

11.end;

编写分页过程

介绍:分页是任何一个网站(bbs,网上商城,blog)都会使用到的技术,因此学习pl/sql编程开发就一定要掌握该技术。

无返回值的存储过程

首先是掌握最简单的存储过程,无返回值的存储过程:

案例:现有一张表book,表结构如下:看图:

书号
书名
出版社
请写一个过程,可以向book 表添加书,要求通过java 程序调用该过程。

1.创建表:

create or replace table Book(

bookId number,

bookName varchar2(20),

publisher varchar2(10)

);

2.创建存储过程:

--in:表示这是一个输入参数,默认为in

--out:表示一个输出参数

Sql 代码:

1. create or replace procedure sp_pro7(spBookId in number,spbookName in varchar2,sppublishHouse in varchar2) is

2. begin

3. insert into book values(spBookId,spbookName,sppublishHouse);

4. end;

5. /

3.在java 中调用:

Java 代码

1. //调用一个无返回值的过程

2. import java.sql.*;

3. public class Test2{

4. public static void main(String[] args){

5.

6. try{

7. //1.加载驱动

8. Class.forName("oracle.jdbc.driver.OracleDriver");

9. //2.得到连接

10. Connection ct = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:MYORA1","scott","m123");

11.

12. //3.创建CallableStatement

13. CallableStatement cs = ct.prepareCall("{call sp_pro7(?,?,?)}");

14. //4.给?赋值

15. cs.setInt(1,10);

16. cs.setString(2,"笑傲江湖");

17. cs.setString(3,"人民出版社");

18. //5.执行

19. cs.execute();

20. } catch(Exception e){

21. e.printStackTrace();

22. } finally{

23. //6.关闭各个打开的资源

24. try{

25. cs.close();

26. ct.close();

27. }catch(Exception ex)

28. {

29. ex.printStackTrace();

30. }

31. }

32. }

33.}

执行,记录被加进去了

有返回值的存储过程(非列表)?

如何处理有返回值的存储过程:

案例1:编写一个过程,可以输入雇员的编号,返回该雇员的姓名。

1.创建存储过程

Sql 代码

1. --有输入和输出的存储过程

2. create or replace procedure sp_pro8

3. (spno in number, spName out varchar2) is

4. begin

5. select ename into spName from emp where empno=spno;

6. end;

7. /

2.Java调用Oracle存储过程

Java 代码

1. import java.sql.*;

2. public class Test2{

3. public static void main(String[] args){

4.

5. try{

6. //1.加载驱动

7. Class.forName("oracle.jdbc.driver.OracleDriver");

8. //2.得到连接

9. Connection ct = DriverManager.getConnection("jdbc:oracle:thin@127.0.0.1:1521:MYORA1","scott","m123");

18. //看看如何调用有返回值的过程

19. //创建CallableStatement

20. CallableStatement cs = ct.prepareCall("{call sp_pro8(?,?)}");

21.

22. //给第一个?赋值

23. cs.setInt(1,7788);

24. //给第二个?赋值

25. cs.registerOutParameter(2,oracle.jdbc.OracleTypes.VARCHAR);

26.

27. //5.执行

28. cs.execute();

29. //取出返回值,要注意?的顺序

30. String name=cs.getString(2);

31. System.out.println("7788 的名字"+name);

32. } catch(Exception e){

33. e.printStackTrace();

34. } finally{

35. //6.关闭各个打开的资源

24. try{

25. cs.close();

26. ct.close();

27. }catch(Exception ex)

28. {

29. ex.printStackTrace();

30. }

38. }

39. }

40.}

运行,成功得出结果。。

案例扩张2:编写一个过程,可以输入雇员的编号,返回该雇员的姓名、工资和岗位。

1.创建存储过程

Sql 代码

1. --有输入和输出的存储过程

2. create or replace procedure sp_pro8

3. (spno in number, spName out varchar2,spSal out number,spJob out varchar2) is

4. begin

5. select ename,sal,job into spName,spSal,spJob from emp where empno=spno;

6. end;

7. /

2.Java调用存储过程

Java 代码

1. import java.sql.*;

2. public class Test2{

3. public static void main(String[] args){

4.

5. try{

6. //1.加载驱动

7. Class.forName("oracle.jdbc.driver.OracleDriver");

8. //2.得到连接

9. Connection ct = DriverManager.getConnection("jdbc:oracle:thin@127.0.0.1:1521:MYORA1","scott","m123");

18. //看看如何调用有返回值的过程

19. //创建CallableStatement

20. /*CallableStatement cs = ct.prepareCall("{call sp_pro8(?,?,?,?)}");

21.

//必须给所有的变量进行关联,也许你不使用它们

22. //给第一个?赋值

23. cs.setInt(1,7788);

24. //给第二个?赋值

25. cs.registerOutParameter(2,oracle.jdbc.OracleTypes.VARCHAR);

26. //给第三个?赋值

27. cs.registerOutParameter(3,oracle.jdbc.OracleTypes.DOUBLE);

28. //给第四个?赋值

29. cs.registerOutParameter(4,oracle.jdbc.OracleTypes.VARCHAR);

30.

31. //5.执行

32. cs.execute();

33. //取出返回值,要注意?的顺序

34. String name=cs.getString(2);

35. String job=cs.getString(4);

36. System.out.println("7788 的名字"+name+" 工作:"+job);

37. } catch(Exception e){

38. e.printStackTrace();

39. } finally{

40. //6.关闭各个打开的资源

24. try{

25. cs.close();

26. ct.close();

27. }catch(Exception ex)

28. {

29. ex.printStackTrace();

30. }

43. }

44. }

45.}

运行,成功找出记录

有返回值的存储过程(列表[结果集])?

案例1:编写一个过程,输入部门号,返回该部门所有雇员信息。

对该题分析如下:

由于oracle 存储过程没有返回值,它的所有返回值都是通过out 参数来替代的,列表同样也不例外,但由于是集合,所以不能用一般的参数,必须要用pagkage 了。所以要分两部分:

1.建立一个包

在该包中,定义类型test_cursor,是个游标。 如下:

Sql 代码

1. create or replace package testpackage as

2. TYPE test_cursor is ref cursor;

3. end testpackage;

2.建立存储过程。如下:

Sql 代码

1. create or replace procedure sp_pro9(spNo in number,p_cursor out testpackage.test_cursor) is

2. begin

3. open p_cursor for select * from emp where deptno = spNo;

4. end sp_pro9;

3.如何在java 程序中调用该过程

Java 代码

1. import java.sql.*;

2. public class Test2{

3. public static void main(String[] args){

4.

5. try{

6. //1.加载驱动

7. Class.forName("oracle.jdbc.driver.OracleDriver");

8. //2.得到连接

9. Connection ct = DriverManager.getConnection("jdbc:o

racle:thin:@127.0.0.1:1521:MYORA1","scott","m123");

10.

11. //看看如何调用有返回值的过程

12. //3.创建CallableStatement

13. CallableStatement cs = ct.prepareCall("{call sp_pro9(?,?)}");

14.

15. //4.给第?赋值

16. cs.setInt(1,10);

17. //给第二个?赋值

18. cs.registerOutParameter(2,oracle.jdbc.OracleTypes.CURSOR);

19.

20. //5.执行

21. cs.execute();

22. //得到结果集

23. ResultSet rs=(ResultSet)cs.getObject(2);

24. while(rs.next()){

25. System.out.println(rs.getInt(1)+" "+rs.getString(2));

26. }

27. } catch(Exception e){

28. e.printStackTrace();

29. } finally{

30. //6.关闭各个打开的资源 下面代码需加异常处理

31. cs.close();

32. ct.close();

33. }

34. }

35.}

运行,成功得出部门号是10 的所有用户

编写分页过程?

有了上面的基础,相信大家可以完成分页存储过程了。

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

--oracle 的分页知识回顾

Sql 代码

--在分页时,大家可以把下面的sql 语句当做一个模板使用

select * from (select t1.*, rownum rn from (select * from emp) t1 where rownum<=10) where rn>=6;

编写分页一

--开发一个包

--建立一个包,在该包中,我定义类型test_cursor,是个游标。 如下:

Sql 代码

1. create or replace package testpackage as

2. TYPE test_cursor is ref cursor;

3. end testpackage;

4. --开始编写分页的过程

5. create or replace procedure fenye

6. (tableName in varchar2,

7. Pagesize in number,--一页显示记录数

8. pageNow in number,

9. myrows out number,--总记录数

10. myPageCount out number,--总页数

11. p_cursor out testpackage.test_cursor--返回的记录集

12. ) is

13.--定义部分

14.--定义sql 语句 字符串

15.v_sql varchar2(1000);

16.--定义两个整数

17.v_begin number:=(pageNow-1)*Pagesize+1;

18.v_end number:=pageNow*Pagesize;

19.begin

20.--执行部分

21.v_sql:='select * from (select t1.*, rownum rn from (select * from '||tableName||') t1 where rownum<='||v_end||') where rn>='||v_begin;

22.--把游标和sql 关联

23.open p_cursor for v_sql;

24.--计算myrows 和myPageCount

25.--组织一个sql 语句

26.v_sql:='select count(*) from '||tableName;

27.--执行sql,并把返回的值,赋给myrows;

28.execute inmediate v_sql into myrows;

29.--计算myPageCount

30.--if myrows%Pagesize=0 then 这样写是错的

31.if mod(myrows,Pagesize)=0 then

32. myPageCount:=myrows/Pagesize;

33.else

34. myPageCount:=myrows/Pagesize+1

35.end if;

36.--关闭游标

37.close p_cursor;

38.end;

39./

--使用java 测试

//测试分页

Java 代码

1. import java.sql.*;

2. public class FenYe{

3. public static void main(String[] args){

4.

5. try{

6. //1.加载驱动

7. Class.forName("oracle.jdbc.driver.OracleDriver");

8. //2.得到连接

9. Connection ct = DriverManager.getConnection("jdbc:oracle:thin@127.0.0.1:1521:MYORA1","scott","m123");

10.

11. //3.创建CallableStatement

12. CallableStatement cs = ct.prepareCall("{call fenye(?,?,?,?,?,?)}");

13.

14. //4.给第?赋值

15. cs.setString(1,"emp");

16. cs.setInt(2,5);

17. cs.setInt(3,2);

18.

19. //注册总记录数

20. cs.registerOutParameter(4,oracle.jdbc.OracleTypes.INTEGER);

21. //注册总页数

22. cs.registerOutParameter(5,oracle.jdbc.OracleTypes.INTEGER);

23. //注册返回的结果集

24. cs.registerOutParameter(6,oracle.jdbc.OracleTypes.CURSOR);

25.

26. //5.执行

27. cs.execute();

28.

29. //取出总记录数 /这里要注意,getInt(4)中4,是由该参数的位置决定的

30. int rowNum=cs.getInt(4);

31.

32. int pageCount = cs.getInt(5);

33. ResultSet rs=(ResultSet)cs.getObject(6);

34.

35. //显示一下,看看对不对

36. System.out.println("rowNum="+rowNum);

37. System.out.println("总页数="+pageCount);

38.

39. while(rs.next()){

40. System.out.println("编号:"+rs.getInt(1)+" 名字:"+rs.getString(2)+" 工资:"+rs.getFloat(6));

41. }

42. } catch(Exception e){

43. e.printStackTrace();

44. } finally{

45. //6.关闭各个打开的资源

46. cs.close();

47. ct.close();

48. }

49. }

50.}

运行,控制台输出:

rowNum=19

总页数:4

编号:7369 名字:SMITH 工资:2850.0

编号:7499 名字:ALLEN 工资:2450.0

编号:7521 名字:WARD 工资:1562.0

编号:7566 名字:JONES 工资:7200.0

编号:7654 名字:MARTIN 工资:1500.0

--新的需要,要求按照薪水从低到高排序,然后取出6-10

只需过程的执行部分做如下改动,如下:

Sql 代码

1. begin

2. --执行部分

3. v_sql:='select * from (select t1.*, rownum rn from (select * fr

om '||tableName||' order by sal) t1 where rownum<='||v_end||')

where rn>='||v_begin;

重新执行一次procedure,java 不用改变,运行,控制台输出:

rowNum=19

总页数:4

编号:7900 名字:JAMES 工资:950.0

编号:7876 名字:ADAMS 工资:1100.0

编号:7521 名字:WARD 工资:1250.0

编号:7654 名字:MARTIN 工资:1250.0

编号:7934 名字:MILLER 工资:1300.0

2.异常处理

异常的分类

oracle 将异常分为预定义异常,非预定义异常和自定义异常三种。

预定义异常用于处理常见的oracle 错误

非预定义异常用于处理预定义异常不能处理的异常

自定义异常用于处理与oracle 错误无关的其它情况

异常处理部分的语法格式:

Exception

WHEN 异常错误1 OR ... THEN

语句段1;

......

WHEN OTHERS THEN

语句段2;

异常传递?

发生异常后,首先在本块中查看有没有对应的异常处理,若没有,就扩散到外层块中查看异常处理,直至找到。当执行完异常处理后,pl/sql将控制权转移到异常处理部分(指实际执行异常错误处理的块,为并非一定是发生异常错误的块)的外层块内的下一个语句。当异常错误发生在声明块或异常处理部分,当前块中的异常处理部分无法捕获,则将异常错误直接传播到它的外层块。

如果不处理异常我们看看会出现什么情况:

案例,编写一个过程,可接收雇员的编号,并显示该雇员的姓名。

问题是,如果输入的雇员编号不存在,怎样去处理呢?

Sql 代码

1. --异常案例

2. declare

3. --定义

4. v_ename emp.ename%type;

6. --

7. select ename into v_ename from emp where empno=&gno;

8. dbms_output.put_line('名字:'||v_ename)

9. /

执行,弹出框:

随便输个不存在的编号,回车,会抛出异常,显示:

ORA-01403: 未找到数据

ORA-06512: 在line 6

经例外处理的sql代码:

Sql 代码

1. declare

2. --定义

3. v_ename emp.ename%type;

4. begin

5. --执行

6. select ename into v_ename from emp where empno=&gno;

7. dbms_output.put_line('名字:'||v_ename)

8. exception

9. when no_data_found then

10. dbms_output.put_line('编号没有!');

11.end;

12./

执行,输入一个不存在的编号,回车,显示:

编号没有!

预定义异常?

预定义异常是由pl/sql 所提供的系统异常。当pl/sql 应用程序违反了oracle规定的限制时,则会隐含的触发一个内部异常。pl/sql 为开发人员提供了二十多个预定义异常。常用的:

case_not_found

在开发pl/sql 块中编写case 语句时,如果在when 子句中没有包含必须的条件分支,就会触发case_not_found 的异常:

Sql 代码

1. create or replace procedure sp_pro6(spno number) is

2. v_sal emp.sal%type;

3. begin

4. select sal into v_sal from emp where empno = spno;

5. case

6. when v_sal < 1000 then

7. update emp set sal = sal + 100 where empno = spno;

8. when v_sal < 2000 then

9. update emp set sal = sal + 200 where empno = spno;

10.end case;

11.exception

12.when case_not_found then

13.dbms_output.put_line('case 语句没有与' || v_sal || '相匹配的条件');

14.end;

cursor_already_open?

当重新打开已经打开的游标时,会隐含的触发异常cursor_already_open

Sql 代码

1. declare

2. cursor emp_cursor is select ename, sal from emp;

3. begin

4. open emp_cursor;

5. for emp_record1 in emp_cursor loop

6. dbms_output.put_line(emp_record1.ename);

7. end loop;

8. exception

9. when cursor_already_open then

10. dbms_output.put_line('游标已经打开');

11.end;

12./

dup_val_on_index?

在具有唯一约束的列上插入重复的值时,会隐含的触发异常dup_val_on_index 异常

Sql 代码

1. begin

2. insert into dept values (10, '公关部', '北京');

3. exception

4. when dup_val_on_index then

5. dbms_output.put_line('在deptno 列上不能出现重复值');

6. end;

invalid_cursor?

当试图在不合法的游标上执行操作时,会触发该异常

例如:试图从没有打开的游标提取数据,或是关闭没有打开的游标。则会触发该异常

Sql 代码

1. declare

2. cursor emp_cursor is select ename, sal from emp;

3. emp_record emp_cursor%rowtype;

4. begin

5. --open emp_cursor; --打开游标

6. fetch emp_cursor into emp_record;

7. dbms_output.put_line(emp_record.ename);

8. close emp_cursor;

9. exception

10. when invalid_cursor then

11. dbms_output.put_line('请检测游标是否打开');

12.end;

invalid_number?

当字符串转换为数字时发生错误

比如:数字100 写成了loo 就会触发该异常

Sql 代码

1. begin

2. update emp set sal= sal + 'loo';

3. exception

4. when invalid_number then

5. dbms_output.put_line('输入的数字不正确');

6. end;

no_data_found

select into语句没有返回任何数据行;或是程序引用了嵌套表中一个删除的元素;或是索引表中一个没有被初始化的元素。

下面是一个pl/sql 块,当执行select into 没有返回行,就会触发该异常

Sql 代码

1. declare

2. v_sal emp.sal%type;

3. begin

4. select sal into v_sal from emp

5. when ename='&name';

6. exception

7. when no_data_found then

8. dbms_output.put_line('不存在该员工');

9. end;

too_many_rows?

当执行select into 语句时,如果返回超过了一行,则会触发该异常。

Sql 代码

1. declare

2. v_ename emp.ename%type;

3. begin

4. select ename into v_ename from emp;

5. exception

6. when too_many_rows then

7. dbms_output.put_line('返回了多行');

8. end;

zero_divide?

发生被0除错误。

value_error

执行赋值操作时,若发生了一个算法/转换/截断或大小约束错误,则会触发该异常value_error。

比如:

Sql 代码

1. declare

2. v_ename varchar2(5);

3. begin

4. select ename into v_ename from emp where empno = &no1;

5. dbms_output.put_line(v_ename);

6. exception

7. when value_error then

8. dbms_output.put_line('变量尺寸不足');

9. end;

其它预定义异常(这些例外不是在pl/sql 里触发的,而是在用oracle 时触发的,所以取名叫其它预定义例外)?

1.login_denied

当用户非法登录时,会触发该异常

2.not_logged_on

如果用户没有登录就执行dml 操作,就会触发该异常

3.storage_error

如果超过了内存空间或是内存被损坏,就触发该异常

4.timeout_on_resource

如果oracle 在等待资源时,出现了超时就触发该异常

非预定义异常?

非预定义异常用于处理与预定义异常无关的oracle 错误。使用预定义异常只能处理21 个oracle 错误,而当使用pl/sql 开发应用程序时,可能会遇到其它的一些oracle 错误。比如在pl/sql 块中执行dml 语句时,违反了约束规定等等。在这样的情况下,也可以处理oracle 的各种异常,因为非预定义异常用的不多,这里我就不举例了。

使用非预定义异常错误的步骤:

step1:声明部分--用EXCEPTION类型声明异常错误的名称;

step2:在声明部分--用EXCEPTION_INIT编译命令建立该异常错误与某个Oracle错误之间的联系;语法格式:PRAGMA EXCEPTION_INIT(exception_name, oracle_error_code);

step3:在异常处理部分--捕获、处理异常错误。

自定义异常

预定义异常和自定义异常都是与oracle 错误相关的,并且出现的oracle 错误会隐含的触发相应的异常;而自定义异常与oracle 错误没有任何关联,它是由开发人员为特定情况所定义的异常。

自定义异常必须要声明,并且必须要用RAISE语句显式抛出,然后才能将程序的控制流程引向异常处理部分。

问题:请编写一个pl/sql 块,接收一个雇员的编号,并给该雇员工资增加1000元,如果该雇员不存在,请提示。

Sql 代码

1. --自定义异常

2. create or replace procedure ex_test(spNo number)

3. is

4. begin

5. --更新用户sal

6. update emp set sal=sal+1000 where empno=spNo;

7. end;

8. /

运行,该过程被成功创建。

SQL> exec ex_test(56);

PL/SQL 过程被成功完成

这里,编号为56 是不存在的,刚才的报异常了,为什么现在不报异常呢?

因为刚才的是select 语句

怎么解决这个问题呢? 修改代码,如下:

Sql 代码

1. --自定义异常

2. create or replace procedure ex_test(spNo number)

3. is

4. --定义一个异常

5. myex exception;

6. begin

7. --更新用户sal

8. update emp set sal=sal+1000 where empno=spNo;

9. --sql%notfound 这是表示没有update

10.--raise myex;触发myex

11.if sql%notfound then

12.raise myex;

13.end if;

14.exception

15.when myex then

16.dbms_output.put_line('没有更新任何用户');

17.end;

18./

现在再测试一次:SQL> exec ex_test(56);

没有更新任何用户

使用SQLCODE和SQLERRM

使用RAISE_APPLICATION_ERROR

3.oracle 的视图

介绍?

视图是一个虚拟表,其内容由查询定义,同真实的表一样,视图包含一系列带有名称的列和行数据。但是,视图并不在数据库中以存储的数据值集形式存在。行和列数据来自由定义视图的查询所引用的表,并且在引用视图时动态生成。(视图不是真实存在磁盘上的)

视图与表的区别


视图与表的区别?

1.表需要占用磁盘空间,视图不需要

2.视图不能添加索引(所以查询速度略微慢点)

3.使用视图可以简化,复杂查询。比如:学生选课系统

4.视图的使用利于提高安全性。比如:不同用户查看不同视图

创建/修改/删除视图

创建视图?

create view 视图名 as select 语句 [with read only]

创建或修改视图?

create or replace view 视图名 as select 语句 [with read only]

删除视图?

drop view 视图名

当表结构国语复杂,请使用视图吧!

--创建视图,把emp 表的sal<1000 的雇员映射到该视图(view)

Sql 代码

1. create view myview as select * from emp where sal<1000;

--为简化操作,用一个视图解决 显示雇员编号,姓名和部门名称

Sql 代码

1. create view myview2 as select emp.empno,emp.ename,dept.dname from emp,dept where emp.deptno=dept.deptno;

视图之间也可以做联合查询
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: