2017-03-17 39 views
6

Mam następujące tabele bazy danych: enter image description hereAktualizuj tabele bazy danych

w tych tabelach Mam następujące elementy:

  • opakowaniu: Może zawierać żadnego elementu container_item; Relacja jest przechowywana za pomocą tabeli CONTAINER_CANDIDATES
  • Container_Item: Może zawierać dowolny element elementu; Relacja jest przechowywana przy użyciu tabeli Elementy: Podstawowy element w moim systemie.

Pozwól fraza pytanie korzystając konkretny przypadek:

w elementach tabeli można przechowywać następujące elementy:

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' 

w tabeli CONTAINER_ITEM mogę się znajdować następujące elementy:

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' 

W tabeli POJEMNIKA, mogę przechowywać następujące elementy:

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

stosując związki Tabela I dokonać następujących połączeń:

- 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) 

Używanie CONTAINER_CANDIDATES Tabela I dokonać następujących połączeń:

 - 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) 

Więc w ten sposób stworzyłem wszystkie swoje połączenia. Teraz pytanie brzmi: jak mogę usunąć ContainerName01 i wszystkie elementy znajdujące się pod nim (elementy kontenerów i elementy pod nim), aby inne pojemniki (przykład: ContainerName02) nie zostały w ogóle zmienione?

Chcę to osiągnąć stosując procedurę Oracle PL SQL

+0

W przypadku, gdy ktoś się zastanawia '(****)' nie jest stłumionym przekleństwem. Wskazuje tę linię w pseudokodzie: '-> uzyskuje wszystkie elementy, które są używane tylko przez bieżącą wartość container_item w bieżącym kontenerze' (przewiń w lewo) – APC

+0

Nie wiem, co" obecny kontener "oznacza w **** pseudo- linia kodu. Czy oznacza to, że poszukiwany element może być używany przez elementy kontenerów innych niż obecne? –

+1

Należy opublikować instrukcje tabeli i wstawiania, aby łatwiej było dla mnie opracować kod. –

Odpowiedz

2

Ok to nie jest naprawdę trudnym problemem, jeśli się dobrymi praktykami.

Po pierwsze, masz dwa „wiele do wielu” tabele Jump (CONTAINER_CANDIDATES & COMPOUNDS), jako sierota wiersz będą one całkowicie bezużyteczne, dodamy DELETE CASCADE na nich.

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; 

Teraz wszystko działa prawie same, małe procedura przechowywana w celu zapewnienia, że ​​nie będzie trzymać nieużywane CONTAINER_ITEM i ELEMENTS i jesteśmy dobrzy.

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; 
/

Nie jesteś pewien, że nigdy nie masz sieroty w żadnym ze swoich stołów.Używa Cascade do wykonania większości prac i po prostu robi małe wykończenie nieużywanych danych w dwóch tabelach slave.

Jedynym minusem jest to, że nie pozwoli ci zachować wpisu w CONTAINER_ITEM i ELEMENTS, jeśli ich nie używasz.

+0

dziękuję, bardzo pomocne rozwiązanie Sir. –

+0

Dziękuję za komentarz. To naprawdę mi pomogło. Zastanawiałem się, jak skomplikować procedurę. – Lucian

+0

@Ugodowe dzięki, że czasami odpowiedzi są łatwiejsze niż się spodziewamy;) BTW, jeśli chcesz zachować trochę sierot z "CONTAINER_ITEM" i "ELEMENTS" lub po prostu potrzebujesz dostrojenia wydajności na dużych tabelach, możesz uruchomić dwa 'DELETE EXISTS' w dedykowanym Prc uruchamianym raz na godzinę/noc/tydzień. – Blag

-1

Jeśli chcesz osiągnąć to poprzez procedury droga będzie przechodzić identyfikator kontenera jako parametr, a następnie usunąć wpisy podrzędne, które pobrane za pomocą kursora. Jak rozumiem, musisz najpierw usunąć wpisy w tabelach CONTAINER_CANDIDATES i COMPOUNDS. Na przykład:

create or replace procedure delete_container(p_container_id number) is 

    -- Get all compound child etries via container ID 
    cursor c_get_compounds(cp_container_id number) is 
    select comp.id 
     from compounds comp, container_candidates cc 
    where comp.containerItemID = cc.containerItemID 
     and cc.containerID = cp_container_id; 

    -- Get all container candidate child entries via container ID 
    cursor c_get_container_candidates(cp_container_id number) is 
    select cc.id 
     from container_candidates cc 
    where cc.containerID = cp_container_id; 

begin 

    -- Fetch all compound entries 
    for r in c_get_compounds(cp_container_id => p_container_id) loop 
    -- Delete compound entries 
    delete from compounds where id = r.id; 
    end loop; 

    -- Fetch all container candidates 
    for r in c_get_container_candidates(cp_container_id => p_container_id) loop 
    -- Delete container candidates 
    delete from container_candidates where id = r.id; 
    end loop; 

    -- Delete container entry 
    delete from container where id = p_container_id; 
end delete_container; 

Sprawdź, czy są poprawne ID w kodzie

+0

Chciałbym usunąć tylko te elementy i elementy container_item, które są używane przez określony kontener. Jeśli jeden z elementów/container_item jest używany przez inny kontener, nie powinien być usuwany. Mam do tego działającą procedurę PL SQL, ale działa bardzo wolno. Mogę mieć do 10 milionów elementów (dowolnego rodzaju) w moich tabelach – Lucian

+0

. Będziemy potrzebować zobaczyć Twój kod, aby dowiedzieć się, jak go ulepszyć. –