PL/SQL 异常不会引发

Posted

技术标签:

【中文标题】PL/SQL 异常不会引发【英文标题】:PL/SQL exceptions dont raise 【发布时间】:2013-12-11 16:47:12 【问题描述】:

我是 PL/SQL 新手,我一直在为这个问题苦苦挣扎太久,所以我想我会在这里问:

我想要达到的目标:

我想使用 pl/sql 将新员工插入到我的“emp”表中 块。 我希望从键盘输入数据。 然后使用异常检查数据是否正确。 之后,我希望用户确认它写“是”或“否”。

什么不起作用:

即使我输入了无效数据,也不会引发异常。

现在它要求用户在要求数据的同时进行确认。我希望它在输入和检查后询问 正确性

我的代码:

DECLARE
  empno   NUMBER;
  ename   Varchar2(30);
  job     Varchar2(30);
  mgr     NUMBER;
  hiredate DATE;
  sal     NUMBER;
  comm    NUMBER;
  deptno  NUMBER;
  confirm VARCHAR2(3);
  negative_number EXCEPTION;
  invalid_date    EXCEPTION;
BEGIN
  INSERT INTO emp
  VALUES (&empno, '&ename', '&job', &mgr, '&hiredate', &sal, &comm, &deptno);
  IF empno < 0 OR mgr < 0 OR sal < 0 OR comm < 0 OR deptno < 0 THEN
    RAISE negative_number;
  ELSIF hiredate > SYSDATE THEN
    RAISE invalid_date;
  END IF;
  IF '&confirm' = 'yes' THEN commit;
  ELSE rollback;
  END IF;
EXCEPTION
  WHEN negative_number THEN
  dbms_output.put_line('number cannot be negative');
  WHEN invalid_date THEN
  dbms_output.put_line('cannot be future date');
END;

【问题讨论】:

您在 exception 块中处理异常。如果你想让它们被加注给调用者,你需要重新加注它们 @a_horse_with_no_name swalling 是什么意思?我如何重新提高它们? 对不起,我的意思是“吞下”。有关引发异常的详细信息,请参阅手册:docs.oracle.com/cd/E11882_01/appdev.112/e25519/… 我不明白,我正在按照它说的那样做:1. 声明 2.raise 3. 处理 你从什么运行这个 - sqlplus?你设置 serveroutput 了吗? 【参考方案1】:

对您当前的代码稍作修改:

DECLARE
  empno   NUMBER := &empno;
  ename   Varchar2(30) := '&ename';
  job     Varchar2(30) := '&job';
  mgr     NUMBER := &mgr;
  hiredate DATE := TO_DATE('&hiredate', 'mm/dd/yyyy');
  sal     NUMBER := &sal;
  comm    NUMBER := &comm;
  deptno  NUMBER := &deptno;
  confirm VARCHAR2(3);
BEGIN
  INSERT INTO emp
  VALUES (empno, ename, job, mgr, hiredate, sal, comm, deptno);
  IF empno < 0 OR mgr < 0 OR sal < 0 OR comm < 0 OR deptno < 0 THEN
    RAISE_APPLICATION_ERROR ('-20001', 'Number cannot be negative!');
  ELSIF hiredate > SYSDATE THEN
    RAISE_APPLICATION_ERROR ('-20002', 'Cannot be future date!');
  END IF;
  confirm := '&confirm';
  IF lower(confirm) IN ('yes', 'y') THEN
    commit;
  ELSE
    rollback;
  END IF;
END;

最后一部分 - confirm 虽然不能使用纯 PL/SQL。代码所做的是在执行本身开始时获取confirm 的值以及其他变量。为此,您应该做的是在发出 DML 之前构建一个可以控制程序流程的前端。

【讨论】:

【参考方案2】:
DECLARE

  empno   NUMBER := 10;
  ename   Varchar2(30) := 'sinha';
  job     Varchar2(30) := 'ITTTT';
  mgr     NUMBER := 100;
  hiredate DATE := TO_DATE('09/09/2014', 'mm/dd/yyyy');
  sal     NUMBER := 2000;
  comm    NUMBER := 50;
  deptno  NUMBER := 10;
  invalid_emp exception;
  invalid_date exception;

BEGIN

  INSERT INTO empl
  VALUES (empno, ename, job, mgr, hiredate, sal, comm, deptno);

  IF empno < 0 OR mgr < 0 OR sal < 0 OR comm < 0 OR deptno < 0 THEN
    RAISE invalid_emp;
  ELSIF hiredate > SYSDATE THEN
    RAISE invalid_date;
  END IF;

  exception
  when invalid_emp then
  dbms_output.put_line('number cannot be negative');
  when invalid_date then 
  dbms_output.put_line('cannot be future date');
END;

这是您可以根据需要使用用户定义的异常的方式

【讨论】:

你又吃掉了所有的异常。 抱歉,如果您为此定义了异常,那么即使您将确认设置为“Y”,它也会被异常缓存并且不会被提交,所以我没有使用确认。 在您的exception 块中,您在提出invalid_empinvalid_date 之后所做的只是显示一条错误消息。您不会阻止程序继续处理INSERT。只需在您的异常块中使用RAISE; 您使用的是编译指示异常初始化,即使这种行为保持不变,我也不会停止任何要执行的 dml。此外,如果您希望在“成功”之后的块中提交和回滚语句DML 然后您可以使用确认部分。问题是要使用用户定义的异常,所以我已经使用了它。

以上是关于PL/SQL 异常不会引发的主要内容,如果未能解决你的问题,请参考以下文章

PL/SQL 异常以啥顺序引发?

引发异常后 PL/SQL 继续

为啥在匿名 PL/SQL 块中没有立即引发异常?

约束违反异常 PL/SQL

PL SQL 过程不引发异常 no_data_found

PL/SQL预定义异常