Заява 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.PersNRдо, tblBana.BanNRале /, і значення в tblDomare.PersNRне збігалися з жодним із значень у tblBana.BanNR. Ви не можете створити відношення, яке порушує референтну цілісність.


87
Це була відповідь для мене, але я все ще боровся з усвідомленням проблеми, тому наведу приклад мирянина. Якщо у вас є таблиця з назвою "Замовлення" та таблиця з назвою "Клієнти", і ви видалили деяких старих клієнтів, але не їхні замовлення, ви отримаєте цю помилку, якщо вирішите зробити іноземний ключ від Orders.CustomerId для клієнтів. .Ід. Деякі замовлення вже не мають відповідного клієнта, тому додати іноземний ключ неможливо.
Чад Хеджкок

10
Ось запит для перевірки неправильних значень: виберіть чіткий refererTable.referenceColumn від refererTable лівий приєднаний referenTable на referenceTable.referenceColumn = referencererTable.referenceColumn, де referenceTable.referenceColumn є нульовим;
jumxozizi

6
Крім того, ви можете також використати опцію "ALTER TABLE tablename With NOCHECK ...", щоб додати FK. Це дозволить вам додати відношення, навіть якщо існуючі дані порушують обмеження. Очевидно, краще спочатку очистити свої дані, але це, принаймні, дає ще один варіант.
DaveInMaine

2
@DaveInMaine Якщо дезактивувати обмеження бази даних "коли це хочеться", я б запитав, чому в першу чергу турбувати себе з ними, а не просто пропускати їх, якщо когось не цікавить цілісність бази даних.
Smutje

1
яке паршиве повідомлення про помилку бачив це раніше, але мене спіймав повністю з
остороги,

42

Цей запит був дуже корисним для мене. Він показує всі значення, які не відповідають

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

37

Спробуйте це рішення:

У вашій таблиці є елемент даних, асоційоване значення якого не існує в таблиці, яку ви хочете використовувати в якості таблиці первинного ключа. Зробіть свою таблицю порожньою або додайте пов’язане значення до другої таблиці.


29

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

"ALTER TABLE name name 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. Якщо таблиця містить не переходите до проектування та зміни, робіть це вручну.

    змінити таблицю Таблиця 1 додати посилання на зовнішній ключ (Назва стовпця) Таблиця 2 (Назва стовпця)

    таблиця змін Таблиця 1 стовпчик «зміна» Атрибут Ім'я стовпця не є нульовим


10

Очистіть свої дані зі своїх таблиць, а потім встановіть зв’язок між ними.


Дякую, макс. це працювало для мене, якщо вони мають дані, навіть стосунки ідеальні, команда Update-Database не буде працювати.
Роберт jebakumar2

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


3

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


2

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

наприклад, ви ввели таблицю з тими даними

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

і ви призначили foreign keyтаблицю, щоб прийняти лише її1,2,3 .

у вас є два рішення, одне - видалити дані, які ви ввели в таблицю, а потім виконати код. інша - написати це слово (з допомогою німецької кнопки), помістити його між назвою таблиці та додати так

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

2

Це трапляється зі мною, оскільки я розробляю свою базу даних, я помічаю, що я міняю своє насіння на своєму головному столі, тепер реляційна таблиця не має стороннього ключа на головному столі.

Тому мені потрібно обрізати обидві таблиці, і це зараз працює!


2

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


2

Smutje правильний, і Chad HedgeCock запропонував чудовий приклад мирян. Мені подобається будувати на прикладі Чада, пропонуючи спосіб знайти / видалити ці записи. Ми будемо використовувати Клієнта як Батька та Порядок як дитину. CustomerId - це загальне поле.

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

якщо ви читаєте цю тему ... ви отримаєте результати. Це діти-сироти. виберіть * із порядку замовлення. Ліворуч приєднайтеся до батьківського клієнта на 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

У своєму проекті я стикаюся з деякою проблемою.

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

У дочірній таблиці немає жодного запису Id, рівного 1 та 11

маг

Я вставив таблицю DEAL_ITEM_THIRD_PARTY_PO, Id якої дорівнює 1 і 11, то я можу створити FK


0

Спочатку видаліть дані з цієї таблиці, а потім знову запустіть міграцію. Ви отримаєте успіх


0

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

У вашому прикладі ваші таблиці містять:

tblДодати з 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

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.