0

我的触发器有什么问题?我使用 toad for oracle
执行此 sql toad 后显示此消息,不再显示!:

Warning: compiled but with compilation errors

并且触发器不起作用

我的触发器在这里:

CREATE OR REPLACE TRIGGER trg_delete_mmtp_user_feature
   BEFORE DELETE
   ON mmtp_user
   FOR EACH ROW
BEGIN
-- for these cases delete not allowed
   IF ((SELECT COUNT (*)
          FROM payment p INNER JOIN mmtp_user mt
               ON mt.customer_id = p.requester_id
         WHERE p.rp_reason_id = 20 AND mt.mmtp_user_id = :OLD.mmtp_user_id) >
                                                                             0
      )
   THEN
      raise_application_error
             (-20654,
              'Query has attempted to delete MMTP_USER with existing payment'
             );

   ELSE                            --befor deleting features should be deleted
      DELETE FROM mmtp_user_feature
            WHERE mmtp_user_id = :OLD.mmtp_user_id;
   END IF;
END;
/

并删除我收到此消息:

ORA-04098: trigger 'DEVX2.TRG_DELETE_MMTP_USER_FEATURE' is invalid and failed re-validation
4

2 回答 2

5

出现编译错误的原因是我们不能在 IF 子句中使用 SELECT 语句。所以你需要像这样打破它:

....
DECLARE
    n pls_integer;
BEGIN
    SELECT COUNT (*)
    into n
    FROM payment p INNER JOIN mmtp_user mt
               ON mt.customer_id = p.requester_id
    WHERE p.rp_reason_id = 20 AND mt.mmtp_user_id = :OLD.mmtp_user_id
-- for these cases delete not allowed
   IF n > 0
   THEN
....

解决了这个问题后,您会发现,正如 Florin 指出的那样,您将收到运行时变异表错误。当我们将查询放入访问拥有该触发器的表的触发器中时,Oracle 会抛出此错误。发生这种情况是因为表处于不稳定状态并且查询的结果是不可预测的。

变异表错误几乎总是表明数据模型不好,罪魁祸首是标准化不足。这意味着修复它们需要了解业务规则。在这种情况下,明显的解决方案是:

SELECT COUNT (*)
into n
FROM payment p 
WHERE p.requester_id = :OLD.customer_id
AND p.rp_reason_id = 20 

如果 和 之间存在一对一的关系,这将user_id起作用customer_id。如果没有这样的关系,您将不得不使用您对业务规则的了解来找出解决方案。

顺便说一句,使用 COUNT(*) 来测试是否存在并不是一个可扩展的解决方案。对于有很多付款的客户来说,这将需要很长时间。当您所需要的只是他们至少有一个这样的记录时,这会浪费很多精力。添加and rownum = 1到查询中将减少不必要的工作。

于 2013-02-05T07:22:58.857 回答
2

问题是

   SELECT COUNT (*)
              FROM payment p INNER JOIN mmtp_user mt
                   ON mt.customer_id = p.requester_id
             WHERE p.rp_reason_id = 20 AND mt.mmtp_user_id = :OLD.mmtp_user_id

您正在读取正在更新/删除的表,因此您会收到 mutating table 错误。

也许如果你只是验证

SELECT COUNT (*)
          FROM payment p 
          WHERE :OLD:customer_id = p.requester_id
            and p.rp_reason_id = 20  

大于零,够吗?

于 2013-02-05T07:06:27.653 回答