2009-10-30 8 views
3

Je viens de trouver un bogue dans mon application Rails qui entraînerait la suppression de certains enregistrements avec leurs objets associés. Le bogue a été corrigé, mais j'ai maintenant plusieurs milliers d'enregistrements dans ma base de données avec des valeurs de clé étrangère pointant vers des enregistrements qui n'existent pas.SQL: supprimer des enregistrements avec des clés étrangères invalides

Est-il possible de supprimer tous les enregistrements dans une table où une clé étrangère entière référence un enregistrement dans une autre table qui n'existe pas dans SQL? Comment?

Répondre

14
delete from child_table where not exists 
    (select 1 from parent_table where parent_table.id=child_table.related_id) 

l'étape suivante est bien sûr de créer une contrainte FOREIGN KEY immédiatement (sauf si vous êtes sur MySQL MyISAM auquel cas vous êtes hors de la chance sur ce).

+0

Merci- travaillé rapidement et efficacement. – igul222

+0

Cela m'a juste sauvé mon arrière-train, merci. –

1

Supprimer de ChildTable où ForeignKeyField pas (sélectionnez PrimaryKeyField de ParentTable)

0

oui - utiliser une instruction composée en utilisant "WHERE col pas (id selecy de FKTABLE)"

5
DELETE FROM tblPerson 
WHERE DepartmentID NOT IN (SELECT ID FROM tblDepartment) 
0

Je don Je ne sais pas s'il y a un moyen simple. Mais vous pouvez écrire un script qui gère cela. Supposons que votre modèle est comme ça

 
class Post 
belongs_to :user 
end 

Ici, vous pouvez utiliser un script comme celui-ci

 
Post.all.each do |post| 
    post.delete if post.user.nil? 
end 

Il est plus facile et straigtforward puis écrire SQL. Mais cette fois prendre un vidage de DB avant d'essayer et de faire la magie

+0

C'était mon essai original, mais nous avons trop de disques - il aurait fallu des jours pour finir. – igul222

2

Oui, il existe plusieurs façons de supprimer toutes les anciennes lignes. Disons que vous avez une table appelée users avec une colonne id et une table appelée posts avec une colonne user_id qui doit référencer un utilisateur existant. Vous pouvez supprimer tous les messages des utilisateurs non-existants avec cette requête:

DELETE FROM posts WHERE user_id NOT IN (SELECT id FROM users); 

Cela a été posté par Damir Sudarevic avant. C'est plus facile et plus rapide que la réponse par zzzeek. Une fois que vous avez supprimé toutes les lignes incriminées, vous pouvez créer une clé étrangère. Cela empêchera cela.

Questions connexes