【问题标题】:trigger to override the message to error(ORA-02292)触发将消息覆盖为错误 (ORA-02292)
【发布时间】:2016-12-26 11:25:52
【问题描述】:

我想覆盖产生错误的消息 (ORA-02292)。 就是这样的消息

ORA-02292: integrity constraint (IVANKA.FK_SUPPLIER) violated - child record found

我想要一个触发器来覆盖上面的消息到他的例子中(我的覆盖:))

我试过这样做

第一次建表

CREATE TABLE supplier
( supplier_id numeric(10) not null,
  supplier_name varchar2(50) not null,
  contact_name varchar2(50),
  CONSTRAINT supplier_pk PRIMARY KEY (supplier_id)
);

CREATE TABLE products
( product_id numeric(10) not null,
  supplier_id numeric(10) not null,
  CONSTRAINT fk_supplier
    FOREIGN KEY (supplier_id)
    REFERENCES supplier (supplier_id)
);

然后插入数据

INSERT INTO supplier
(supplier_id, supplier_name, contact_name)
VALUES (1000, 'Microsoft', 'Bill Gates');

INSERT INTO products
(product_id, supplier_id)
VALUES (50000, 1000);

然后触发

create or replace trigger  sup_z 
after delete on supplier
for each row
declare 
v_error_constraint exception;
  pragma exception_init(v_error_constraint, -2292);
begin
     null;
exception
      When v_error_constraint then
      raise_application_error(-20001, 
         'My ovvervide:)');
End;  

然后执行删除以生成消息

DELETE from supplier
WHERE supplier_id = 1000

但我在触发器中看不到我的消息我看到了

   ORA-02292: integrity constraint (IVANKA.FK_SUPPLIER) violated - child record found

你能帮帮我吗?我做错了什么?

【问题讨论】:

  • 在触发器触发之前抛出约束冲突。
  • 您的 proc 违反了父子约束,这种违反可能会留下孤立的记录。您应该在删除父记录之前删除子记录,或者删除约束。
  • 我知道如何通过约束来判断错误,但我只需要打印另一条消息
  • 如果您想为最终用户显示更有意义的消息(我认为这是主要原因),您可以将 DML 语句放在 PL/SQL 块中,并在其中捕获异常部分该异常,或创建数据库事件触发器(将是一个矫枉过正,只是指出的可能性)。
  • 我认为您不了解触发器的工作原理。您不能使用触发器来“拦截”异常。并且忽略异常对您没有任何好处,因为数据库仍然会拒绝提交您的更改。如果您碰巧不喜欢约束违规,则无法选择忽略它们 - 您必须编写代码,在给定数据库中存在的约束的情况下正常工作。祝你好运。

标签: sql oracle oracle11g triggers oracle10g


【解决方案1】:

当您只需要要打印的消息时,为什么我们首先需要触发器?我们不应该只处理一个例外吗?

declare 
    v_error_constraint exception;
    pragma exception_init(v_error_constraint, -2292);
begin
     DELETE from supplier
     WHERE supplier_id = 1000;
exception
      When v_error_constraint then
      raise_application_error(-20001, 
         'My ovvervide:)');
End;

【讨论】:

    【解决方案2】:

    您的触发器在DELETE 完成后触发,因此如果DELETE 出现错误,它将永远不会触发。 如果您发现一些子记录,您可以使用BEFORE 触发器来避免DELETE;例如:

    create or replace trigger  sup_z 
    before delete on supplier
    for each row
    declare 
      vNumberOfChild number;
    begin
         select count(1)
         into vNumberOfChild
         from products
         where  supplier_id = :old.supplier_id;
         --
         if vNumberOfChild > 0 then
            raise_application_error(-20001, 'My ovveride:)');
         end if;
    End;  
    

    另一种方法是定义处理删除的过程:

    SQL> create or replace procedure deleteSupplier(p_id in numeric) is
      2  vNumberOfChild number;
      3  begin
      4       select count(1)
      5       into vNumberOfChild
      6       from products
      7       where  supplier_id = p_id;
      8       --
      9       if vNumberOfChild > 0 then
     10          dbms_output.put_line('My ovveride');
     11       else
     12          delete supplier
     13          where supplier_id = p_id;
     14       end if;
     15  end;
     16  /
    
    Procedure created.
    
    SQL> set serveroutput on
    SQL> exec deleteSupplier(1000);
    My ovveride
    
    PL/SQL procedure successfully completed.
    

    这避免了运行delete之前检查数据,因此您不需要触发器。

    【讨论】:

    • 如果我使用你的变体触发器。我看到消息 ORA-20001: My ovveride:) ORA-06512: at "IVANKA.SUP_Z", line 10 ORA-04088: error during execution of trigger 'IVANKA.SUP_Z' 1. 从供应商那里删除供应商 ID=1(如何查看只有我的消息?)
    • 你看到的是错误堆栈;我刚刚编辑以显示您可以使用的不同方式,但这取决于您要调用删除的方式
    • 但我不知道如何在触发器中添加您的程序?
    • 如果使用过程,触发器将无用:过程完成所有操作
    • 我真的需要触发器来显示我的信息 INSTEAD 约束错误?但是当我使用您的触发器时,会显示三个消息,例如(ORA-20001:我的 ovveride :) ORA-06512:在“IVANKA.SUP_Z” ,第 10 行 ORA-04088: 执行触发器 'IVANKA.SUP_Z' 1) 期间出错,如何修复它以仅在触发器中看到我的消息,您能帮忙吗?
    【解决方案3】:

    检查this当违反 PL/SQL 约束时显示自定义消息)。我想你想要类似的东西。

    【讨论】:

    • 我喜欢你在删除供应商之前为每一行找到创建或替换触发器 sup_z 声明 v_error_constraint 异常; pragma exception_init(v_error_constraint, -2292);开始为空;异常当 v_error_constraint 然后 raise_application_error(-20001, 'My ovvervide:)');结尾; (但在此触发后,我会看到我想要的消息),可以帮忙吗?
    猜你喜欢
    • 2012-08-23
    • 2019-07-18
    • 1970-01-01
    • 2013-07-13
    • 2013-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-06
    相关资源
    最近更新 更多