Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update database tables

Tags:

sql

oracle

plsql

I have the following database tables : enter image description here

In these tables I have the following elements :

  • Container : Can contain any container_item element; The relation is stored using the table CONTAINER_CANDIDATES
  • Container_Item: Can contain any element item; The relation is stored using the table COMPOUNDS
  • Elements: The basic element in my system.

Let me phrase the question using a concrete case:

In the table ELEMENTS I can store the following elements:

Id = 1 ; ElementName = 'element001'
Id = 2 ; ElementName = 'element002'
Id = 3 ; ElementName = 'element003'
Id = 4 ; ElementName = 'element004'
Id = 5 ; ElementName = 'element005'
Id = 6 ; ElementName = 'element006'
Id = 7 ; ElementName = 'element007'

In table CONTAINER_ITEM I can store the following elements:

Id = 1 ; ContainerItemName = 'item-id-aaa'
Id = 2 ; ContainerItemName = 'item-id-bbb'
Id = 3 ; ContainerItemName = 'item-id-ccc'
Id = 4 ; ContainerItemName = 'item-id-ddd'
Id = 5 ; ContainerItemName = 'item-id-eee'

In table CONTAINER, I can store the following elements:

Id = 1; ContainerName = 'ContainerName01';
Id = 2; ContainerName = 'ContainerName02';

Using the table COMPOUNDS I make the following connections:

    - item-id-aaa  (id = 1 in Container_Item table)
        -> element001 (id = 1 in Elements table)
        -> element002 (id = 2 in Elements table)
    - item-id-bbb (id = 2 in Container_Item table)
        -> element003 (id = 3 in Elements table)
        -> element004 (id = 4 in Elements table)
    - item-id-ccc (id = 3 in Container_Item table)
        -> element005 (id = 5 in Elements table)
        -> element006 (id = 6 in Elements table)
    - item-id-ddd (id = 4 in Container_Item table)
        -> element005 (id = 5 in Elements table)
        -> element007 (id = 7 in Elemens table);
    - item-id-eee (id = 5 in Container_Item table)
        -> element-007 (id = 7 in Elemens table)

Using the table CONTAINER_CANDIDATES I make the following connections:

        - ContainerName01 contains the following :
            -> item-id-aaa (id = 1 in Container_Item table)
            -> item-id-bbb (id = 2 in COntainer_Item table)
            -> item-id-ccc (id = 3 in COntainer_Item table)
            -> item-id-ddd (id = 4 in COntainer_Item table)
        - ContainerName02 contains the following:
            -> item-id-aaa (id = 1 in Container_Item table)
            -> item-id-eee (id = 5 in COntainer_Item table) 

So in this way I created all my connections. Now the question is how can I delete the ContainerName01 and all the items under it (Container Items and Elements under it) so that other Containers (example : ContainerName02) is not affected at all ?

I want to achieve this using an Oracle PL SQL procedure

like image 625
Lucian Avatar asked Mar 17 '17 09:03

Lucian


1 Answers

Ok this is not a really hard problem if you follow good practices.

First, you have two "many-to-many" jump tables (CONTAINER_CANDIDATES & COMPOUNDS), as orphan row in these will be totally useless, we'll add a DELETE CASCADE on them.

ALTER TABLE CONTAINER_CANDIDATES
ADD CONSTRAINT FK_CC_CONTAINER
   FOREIGN KEY (CONTAINERID)
   REFERENCES CONTAINER (ID)
   ON DELETE CASCADE;

ALTER TABLE CONTAINER_CANDIDATES
ADD CONSTRAINT FK_CC_CONTAINER_ITEM
   FOREIGN KEY (CONTAINERITEMID)
   REFERENCES CONTAINER_ITEM (ID)
   ON DELETE CASCADE;

ALTER TABLE COMPOUNDS
ADD CONSTRAINT FK_COMPOUNDS_CONTAINER_ITEM
   FOREIGN KEY (CONTAINERITEMID)
   REFERENCES CONTAINER_ITEM (ID)
   ON DELETE CASCADE;

ALTER TABLE COMPOUNDS
ADD CONSTRAINT FK_COMPOUNDS_ELEMENTS
   FOREIGN KEY (ELEMENTSID)
   REFERENCES ELEMENTS (ID)
   ON DELETE CASCADE;

Now, things nearly work by themselves, a small stored procedure to ensure we will not keep unused CONTAINER_ITEM and ELEMENTS and we are good.

CREATE OR REPLACE PROCEDURE cascaded_delete_container (
    P_CONTAINER_ID VARCHAR2
) IS
BEGIN
        -- remove the master from supplied ID
        -- cascade on CONTAINER_CANDIDATES
    DELETE FROM CONTAINER
    WHERE ID = P_CONTAINER_ID;

        -- remove CONTAINER_ITEM not used in CONTAINER_CANDIDATES
        -- cascade on COMPOUNDS
    DELETE FROM CONTAINER_ITEM
    WHERE NOT EXISTS(
        SELECT 1 
        FROM CONTAINER_CANDIDATES 
        WHERE CONTAINER_ITEM.ID = CONTAINER_CANDIDATES.CONTAINERITEMID
        );

        -- remove ELEMENTS not used in COMPOUNDS
    DELETE FROM ELEMENTS
    WHERE NOT EXISTS(
        SELECT 1 
        FROM COMPOUNDS 
        WHERE ELEMENTS.ID = COMPOUNDS.ELEMENTSID
        );

    COMMIT;

END;
/

This unsure you never have orphan in any of your table. It use the Cascade to do most of the work and just do a small trim of unused data in the two slave tables.

The only downside is this will not allow you to keep entry in CONTAINER_ITEM and ELEMENTS if you don't use them.

like image 51
Blag Avatar answered Nov 15 '22 04:11

Blag