คำสั่ง 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
นี่คือคำตอบสำหรับฉัน แต่ฉันยังคงดิ้นรนกับการตระหนักถึงปัญหาที่เกิดขึ้นดังนั้นฉันจะให้ตัวอย่างของคนธรรมดา หากคุณมีตารางชื่อ 'คำสั่งซื้อ' และตารางชื่อ 'ลูกค้า' และคุณได้ลบลูกค้าเก่าบางคน แต่ไม่ใช่คำสั่งซื้อของพวกเขาคุณจะได้รับข้อผิดพลาดนี้หากคุณตัดสินใจที่จะทำรหัสต่างประเทศจากคำสั่งซื้อลูกค้าลูกค้า .Id คำสั่งซื้อบางรายการไม่มีลูกค้าที่เกี่ยวข้องอีกต่อไปดังนั้นจึงเป็นไปไม่ได้ที่จะเพิ่มรหัสต่างประเทศ
Chad Hedgcock

10
ต่อไปนี้เป็นแบบสอบถามเพื่อตรวจสอบค่าที่ไม่ถูกต้อง: select different referrerTable.referenceColumn จากการอ้างอิงที่เหลือซ้าย referrerTable และการอ้างอิง ReferTable บน
jumxozizi

6
คุณสามารถใช้ตัวเลือก "แก้ไขตาราง tablename ด้วย NOCHECK ... " เพื่อเพิ่ม FK สิ่งนี้จะช่วยให้คุณเพิ่มความสัมพันธ์แม้ว่าข้อมูลที่มีอยู่จะแบ่งข้อ จำกัด เห็นได้ชัดว่าดีกว่าการล้างข้อมูลของคุณก่อน แต่อย่างน้อยก็ให้ทางเลือกอื่นแก่คุณ
DaveInMaine

2
@DaveInMaine หากมีการยกเลิกข้อ จำกัด ของฐานข้อมูล "เมื่อต้องการ" ฉันจะถามว่าทำไมปัญหาตัวเองกับพวกเขาในสถานที่แรกและไม่เพียงแค่ข้ามพวกเขาหากไม่มีความสนใจในความสมบูรณ์ของฐานข้อมูล
Smutje

1
ข้อความแสดงข้อผิดพลาดมีหมัดอะไร เห็นมาก่อน แต่จับฉันอย่างสมบูรณ์ยามตอนนี้คิดว่าบางสิ่งบางอย่างเสียหาย
Simon_Weaver

42

แบบสอบถามนี้มีประโยชน์มากสำหรับฉัน มันแสดงค่าทั้งหมดที่ไม่มีการจับคู่ใด ๆ

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

37

ลองวิธีนี้:

มีรายการข้อมูลในตารางของคุณซึ่งไม่มีค่าที่เกี่ยวข้องอยู่ในตารางที่คุณต้องการใช้เป็นตารางคีย์หลัก ทำให้ตารางของคุณว่างเปล่าหรือเพิ่มค่าที่เกี่ยวข้องลงในตารางที่สอง


29

เป็นไปได้ที่จะสร้าง foreign key โดยใช้ ALTER Table tablename กับ NOCHECK ... ซึ่งจะอนุญาตข้อมูลที่ละเมิด foreign key

"แก้ไขตาราง tablename ด้วยตัวเลือก NOCHECK ... " เพื่อเพิ่ม FK - วิธีนี้ใช้ได้สำหรับฉัน


17
โปรดทราบว่าการอนุญาตให้มีการละเมิดดังกล่าวจะทำให้จุดประสงค์ของการ จำกัด คีย์ต่างประเทศ
ปรับปรุงใหม่

อันตราย ... !!! ควรใช้หากคุณไม่ต้องการปล่อยข้อมูลที่อยู่ในตาราง แต่ถึงอย่างนั้นทำไมไม่ทำการสำรองข้อมูลแล้วเอารหัสที่ไม่ถูกต้องออก
Andrei Bazanov

ฉันต้องใช้ผ่าน java / ฤดูใบไม้ผลิ / รหัสจะทำอย่างนั้นไม่ได้โดยตรงผ่านทางแบบสอบถาม SQL, ideia ใด ๆ วิธีการทำเช่นนี้กับรหัสต่อไปนี้: @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
ฟรานซิสซูซ่า

11

ฉันเดาค่าคอลัมน์ในตารางคีย์ต่างประเทศควรจับคู่กับค่าคอลัมน์ของตารางคีย์หลัก หากเราพยายามสร้างข้อ จำกัด foreign key ระหว่างสองตารางโดยที่ค่าภายในหนึ่งคอลัมน์ (จะเป็น Foreign key) นั้นแตกต่างจากค่าของคอลัมน์ของตาราง Key หลักดังนั้นมันจะทำการทิ้งข้อความ

ดังนั้นจึงขอแนะนำให้ใส่เฉพาะค่าเหล่านั้นในคอลัมน์คีย์ต่างประเทศซึ่งมีอยู่ในคอลัมน์ตารางคีย์หลัก

สำหรับอดีต หากคอลัมน์ตารางหลักมีค่า 1, 2, 3 และในคอลัมน์คีย์ต่างประเทศค่าที่แทรกจะแตกต่างกันดังนั้นแบบสอบถามจะไม่ถูกเรียกใช้เนื่องจากคาดว่าค่าจะอยู่ระหว่าง 1 และ 3


11

ก่อนที่คุณจะเพิ่มรหัสต่างประเทศลงในตารางให้ทำดังต่อไปนี้

  1. ตรวจสอบให้แน่ใจว่าตารางต้องว่างเปล่าหรือข้อมูลคอลัมน์ควรตรงกัน
  2. ตรวจสอบให้แน่ใจว่ามันไม่เป็นโมฆะ
  3. หากตารางมีอยู่อย่าไปที่การออกแบบและการเปลี่ยนแปลงให้ทำด้วยตนเอง

    แก้ไขตารางที่ 1 เพิ่มการอ้างอิงคีย์ต่างประเทศ (ชื่อคอลัมน์) ตารางที่ 2 (ชื่อคอลัมน์)

    แก้ไขตารางที่ 1 ตารางที่แก้ไขคอลัมน์ชื่อแอตทริบิวต์คอลัมน์ไม่เป็นโมฆะ


10

ทำความสะอาดข้อมูลของคุณจากตารางของคุณแล้วสร้างความสัมพันธ์ระหว่างกัน


ขอบคุณสูงสุด มันใช้งานได้สำหรับฉันหากพวกเขามีข้อมูลแม้ความสัมพันธ์จะสมบูรณ์แบบคำสั่ง Update-Database จะไม่ทำงาน
เบิ

ไม่จำเป็นต้องลบข้อมูลใด ๆ ตราบใดที่ข้อมูลนั้นถูกต้องตามรหัสต่างประเทศที่ถูกสร้างขึ้น
jumxozizi


3

ฉันมีข้อผิดพลาดนี้เช่นกันเมื่อ Smutje reffered ตรวจสอบให้แน่ใจว่าคุณไม่มีค่าในคอลัมน์ foreign key ของตาราง foreign key หลักของคุณที่ไม่ได้อยู่ในตารางอ้างอิงของคุณเช่น (ทุกค่าในตาราง key foreign ฐานของคุณ (ค่าของคอลัมน์ที่ foreign key) จะต้องอยู่ในคอลัมน์ตารางอ้างอิงของคุณด้วย) เพื่อดีในการล้างตาราง foreign key ของคุณก่อนจากนั้นตั้งค่า foreign key


2

ข้อมูลที่คุณป้อนตาราง (tbldomare) ไม่ตรงกับข้อมูลที่คุณได้กำหนดตารางคีย์หลัก เขียนระหว่าง tbldomare และเพิ่มคำนี้ (ด้วย nocheck) จากนั้นรันโค้ดของคุณ

ตัวอย่างเช่นคุณป้อนตาราง tbldomar ข้อมูลนี้

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

และคุณได้รับมอบหมายตารางที่จะยอมรับเท่านั้นforeign key1,2,3

คุณมีวิธีแก้ไขสองวิธีวิธีหนึ่งคือลบข้อมูลที่คุณป้อนในตารางจากนั้นเรียกใช้รหัส อีกอันหนึ่งเขียนคำนี้ (โดยไม่มีเครื่องหมาย) วางไว้ระหว่างชื่อตารางของคุณและเพิ่มเช่นนี้

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

2

สิ่งนี้เกิดขึ้นกับฉันเนื่องจากฉันกำลังออกแบบฐานข้อมูลของฉันฉันสังเกตเห็นว่าฉันเปลี่ยนเมล็ดพันธุ์ของฉันบนตารางหลักของฉันตอนนี้ตารางสัมพันธ์ไม่มีรหัสต่างประเทศในตารางหลัก

ดังนั้นฉันต้องตัดทั้งสองตารางและตอนนี้ใช้งานได้!


2

คุณควรดูว่าตารางของคุณมีข้อมูลใด ๆ ในแถวหรือไม่ หาก "ใช่" คุณควรตัดทอนตารางมิฉะนั้นคุณสามารถทำให้ตารางมีข้อมูลจำนวนเท่ากันได้tblDomare.PersNRถึงtblBana.BanNRและ vise-verse


2

Smutje ถูกต้องและ Chad HedgeCock เสนอตัวอย่างของคนธรรมดาที่ดี ID ต้องการสร้างจากตัวอย่างของ Chad โดยเสนอวิธีการค้นหา / ลบบันทึกเหล่านั้น เราจะใช้ลูกค้าเป็นผู้ปกครองและสั่งซื้อเป็นเด็ก CustomerId เป็นเขตข้อมูลทั่วไป

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

หากคุณกำลังอ่านหัวข้อนี้ ... คุณจะได้รับผลลัพธ์ เหล่านี้เป็นเด็กกำพร้า เลือก * จาก Order Child ซ้ายเข้าร่วม Parent พาเรนต์ลูก Child.CustomerId = Parent.CustomerId โดยที่ Parent.CustomerId เป็นโมฆะหมายเหตุจำนวนแถวที่ด้านล่างขวา

ไปตรวจสอบ w / ใครก็ตามที่คุณต้องการที่จะลบแถวเหล่านี้!

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

รันบิตแรก ตรวจสอบจำนวนแถว = สิ่งที่คุณคาดหวัง

กระทำ tran

commit tran 

ระวัง. การเขียนโปรแกรมเลอะเทอะของใครบางคนทำให้คุณยุ่งเหยิง ตรวจสอบให้แน่ใจว่าคุณเข้าใจเหตุผลก่อนที่จะลบเด็กกำพร้า บางทีผู้ปกครองจำเป็นต้องกู้คืน


ขอบคุณสำหรับการตอบกลับ. ฉันกำลังเล่นกับฐานข้อมูล stackoverflow (จริง ๆ แล้ว gamedev) และพบ NULL สองตัวเมื่อฉันออกจากป้ายผนึกผู้ใช้ ไม่น่าแปลกใจที่ข้อ จำกัด ใช้งานไม่ได้ ...
Nicholas Humphrey

1

ในสถานการณ์ของฉันโดยใช้ EF เมื่อพยายามสร้างรหัสต่างประเทศใหม่นี้กับข้อมูลที่มีอยู่ฉันพยายามใส่ข้อมูลผิดพลาด (สร้างลิงก์) หลังจากสร้างคีย์ต่างประเทศ

การแก้ไขคือการเติมข้อมูลของคุณก่อนที่จะสร้างคีย์ต่างประเทศเนื่องจากมันจะตรวจสอบทั้งหมดเพื่อดูว่าการเชื่อมโยงนั้นใช้ได้จริงหรือไม่ ดังนั้นจึงไม่สามารถทำงานได้หากคุณยังไม่ได้ใส่ข้อมูล


1

ฉันพบปัญหาบางอย่างในโครงการของฉัน

ป้อนคำอธิบายรูปภาพที่นี่

ในตารางลูกไม่มีรหัสบันทึกเท่ากับ 1 และ 11

นักเวทย์

ฉันแทรกตาราง DEAL_ITEM_THIRD_PARTY_PO ซึ่ง Id เท่ากับ 1 และ 11 จากนั้นฉันสามารถสร้าง FK


0

โปรดลบข้อมูลออกจากตารางก่อนแล้วจึงเรียกใช้การย้ายข้อมูลอีกครั้ง คุณจะประสบความสำเร็จ


0

เมื่อคุณกำหนด Foreign Key ในตาราง B ที่อ้างอิงถึง Primary Key ของตาราง 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ต้องมี correspondance ในตารางบนปุ่มtblBana BanNRข้อผิดพลาดของคุณเป็นเพราะคุณมีสายที่แทรกอยู่ในtblDomareที่ไม่มี correspondance tblBanaใน

2 วิธีแก้ไขปัญหาของคุณ: - เพิ่มบรรทัดtblBanaด้วยBanNR in (6811034679, 7606091347, 8508284163) - or remove all lines intblDomare that have no correspondance intblBana` (แต่ตารางของคุณจะว่างเปล่า)

คำแนะนำทั่วไป : คุณควรมีข้อ จำกัด Foreign Key ก่อนการเติมข้อมูลในตาราง แป้นต่างประเทศอยู่ที่นี่เพื่อป้องกันไม่ให้ผู้ใช้ของตารางกรอกข้อมูลตารางด้วยความไม่สอดคล้องกัน


-3

และเพียงแค่ FYI ในกรณีที่คุณทำการตรวจสอบข้อมูลอ้างอิงทั้งหมดและไม่พบข้อมูลที่ไม่ดี ... เห็นได้ชัดว่าเป็นไปไม่ได้ที่จะสร้างข้อ จำกัด คีย์ต่างประเทศระหว่างสองตารางและเขตข้อมูลที่เขตข้อมูลเหล่านั้นเป็นคีย์หลักในทั้งสองตาราง! อย่าถามฉันว่าฉันรู้สิ่งนี้ได้อย่างไร

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.