Erro 1022 - Não é possível escrever; chave duplicada na tabela

218

Estou recebendo um erro 1022 sobre chaves duplicadas no comando create table. Tendo examinado a consulta, não consigo entender onde a duplicação está ocorrendo. Alguém mais pode vê-lo?

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-capaz
fonte
4
Se bem me lembro, a chave primária também é sempre um ÍNDICE ÚNICO, então você teria que descartar a instrução de índice exclusivo?
Mr47
1
ON DELETE NO ACTIONapenas descartaria todo o uso da chave estrangeira. A menos que você tenha razões muito específicas para fazer isso.
AmazingDreams
4
@AmazingDreams Why? Ele ainda reforça a integridade referencial. Somente você tem que excluir os filhos você mesmo. Isso é mais seguro do que uma exclusão em cascata, na qual você pode excluir acidentalmente muitos dados, excluindo uma palavra-chave incorreta.
GolezTrol
1
stackoverflow.com/a/5810024/1567737 Por que usar um alias ao usar o 'alias' torna o objetivo claro imediatamente?
AmazingDreams
@AmazingDreams Obrigado pela dica. Também gosto do debate sobre o assunto - isso me ajuda a aprender sobre os prós e os contras.
Git-capaz

Respostas:

534

O mais provável é que você já tenha uma restrição com o nome iduserou idcategoryno seu banco de dados. Apenas renomeie as restrições, se houver.

As restrições devem ser exclusivas para todo o banco de dados, não apenas para a tabela específica que você está criando / alterando.

Para descobrir onde as restrições estão em uso no momento, você pode usar a seguinte consulta:

SELECT `TABLE_SCHEMA`, `TABLE_NAME`
FROM `information_schema`.`KEY_COLUMN_USAGE`
WHERE `CONSTRAINT_NAME` IN ('iduser', 'idcategory');
Maksym Polshcha
fonte
15
Exatamente como você disse. Muitas restrições foram geradas automaticamente com os mesmos nomes de idcategory iduser no restante da consulta CREATE - obrigado por sua ajuda!
Git-capaz
1
Eu pensei que o MySQL Workbench teria corrigido isso ao exportar o script de criação, mas é isso que recebo por "Ignorar" o aviso sobre esse tipo de coisa quando abri o projeto.
SnowInferno
Obrigado, companheiro :) Isso me ajuda muito e agora meu convenção para chaves estrangeiras é diferente e eu não posso conheci esse problema novamente :)
Pode confirmar isso. Mas o que posso fazer se a restrição nomeada existir, embora a tabela referenciada já tenha sido eliminada? Posso eliminar uma restrição de uma tabela inexistente? Acho que devo atualizar do MySQL 5.6 para o atual MariaDB.
Anse
3
Obrigado por este: Restrições deve ser exclusivo para o banco de dados inteiro
sebasira
31

Mude o nome da chave estrangeira no MySQL. Você não pode ter os mesmos nomes de chave estrangeira nas tabelas do banco de dados.

Verifique todas as suas tabelas e todas as suas chaves estrangeiras e evite ter duas chaves estrangeiras com o mesmo nome exato.

Wassim Sabra
fonte
Esse foi o problema no meu caso. Eu nunca teria adivinhado e você salvou o meu dia. Usando fk_id_1, fk_id_2 etc, agora. Obrigado.
JackLeEmmerdeur
15

Dos dois links Resolvidos com Sucesso e Convenção de Nomeação , resolvi facilmente esse mesmo problema que enfrentei. ou seja, para o nome da chave estrangeira, forneça como fk _colName_ TableName . Essa convenção de nomenclatura não é ambígua e também torna todas as ForeignKey em seu modelo de banco de dados exclusivas e você nunca receberá esse erro.

Erro 1022: Não é possível gravar; chave duplicada na tabela

Chandz
fonte
6

Como outros já mencionaram, é possível que o nome da sua restrição já esteja sendo usado por outra tabela no seu banco de dados . Eles devem ser exclusivos no banco de dados.

Uma boa convenção para nomear restrições de chave estrangeira é:

fk_TableName_ColumnName

Para investigar se há um possível conflito, você pode listar todas as restrições usadas pelo seu banco de dados com esta consulta:

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

Quando executei essa consulta, descobri que já havia feito uma cópia temporária de uma tabela e essa cópia já estava usando o nome da restrição que estava tentando usar.

Simon East
fonte
4

Passei as últimas 4 horas com o mesmo problema. O que fiz foi simplesmente garantir que as restrições tivessem nomes únicos.

Você pode renomear as restrições. Anexei um número ao meu para que eu pudesse rastrear facilmente o número de ocorrências.

Exemplo

Se uma restrição em uma tabela for nomeada menino com uma chave estrangeira X A próxima restrição com a chave estrangeira X pode ser chamada de menino1

Tenho certeza que você descobriria nomes melhores do que eu. 🙂

Script desconhecido
fonte
3

Isso também pode surgir em conexão com um bug em certas versões da ferramenta de mudança de esquema on-line do Percona Toolkit. Para alterar uma tabela grande, o pt-osc primeiro cria uma tabela duplicada e copia todos os registros nela. Sob algumas circunstâncias, algumas versões do pt-osc 2.2.x tentarão atribuir às restrições na nova tabela os mesmos nomes que as restrições na tabela antiga.

Uma correção foi lançada na 2.3.0.

Consulte https://bugs.launchpad.net/percona-toolkit/+bug/1498128 para obter mais detalhes.

MJD
fonte
1

Também encontrei esse problema. Verifique se o nome do banco de dados já existe no Mysql e renomeie o antigo.


fonte
1

Eu tive esse problema ao criar uma nova tabela. Acontece que o nome da chave estrangeira que eu dei já estava em uso. Renomear a chave foi corrigida.

user3076750
fonte