Question

I have a problem in a hierarchical query. I have a self-referencing table like this:

    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

I need to add a trigger in the database which prevents the user from adding a cabin which exceeds the remaining size of that ship.

For example, in the table, for ship 1, we have a total size of 50. There are 2 cabins present which consume the size of 40. So now we are left with 10 as the available space. We should not be able to add another cabin(s) with size>10. Anything <= 10 is fine. Similar is the case for cabins and shelves. The total size of all the shelves in a cabin should not exceed the total size allotted for that cabin.

There can be any number of ship-entries in the table (which is the root).

I know about hierarchical queries and i can traverse a tree and all but I'm finding it difficult to gather my thoughts on the problem. Could anyone please point me in the right direction so that I can add that trigger successfully?

Was it helpful?

Solution

I agree with @N_west that you should probably have separate tables for Ships, Cabins and Shelves, for your minimalist purpose and for the ease of maintenance (archiving/purging etc.). If you want to have a Trigger to handle this then you will have to capture the data from SHIPS to a log table using a trigger on SHIPS then use the data on log table to verify against insert on SHIPS. Its not best of solution but can achieve what you want. You can have a user defined exception to handle ALERTS in your application based on the error code (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;
/

Another approach would be to use COMPOUND TRIGGERS only if you are using Oracle 11g.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top