Ответ 1
Определите внешние ключи с каскадным удалением. Затем вам нужно удалить только родительскую строку.
Вместо того, чтобы удалять дочернюю строку, а затем писать другой оператор sql для удаления родительской строки, я хотел использовать один оператор, который будет делать оба. FYI: мы используем базу данных Oracle.
Обновление: У меня нет привилегии делать DELETE ON CASCADE
Определите внешние ключи с каскадным удалением. Затем вам нужно удалить только родительскую строку.
delete from
(
select * from parent join child using (id)
where id = 1
)
ВНИМАНИЕ! Будет удаляться только там, где существуют как родительские, так и дочерние строки. НЕ удалит родителей без детей
Вы можете сделать это плохо, т.е. использовать триггеры.
create table parent
(pid number,
constraint parent_pk
primary key (pid)
using index
);
create table child
(cid number,
pid number,
constraint child_pk
primary key(cid)
using index,
constraint child_fk
foreign key (pid)
references parent (pid)
);
create index child_fk on child (pid);
create trigger fake_delete_cascade
before delete on parent
for each row
begin
delete from child where pid = :old.pid;
end;
/
insert into parent values (1);
insert into child values (1,1);
commit;
select count(*) from child;
delete from parent where pid = 1;
select count(*) from child;
Если вы всегда хотите удалить детей при удалении родительской строки, вы можете объявить ограничение внешнего ключа, чтобы Oracle автоматически удалял дочерний элемент
create table parent (
parentID number primary key,
parentData varchar2(100)
);
create table child (
childID number primary key,
parentID number references parent( parentID ) on delete cascade,
childData varchar2(100)
);
например, объявит родительскую таблицу и дочернюю таблицу и автоматически удалит дочерние строки при удалении родительской строки. Если вы не хотите, чтобы такие вещи выполнялись автоматически или вам не нравилась сложность, которая добавляется, когда что-то происходит "автоматически" в фоновом режиме, вы, вероятно, придерживаетесь нескольких операторов DELETE
.
Другой (скучный способ, мы имеем это в базе данных, которая по неизвестной причине не использует внешние ключи в качестве ограничений - да да), чтобы сделать это, было бы создать триггер после (или до) удаления.
Вам нужно будет написать еще один запрос на удаление, но только в триггере.
Но если вы не можете поставить каскад delete, я не уверен, что вы можете добавить триггеры...
В случае, если это кому-то поможет, я просто написал сценарий PLSQL, чтобы сделать это для всех ограничений внешнего ключа в таблице с некоторой помощью из fooobar.com/questions/56178/.... Надеюсь, поможет.
DECLARE
CURSOR constraint_cursor IS SELECT *
FROM (SELECT a.table_name,
a.constraint_name,
a.column_name,
c_pk.table_name r_table_name,
b.column_name r_column_name
FROM user_cons_columns a
JOIN user_constraints c ON a.owner = c.owner
AND a.constraint_name = c.constraint_name
JOIN user_constraints c_pk ON c.r_owner = c_pk.owner
AND
c.r_constraint_name = c_pk.constraint_name
JOIN user_cons_columns b ON C_PK.owner = b.owner
AND
C_PK.CONSTRAINT_NAME = b.constraint_name AND
b.POSITION = a.POSITION
WHERE c.constraint_type = 'R'
and c_pk.owner = 'YOUR SCHEMA HERE') tbl;
sql_statement VARCHAR2(2048) := NULL;
tab_row constraint_cursor%rowtype;
BEGIN
OPEN constraint_cursor;
FOR i in 1..80 LOOP
FETCH constraint_cursor into tab_row;
EXECUTE IMMEDIATE 'ALTER table ' || tab_row.table_name || ' drop constraint ' || tab_row.constraint_name;
EXECUTE IMMEDIATE 'ALTER table ' || tab_row.table_name || ' add constraint ' || tab_row.constraint_name || ' FOREIGN KEY (' ||
tab_row.column_name || ') references ' || tab_row.r_table_name || '(' || tab_row.r_column_name || ') ON DELETE CASCADE ';
end loop;
close constraint_cursor;
end;
После некоторых действительно неудачных опытов с этой проблемой на относительно большой и чрезвычайно важной базе данных я решил сделать для нее Серебряную пулю ! потому что я не мог найти ни одного ! На самом деле, ни одно из решений/ответов в этой теме не отвечает потребностям проблемы.
Смотрите CASCADELETE репо на моем github.