Удалить из трех таблиц сразу [дубликат]

Если вы не хотите использовать какое-либо из множества доступных пакетов маршрутизации, вам необходимо самостоятельно проанализировать путь:

Проложить путь / provision к вашему обработчику

http.HandleFunc("/provisions/", Provisions)

Затем разделите путь по мере необходимости в обработчике

id := strings.TrimPrefix(req.URL.Path, "/provisions/")
// or use strings.Split, or use regexp, etc.
6
задан ziggy 4 March 2011 в 17:45
поделиться

3 ответа

Два возможных подхода.

  1. Если у вас есть внешний ключ, объявите его как on-delete-cascade и удалите родительские строки старше 30 дней. Все дочерние строки будут удалены автоматически.
  2. Основываясь на вашем описании, похоже, что вы знаете родительские строки, которые хотите удалить, и должны удалить соответствующие дочерние строки. Вы пробовали SQL как это?
      delete from child_table
          where parent_id in (
               select parent_id from parent_table
                    where updd_tms != (sysdate-30)
    
    - теперь удалить записи родительской таблицы
    delete from parent_table
    where updd_tms != (sysdate-30);
    

---- Исходя из вашего требования, похоже, что вам, возможно, придется использовать PL / SQL. Я посмотрю, может ли кто-нибудь опубликовать на нем чистое SQL-решение (в этом случае это определенно будет способ).

declare
    v_sqlcode number;
    PRAGMA EXCEPTION_INIT(foreign_key_violated, -02291);
begin
    for v_rec in (select parent_id, child id from child_table
                         where updd_tms != (sysdate-30) ) loop

    -- delete the children
    delete from child_table where child_id = v_rec.child_id;

    -- delete the parent. If we get foreign key violation, 
    -- stop this step and continue the loop
    begin
       delete from parent_table
          where parent_id = v_rec.parent_id;
    exception
       when foreign_key_violated
         then null;
    end;
 end loop;
end;
/
7
ответ дан cNgamba 18 August 2018 в 10:59
поделиться
  • 1
    Столбец с значением даты находится в дочерней таблице, а не в родительской таблице. благодаря – ziggy 4 March 2011 в 17:20
  • 2
    Итак .. для каждого вашего ребенка, который вы удаляете, вы хотите узнать, не имеет ли родителя других детей, а затем удалить родителя? – Rajesh Chamarthi 4 March 2011 в 17:22
  • 3
    Да, это правильно - Спасибо – ziggy 4 March 2011 в 17:25
  • 4
    @ziggy, обновил мой пост выше. – Rajesh Chamarthi 4 March 2011 в 20:03
  • 5
    Да, я решил использовать этот подход, поскольку он чище. благодаря – ziggy 5 March 2011 в 12:26

Вот полный пример того, как это можно сделать. Однако вам нужны привилегии запроса flashback в дочерней таблице.

Вот настройка.

create table parent_tab
  (parent_id number primary key,
  val varchar2(20));

create table child_tab
    (child_id number primary key,
    parent_id number,
    child_val number,
     constraint child_par_fk foreign key (parent_id) references parent_tab);

insert into parent_tab values (1,'Red');
insert into parent_tab values (2,'Green');
insert into parent_tab values (3,'Blue');
insert into parent_tab values (4,'Black');
insert into parent_tab values (5,'White');

insert into child_tab values (10,1,100);
insert into child_tab values (20,3,100);
insert into child_tab values (30,3,100);
insert into child_tab values (40,4,100);
insert into child_tab values (50,5,200);

commit;

select * from parent_tab
where parent_id not in (select parent_id from child_tab);

Теперь удалите подмножество детей (с родителями 1,3 и 4 - но а не 5).

delete from child_tab where child_val = 100;

Затем получите parent_ids из текущего состояния COMMITTED child_tab (т. е. до того, как они были до удаления), и удалите те, которые ваш сеанс НЕ удалил. Это дает вам подмножество, которое было удалено. Затем вы можете удалить их из родителя_tab

delete from parent_tab
where parent_id in
  (select parent_id from child_tab as of scn dbms_flashback.get_system_change_number
  minus
  select parent_id from child_tab);

«Зеленый» все еще там (так как он еще не имел записи в дочерней таблице), а «Красный» все еще существует (так как он все еще имеет запись в дочерней таблице)

select * from parent_tab
where parent_id not in (select parent_id from child_tab);

select * from parent_tab;

Это экзотическая / необычная операция, поэтому, если бы я это делал, я, вероятно, был бы немного осторожен и блокировал бы дочерние и родительские таблицы в эксклюзивном режиме в начале транзакции. Кроме того, если дочерняя таблица была большой, она не была бы особенно эффективной, поэтому я бы выбрал PL / SQL-решение, такое как Rajesh's.

3
ответ дан Gary Myers 18 August 2018 в 10:59
поделиться
  • 1
    Спасибо, Гэри, я не использовал этот подход, но было полезно знать, что я могу это сделать. – ziggy 5 March 2011 в 12:27

Если у детей есть FKs, связывающие их с родителем, вы можете использовать DELETE CASCADE для родителя.

, например

CREATE TABLE supplier 
( supplier_id numeric(10) not null, 
 supplier_name varchar2(50) not null, 
 contact_name varchar2(50),  
 CONSTRAINT supplier_pk PRIMARY KEY (supplier_id) 
); 



CREATE TABLE products 
( product_id numeric(10) not null, 
 supplier_id numeric(10) not null, 
 CONSTRAINT fk_supplier 
   FOREIGN KEY (supplier_id) 
  REFERENCES supplier(supplier_id) 
  ON DELETE CASCADE 
); 

Удалить поставщика, и он будет делить все продукты для этого поставщика

7
ответ дан Mark Baker 18 August 2018 в 10:59
поделиться
  • 1
    Да, но проблема в том, что, чтобы узнать, какой поставщик удалить, я должен посмотреть на таблицу продуктов. А также столбец, с которым я работаю, не был создан с помощью «ВКЛЮЧЕНА УДАЛИТЬ КАСКАД» пункт. – ziggy 4 March 2011 в 17:27
  • 2
    Можете ли вы создать ON DELETE CASCADE? Если это так, вы можете написать инструкцию удаления, которая вытаскивает совокупный набор ключей из дочерней таблицы. – Ken Downs 4 March 2011 в 20:08
  • 3
    Спасибо, Марк, я решил пойти с подходом pl / sql в конце, поскольку это было легче. изменение структуры таблицы также сработало бы, но мне пришлось бы делать больше тестов :) Спасибо – ziggy 5 March 2011 в 12:28
Другие вопросы по тегам:

Похожие вопросы: