Ошибка 1022 - Не могу написать; дубликат ключа в таблице

218

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

SQL query:

-- -----------------------------------------------------
-- Table `apptwo`.`usercircle`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS  `apptwo`.`usercircle` (

 `idUserCircle` MEDIUMINT NOT NULL ,
 `userId` MEDIUMINT NULL ,
 `circleId` MEDIUMINT NULL ,
 `authUser` BINARY NULL ,
 `authOwner` BINARY NULL ,
 `startDate` DATETIME NULL ,
 `endDate` DATETIME NULL ,
PRIMARY KEY (  `idUserCircle` ) ,
INDEX  `iduser_idx` (  `userId` ASC ) ,
INDEX  `idcategory_idx` (  `circleId` ASC ) ,
CONSTRAINT  `iduser` FOREIGN KEY (  `userId` ) REFERENCES  `apptwo`.`user` (
`idUser`
) ON DELETE NO ACTION ON UPDATE NO ACTION ,
CONSTRAINT  `idcategory` FOREIGN KEY (  `circleId` ) REFERENCES  `apptwo`.`circle` (
`idCircle`
) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE = INNODB;

MySQL said: Documentation

#1022 - Can't write; duplicate key in table 'usercircle' 
Git-состоянии
источник
4
Если я правильно помню, первичный ключ всегда также является УНИКАЛЬНЫМ ИНДЕКСОМ, так что вам придется отбросить уникальный оператор индекса?
Mr47
1
ON DELETE NO ACTIONпросто отбросит все использование внешнего ключа. Если у вас нет особых причин для этого.
AmazingDreams
4
@AmazingDreams Почему? Это все еще обеспечивает ссылочную целостность. Только вы должны удалить детей самостоятельно. Это безопаснее, чем каскадное удаление, когда вы можете случайно удалить много данных, удалив одно неверное ключевое слово.
GolezTrol
1
stackoverflow.com/a/5810024/1567737 Почему использование псевдонима при использовании «aliased» сразу дает понять цель?
AmazingDreams
@AmazingDreams Спасибо за совет. Мне также нравятся дебаты вокруг этого - это помогает мне узнать о плюсах и минусах.
Git-состоянии

Ответы:

534

Скорее всего, у вас уже есть ограничение с именем iduserили idcategoryв вашей базе данных. Просто переименуйте ограничения, если так.

Ограничения должны быть уникальными для всей базы данных, а не только для конкретной таблицы, которую вы создаете / изменяете.

Чтобы узнать, где в настоящее время используются ограничения, вы можете использовать следующий запрос:

SELECT `TABLE_SCHEMA`, `TABLE_NAME`
FROM `information_schema`.`KEY_COLUMN_USAGE`
WHERE `CONSTRAINT_NAME` IN ('iduser', 'idcategory');
Максим Польща
источник
15
Точно так же, как вы сказали. Многие ограничения были автоматически сгенерированы с теми же именами идентификатора idcategory в остальной части запроса CREATE - спасибо за вашу помощь!
Git-состоянии
1
Я думал, что MySQL Workbench исправит это при экспорте сценария создания, но это то, что я получаю за «Игнорирование» предупреждения о подобных вещах при открытии проекта.
SnowInferno
Спасибо, приятель :) Это мне очень помогает, и теперь мое соглашение о внешних ключах отличается, и я не могу встретиться с этой проблемой снова :)
Могу это подтвердить. Но что я могу сделать, если указанное ограничение существует, хотя ссылочная таблица уже была удалена ?? Могу ли я удалить ограничение из несуществующей таблицы? Я думаю, что я должен обновить с MySQL 5.6 до текущей MariaDB.
Anse
4
Спасибо за это: ограничения должны быть уникальными для всей базы данных
Себасира
31

Измените имя внешнего ключа в MySQL. Вы не можете иметь одинаковые имена внешних ключей в таблицах базы данных.

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

Вассим Сабра
источник
Это была проблема в моем случае. Я бы никогда не догадался, и ты спас мой день. Используя fk_id_1, fk_id_2 и т. Д., Сейчас. Спасибо.
JackLeEmmerdeur
15

Из двух ссылок « Решено успешно» и « Соглашение об именах» я легко решил ту же проблему, с которой столкнулся. т. е. для имени внешнего ключа укажите как fk _colName_ TableName . Это соглашение об именах не является двусмысленным и также делает каждый ForeignKey в вашей модели БД уникальным, и вы никогда не получите эту ошибку.

Ошибка 1022: не могу написать; дубликат ключа в таблице

Chandz
источник
6

Как уже упоминали другие, возможно, что имя для вашего ограничения уже используется другой таблицей в вашей БД . Они должны быть уникальными по всей базе данных.

Хорошее соглашение для именования ограничений внешнего ключа:

fk_TableName_ColumnName

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

SELECT * FROM information_schema.table_constraints WHERE constraint_schema = 'YOUR_DB';

Запустив этот запрос, я обнаружил, что ранее создал временную копию таблицы, и эта копия уже использовала имя ограничения, которое я пытался использовать.

Саймон Ист
источник
4

Я просто провел последние 4 часа с той же проблемой. Я просто убедился, что ограничения имеют уникальные имена.

Вы можете переименовать ограничения. Я добавил номер к своему, чтобы я мог легко отследить количество случаев.

пример

Если ограничение в таблице называется boy с внешним ключом X Следующее ограничение с внешним ключом X может называться boy1

Я уверен, что ты найдешь лучшие имена, чем я. 🙂

Незнакомый скрипт
источник
3

Это также может возникнуть в связи с ошибкой в ​​некоторых версиях онлайн-инструмента изменения схемы Percona Toolkit. Чтобы изменить большую таблицу, pt-osc сначала создает дублирующую таблицу и копирует в нее все записи. При некоторых обстоятельствах некоторые версии pt-osc 2.2.x будут пытаться присвоить ограничениям для новой таблицы те же имена, что и ограничениям для старой таблицы.

Исправление было выпущено в 2.3.0.

См. Https://bugs.launchpad.net/percona-toolkit/+bug/1498128 для получения дополнительной информации.

MJD
источник
1

Я также столкнулся с этой проблемой. Проверьте, если имя базы данных уже существует в Mysql, и переименуйте старое.


источник
1

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

user3076750
источник