Проблема с удалением строк

Когда я делаю что-то вроде:

УДАЛИТЬ ОТ users_has_pais, ГДЕ users_id = 151

Я получаю следующее сообщение об ошибке:

SQLSTATE [23000]: нарушение ограничения целостности: 1451 Невозможно удалить или обновить родительскую строку: ограничение внешнего ключа не работает (gisele.users_has_pais, ОГРАНИЧЕНИЕ users_has_pais_ibfk_3 ВНЕШНИЙ КЛЮЧ (users_id) ССЫЛКИ users (id) ПРИ УДАЛЕНИИ НЕТ ДЕЙСТВИЙ ПРИ ОБНОВЛЕНИИ НЕТ ДЕЙСТВИЙ)

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

CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(50) DEFAULT NULL,
`password` varchar(250) DEFAULT NULL,
`url` varchar(50) DEFAULT NULL,
`responsable` varchar(50) DEFAULT NULL,
`role` varchar(25) DEFAULT NULL,
`fecha` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=162 ;

CREATE TABLE IF NOT EXISTS `pais` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`pais` varchar(20) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `pais` (`pais`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;

users_has_pais | CREATE TABLE `users_has_pais` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`users_id` int(11) NOT NULL,
`pais_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `user` (`users_id`),
KEY `index3` (`pais_id`),
KEY `users_id` (`users_id`),
KEY `pais_id` (`pais_id`),
CONSTRAINT `users_has_pais_ibfk_3` FOREIGN KEY (`users_id`) REFERENCES `users` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `users_has_pais_ibfk_2` FOREIGN KEY (`pais_id`) REFERENCES `pais` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=46 DEFAULT CHARSET=latin1 |

РЕДАКТИРОВАТЬ: вставка информации об ограничениях


person la_f0ka    schedule 16.06.2011    source источник
comment
можете ли вы найти и опубликовать определение ограничения users_has_pais_ibfk_3?   -  person mtazva    schedule 16.06.2011
comment
@mtazva Я скопировал информацию, связанную с ограничением, в ссылку на пирог, которую я оставил в ветке сообщений.. Не уверен, что вы меня просили об этом.   -  person la_f0ka    schedule 16.06.2011
comment
ограничение, по-видимому, определено правильно - это была просто догадка (так же, как и @Adrian). Извините, это была моя единственная подсказка. Я вернусь, если что-то еще ударит меня.   -  person mtazva    schedule 17.06.2011


Ответы (2)


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

  • Измените ограничение на каскадное удаление (или другое правило ограничения), если это имеет смысл в вашей логике.
  • Предупредите пользователя о проблеме и посоветуйте ему сначала удалить другой объект.
  • Заставьте ваше приложение удалить зависимые строки, а затем строку, которую вы пытаетесь удалить (согласно комментарию @RacerX).

Обновить

После просмотра вашей структуры данных с более подробной информацией я подозреваю, что ваше ограничение может быть определено в обратном порядке. Можете ли вы опубликовать определение ограничения?

person Adriano Carneiro    schedule 16.06.2011
comment
Я предпочитаю, чтобы приложение сначала удаляло зависимые строки FK, а затем удаляло рассматриваемую строку. Каскадные удаления хороши, но они устраняют одну защиту, которую обеспечивают FK. Если приложение выходит из-под контроля (глючит), проектирование его с большим количеством каскадных удалений может стать проблемой. - person RacerX; 16.06.2011
comment
Я знаю. Вот почему я дал варианты ОП. ОП должен знать, что он может сделать. Кроме того, есть такие вещи, как глючные FK (неправильно определенные) - person Adriano Carneiro; 16.06.2011

Мои знания SQL не совсем на высшем уровне, но похоже, что вы удаляете что-то, на что ссылаются как на внешний ключ.

person MGZero    schedule 16.06.2011
comment
Вы не работаете вокруг этого. Это правило целостности определено в базе данных, и вы должны его соблюдать. Это означает, что либо вы удаляете все (я имею в виду все задействованные строки), либо вообще ничего не удаляете. Если вы удаляете все, то вам решать, будете ли вы делать это с помощью каскадного удаления, удаления, управляемого приложением, триггера удаления в таблице или путем помещения всей операции в хранимую процедуру. На опасность каскадного удаления указал RacerX в своем замечании. - person Erwin Smout; 21.06.2011