web-dev-qa-db-fra.com

Supprimer un enfant et une ligne parent avec un script SQL

Au lieu de supprimer la ligne enfant, puis d'écrire une autre instruction sql pour supprimer la ligne parent, je voulais utiliser une instruction qui fera les deux. Pour info: nous utilisons la base de données Oracle.

pdate: Je n'ai pas le privilège de faire DELETE ON CASCADE

17
WowBow

Définissez vos clés étrangères avec suppressions en cascade . Il vous suffit ensuite de supprimer la ligne "parent".

14
Albin Sunnanbo
delete from 
(
select * from parent join child using (id)
where id = 1
)

AVERTISSEMENT! Supprime uniquement les emplacements des lignes parent ET enfant. NE supprimera PAS les parents sans enfants

4
grokster

Vous ne pouvez le faire que mal, c'est-à-dire en utilisant des déclencheurs.

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;
2
Adam Musch

Si vous souhaitez toujours supprimer les enfants lorsque vous supprimez une ligne parent, vous pouvez déclarer la contrainte de clé étrangère afin qu'Oracle supprime automatiquement l'enfant.

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

par exemple, déclarera une table parent et une table enfant et supprimera automatiquement les lignes enfants lorsque vous supprimez la ligne parent. Si vous ne voulez pas que ce genre de chose soit appliqué automatiquement ou que vous n'aimez pas la complexité qui est ajoutée lorsque les choses se produisent "automagiquement" en arrière-plan, vous êtes probablement coincé avec l'utilisation de plusieurs instructions DELETE .

1
Justin Cave

Après de très mauvaises expériences avec ce problème sur une base de données relativement grande et extrêmement critique, j'ai décidé de faire un Silver bullet pour cela! parce que je n'ai pas pu trouver n'importe lequel ! En fait, aucune des solutions/réponses dans ce fil ne répond aux besoins du problème.

Voir CASCADELETE repo sur mon github.

1
faghani

Une autre (façon ennuyeuse, nous l'avons dans une base de données qui, pour une raison inconnue, n'utilise pas de clés étrangères comme contraintes - oui oui) pour ce faire serait de créer un déclencheur après (ou avant) la suppression.

Vous devrez écrire une autre requête de suppression, mais juste dans le déclencheur.

Mais si vous ne pouvez pas mettre la cascade de suppression, je ne suis pas sûr que vous puissiez ajouter des déclencheurs ...

0
Raphaël Althaus

Au cas où cela aiderait quelqu'un d'autre, je viens d'écrire un script PLSQL pour le faire pour toutes les contraintes de clé étrangère dans une table avec l'aide de cette question Stackoverflow . J'espère que cela aide.

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;
0
Katie.Sun