Оператор ALTER TABLE конфликтует с ограничением FOREIGN KEY


184

У меня проблема при попытке добавить внешний ключ к моей tblDomareтаблице; что я тут не так делаю?

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);

Сообщение об ошибке:

Оператор ALTER TABLE конфликтовал с ограничением FOREIGN KEY "FK_ tblDomare _PersN__5F7E2DAC". Конфликт произошел в базе данных «almu0004», таблице «dbo.tblBana», столбце «BanNR».

Ответы:


333

Это произошло потому, что вы пытались создать внешний ключ из tblDomare.PersNRto, tblBana.BanNRно / и значения в tblDomare.PersNRне совпадали ни с одним из значений в tblBana.BanNR. Вы не можете создать отношение, которое нарушает ссылочную целостность.


87
Это был ответ для меня, но я все еще пытался понять, в чем проблема, поэтому приведу пример для неспециалистов. Если у вас есть таблица с именем «Заказы» и таблица с именем «Клиенты», и вы удалили некоторых старых клиентов, но не их заказы, вы получите эту ошибку, если решите сделать внешний ключ из Orders.CustomerId для клиентов .Мне бы. Некоторые заказы больше не имеют соответствующего клиента, поэтому добавить внешний ключ невозможно.
Чед Хедккок,

10
Вот запрос для проверки неправильных значений: выберите отличимый referrerTable.referenceColumn из referrerTable, оставленное левым соединением referTable на ReferTable.referenceColumn = referrerTable.referenceColumn, где referTable.referenceColumn является нулем;
jumxozizi

6
В крайнем случае, вы также можете использовать опцию «ALTER TABLE tablename WITH NOCHECK ...», чтобы добавить FK. Это позволит вам добавить отношение, даже если существующие данные нарушают ограничение. Очевидно, лучше сначала очистить ваши данные, но это, по крайней мере, дает вам другой вариант.
DaveInMaine

2
@DaveInMaine Если кто-то деактивирует ограничения базы данных «когда это желательно», я бы спросил, зачем вообще беспокоиться о них, а не просто пропускать их, если не интересует целостность базы данных.
Smutje

1
что за паршивое сообщение об ошибке. видел это раньше, но застал меня совершенно врасплох, только теперь думая, что что-то было повреждено
Simon_Weaver

43

Этот запрос был очень полезен для меня. Он показывает все значения, которые не имеют совпадений

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

37

Попробуйте это решение:

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


29

Можно создать внешний ключ, используя имя таблицы ALTER TABLE WITH NOCHECK ..., что позволит использовать данные, которые нарушают внешний ключ.

Опция «ALTER TABLE tablename WITH NOCHECK ...» для добавления FK - Это решение сработало для меня.


17
Имейте в виду, что разрешение таких нарушений противоречит цели ограничения внешнего ключа.
реформирован

Опасные ... !!! Следует использовать, только если вы не хотите потерять данные, которые в данный момент находятся в таблице. Но даже тогда, почему бы не сделать резервную копию, а затем удалить недействительные идентификаторы.
Андрей Базанов

Мне нужно реализовать через java / spring / code, чтобы сделать это, а не напрямую через SQL-запрос, любые идеи, как это сделать с помощью следующего кода: @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.DETACH) @JoinTable(name = "tbUsuariosTipoOcorrencia", joinColumns = { @JoinColumn(name = "idUsuario") }, inverseJoinColumns = { @JoinColumn(name = "idTipoOcorrencia") }) и я сделал это решить с помощью запроса к базе данных:alter table tbUsuariosTipoOcorrencia WITH NOCHECK add constraint FKnbxg3ua7b8c5d53wps69q6jh foreign key (idUsuario) references tbUsuarios
Francisco Souza

11

Я предполагаю, что значение столбца в таблице внешнего ключа должно совпадать со значением столбца таблицы первичного ключа. Если мы пытаемся создать ограничение внешнего ключа между двумя таблицами, в котором значение внутри одного столбца (который будет внешним ключом) отличается от значения столбца таблицы первичного ключа, то будет выдано сообщение.

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

Например Если столбец первичной таблицы имеет значения 1, 2, 3, а в столбце внешнего ключа вставленные значения различны, то запрос не будет выполнен, поскольку он ожидает, что значения будут между 1 и 3.


11

Прежде чем добавить внешний ключ в таблицу, сделайте следующее

  1. Убедитесь, что таблица должна быть пустой или данные столбца должны совпадать.
  2. Убедитесь, что это не ноль.
  3. Если таблица содержит не переходить на дизайн и изменения, сделать это вручную.

    alter table Таблица 1 добавить ссылки на внешний ключ (имя столбца) Таблица 2 (имя столбца)

    таблица изменения alter Таблица 1 атрибут столбца Имя атрибута не ноль


10

Очистите ваши данные от ваших таблиц и затем установите связь между ними.


Спасибо, макс. у меня сработало, если у них есть данные, даже если отношения идеальны, команда Update-Database не будет работать.
Роберт Jebakumar2

Нет необходимости удалять какие-либо данные, если они действительны в соответствии с создаваемым внешним ключом.
jumxozizi


3

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


2

данные, введенные вами в таблицу (tbldomare), не совпадают с данными, которым вы присвоили таблицу первичных ключей. напишите между tbldomare и добавьте это слово (с помощью nocheck), затем выполните ваш код.

например вы ввели в таблицу tbldomar эти данные

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

и вы назначили foreign keyтаблицу для принятия только1,2,3 .

у вас есть два решения, одно из которых - удалить введенные вами в таблицу данные и выполнить код. другое - напишите это слово (с помощью nocheck), поместите его между именем таблицы и добавьте вот так

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

2

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

Поэтому мне нужно обрезать обе таблицы, и теперь это работает!


2

Вы должны увидеть, есть ли в ваших таблицах какие-либо данные по строкам. Если «да» , то вы должны усечение стола (ы) , или же вы можете сделать , чтобы они имели одинаковое количество данных на tblDomare.PersNRдо tblBana.BanNRи тисков стиха.


2

Смутье прав, и Чед ХеджКок привел пример великого мирянина. Я хотел бы опираться на пример Чада, предлагая способ найти / удалить эти записи. Мы будем использовать Клиента как Родителя, а Заказ - как ребенка. CustomerId - это общее поле.

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

если вы читаете эту ветку ... вы получите результаты. Это дети-сироты. выберите * из заказа. Дочернее слева присоедините Customer Parent к Child.CustomerId = Parent.CustomerId, где Parent.CustomerId равен нулю. Обратите внимание на количество строк в правом нижнем углу.

Идите и убедитесь, кому вы хотите удалить эти строки!

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

Запустите первый бит. Проверьте количество строк = то, что вы ожидали

совершить транс

commit tran 

Быть осторожен. Нечистое программирование втянуло вас в этот беспорядок. Убедитесь, что вы понимаете, почему, прежде чем удалить сирот. Может быть, родитель должен быть восстановлен.


Спасибо за ответ. Я играю с базой данных stackoverflow (на самом деле gamedev) и обнаружил два NULL, когда оставляю значки с пользователями. Неудивительно, что ограничения не сработали ...
Николас Хамфри

1

В моем сценарии, используя EF, при попытке создать этот новый внешний ключ на существующих данных я ошибочно пытался заполнить данные (сделать ссылки) ПОСЛЕ создания внешнего ключа.

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


1

Я столкнулся с некоторой проблемой в моем проекте.

введите описание изображения здесь

В дочерней таблице нет ни одного идентификатора записи, равного 1 и 11

маг

Я вставил таблицу DEAL_ITEM_THIRD_PARTY_PO, Id которой равен 1 и 11, после чего я могу создать FK


0

Сначала удалите данные из этой таблицы, а затем снова запустите миграцию. Вы получите успех


0

Когда вы определяете внешний ключ в таблице B, ссылаясь на первичный ключ таблицы A, это означает, что когда значение находится в B, оно должно быть в A. Это предотвращает несогласованные изменения таблиц.

В вашем примере ваши таблицы содержат:

tblDomare с PRIMARY KEY (PersNR):

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

tblBana:

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

Это утверждение:

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

говорит, что любая строка tblDomareс ключом PersNRдолжна иметь соответствие в таблице tblBanaпо ключу BanNR. Ваша ошибка в том, что у вас вставлены строки tblDomareбез соответствия в tblBana.

2 решения , чтобы решить проблему: - либо добавить строки в tblBanaс BanNR in (6811034679, 7606091347, 8508284163) - or remove all lines intblDomarethat have no correspondance in tblBana` (но ваша таблица будет пустой)

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


-3

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.