2010-07-02 11 views
4

Bon, c'est (probablement) un très question simple, mais je crains de ne connaître presque pas MySQL, alors s'il vous plaît mettre en place avec moi. J'essaye juste de supprimer chaque rangée d'une table qui n'est pas contrainte par une clé étrangère dans une autre table - une table spécifique, il y a seulement deux tables impliquées ici. Les instructions create ressemblent un peu:MySQL tentant de supprimer toutes les lignes qui ne sont pas contraints par la clé étrangère

CREATE TABLE `testschema`.`job` (
    `Job_Id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `Comment` varchar(255) DEFAULT NULL, 
    PRIMARY KEY (`Job_Id`) USING BTREE, 
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 

CREATE TABLE `ermieimporttest`.`jobassignment` (
    `JobAssignment_Id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `JobId` int(10) unsigned DEFAULT NULL, 
    PRIMARY KEY (`JobAssignment_Id`), 
    KEY `FK_jobassignment_1` (`JobId`), 
    CONSTRAINT `FK_jobassignment_1` FOREIGN KEY (`JobId`) REFERENCES `job` (`Job_Id`), 
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 

Toute ma déclaration SQL est:

DELETE FROM job USING job INNER JOIN jobAssignment WHERE job.Job_Id != jobAssignment.JobId; 

Je pensais que cela était exact - il devrait supprimer tous les emplois de la table de travail pour lequel il n'existe pas l'affectation de travail qui a ce travail comme c'est la clé étrangère. Cependant, cela ne fonctionne pas avec l'erreur suivante quand je tente de l'exécuter:

Impossible de supprimer ou mettre à jour une ligne de parent. une contrainte de clé étrangère échoue (testdatabasejobassignment, CONTRAINTE FK_jobassignment_1 FOREIGN KEY (JobId) RÉFÉRENCES job (Job_Id))

Alors quelle chose stupide que je fais mal?

EDIT: Comme d'habitude, j'ai trouvé une réponse seulement quelques secondes après avoir posté ici. J'ai utilisé la requête (complètement différente):

DELETE FROM job WHERE Job_Id NOT IN (SELECT JobId FROM jobassignment) 

Par curiosité, est-ce la meilleure façon de le faire? Mon idée originale était-elle réalisable? Et si oui, qu'est-ce qui n'allait pas?

+0

Dans votre instruction, la sous-requête dependend est exécutée pour chaque ligne d'une table de travail, donc c'est très inefficace. – Naktibalda

+1

Votre instruction 'DELETE' affichée semble un peu confuse, mais pour répondre à votre curiosité: pour chaque ligne dans' job', votre 'JOIN' produit une liste de lignes pour chaque ligne dans' jobassignment' qui a un identifiant pas égal à l'ID du travail. Pour le voir plus clairement, transformez votre instruction 'DELETE' en une instruction SELECT. Quelque chose comme ceci: 'SELECT * FROM travail INNER JOIN jobassignment ON travail.Job_Id! = Jobassignment.JobId;' – Mike

+0

Merci Mike. Je vois ce que vous voulez dire maintenant - ma déclaration comme il a été créé un produit croisé des deux tables, moins les lignes où Job_Id == JobId. Essayer de supprimer ceci échoue bien sûr, car il inclut des Jobs qui sont contraints. À votre santé. – Stephen

Répondre

6
DELETE FROM job USING job 
LEFT JOIN jobAssignment ON(job.Job_Id = jobAssignment.JobId) 
WHERE jobAssignment.JobId IS NULL; 
+0

Je choisis ceci comme réponse parce que c'est la réponse à ma question de comment faire la suppression en utilisant une jointure. Bien que j'aie effectivement utilisé la réponse de Jaymz, je l'ai trouvé de façon indépendante en l'utilisant ici, donc pendant que je lui donne ma graditude, c'est la réponse la plus proche à ma dernière question. Merci, Naktibalda. – Stephen

5

Vous aurez probablement besoin d'un sous-requête, pas sûr que cela fonctionnera dans mySQL, mais quelque chose de similaire au moins:

DELETE FROM job 
WHERE job.Job_Id NOT IN (
    SELECT JobId FROM jobAssignment 
) 
+0

Merci. J'ai peur de choisir la réponse de Naktibalda pour la réponse «correcte» parce qu'elle a répondu à ma question éditée le plus proche, mais cette solution était celle que j'ai trouvée et utilisée en premier!Merci Jaymz. – Stephen

1

Naktibalda suggère la sous-requête peut être inefficace; Si oui, vous pouvez essayer

DELETE FROM job 
    WHERE NOT EXISTS (SELECT * 
          FROM jobassignment 
          WHERE job.Job_Id = jobassignment.Job_Id); 

J'ai eu de mauvaises expériences avec IN et PAS DANS le passé; moins de problèmes avec NOT EXISTS.

+0

Merci pour la suggestion - l'approche sous-requête a fonctionné en <1 seconde (au moins, je pense - tout au plus, ce n'était pas une pause notable) pour 6500 lignes, mais je sais que quand il s'agit de bases de données, il peut y avoir beaucoup plus de lignes que cela assez facilement! – Stephen