oracle触发器疑问

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了oracle触发器疑问相关的知识,希望对你有一定的参考价值。

exception
when others then

raise;

这几行是什么 意思?

为什么我 end 后面要加上触发器的名字,不然会报错?

首先,  那个  exception   when others then  意思是,  发生了前面没有捕获的异常的情况下, 做什么处理。

下面是一个简单的例子。


SQL> DECLARE
  2    p_test_val  INT;
  3  BEGIN
  4    -- 导致一个 除零错误
  5    p_test_val := 1024 / 0;
  6    dbms_output.put_line(TO_CHAR(p_test_val));
  7
  8    EXCEPTION
  9      WHEN OTHERS THEN
 10        -- 异常自己处理
 11        dbms_output.put_line('Exception Happen!');
 12  END;
 13  /
Exception Happen!

PL/SQL procedure successfully completed.




然后   raise   是抛出一个异常的意思。

下面是一个例子

SQL> DECLARE
  2    -- 测试异常.
  3    e_test_exception EXCEPTION;
  4  BEGIN
  5
  6    -- 直接抛出异常,测试下面的捕获
  7    RAISE e_test_exception;
  8
  9    EXCEPTION
 10      WHEN e_test_exception THEN
 11        dbms_output.put_line('Test Error !');
 12      WHEN OTHERS THEN
 13        dbms_output.put_line('OTHERS Error!');
 14  END;
 15  /
Test Error !

PL/SQL procedure successfully completed.



最后。 在触发器里面, 上面的那段代码, 就是意味着, 如果触发器处理出错了, 那么向外抛出异常。

这样, 外部语句检测到异常了, 那么就会   回滚本次修改,恢复到数据 未发生修改的情况下。



下面是一个例子

触发器实现数据完整性的处理1

-- 货物表
CREATE TABLE Goods(
  id  INT,
  Amount INT
);

-- 订单表
CREATE TABLE OrderDetail(
  ID   INT,
  GoodsID  INT,
  Amount   INT
);

-- 库存测试数据:
INSERT INTO Goods VALUES (1, 100);

要求:当订单表插入数据的时候,自动去货物表检查,是否有足够的库存
如果有,那么更新 货物表 的 库存 = 原库存 – 本次订单数量
如果库存不足,抱错返回.




CREATE OR REPLACE TRIGGER BeforeInsertDetail
  BEFORE INSERT ON OrderDetail
FOR EACH ROW
DECLARE v_nowCount INT;
BEGIN
  SELECT
    Amount INTO v_nowCount
  FROM
    Goods
  WHERE
    ID = :new.GoodsID;

  IF v_nowCount - :new.Amount <  0 THEN
    RAISE_APPLICATION_ERROR(-20000, '库存不足!');
  ELSE
    UPDATE
      Goods
    SET
      Amount = Amount - :new.Amount
    WHERE
      ID = :new.GoodsID;
  END IF;
END;


SQL> INSERT INTO OrderDetail VALUES(1, 1, 90);
已创建 1 行。

SQL> INSERT INTO OrderDetail VALUES(1, 1, 20);
INSERT INTO OrderDetail VALUES(1, 1, 20)
            *
第 1 行出现错误:
ORA-20000: 库存不足!
ORA-06512: 在 "TEST.BEFOREINSERTDETAIL", line 11
ORA-04088: 触发器 'TEST.BEFOREINSERTDETAIL' 执行过程中出错


SQL> select * from goods;
        ID     AMOUNT
---------- ----------
         1         10

SQL>  select * from OrderDetail;
        ID    GOODSID     AMOUNT
---------- ---------- ----------
         1          1         90

请注意, 当第2次更新的时候, 由于触发器代码里面, 抛异常了, 因此, 插入的更新操作将不生效。

参考技术A 当执行过程中产生异常(任何异常)时,跳转到exception语句块,执行raise操作。
end后面加上触发器名是Oracle定义程序模块的规范,表示该触发器执行过程语句块在此结束。

oracle数据库中的number数据类型疑问

如果有一个字段是number类型,字段可以为空,我什么值都没有穿过去,数据库中的这个字段,会自动为0吗?
还是为null。
数据库中的number需要注意什么地方啊?

不加默认值当然不会自动为0了。读取的时候值为NULL
定义时注明小数位例如 number(18,4) 4即为小数位。
想要默认值是0可以在定义字段时候在后面加上default 0
例 create table test(
id number(10,2)default 0,
name varchar2(20)
);
再执行insert into test(name) values('a');后
查询 select id from test where name='a';
结果就是0.00
参考技术A 不加默认值当然不会自动为0了。读取的时候值为NULL。
定义时注明小数位例如 number(18,4) 4即为小数位。
参考技术B number类型的定义格式:number(5, 3)
其中,5代表所定义的总长度。3代表小数数位所占的长度。
参考技术C 不错,回答的很好哦

以上是关于oracle触发器疑问的主要内容,如果未能解决你的问题,请参考以下文章

oracle触发器

oracle登录触发器造成无法登录

oracle 创建触发器问题

oracle 触发器自治事务

oracle触发器出错

oracle 中如何删除或修改 触发器?