GVKun编程网logo

Oracle SQL 异常处理(oracle数据库异常处理)

25

对于OracleSQL异常处理感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍oracle数据库异常处理,并为您提供关于cx_Oracle和异常处理-好的做法?、Objective-C编程语言(

对于Oracle SQL 异常处理感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍oracle数据库异常处理,并为您提供关于cx_Oracle和异常处理-好的做法?、Objective-C 编程语言(11)异常处理----使能异常处理、异常处理、Oracle --异常处理、Oracle PL/SQL异常处理方法解析的有用信息。

本文目录一览:

Oracle SQL 异常处理(oracle数据库异常处理)

Oracle SQL 异常处理(oracle数据库异常处理)

今天学了异常处理

预定义异常用户自定义异常 还有 raise_application_error()函数
raise_application_error() 只能把异常抛出而不能处理异常。

预定义异常包括
– NO_DATA_FOUND --没有找到数据
– TOO_MANY_ROWS --找到多行数据
– INVALID_CURSOR --失效的游标
– ZERO_DIVIDE --除数为零
– DUP_VAL_ON_INDEX –唯一索引中插入了重复值

预定义异常的示例:

declare
    v_id emp.empno%type;           --声明变量
begin
    select empno into v_id from emp where deptno =40;
exception                          --异常处理
    when no_data_found then        --no_data_found 是使用 select 某字段,然后 into 的时候,该字段没有出。
        rollback;
        dbms_output.put_line(''没有40号部门记录'');
    when too_many_rows then        --too_many_rows 是使用 select 某字段,然后 into 的时候,该字段有多个值。
        rollback;
        dbms_output.put_line(''返回多条记录'');
    when others then               --其它的异常出现
        rollback;
        dbms_output.put_line(''出现其他错误.'');
end;

 

用户自定义异常就是用户定义一个异常情况,遇到这种情况再对这种情况进行处理
因为用户定义的异常不一定是oracle返回的系统错误,系统不会自动触发,需要在声明部分定义。用户定义的异常处理部分基本上和预定义异常相同。

declare
    salary_level           varchar2(1);
    invalid_salary_level   exception; --声明异常
begin
    salary_level := ''D'';
    if salary_level not in (''A'',''B'',''C'') then
      raise invalid_salary_level;     --触发异常
    end if;
exception                             --异常处理
    when invalid_salary_level then
      dbms_output.put_line(''invalid salary level'');
end;

 

raise_application_error() 函数只是将异常抛出,不进行异常处理,并且终止程序。而用户自定义异常以及预定义异常不回终止程序,但会终止该 PL/SQL 代码块,所以一个存储过程中可以有多个 PL/SQL 代码块。

关于异常的语法及定义:

什么是异常:

PL/SQL用异常和异常处理器来实现错误处理
Oracle中出现错误的情形通常分为编译时错误(compile-time error)和运行时错误(run-time error)。
异常在PL/SQL执行过程中很可能出现
对异常如果不进行处理,异常可能会中断程序的运行

捕获异常的规则:

在异常部分WHEN 子句没有数量限制
当异常抛出后,控制无条件转到异常处理部分
EXCEPTION 关键词开始异常处理部分 WHEN OTHERS 为最后的一条子句
在异常块中,只有一个句柄会处理异常

关于异常捕获的函数:

SQLCODE 返回错误代码
SQLERRM 返回与错误代码关联的消息

保存任何非预期的异常的错误编码和错误消息

declare
  v_error_code      NUMBER;
  v_error_message   VARCHAR2(255);
BEGIN
EXCEPTION
     WHEN OTHERS THEN
         ROLLBACK;
         v_error_code := SQLCODE;
         v_error_message := SQLERRM;
      INSERT INTO err_logs VALUES (v_error_code,  v_error_message);
END;

异常的传播

PL/SQL中错误处理的步骤:
步骤1:如果当前块中有该异常的处理器,则执行该异常处理语句块,然后控制权传递到外层语句块 步骤2:如果没有当前异常的处理器,把该异常传播给外层块。然后在外层执行步骤1:如果此语句在最外层语句块,则该异常将被传播给调用环境
没有处理的异常将沿检测异常调用程序传播到外面,当异常被处理并解决或到达程序最外层传播停止。异常是自里向外逐级传递的。

小题:

1.根据员工号,获得员工到目前为止参加工作年限(保留到整数),员工号不存在时提示“此员工号不存在”。

create or replace function get_workyear
    (v_id in emp.empno%type)
    return varchar2
IS
    v_workyear integer;
BEGIN
    select to_char(sysdate,''yyyy'')-to_char(hiredate,''yyyy'') --两个数字字符串相减的值存到整数型变量中
    into v_workyear 
    from emp
    where emp.empno = v_id;
    return v_workyear;
EXCEPTION
    when no_data_found then
      dbms_output.put_line(''此员工号不存在'');
      return -1;
END get_workyear;

2.

①建表myemp。该表内容与emp一致;
②建存储过程。存储过程要的参数,和表里的字段一一对应。比如,表里有empno,存储过程就要有一个参数对应这字段i_empno,类型肯定和empno一样,如果你知道类型是number(4),就直接写成(i_empno in number(4),...)以此类推.
③功能实现,根据empno判断,如果myemp表里已经有这个empno,你就根据你传入的信息把empno的信息更新了,如果没有,就把你这些传入的字段,插入到表里,
eg:我只用两个字段来说明:empno、sal
入参1:123,1000,经过判断,myemp表里没有123这个empno,那么执行完存储过程,这个信息要插入到表里;
入参2:7369,2000,经判断,表里已经有这个编号,但sal为800,那么执行完存储过程,7369的sal更新为2000;
create or replace procedure store_info
    (v_empno      in        myemp.empno%type,
     v_ename      in        myemp.ename%type,
     v_job        in        myemp.job%type,
     v_mgr        in        myemp.mgr%type,
     v_hiredate   in        myemp.hiredate%type,
     v_sal        in        myemp.sal%type,
     v_comm       in        myemp.comm%type,
     v_deptno     in        myemp.deptno%type
    )
IS
    v_id myemp.empno%type:=0;
BEGIN
    select count(*) into v_id 
    from myemp 
    where myemp.empno = v_empno;
    if (v_id=0) then 
        insert into myemp(empno, ename, job, mgr, hiredate, sal, comm, deptno)
        values (v_empno,v_ename,v_job,v_mgr,v_hiredate,v_sal,v_comm,v_deptno); 
    else 
        update myemp
        set myemp.ename=nvl(v_ename,myemp.ename) , myemp.job=nvl(v_job,myemp.job),
            myemp.mgr=nvl(v_mgr,myemp.mgr) , myemp.hiredate=nvl(v_hiredate,myemp.hiredate),
            myemp.sal=nvl(v_sal,myemp.sal) , myemp.comm=nvl(v_comm,myemp.comm),
            myemp.deptno=nvl(v_deptno,myemp.deptno)
    where myemp.empno = v_empno ;
    end if;
END store_info;

begin 
  store_info(7369,null,null,null,null,2000,null,null);
end;

 结果

【注意】:
为什么要把这一题关于存储过程的题放到这里?
因为我起初用异常处理部分来写这一题......,这是不规范的。
本题中用到 count() 函数,count() 是用来计算满足条件的行数的,count(*) 计算所有的行,包括空值。

用异常处理来写本题的代码:

create table myemp(empno, ename, job, mgr, hiredate, sal, comm, deptno)
as 
select empno, ename, job, mgr, hiredate, sal, comm, deptno
from emp;

create or replace procedure store_info
    (v_empno      in        myemp.empno%type,
     v_ename      in        myemp.ename%type,
     v_job        in        myemp.job%type,
     v_mgr        in        myemp.mgr%type,
     v_hiredate   in        myemp.hiredate%type,
     v_sal        in        myemp.sal%type,
     v_comm       in        myemp.comm%type,
     v_deptno     in        myemp.deptno%type
    )
IS
    v_id myemp.empno%type;
BEGIN
    select myemp.empno into v_id 
    from myemp 
    where myemp.empno = v_empno;
    update myemp
    set myemp.ename=v_ename, myemp.job=v_job,myemp.mgr=v_mgr,
        myemp.hiredate=v_hiredate, myemp.sal=v_sal,
        myemp.comm=v_comm,myemp.deptno=v_deptno
    where myemp.empno = v_id;
EXCEPTION
    when no_data_found then 
    insert into myemp(empno, ename, job, mgr, hiredate, sal, comm, deptno)
    values (v_empno,v_ename,v_job,v_mgr,v_hiredate,v_sal,v_comm,v_deptno);
END store_info;

3.
编写PL/SQL块,使用SELECT语句将管理者编号为空的员工的姓名及工作编号显示出来,如果符合条件的员工多于一人,则返回字符串“最高管理者人员过多!”字符串,如果找到没有符合条件的记录,则返回字符串“没有最高管理者,请指定”
代码:

declare
    o_ename emp.ename%type;
    o_empno emp.empno%type;
    v_id    emp.empno%type;
begin
    select emp.empno into v_id
    from emp
    where emp.mgr is null;
    select emp.ename into o_ename from emp where emp.empno = v_id;
    select emp.empno into o_empno from emp where emp.empno = v_id;
    dbms_output.put_line(''员工姓名:''||o_ename||'',''|| ''员工编号:''||o_empno);
exception
    when no_data_found then
      dbms_output.put_line(''没有最高管理者,请指定'');
    when too_many_rows then
      dbms_output.put_line(''最高管理者人员过多'');
end;

4.获得每个部门的平均工资,如果平均工资大于2000,视为用户定义的异常,提示“该部门的平均工资过高”。

declare
    cursor cemp 
    is 
    select dept.dname,avg(sal) 
    from emp,dept
    where emp.deptno = dept.deptno
    group by emp.deptno ,dept.dname;
    v_dname   dept.dname%type ;
    v_asal emp.sal%type ;
    too_high_sal   exception;
begin
    open cemp;
    loop                                  --打开循环
        fetch cemp into v_dname,v_asal;
        exit when cemp%notfound;
        begin                             --这里写了一个 PL/SQL 代码块,里面可以做异常处理
          if v_asal > 2000 then
             raise too_high_sal;
          end if;
        exception                         --异常处理,会终止此代码块。进入下一次循环
          when too_high_sal then
            dbms_output.put_line(v_dname||''该部门工资过高'');
        end;
    end loop;
    close cemp;--注意end loop 与 close cemp 的先后顺序。必须是先结束循环,再关闭游标。
end;

附一张图:

 

cx_Oracle和异常处理-好的做法?

cx_Oracle和异常处理-好的做法?

我正在尝试使用cx_Oracle连接到Oracle实例并执行一些DDL语句:

db = Nonetry:    db = cx_Oracle.connect(''username'', ''password'', ''hostname:port/SERVICENAME'')#print(db.version)except cx_Oracle.DatabaseError as e:    error, = e.args    if error.code == 1017:        print(''Please check your credentials.'')        # sys.exit()?    else:        print(''Database connection error: %s''.format(e))cursor = db.cursor()try:    cursor.execute(ddl_statements)except cx_Oracle.DatabaseError as e:    error, = e.args    if error.code == 955:        print(''Table already exists'')    if error.code == 1031:        print("Insufficient privileges - are you sure you''re using the owner account?")    print(error.code)    print(error.message)    print(error.context)cursor.close()db.commit()db.close()

但是,我不确定在这里异常处理的最佳设计是什么。

首先,我db在try块内创建对象,以捕获任何连接错误。

但是,如果无法连接,则db不会再存在-这就是我在db = None上面进行设置的原因。但是,这是好习惯吗?

理想情况下,我需要在连接时捕获错误,然后在运行DDL语句时捕获错误,依此类推。

嵌套异常是个好主意吗?还是有更好的方法来处理像这样的依存/级联异常?

另外,有些地方(例如连接失败)我希望脚本终止,因此注释掉了sys.exit()调用。但是,我听说将异常处理用于流控制是不好的做法。有什么想法吗?

答案1

小编典典

但是,如果无法连接,则db不会再存在-这就是我在db = None上面进行设置的原因。但是,这是好习惯吗?

不,设置db = None不是最佳实践。有两种可能性,要么连接到数据库将起作用,要么将它不起作用。

  • 连接到数据库不起作用:

由于引发的异常已被捕获且未重新引发,因此请继续直至到达cursor = db.Cursor()

db == None,因此,TypeError: ''NoneType'' object has no attribute''Cursor''将引发类似的异常。由于已经捕获了数据库连接失败时生成的异常,因此掩盖了失败的原因。

就我个人而言,除非您打算稍后再次尝试,否则我总是会提出连接异常。如何捕捉取决于您自己;如果错误仍然存​​在,我将通过电子邮件发送“去检查数据库”的电子邮件。

  • 连接到数据库确实有效:

该变量db在您的try:... except块中分配。如果该connect方法有效,则将db其替换为连接对象。

无论哪种方式,db都不会使用的初始值。

但是,我听说将异常处理用于流控制是不好的做法。

与其他语言不同,Python 确实
将异常处理用于流控制。在回答的最后,我已经链接到有关堆栈溢出和程序员的几个问题,这些问题都提出了类似的问题。在每个示例中,您都会看到“ but but in
Python”一词。

这并不是说您应该精打细算,但是Python通常使用EAFP的口头禅:
“请求宽恕比允许容易。” 我如何检查变量是否存在中投票最多的三个示例?很好地说明了如何同时使用和不使用流量控制。

嵌套异常是个好主意吗?还是有更好的方法来处理像这样的依存/级联异常?

嵌套异常没有任何问题,只要您明智地执行它即可。考虑您的代码。您可以删除所有异常并将整个内容包装在一个try:...except块中。如果引发了异常,那么您就知道它是什么,但是要精确地查明出了什么问题要困难一些。

如果您想通过电子邮件发送电子邮件给自己,会发生cursor.execute什么?cursor.execute为了执行这一任务,您应该有一个例外。然后,您重新引发异常,以便将其捕获在外部try:...。不重新引发代码将导致您的代码继续运行,好像什么都没发生,并且您在外部try:...处理异常的任何逻辑都将被忽略。

最终,所有异常都继承自BaseException

另外,有些部分(例如连接失败)我希望脚本终止,因此注释掉了sys.exit()调用。

我添加了一个简单的类以及如何调用它,这大致就是我将要做的事情。如果要在后台运行,那么打印错误是不值得的-
人们不会坐在那里手动寻找错误。无论采用哪种标准方式,都应将其记录下来,并通知适当的人员。由于这个原因,我已经删除了打印内容,并替换为要记录的提醒。

connect方法失败并引发异常时,由于将类拆分为多个函数execute,因此在尝试断开连接后,调用将不会运行且脚本将完成。

import cx_Oracleclass Oracle(object):    def connect(self, username, password, hostname, port, servicename):        """ Connect to the database. """        try:            self.db = cx_Oracle.connect(username, password                                , hostname + '':'' + port + ''/'' + servicename)        except cx_Oracle.DatabaseError as e:            # Log error as appropriate            raise        # If the database connection succeeded create the cursor        # we-re going to use.        self.cursor = self.db.cursor()    def disconnect(self):        """        Disconnect from the database. If this fails, for instance        if the connection instance doesn''t exist, ignore the exception.        """        try:            self.cursor.close()            self.db.close()        except cx_Oracle.DatabaseError:            pass    def execute(self, sql, bindvars=None, commit=False):        """        Execute whatever SQL statements are passed to the method;        commit if specified. Do not specify fetchall() in here as        the SQL statement may not be a select.        bindvars is a dictionary of variables you pass to execute.        """        try:            self.cursor.execute(sql, bindvars)        except cx_Oracle.DatabaseError as e:            # Log error as appropriate            raise        # Only commit if it-s necessary.        if commit:            self.db.commit()

然后调用它:

if __name__ == "__main__":    oracle = Oracle.connect(''username'', ''password'', ''hostname''                           , ''port'', ''servicename'')    try:        # No commit as you don-t need to commit DDL.        oracle.execute(''ddl_statements'')    # Ensure that we always disconnect from the database to avoid    # ORA-00018: Maximum number of sessions exceeded.     finally:        oracle.disconnect()

Objective-C 编程语言(11)异常处理----使能异常处理、异常处理

Objective-C 编程语言(11)异常处理----使能异常处理、异常处理

转载请标明出处: http://blog.csdn.net/zhangxingping

异常处理

 

Objective-C的异常处理语法和Java以及C++中的有些类似。通常在程序需要使用到NSException或者是NSError或者是自定义的类来增加程序处理错误的能力。本章中将对异常处理进行概括的叙述,更多信息请参考《Cocoa中的异常处理》

 

使能异常处理

Objective-C语言提供了对异常处理的支持。使用GCC 3.3或者更高版本的编译器时,需要打开-fobjc -exceptions选项来支持异常处理。(注意:这将使得应用程序只能在Mac OS X v10.3或者更高版本的系统上运行。之前的系统是不支持运行时异常处理和同步的。)

 

异常处理

异常是一种能打断程序正常执行的状况。产生异常的原因很多,有硬件的也有软件的。例如,做算数运算时,被除数为零就会产生异常;运算出现上溢或者下溢都会产生异常;调用未定义的指令(比如企图调用没有实现的方法)或者企图越界访问集合都会产生异常。

 

Objective-C中支持异常处理的指令有:@try@catch@throw@finally四个:

  有可能产生异常的代码放置在@try代码块中。

  @catch()代码块负责处理@try代码中抛出的异常。可以使用多个@catch()块来捕获不同种类的多个异常。

  @finally()块中的代码是必须执行的,无论是否有异常抛出。

  使用@throw命令字抛出的异常实际上是一个Objective-C对象。通常使NSException类型的对象,但这不是必须的。

 下面的示例代码描述了简单的异常处理流程:

Cup * cup = [ [Cup alloc] init]; @try { [Cup fill]; } @catch(NSException * exception) { NSLog(@”main: Caught %@: %@”,[exception name],[exception reason] ); } @finally { [cup release]; }

Oracle --异常处理

Oracle --异常处理

pl/sql有三种类型的异常错误

1. 预定义错误

oracle预定义的异常错误大约有24个,这种异常无需在程序中定义,由oracle自动将其引发。

ORA-1403  no_data_found  select into 没有找到数据

ORA-1422  too_many_rows  select into  返回多行

2.  非预定义错误

预定义之外其它标准的oracle错误,这种异常情况需要在程序中定义,由oracle自动将其引发。

2.1 在pl/sql块的定义部分定义异常情况

用户定义的异常错误是通过显示使用raise语句来触发。当引发一个异常错误时,控制就转向到exception块异常错误部分,执行错误处理代码。

3. 用户定义错误

程序执行过程中,出现编程人员认为的非正常情况,这种异常情况需要程序员在程序中定义,然后显示的在程序中将其引发。

<异常名称>  exception;

declare
        no_result exception;
begin
        --sql语句
        if sql%notfound then
            raise no_result;                                 
exception
        when no_result then
                dbms_output.put_line(''没有结果异常'')
end;

4.  在pl/sql中使用sqlcode、sqlerrm

为了得到完整的错误信息提示,我们可以使用sqlerrm和substr函数一起得到错误提示信息。

sqlcode  返回错误代码数字

sqlerrm  返回错误信息

eg:

sqlcode = -100  -->sqlerrm=''no_data-found''

sqlcode = 0    -->sqlerrm=''normal,successful completion''







Oracle PL/SQL异常处理方法解析

Oracle PL/SQL异常处理方法解析

Oracle数据库中的异常:没有异常的转移,因为没有受检异常和非受检异常得区分。

1.异常的产生:

2.异常的处理:

declare

  --变量定义,初始化赋值。

begin

  --变量的赋值,函数调用,if,while等。

exception

  --异常处理代码

  when others then 异常处理语句。

end;

3.异常的抛出:raise

4.多异常处理:Java的多异常是通过数据类型区分,Oracle数据库的多异常是通过异常编号区分。
区别不同的异常是实现多异常处理前提。

declare

  verror exception;--定义异常变量

  PRAGMA EXCEPTION_INIT(verror ,-111111);--设定异常变量的编号

begin

  --变量的赋值,函数调用,if,while等。

exception

  •   when verror then 异常处理语句。--所抛出的异常变量的编号是否和设定好的异常变量的编号一致。
  •   when others then 异常处理语句。--当所抛出的异常编号在exception语句块中不存在时,执行该语句(写在最后)。

end;

5.自定义异常:Java中通过定义一个新的异常类实现的。Oracle中通过异常编号实现的。

eclare
  n number(1);
  v_error exception;
begin
  dbms_output.put_line(''抛出单个异常练习--n只有1位不能保存数字10'');
  n:=10;
  if n<=0 then
    raise v_error;
  end if;
  dbms_output.put_line(n);
exception
  when others then dbms_output.put_line(''数值溢出'');
end;

declare
  n number(1);
  v_error exception;
  PRAGMA EXCEPTION_INIT(v_error,-112122);
begin
  dbms_output.put_line(''抛出多个异常练习'');
  n:=-1;
  if n<=0 then
    raise v_error;
  end if;
  dbms_output.put_line(n);
exception
  when v_error then dbms_output.put_line(''不能为负'');
  when others then dbms_output.put_line(''数值溢出'');
end;

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

您可能感兴趣的文章:
  • 通过PLSQL Developer创建Database link,DBMS_Job,Procedure,实现Oracle跨库传输数据的方法(推荐)
  • Oracle SQLPlus导出数据到csv文件的方法
  • python实现自动化报表功能(Oracle/plsql/Excel/多线程)
  • PL/SQL登录Oracle数据库报错ORA-12154:TNS:无法解析指定的连接标识符已解决(本地未安装Oracle需要连接服务器上的)
  • PLSQL Developer连接oracle数据库配置教程
  • plsql 连接oracle数据库详细配置的方法步骤
  • PLSQL配置远程Oracle数据库连接的示例代码
  • Oracle通过sqlplus连接数据库的方式
  • PL/SQL中编写Oracle数据库分页的存储过程

关于Oracle SQL 异常处理oracle数据库异常处理的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于cx_Oracle和异常处理-好的做法?、Objective-C 编程语言(11)异常处理----使能异常处理、异常处理、Oracle --异常处理、Oracle PL/SQL异常处理方法解析的相关知识,请在本站寻找。

本文标签: