Oracle AFTER INSERT触发器

时间:2013-12-07 03:47:26

标签: plsql triggers oracle11g

以下触发器不会触发。在添加'SELECT c.deposit_id ...代码段之前,触发器有效。任何帮助将不胜感激。如果发现此表中的外键链接到另一个表(TRANSACTION_TABLE),则触发器将在CASH_OR_CREDIT表上插入后触发。

`
 CREATE OR REPLACE TRIGGER SEND_MONEY
 AFTER INSERT
 ON cash_or_credit
 REFERENCING NEW AS NEW OLD AS OLD
 FOR EACH ROW
DECLARE
 system_header_info           NUMBER := 0;
 l_dep_key                     NUMBER := 0;


 CURSOR cur (cover_id NUMBER)
 IS
  SELECT header_id
    FROM headers
   WHERE party_site_id = cover_id;


  system_header_info   VARCHAR2 (10)
        := schema.necessay_functions.get_system_id ('DEPOSITS');


 BEGIN
 fnd_profile.put ('company_debugger', 'Y');
 schema.necessay_functions.debugger ('old.deposit_id =' || :OLD.deposit_id);
  schema.necessay_functions.debugger ('new.deposit_id =' || :NEW.deposit_id);

   OPEN cur (system_header_info);

  system_header_info := 0;

  FETCH cur1 INTO system_header_info;

  CLOSE cur1;

  schema.necessay_functions.debugger (
    'super_user.user_id =' || super_user.user_id);
   schema.necessay_functions.debugger (
    schema.necessay_functions.obtain_user_id (
     schema.necessay_functions.get_system_id ('DEPOSITS')));

  SELECT c.deposit_id
   INTO l_dep_key
  FROM schema.transaction_table o,
      schema.linker_table r,
      schema.cash_or_credit c
  WHERE     o.primary_key = r.primary_key
      AND o.table_name = 'INDIVIDUAL_REC'
      AND o.system_id = '265226'
      AND o.status = 'A'
      AND r.status = 'A'
      AND c.foreign_key = r.primary_key
      AND c.deposit_id = :NEW.deposit_id
      AND r.relationship_code IN ('EMPLOYER_OF');



    IF     super_user.user_id =
         schema.necessay_functions.obtain_user_id (
            schema.necessay_functions.get_system_id ('DEPOSITS'))
  AND l_dep_key = :NEW.deposit_id
  THEN
  schema.necessay_functions.debugger ('Inside If Condition');

  FOR sys_comp
     IN (SELECT *
           FROM schema.transaction_table
          WHERE     status = 'A'
                AND table_name = 'DEPOSITS'
                AND primary_key = :NEW.deposit_id
                AND system_id =
                       schema.necessay_functions.get_system_id (
                          'DEPOSITS'))
  LOOP
     schema.necessay_functions.debugger ('Inside Loop');
     schema.necessay_functions.send_xml_message ('SEND_SYSTEM_MSG',
                                                 'SEND.UPDATE',
                                                 system_header_info,
                                                 sys_comp.system_id,
                                                 sys_comp.system_key);
         END LOOP;
     ELSE
        schema.necessay_functions.send_xml_message ('SEND_SYSTEM_MSG',
                                              'SEND.CREATE',
                                              system_header_info,
                                              system_header_id,
                                              :NEW.deposit_id);
    END IF;
   EXCEPTION
    WHEN OTHERS
     THEN
  schema.necessay_functions.debugger ('Sqlerrm:' || SQLERRM);
 END SEND_MONEY;
   /`

2 个答案:

答案 0 :(得分:0)

如果它在没有SELECT c.deposit_id …的情况下工作,那么,大概是,这就是导致异常的原因,然后被正在使用的WHEN OTHERS异常处理程序吞并并导致触发器看起来像是不开火。您应该能够通过检查登录的任何表/日志schema.necessay_functions.debugger(来确认。

围绕l_dep_key值有哪些业务规则?具体来说,是否期望用于填充l_dep_key的SELECT语句将始终返回结果(并且只有1个结果)?如果是这样,至少用匿名块包装该语句并显式处理与这些业务规则冲突的任何异常。

BEGIN
    SELECT c.deposit_id
     INTO l_dep_key
    FROM schema.transaction_table o,
         schema.linker_table r,
         schema.cash_or_credit c
    WHERE     o.primary_key = r.primary_key
        AND o.table_name = 'INDIVIDUAL_REC'
        AND o.system_id = '265226'
        AND o.status = 'A'
        AND r.status = 'A'
        AND c.foreign_key = r.primary_key
        AND c.deposit_id = :NEW.deposit_id
        AND r.relationship_code IN ('EMPLOYER_OF');

EXCEPTION
    WHEN NO_DATA_FOUND THEN
        ...TAKE APPROPRIATE ACTION HERE...
        ...POSSIBLY LOG AND RAISE...

    WHEN TOO_MANY_ROWS THEN
        ...TAKE APPROPRIATE ACTION HERE...
        ...POSSIBLY LOG AND RAISE...
END;

正如OldProgrammer在评论中所说,您提供的代码中的异常处理还有很大的提升空间。你真的应该吞下这个触发器中代码可能引发的任何和所有异常吗?

此外,作为一般提示,当记录异常而不是仅记录SQLERRM时,请使用DBMS_UTILITY.FORMAT_ERROR_BACKTRACE(),因为它为您提供了有关异常的更多上下文。未来你和/或未来的调试人员会感谢你。

答案 1 :(得分:0)

感谢您的所有建议和意见。我解决了这个问题。异常文本显示,当您尝试查询表时,该表会发生变化,从而导致触发器失败。在INSERT之后检查子表到父表的有效性并允许触发器触发的技巧是删除对子(触发器)表的引用并使用以下命令执行连接:NEW.foreign_key以加入父进程表。我在尝试调试时学到了很多东西:)

BEGIN
    SELECT COUNT(1)
    INTO l_dep_key
   FROM schema.transaction_table o,
     schema.linker_table r
  WHERE     o.primary_key = r.primary_key
    AND o.table_name = 'INDIVIDUAL_REC'
    AND o.system_id = '265226'
    AND o.status = 'A'
    AND r.status = 'A'
    AND o.foreign_key = r.primary_key
    AND r.primary_key = :NEW.foreign_key
    AND r.relationship_code IN ('EMPLOYER_OF');