2010-07-02 1 views
4

Хорошо, это (возможно) очень простой вопрос, но я боюсь, что почти не знаю MySQL, поэтому, пожалуйста, мириться со мной. Я просто пытаюсь удалить каждую строку из одной таблицы, которая не ограничена внешним ключом в другой таблице - конкретной таблицей, здесь задействованы только две таблицы. Операторы создания выглядят как:MySQL пытается удалить все строки, которые не ограничены внешним ключом

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; 

Любой мой SQL заявление:

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

Я думал, что это было правильно - он должен удалить все задания из таблицы заданий, для которых не существует задание на работу, которое имеет эту работу, поскольку это внешний ключ. Тем не менее, это не удается из-за ошибки, когда я пытаюсь и выполнить его:

Невозможно удалить или обновить родительскую строку:. ограничение внешнего ключа терпит неудачу (testdatabasejobassignment, CONSTRAINT FK_jobassignment_1 FOREIGN KEY (JobId) СПИСОК ЛИТЕРАТУРЫ job (Job_Id))

Так что глупо я делаю неправильно?

EDIT: Как обычно, я нашел ответ только через несколько секунд после публикации здесь. Я использовал (совершенно другой) запрос:

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

Из любопытства, это лучший способ сделать это? Была ли моя оригинальная идея осуществимой? И если да, что с этим случилось?

+0

В вашем заявлении зависимый подзапрос выполняется для каждой строки таблицы заданий, поэтому он очень неэффективен. – Naktibalda

+1

Ваш опубликованный оператор 'DELETE' выглядит немного запутанным, но для ответа на ваше любопытство: для каждой строки в' задании' ваш 'JOIN' производит список строк для каждой строки в' jobassignment', который имеет идентификатор не равный идентификатору задания. Чтобы это было более ясно, превратите инструкцию 'DELETE' в инструкцию' SELECT'. Что-то вроде этого: 'SELECT * FROM job INNER JOIN jobassignment ON job.Job_Id! = Jobassignment.JobId;' – Mike

+0

Спасибо Майку. Я понимаю, что вы сейчас имеете в виду - мое утверждение, поскольку было создано кросс-произведение из двух таблиц, за вычетом строк, где Job_Id == JobId. Попытка удалить это, а затем, конечно, не удалась, потому что она включает в себя задания, которые ограничены. Приветствия. – Stephen

ответ

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

Я выбираю это как ответ, потому что это ответ на мой вопрос о том, как сделать удаление, используя соединение. Хотя я действительно использовал ответ Джеймза, я нашел его безразличным в использовании его здесь, поэтому, пока я даю ему свою градацию, это более близкий ответ на мой последний вопрос. Спасибо, Нактибалда. – Stephen

5

Вы, вероятно, понадобится подзапрос, не уверен, если это будет работать в MySql, но что-то подобное, по крайней мере:

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

Спасибо. Боюсь, я выбрал ответ Нактибалды для «правильного» ответа, потому что он ответил на мой отредактированный вопрос, ближайший, но это решение было тем, что я на самом деле нашел и использовал первым!Спасибо, Джеймс. – Stephen

1

Naktibalda предлагает подзапрос может быть неэффективным; если да, то можете попробовать

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

У меня были плохие переживания с IN и NOT IN в прошлом; меньше проблем с НЕ СУЩЕСТВУЕТ.

+0

Спасибо за предложение - подзапрос запустился за <1 секунду (по крайней мере, я думаю - в лучшем случае это была не заметная пауза) для 6500 строк, но я знаю, что когда дело доходит до баз данных, может быть много больше строк, чем это довольно легко! – Stephen