1

我在分层查询中遇到问题。我有一个这样的自引用表:

    id    parent_id    name    size
-----------------------------------------
    1       null       Ship1    50
    2        1         cabin1   10
    3        1         cabin2   30
    4        3         shelf1    5
    5        3         shelf2   20
    6       null       Ship2    50
    7        6         cabin1   10
    8        6         cabin2   30
    9        7         shelf1   15

我需要在数据库中添加一个触发器,以防止用户添加超过该船剩余大小的客舱。

例如,在表中,对于 1 号船,我们的总尺寸为 50。存在 2 个舱室,消耗 40 的尺寸。所以现在我们剩下 10 个作为可用空间。我们应该不能再添加一个大小>10 的客舱。任何 <= 10 都可以。小木屋和货架也是如此。一个客舱内所有货架的总尺寸不应超过分配给该客舱的总尺寸。

表中可以有任意数量的船舶条目(这是根)。

我知道分层查询,我可以遍历一棵树,但我发现很难收集我对这个问题的想法。谁能指出我正确的方向,以便我可以成功添加该触发器?

4

1 回答 1

1

我同意@N_west 的观点,为了您的极简主义目的和便于维护(存档/清除等),您可能应该为 和 设置单独Ships的表CabinsShelves如果您想要一个触发器来处理这个问题,那么您将必须SHIPS使用触发器将数据从日志表捕获,SHIPS然后使用日志表上的数据来验证是否插入 on SHIPS。它不是最好的解决方案,但可以实现您想要的。您可以ALERTS根据错误代码 (20101) 在应用程序中处理用户定义的异常。

SQL> CREATE TABLE LOG_SHIPS AS SELECT * FROM SHIPS;

SQL> CREATE or REPLACE TRIGGER TRG_SHIP
BEFORE INSERT ON SHIPS
FOR EACH ROW

L_count   NUMBER(10);
L_total   NUMBER(10);
e_exp     EXCEPTION;

BEGIN
     SELECT sum(size) INTO L_count
       FROM LOG_SHIPS
      WHERE parent_id = :new.parent_id;

     SELECT size INTO L_total
       FROM LOG_SHIPS
      WHERE id = :new.parent_id;

     if L_count+:new.size > L_total then
        RAISE e_exp;
     else
        INSERT INTO LOG_SHIPS VALUES (:new.id,:new.parent_id,:new.name,:new.size);
     end if;

EXCEPTION
   WHEN e_exp THEN
     RAISE_APPLICATION_ERROR (-20101,'Size entered exceeds limit.');
   WHEN others THEN
      null; -- do some meaningful exception handling here
END;
/

另一种方法是COMPOUND TRIGGERS仅在您使用 Oracle 11g 时使用。

于 2012-08-04T18:04:00.353 回答