2017-03-17 40 views
6

tôi có các bảng cơ sở dữ liệu sau đây: enter image description herebảng cơ sở dữ liệu Cập nhật

Trong các bảng tôi có các yếu tố sau:

  • container: Có thể chứa bất kỳ yếu tố container_item; Mối quan hệ được lưu trữ bằng cách sử dụng bảng CONTAINER_CANDIDATES
  • Vùng chứa_Item: Có thể chứa bất kỳ mục yếu tố nào; Mối quan hệ được lưu trữ bằng cách sử dụng bảng COMPOUNDS
  • Thành phần: Phần tử cơ bản trong hệ thống của tôi.

Hãy để tôi cụm từ câu hỏi sử dụng một trường hợp cụ thể:

Trong YẾU TỐ bảng tôi có thể lưu trữ các yếu tố sau:

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' 

Trong bảng CONTAINER_ITEM Tôi có thể lưu trữ các yếu tố sau:

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' 

Trong bảng CONTAINER, tôi có thể lưu trữ các yếu tố sau:

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

Sử dụng hợp chất bảng tôi làm cho các kết nối sau:

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

Sử dụng CONTAINER_CANDIDATES bảng tôi làm cho các kết nối sau:

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

Vì vậy, bằng cách này tôi đã tạo tất cả các kết nối của tôi. Bây giờ câu hỏi là làm thế nào tôi có thể xóa ContainerName01 và tất cả các mục bên dưới nó (Container Items và Elements bên dưới) để các Container khác (ví dụ: ContainerName02) không bị ảnh hưởng gì cả?

Tôi muốn đạt được điều này bằng một thủ tục Oracle PL SQL

+0

Trong trường hợp bất kỳ ai đang thắc mắc '(****)' không phải là một lời giải thích bị chặn. Nó cho biết dòng này trong mã giả: '-> có được tất cả các phần tử chỉ được sử dụng bởi container_item hiện tại trong vùng chứa hiện tại' (cuộn sang trái) – APC

+0

Không chắc chắn" vùng chứa hiện tại "có nghĩa là gì trong **** pseudo- dòng mã. Điều đó có nghĩa là thành phần được tìm kiếm có thể được sử dụng bởi các vật chứa chứa đồ chứa khác ngoài hiện tại? –

+1

Vui lòng đăng tạo bảng và chèn câu lệnh để tôi có thể dễ dàng phát triển một số mã cho bạn. –

Trả lời

2

Ok đây không phải là một vấn đề thực sự khó khăn nếu bạn làm theo thông lệ tốt.

Trước tiên, bạn có hai bảng nhảy "nhiều-nhiều" (CONTAINER_CANDIDATES & COMPOUNDS), như hàng trẻ mồ côi trong những sẽ hoàn toàn vô dụng, chúng ta sẽ thêm một DELETE CASCADE trên chúng.

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; 

Bây giờ, mọi thứ gần như làm việc một mình, một thủ tục được lưu trữ nhỏ để đảm bảo chúng tôi sẽ không giữ không sử dụng CONTAINER_ITEMELEMENTS và chúng tôi rất tốt.

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

Điều này chắc chắn bạn không bao giờ có trẻ mồ côi trong bất kỳ bảng nào của bạn.Nó sử dụng Cascade để thực hiện hầu hết công việc và chỉ làm một phần nhỏ dữ liệu không sử dụng trong hai bảng nô lệ.

Nhược điểm duy nhất là điều này sẽ không cho phép bạn giữ mục nhập trong CONTAINER_ITEMELEMENTS nếu bạn không sử dụng chúng.

+0

cảm ơn bạn, giải pháp rất hữu ích sir. –

+0

Cảm ơn bạn đã bình luận. Điều này thực sự đã giúp tôi. Tôi đã suy nghĩ cách phức tạp trong thủ tục rõ ràng. – Lucian

+0

@Lucian cảm ơn, đôi khi câu trả lời là dễ dàng hơn chúng tôi mong đợi;) BTW, nếu bạn cần phải giữ một chút trẻ mồ côi 'CONTAINER_ITEM' và' ELEMENTS' hoặc chỉ cần một số điều chỉnh hiệu suất trên bảng lớn, bạn có thể chạy hai DELETE EXISTS' trong một Prc chuyên dụng bạn chạy một lần một giờ/đêm/tuần. – Blag

-1

Nếu bạn muốn đạt được điều này thông qua một thủ tục con đường để đi sẽ để vượt qua ID chứa như một tham số và sau đó xóa các mục con mà bạn được tìm nạp thông qua con trỏ. Như tôi đã hiểu, trước tiên bạn cần xóa các mục nhập trong CONTAINER_CANDIDATES và COMPOUNDS bảng. Ví dụ:

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; 

Kiểm tra xem ID là chính xác trong các mã

+0

Tôi chỉ muốn xóa các phần tử và container_items được sử dụng bởi một vùng chứa cụ thể. Trong trường hợp một trong những phần tử/container_items được sử dụng bởi các vùng chứa khác thì chúng sẽ không bị xóa. Tôi có một thủ tục PL SQL làm việc cho điều này, nhưng nó hoạt động rất chậm. tôi có thể có tối đa 10 milion elemnts (dưới bất kỳ hình thức nào) trong các bảng của tôi – Lucian

+0

Cũng sẽ cần phải xem mã của bạn để tìm hiểu cách cải thiện nó. –

Các vấn đề liên quan