Não é possível adicionar ou atualizar uma linha filho: uma restrição de chave estrangeira falha

174

tabela 1

+----------+-------------+------+-----+---------+----------------+
| Field    | Type        | Null | Key | Default | Extra          |
+----------+-------------+------+-----+---------+----------------+
| UserID   | int(11)     | NO   | PRI | NULL    | auto_increment |
| Password | varchar(20) | NO   |     |         |                |
| Username | varchar(25) | NO   |     |         |                |
| Email    | varchar(60) | NO   |     |         |                |
+----------+-------------+------+-----+---------+----------------+

mesa 2

+------------------+--------------+------+-----+---------+----------------+
| Field            | Type         | Null | Key | Default | Extra          |
+------------------+--------------+------+-----+---------+----------------+
| UserID           | int(11)      | NO   | MUL |         |                |
| PostID           | int(11)      | NO   | PRI | NULL    | auto_increment |
| Title            | varchar(50)  | NO   |     |         |                |
| Summary          | varchar(500) | NO   |     |         |                |
+------------------+--------------+------+-----+---------+----------------+

Erro:

com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: 
Cannot add or update a child row: a foreign key constraint fails 
(`myapp/table2`, CONSTRAINT `table2_ibfk_1` FOREIGN KEY (`UserID`) 
REFERENCES `table1` (`UserID`)) 

O que eu fiz errado? Li http://www.w3schools.com/Sql/sql_foreignkey.asp e não vejo o que há de errado.

Tom
fonte
4
Você pode postar a consulta que aciona o erro?
Damp
38
Em poucas palavras, você está tentando inserir / atualizar um valor em table2.UserIDque não existe table1.UserID.
Joe Stefanelli
Não sei por que, mas depois de mover meu banco de dados de um ambiente Windows para o Linux, tive que excluir e recriar uma relação (foi quando percebi o problema). O valor existia, mas remover e adicionar novamente a relação o corrigiu. Você pode ter muito cuidado ao fazê-lo, obviamente.
johnsnails

Respostas:

235

Você está recebendo este erro porque está tentando adicionar / atualizar uma linha table2que não possui um valor válido para o UserIDcampo com base nos valores atualmente armazenados table1. Se você postar mais algum código, eu posso ajudá-lo a diagnosticar a causa específica.

Brian Driscoll
fonte
PreparedStatement st = connection.prepareStatement ("Inserir na tabela2 (ID do usuário, ID da postagem, título, resumo)" + "valores (ID do usuário,?,?,") ");
Tom
15
não sei para que serve o voto negativo; minha resposta é perfeitamente válida e correta.
Brian Driscoll
Hmm ... definitivamente não é uma boa ideia misturar parâmetros nomeados com parâmetros sem nome na sua declaração preparada. deve ser "valores (?,?,?,?)" com o valor apropriado para UserID especificado em sua instrução de execução.
Brian Driscoll
Então, eu preciso fazer para outra instrução SQL para obter o ID do usuário da tabela1?
Tom
5
Provavelmente um 0, substitua-o por Null, se for o caso
Jeffrey Nicholson Carré
123

Isso significa que você está tentando inserir table2um UserIDvalor que não existe table1.

Rami C
fonte
104

Um hack simples pode ser desativar as verificações de chave estrangeira antes de executar qualquer operação na tabela. Basta consultar

SET FOREIGN_KEY_CHECKS=0

Isso desativará a correspondência de chave estrangeira em outras tabelas. Depois de terminar a tabela, ative-a novamente

SET FOREIGN_KEY_CHECKS=1

Isso funciona para mim muitas vezes.

Sandeep Giri
fonte
Como eu uso isso ??
Sachin de Pune
2
@SachinfromPune basta adicionar SET FOREIGN_KEY_CHECKS = 0; no início do arquivo mysql e SET FOREIGN_KEY_CHECKS = 1; no final do arquivo mysql, reimporte dados
inrsaurabh 15/09
1
Isso não é problemático? Você perde a integridade referencial, certo?
roadrunner66
A integridade referencial é suportada pela presença das entradas de índice corretas. Contanto que você tenha as chaves e os índices corretos, poderá desativar a verificação de chaves durante uma entrada em massa.
Vernon Keenan
46

Eu descobri outro caso estranho: se você acidentalmente criar uma chave estrangeira de uma tabela InnoDB para uma tabela MyISAM, o MySQL lançará esse erro no momento da inserção, mesmo que os dados sejam válidos.

Veja http://nick.zoic.org/art/mysql-foreign-key-error/

NickZoic
fonte
1
Sim, tenho o mesmo problema. Duas tabelas devem ser o InnoDB!
Emeraldhieu
2
Eu tive o mesmo problema, obrigado pela dica. Aqui está um link para a documentação do MySQL sobre como converter tabelas do MyISAM para o InnoDB dev.mysql.com/doc/refman/5.7/en/… TLDR: ALTER TABLE table_name ENGINE = InnoDB;
Guilherme Vaz
De fato, esse foi o caso no meu banco de dados. Decidi mudar o mecanismo MyISAM para InnoDB. Finalmente, posso trabalhar com o banco de dados da maneira que eu queria.
11769 Mike
17

Você está recebendo esse erro porque há algum valor int table2.UserIDque não existe table1.UserID(acho que você definiu o table2.UserIDvalor manualmente antes de criar essa chave estrangeira).
Um exemplo para esta cena: table1.UserIDobter valores 1,2,3 e table2.UserIDobter valores 4 (adicionar pelo manual). Então, quando você faz uma chave estrangeira, eles não conseguem encontrar UserID = 4a partir table1e o erro será ocurse.
Para corrigir este erro, basta remover UserID = 4a partir de table2ou você pode esvaziar ambos e, em seguida, criar a chave estrangeira e.
Boa sorte!

Justin
fonte
11

Demorei um pouco para descobrir. Simplificando, a tabela que referencia a outra tabela já possui dados e um ou mais de seus valores não existe na tabela pai.

por exemplo, a Tabela2 possui os seguintes dados:

UserID    PostID    Title    Summary
5         1         Lorem    Ipsum dolor sit

Tabela 1

UserID    Password    Username    Email
9         ********    JohnDoe     john@example.com

Se você tentar ALTERAR a tabela2 e adicionar uma chave estrangeira, a consulta falhará porque o UserID = 5 não existe na Tabela1.

Sbudah
fonte
10

Se você inseriu uma linha na tabela 1 antes de criar a chave estrangeira na tabela 2, receberá um erro de restrição de chave estrangeira, porque o valor do incremento automático é 2 na tabela 1 e 1 na tabela 2. Para resolver isso, é necessário trunque a tabela 1 e defina o valor de incremento automático de volta para 1. Em seguida, você pode adicionar a tabela 2.

Attaque
fonte
10

Verifique se você configurou o mecanismo de banco de dados como InnoDB, porque no MySQL a chave estrangeira e a transação não são suportadas

Aman Maurya
fonte
2
ALTER TABLE my_table ENGINE = InnoDB;
Bishwas Mishra 28/05/19
7

Apenas uma pequena correção: torne o JoinColumn 'nullable = true' na Tabela1 e o campo 'UserID' 'insertable = false' e 'nullable = true' na Tabela2.

Na Entidade Tabela1:

@OneToMany(targetEntity=Table2.class, cascade = CascadeType.ALL)
@JoinColumn(name = "UserID", referencedColumnName = "UserID", nullable = true)
private List<Table2> table2List;

Na Entidade Tabela2:

@Column(insertable = false, nullable = true)
private int UserID;
Ujjwal Chaudhary
fonte
Esta resposta resolveu totalmente o meu problema, muito obrigado por compartilhar isso. A chave para mim foi adicionar o @Column (insertable = false, nullable = true) no arquivo que eu estou usando como a chave de saída no meu objeto / tabela filho.
Israelm
6

Acabei de ter o mesmo problema, a solução é fácil.

Você está tentando adicionar um ID na tabela filho que não existe na tabela pai.

verifique bem, porque o InnoDB possui o bug que às vezes aumenta a coluna auto_increment sem adicionar valores, por exemplo, INSERT ... ON DUPLICATE KEY

Blaztix
fonte
seriamente? não insira uma referência de id que não existe ... apenas verificar
Blaztix
5

Eu tive uma questão semelhante. Você está tentando aplicar chave estrangeira em uma tabela que possui conteúdo e a coluna não é anulável. Você tem duas opções.

  1. Torne a coluna na qual você deseja aplicar restrições de chave estrangeira seja anulável. Dessa forma, a chave estrangeira será aplicada sabendo que alguns campos podem ser anuláveis. ( Isto é o que eu fiz. )
  2. Crie a coluna na qual deseja aplicar a restrição de chave estrangeira, escreva uma consulta para inserir a chave estrangeira na coluna e aplique as restrições de chave estrangeira. ( Não tentei isso, mas deve funcionar )
Jacob
fonte
4

Verifique se o valor que você está inserindo na chave estrangeira existe na tabela pai. Isso me ajudou. Por exemplo, se você inserir user_id = 2em table.2, mas table.1não tiver um user_id = 2, a restrição gerará um erro. O meu era o código de erro # 1452 para ser exato. Espero que isso ajude outras pessoas com o mesmo problema!

Dustin Hammack
fonte
3

Eu tive o mesmo problema, e o motivo era que eu tinha uma linha na primeira tabela antes de adicionar a chave estrangeira.

Ouissal
fonte
1

Também enfrentei o mesmo problema e o problema era que o valor das entradas da tabela pai não coincide com o valor da tabela de chave estrangeira. Então, tente limpar todas as linhas.

Justin Jose
fonte
A restrição requer que os usuários mencionados na Tabela2 já estejam definidos na Tabela1.
Sorak
1

Caso as soluções fornecidas por outros não funcionassem. Tente verificar os mecanismos de banco de dados das tabelas pai e filho. No meu caso, eu tinha o mecanismo das tabelas pai definido como "MyISAM", alterando-o para o InnoDB corrigido.

Espero que isso ajude outras pessoas que estão presas como eu.

Arun Shankar
fonte
1

Você não deve colocar um campo ondelete em uma cascata no banco de dados.

Portanto, defina o campo onDelete como RESTRICT

Boa sorte ♥

HamidReza Biglari
fonte
0

Outro caso estranho que me deu esse erro. Eu referenciei erroneamente minhas chaves estrangeiras à chave primária de identificação. Isso foi causado por comandos incorretos de alteração da tabela. Descobri isso consultando a tabela INFORMATION_SCHEMA (consulte esta resposta do stackoverflow)

A tabela estava tão confusa que não pôde ser corrigida por nenhum comando ALTER TABLE . Eu finalmente larguei a mesa e a reconstruí. Isso se livrou do erro de integridade.

Vicky T
fonte
0

Talvez enquanto você adicionou a userIDcoluna, existem dados para essa determinada tabela que ela está estabelecida e, portanto, terá um valor padrão 0, tente adicionar a coluna sem oNOT NULL

WTFZane
fonte
0

Também recebi este erro: "Não é possível adicionar ou atualizar uma linha filho: uma restrição de chave estrangeira falha". Recebi o erro ao adicionar uma nova linha à tabela pai

O problema era que a restrição de chave estrangeira havia sido definida na tabela pai em vez da tabela filho.

Nadir Latif
fonte
0

Se você usar o índice mysql ou a relação entre tabelas, primeiro exclua as colunas (por exemplo: city_id) e crie novas colunas com o mesmo nome (por exemplo: city_id). Em seguida, tente novamente ...

Mahmut Aydın
fonte
0

Existe algum dado existente que a tabela contenha? Nesse caso, tente limpar todos os dados da tabela que você deseja adicionar uma chave estrangeira. Em seguida, execute o código (adicione uma chave estrangeira) novamente.

Eu encontrei esse problema tantas vezes. Essa limpeza de todos os dados da tabela funciona quando você deseja adicionar uma chave estrangeira a uma tabela existente.

Espero que isso funcione :)

Noldy
fonte
0

Exclua índices do campo UserID da tabela2. Seus ternos para mim

Anton
fonte
-1

a restrição de chave estrangeira da tabela filho está falhando

Esse problema pode ocorrer devido ao seguinte motivo:

Se você estiver fazendo isso no Spring mvc, precisará descrever explicitamente o tipo de id, porque às vezes o mysql falha em reconhecer o tipo de id. para que você defina explicitamente como nas duas tabelas da sua classe de entidade@GeneratedValue (strategy = GenerationType.IDENTITY)

Qaiser Iqbal Moeeni
fonte