【问题标题】:Oracle AFTER INSERT TriggerOracle AFTER INSERT 触发器
【发布时间】:2013-12-09 04:17:56
【问题描述】:

以下触发器不会触发。触发器在添加 '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;
   /`

【问题讨论】:

  • 你看异常逻辑了吗?它正在调用一些调试器过程。注释掉异常处理程序,看看你得到了什么错误。顺便说一句,像这样使用 WHEN OTHERS 只是一个糟糕的异常处理解决方案。

标签: plsql triggers oracle11g


【解决方案1】:

如果它在没有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(),因为它可以为您提供有关异常的更多上下文。未来的你和/或未来的调试者会感谢你的。

【讨论】:

    【解决方案2】:

    感谢您的所有建议和意见。我解决了这个问题。异常文本显示,当您尝试查询导致触发器失败的表时,该表发生了变异。在插入后检查子表对父表的有效性并允许触发器触发的技巧是删除对子(触发器)表的引用并使用 :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');
    

    【讨论】:

      猜你喜欢
      • 2013-03-29
      • 1970-01-01
      • 2017-10-04
      • 1970-01-01
      • 2020-12-23
      • 1970-01-01
      • 2015-09-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多