คำสั่ง DELETE ขัดแย้งกับข้อ จำกัด การอ้างอิง


11

ฉันกำลังพยายามลบผู้ใช้ทั้งหมด แต่ได้รับข้อผิดพลาด:

Msg 547, Level 16, State 0, Line 1
The DELETE statement conflicted with the REFERENCE constraint "FK_M02ArticlePersons_M06Persons". The conflict occurred in database "workdemo.no", table "dbo.M02ArticlePersons", column 'M06PersonId'.
The statement has been terminated.

แบบสอบถาม:

DELETE FROM [workdemo.no].[dbo].[M06Persons] 
WHERE ID > '13'
GO

ดูเหมือนว่าฉันต้องใช้on delete cascade;แต่ฉันติดอยู่

คำตอบ:


18

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

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


9

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

ALTER TABLE [workdemo.no].[dbo].[M06Persons] NOCHECK CONSTRAINT [FK_M02ArticlePersons_M06Persons]

อย่าลืมเปิดข้อ จำกัด อีกครั้งหลังจากลบด้วย

ALTER TABLE [workdemo.no].[dbo].[M06Persons] WITH CHECK CHECK CONSTRAINT [FK_M02ArticlePersons_M06Persons]

ตัวเลือกที่สองคือการปล่อยและเพิ่มข้อ จำกัด ด้วยตัวเลือก ON DELETE CASCADE โดยใช้:

ALTER TABLE [workdemo.no].[dbo].[M06Persons] DROP CONSTRAINT [FK_M02ArticlePersons_M06Persons]

ALTER TABLE [workdemo.no].[dbo].[M06Persons] WITH NOCHECK ADD CONSTRAINT [FK_M02ArticlePersons_M06Persons] FOREIGN KEY(M06PersonId)
REFERENCES <parent table here> (<parent column here>)
ON DELETE CASCADE

ตามชื่อ FK ของคุณดูเหมือนว่าตารางหลักของคุณคือ M02ArticlePersons และคอลัมน์หลักคือ M06Persons

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


2

ตาราง dbo.M02ArticlePersons ของคอลัมน์ M06PersonId นั้นถูกอ้างถึงในอีกตารางหนึ่ง ดังนั้นก่อนที่จะลบคำสั่งปิดการใช้งานความสัมพันธ์นี้และลองอีกครั้ง

ด้านล่างมีไว้สำหรับการปลดคีย์ต่างประเทศ

 ALTER TABLE dbo.M02ArticlePersons NOCHECK CONSTRAINT FK_M02ArticlePersons_M06Persons

DELETE FROM [workdemo.no].[dbo].[M06Persons] 
  WHERE ID > '13'
GO

และนี่คือการเปิดใช้งาน

ALTER TABLE dbo.M02ArticlePersons CHECK CONSTRAINT FK_M02ArticlePersons_M06Persons

หวังว่ามันจะใช้ได้


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

1

มีตัวเลือกอื่นด้วยตนเอง:

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


1

รหัสเล็กน้อยนี้จะช่วยให้ตารางใด ๆ ที่คุณต้องการลบระเบียน ดูแลความซื่อสัตย์อ้างอิงเช่นกัน ...

โค้ดด้านล่างจะสร้างคำสั่ง DELETE .. เพียงระบุ schema.table_Name

Declare @sql1 varchar(max)
      , @ptn1 varchar(200)
      , @ctn1 varchar(200)
      , @ptn2 varchar(200)
      , @ctn2 varchar(200)
--
SET @ptn1 = ''
--
SET @ctn1 = ''
--
SET @ptn2 = ''
--
SET @ctn2 = ''
--
SELECT @sql1 = case when (@ptn1 <> OBJECT_NAME (f.referenced_object_id)) then
                         COALESCE( @sql1 + char(10), '') + 'DELETE' + char(10) + ' ' + OBJECT_NAME (f.referenced_object_id) + ' FROM ' + OBJECT_NAME(f.parent_object_id) + ', '+OBJECT_NAME (f.referenced_object_id) + char(10) +' WHERE ' + OBJECT_NAME(f.parent_object_id) + '.' + COL_NAME(fc.parent_object_id, fc.parent_column_id) +'='+OBJECT_NAME (f.referenced_object_id)+'.'+COL_NAME(fc.referenced_object_id, fc.referenced_column_id)
                    else
                         @sql1 + ' AND ' + OBJECT_NAME(f.parent_object_id) + '.' + COL_NAME(fc.parent_object_id, fc.parent_column_id) +'='+OBJECT_NAME (f.referenced_object_id)+'.'+COL_NAME(fc.referenced_object_id, fc.referenced_column_id)
                    end + char(10)
     , @ptn1 = OBJECT_NAME (f.referenced_object_id)
     , @ptn2  = object_name(f.parent_object_id)
FROM   sys.foreign_keys AS f
       INNER JOIN
       sys.foreign_key_columns AS fc ON f.object_id = fc.constraint_object_id
WHERE  f.parent_object_id = OBJECT_ID('dbo.M06Persons'); -- CHANGE here schema.table_name
--
print  '--Table Depended on ' + @ptn2 + char(10) + @sql1
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.