A instrução ALTER TABLE entra em conflito com a restrição FOREIGN KEY

184

Tenho um problema ao tentar adicionar uma chave estrangeira à minha tblDomaretabela; O que eu estou fazendo errado aqui?

CREATE TABLE tblDomare
(PersNR VARCHAR (15) NOT NULL,
fNamn VARCHAR (15) NOT NULL,
eNamn VARCHAR (20) NOT NULL,
Erfarenhet VARCHAR (5),
PRIMARY KEY (PersNR));

INSERT INTO tblDomare (PersNR,fNamn,eNamn,Erfarenhet)
Values (6811034679,'Bengt','Carlberg',10);

INSERT INTO tblDomare (PersNR,fNamn,eNamn,Erfarenhet)
Values (7606091347,'Josefin','Backman',4);

INSERT INTO tblDomare (PersNR,fNamn,eNamn,Erfarenhet)
Values (8508284163,'Johanna','Backman',1);

CREATE TABLE tblBana
(BanNR VARCHAR (15) NOT NULL,
PRIMARY KEY (BanNR));

INSERT INTO tblBana (BanNR)
Values (1);

INSERT INTO tblBana (BanNR)
Values (2);

INSERT INTO tblBana (BanNR)
Values (3);

ALTER TABLE tblDomare
ADD FOREIGN KEY (PersNR)
REFERENCES tblBana(BanNR);

Mensagem de erro:

A instrução ALTER TABLE entra em conflito com a restrição FOREIGN KEY "FK_ tblDomare _PersN__5F7E2DAC". O conflito ocorreu no banco de dados "almu0004", tabela "dbo.tblBana", coluna 'BanNR'.

user3162932
fonte

Respostas:

333

Ocorreu porque você tentou criar uma chave estrangeira de tblDomare.PersNRpara tblBana.BanNRmas / e os valores em tblDomare.PersNRnão correspondiam a nenhum dos valores em tblBana.BanNR. Você não pode criar uma relação que viole a integridade referencial.

Smutje
fonte
87
Essa foi a resposta para mim, mas ainda lutei para perceber onde estava o problema, então darei um exemplo de leigo. Se você tiver uma tabela denominada 'Pedidos' e uma tabela denominada 'Clientes', e tiver excluído alguns clientes antigos, mas não os pedidos deles, receberá esse erro se decidir criar uma chave estrangeira de Pedidos. .Eu iria. Como alguns pedidos não têm mais um cliente correspondente, é impossível adicionar a chave estrangeira.
Chad Hedgcock
10
Aqui está uma consulta para verificar os valores incorretos: selecione referrerTable.referenceColumn distinto da junção esquerda referrerTable referTable em referTable.referenceColumn = referrerTable.referenceColumn em que referidosTable.referenceColumn é nulo;
21816 jumxozizi
6
Em uma pitada, você também pode usar a opção "ALTER TABLE TABename WITH NOCHECK ..." para adicionar o FK. Isso permitirá que você adicione a relação, mesmo que os dados existentes quebrem a restrição. Obviamente, é melhor limpar seus dados primeiro, mas isso pelo menos oferece outra opção.
DaveInMaine 8/04
2
@DaveInMaine Se alguém desativar as restrições do banco de dados "quando desejado", eu perguntaria por que se preocupar com elas em primeiro lugar e não as pulará se não estiver interessado na integridade do banco de dados.
Smutje 9/04
1
que péssima mensagem de erro. visto isso antes, mas me pegou completamente desprevenido agora pensando em algo foi corrompido
Simon_Weaver
43

Esta consulta foi muito útil para mim. Mostra todos os valores que não têm correspondências

select FK_column from FK_table
WHERE FK_column NOT IN
(SELECT PK_column from PK_table)
dantey89
fonte
37

Experimente esta solução:

Há um item de dados em sua tabela cujo valor associado não existe na tabela em que você deseja usá-lo como uma tabela de chave primária. Esvazie sua tabela ou adicione o valor associado à segunda tabela.

PatsonLeaner
fonte
29

É possível criar a chave estrangeira usando o nome da tabela ALTER TABLE WITH NOCHECK ..., que permitirá dados que violam a chave estrangeira.

"ALTER TABLE tablename WITH NOCHECK ..." opção para adicionar o FK - Esta solução funcionou para mim.

Ankita Biswas
fonte
17
Esteja ciente de que permitir tais violações anula o objetivo da restrição de chave estrangeira.
reformada
Perigoso...!!! Só deve ser usado se você não quiser perder os dados atualmente na tabela. Mas, mesmo assim, por que não fazer um backup e remover os IDs inválidos.
Andrei Bazanov 6/11/19
Eu preciso implementar via java / spring / code para fazer isso, não diretamente via query SQL, alguma idéia de como fazer isso com o seguinte código: @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.DETACH) @JoinTable(name = "tbUsuariosTipoOcorrencia", joinColumns = { @JoinColumn(name = "idUsuario") }, inverseJoinColumns = { @JoinColumn(name = "idTipoOcorrencia") }) e eu fiz isso resolver via query de banco de dados:alter table tbUsuariosTipoOcorrencia WITH NOCHECK add constraint FKnbxg3ua7b8c5d53wps69q6jh foreign key (idUsuario) references tbUsuarios
Francisco Souza
11

Eu acho que um valor de coluna em uma tabela de chave estrangeira deve corresponder ao valor da coluna da tabela de chave primária. Se estamos tentando criar uma restrição de chave estrangeira entre duas tabelas em que o valor dentro de uma coluna (que será a chave estrangeira) é diferente do valor da coluna da tabela de chave primária, ele emitirá a mensagem.

Portanto, é sempre recomendável inserir apenas os valores na coluna Chave estrangeira que estão presentes na coluna Tabela da chave primária.

Por ex. Se a coluna da tabela Primária tiver valores 1, 2, 3 e na coluna Chave Externa os valores inseridos forem diferentes, a consulta não será executada, pois espera que os valores estejam entre 1 e 3.

sam05
fonte
11

Antes de adicionar chave estrangeira à tabela, faça o seguinte

  1. Verifique se a tabela deve esvaziar ou Os dados da coluna devem corresponder.
  2. Verifique se não é nulo.
  3. Se a tabela contiver não vá para o design e a alteração, faça-o manualmente.

    alterar tabela Tabela 1 adicionar referências de chave estrangeira (nome da coluna) Tabela 2 (nome da coluna)

    alterar tabela Tabela 1 atributo da coluna Alterar nome da coluna não nulo

GirishBabuC
fonte
10

Limpe seus dados de suas tabelas e faça uma relação entre eles.

max
fonte
Obrigado, máx. funcionou para mim se eles tiverem dados, mesmo que os relacionamentos sejam perfeitos, o comando Update-Database não funcionará.
robert jebakumar2
Não é necessário remover nenhum dado, desde que seja válido de acordo com a chave estrangeira que está sendo criada.
21817 jumxozizi
7

Experimente DELETEos dados atuais de tblDomare.PersNR. Porque os valores em tblDomare.PersNRnão coincidem com nenhum dos valores em tblBana.BanNR.

Pensador Bell
fonte
@agenc, respondi sua pergunta?
Thinker Bell
3

Eu também tive esse erro, pois Smutje se referiu. Certifique-se de que você não tenha um valor na coluna de chave estrangeira da sua tabela de chave estrangeira de base que não esteja na sua tabela de referência, ou seja, (todo valor na tabela de chave estrangeira de base (valor de uma coluna que seja chave estrangeira) também deve estar na coluna da tabela de referência) é bom esvaziar sua tabela de chaves estrangeiras de base primeiro e depois definir chaves estrangeiras

ako
fonte
2

os dados que você inseriu em uma tabela (tbldomare) não correspondem aos dados que você atribuiu à tabela de chave primária. escreva entre tbldomare e adicione esta palavra (com nocheck) e depois execute seu código.

por exemplo, você inseriu uma tabela para marcar esses dados

INSERT INTO tblDomare (PersNR,fNamn,eNamn,Erfarenhet)
Values (6811034679,'Bengt','Carlberg',10);

e você atribuiu uma foreign keytabela para aceitar apenas1,2,3 .

você tem duas soluções: uma é excluir os dados inseridos em uma tabela e executar o código. outra é escrever esta palavra (com nocheck) coloque-a entre o nome da sua tabela e adicione assim

ALTER TABLE  tblDomare with nocheck
ADD FOREIGN KEY (PersNR)
REFERENCES tblBana(BanNR);
khadar
fonte
2

Isso acontece comigo, como estou projetando meu banco de dados, noto que altero minha semente na minha tabela principal, agora a tabela relacional não tem chave estrangeira na tabela principal.

Então, eu preciso truncar as duas tabelas, e agora funciona!

Willy David Jr
fonte
2

Você deve ver se suas tabelas possuem algum dado nas linhas. Se "sim", então você deve truncar a tabela (s), ou então você pode torná-los a ter o mesmo número de dados a tblDomare.PersNRque tblBana.BanNRe vice-versa.

adrianex03
fonte
2

Smutje está correto e Chad HedgeCock ofereceu um ótimo exemplo de leigo. Eu gostaria de aproveitar o exemplo do Chade, oferecendo uma maneira de encontrar / excluir esses registros. Usaremos o Cliente como pai e o pedido como filho. CustomerId é o campo comum.

select * from Order Child 
left join Customer Parent on Child.CustomerId = Parent.CustomerId
where Parent.CustomerId is null 

se você estiver lendo este tópico ... obterá resultados. São crianças órfãs. selecione * de Filho do Pedido deixado ingressar no Cliente Pai em Child.CustomerId = Parent.CustomerId em que Parent.CustomerId é nulo Observe a contagem de linhas no canto inferior direito.

Vá verificar com quem quer que você queira excluir essas linhas!

begin tran 
delete Order
from Order Child 
left join Customer Parent on Child.CustomerId = Parent.CustomerId
where Parent.CustomerId is null 

Execute o primeiro bit. Verifique se a contagem de linhas = o que você esperava

comprometer o tran

commit tran 

Seja cuidadoso. A programação desleixada de alguém colocou você nessa bagunça. Certifique-se de entender o porquê antes de excluir os órfãos. Talvez o pai precise ser restaurado.

greg
fonte
Obrigado pela resposta. Estou brincando com o banco de dados stackoverflow (gamedev, na verdade) e encontrei dois NULLs quando deixei JOIN Badges with Users. Não admira que as restrições não funcionou ...
Nicholas Humphrey
1

No meu cenário, usando EF, ao tentar criar essa nova chave estrangeira nos dados existentes, eu estava tentando preencher os dados incorretamente (criar os links) APÓS a criação da chave estrangeira.

A correção é preencher seus dados antes de criar a chave estrangeira, uma vez que verifica todos eles para ver se os links são realmente válidos. Portanto, não poderia funcionar se você ainda não o tiver preenchido.

jeromej
fonte
1

Encontro algum problema no meu projeto.

insira a descrição da imagem aqui

Na tabela filho, não há nenhum ID de registro igual a 1 e 11

mago

Inseri a tabela DEAL_ITEM_THIRD_PARTY_PO cujo ID é igual a 1 e 11, para que eu possa criar FK

Metin Atalay
fonte
0

Primeiro, exclua os dados dessa tabela e execute a migração novamente. Você terá sucesso

M Arslan Riaz
fonte
0

Quando você define uma chave estrangeira na tabela B, referenciando a chave primária da tabela A, significa que quando um valor está em B, ele deve estar em A. Isso evita modificações inconsistentes nas tabelas.

No seu exemplo, suas tabelas contêm:

tblDomare com PRIMARY KEY (PersNR):

PersNR     |fNamn     |eNamn      |Erfarenhet
-----------|----------|-----------|----------
6811034679 |'Bengt'   |'Carlberg' |10
7606091347 |'Josefin' |'Backman'  |4
8508284163 |'Johanna' |'Backman'  |1
---------------------------------------------

tblBana:

BanNR
-----
1
2
3
-----

Esta afirmação:

ALTER TABLE tblDomare
ADD FOREIGN KEY (PersNR)
REFERENCES tblBana(BanNR);

diz que qualquer linha tblDomarecom chave PersNRdeve ter uma correspondência na tabela tblBanana chave BanNR. Seu erro é porque você tem linhas inseridas tblDomaresem correspondência emtblBana .

2 soluções para corrigir seu problema: - adicione linhas tblBanacom o BanNR in (6811034679, 7606091347, 8508284163) - or remove all lines intblDomarethat have no correspondance in tblBana` (mas sua tabela estaria vazia)

Conselho geral : você deve ter a restrição de chave estrangeira antes de preencher as tabelas. As chaves estrangeiras estão aqui para impedir que o usuário da tabela preencha as tabelas com inconsistências.

Belka
fonte
-3

e apenas para sua informação, caso você faça todas as suas verificações de referência de dados e não encontre dados ruins ... aparentemente não é possível criar uma restrição de chave estrangeira entre duas tabelas e campos em que esses campos são a chave primária em ambas as tabelas! Não me pergunte como eu sei disso.

Doug Boude
fonte