ฉันจะใช้การลบแบบเรียงซ้อนกับ SQL Server ได้อย่างไร


332

ฉันมี 2 ตาราง: T1 และ T2 เป็นตารางที่มีข้อมูลอยู่ เรามีความสัมพันธ์แบบหนึ่งถึงหลายอย่างระหว่าง T1 และ T2 ฉันจะเปลี่ยนคำจำกัดความของตารางเพื่อทำการลบแบบเรียงซ้อนใน SQL Server ได้อย่างไรเมื่อลบระเบียนจาก T1 แล้วระเบียนที่เกี่ยวข้องทั้งหมดใน T2 ก็ถูกลบด้วยเช่นกัน

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

T1 - พนักงาน

Employee ID      
Name
Status

T2 - รีวิวประสิทธิภาพ

Employee ID - 2009 Review
Employee ID - 2010 Review

คำตอบ:


362

คุณจะต้อง

  • ปล่อยข้อ จำกัด กุญแจต่างประเทศที่มีอยู่
  • เพิ่มรายการใหม่โดยON DELETE CASCADEเปิดใช้งานการตั้งค่า

สิ่งที่ต้องการ:

ALTER TABLE dbo.T2
   DROP CONSTRAINT FK_T1_T2   -- or whatever it's called

ALTER TABLE dbo.T2
   ADD CONSTRAINT FK_T1_T2_Cascade
   FOREIGN KEY (EmployeeID) REFERENCES dbo.T1(EmployeeID) ON DELETE CASCADE

3
ทีมของฉันและฉันเพิ่งทำสิ่งนี้ เราต้องลดข้อ จำกัด ของเราและเพิ่มมันอีกครั้ง สิ่งนี้ใช้ได้สำหรับเรา
Daniel L. VanDenBosch

2
นี่เป็นวิธีการที่จะลบยาก? การลบแบบไม่ลบเลือนจะไม่มีปัญหาเรื่องข้อ จำกัด ดูเหมือนจะค่อนข้างตรงข้ามกับฉัน
Maxx

2
@Maxx ในการลบฮาร์ดคุณลบหนึ่งบันทึกและไม่จำเป็นต้องกังวลเกี่ยวกับการลงทะเบียนกำพร้าในขณะที่การลบนุ่มคุณต้องทำด้วยตนเอง
Ronaldo Araújo Alves

319

ในการเพิ่ม "ลบทั้งหมด" ลงใน foreign key ที่มีอยู่ใน SQL Server Management Studio:

ก่อนอื่นให้เลือก Foreign Key ของคุณและเปิดเป็น "DROP and Create To .. " ในหน้าต่าง Query ใหม่

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

จากนั้นเพียงแค่เพิ่มON DELETE CASCADEไปที่ADD CONSTRAINTคำสั่ง:

n และกดปุ่ม "ดำเนินการ" เพื่อเรียกใช้แบบสอบถามนี้

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

SELECT 
   OBJECT_NAME(f.parent_object_id) AS 'Table name',
   COL_NAME(fc.parent_object_id,fc.parent_column_id) AS 'Field name',
   delete_referential_action_desc AS 'On Delete'
FROM sys.foreign_keys AS f,
     sys.foreign_key_columns AS fc,
     sys.tables t 
WHERE f.OBJECT_ID = fc.constraint_object_id
AND t.OBJECT_ID = fc.referenced_object_id
ORDER BY 1

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

sp_help 'TableName'

SQL ในบทความนั้นแสดงรายการ FK ทั้งหมดที่อ้างอิงถึงตารางเฉพาะ

หวังว่าทั้งหมดนี้จะช่วยให้

ขอโทษสำหรับนิ้วยาว ฉันแค่พยายามทำจุด


163

คุณสามารถทำได้ด้วย SQL Server Management Studio

→คลิกขวาที่การออกแบบตารางและไปที่ความสัมพันธ์และเลือกคีย์ต่างประเทศในบานหน้าต่างด้านซ้ายและในบานหน้าต่างด้านขวาขยายเมนู "ข้อมูลจำเพาะ INSERT และ UPDATE" และเลือก "น้ำตก" เป็นลบกฎ

SQL Server Management Studio


สวัสดีความแตกต่างระหว่าง 4 คืออะไรการเปิดการเรียงซ้อนทำให้ง่ายต่อการลบข้อมูลทั้งหมดในตาราง ฉันจะดูคีย์การขึ้นต่อกัน / fk ทั้งหมดบนตารางนี้ได้อย่างไรไม่ใช่จากตารางนี้ แม้หลังจากการลบ FK ทั้งหมดฉันยังคงได้รับข้อผิดพลาด
aggie

@aggie - คุณสามารถตรวจสอบการอ้างอิงโดย - คลิกขวาที่ตาราง -> "ดูการพึ่งพา" และเซิร์ฟเวอร์ sql จะให้ข้อผิดพลาดโดยละเอียดกับชื่อตารางและชื่อคอลัมน์เช่นนี้ "คำสั่ง DELETE ขัดแย้งกับข้อ จำกัด ของการอ้างอิง" FK_Child1_Parent1 " ความขัดแย้งเกิดขึ้นในฐานข้อมูล "TESTDB", ตาราง "dbo.Child1", คอลัมน์ 'Parent1ID'
Palanikumar

@aggie - กรณีที่ 4 "Set Default" คือคุณต้องตั้งค่าข้อ จำกัด เริ่มต้นในคอลัมน์ Foreign Key เมื่อเราลบ parent แล้วค่าเริ่มต้นจะถูกแทนที่ในตารางลูก (หมายเหตุ: ค่าเริ่มต้นจะต้องตรงกับตารางหลัก) สำหรับข้อมูลเพิ่มเติมโปรดไปที่mssqltips.com/sqlservertip/2365/…
Palanikumar

สิ่งนี้มีประโยชน์มาก ฉันสงสัยว่าทำไมไม่มีกฎแทรก? กล่าวอีกนัยหนึ่งเมื่อฉันเพิ่มแถวใน T1 ฉันต้องการให้รายการที่เกี่ยวข้องใน T2 ถูกสร้างขึ้นโดยอัตโนมัติ
Robert M.

@RobertM เพราะนั่นทำให้รู้สึกไม่ จะรู้ได้อย่างไรว่า INSERT ให้คุณค่าอะไร? คุณอาจสามารถใช้ทริกเกอร์ INSERT เพื่อสร้างแถวลูก ๆ ได้ลองค้นคว้าดู
Dan Bechard

47

ใช้สิ่งที่ชอบ

ALTER TABLE T2
ADD CONSTRAINT fk_employee
FOREIGN KEY (employeeID)
REFERENCES T1 (employeeID)
ON DELETE CASCADE;

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


41
@marc_s - จริง ๆ แล้วคุณสามารถเพิ่ม foreign key ตัวที่สองตรงกับคอลัมน์เดียวกันทั้งสองข้างและมันจะทำงานได้อย่างถูกต้อง หากทำงานในสภาพแวดล้อมการผลิตที่ไม่มีการหยุดทำงานอาจเป็นการดีกว่าที่จะแนะนำ FK ใหม่ที่มี cascade แล้วปล่อย FK ที่เก่ากว่าแทนที่จะปล่อยให้หน้าต่างอยู่บนโต๊ะเมื่อไม่มี FK อยู่ (เพิ่งทดสอบกับ SQL 2008)
Damien_The_Unbeliever

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

15

ก่อนเพื่อเปิดใช้งานคุณสมบัติ ONCascade:

1. ลดข้อ จำกัด foreign key ที่มีอยู่

2. เพิ่มใหม่โดยเปิดใช้งานการตั้งค่า ON DELETE CASCADE

Ex:

IF EXISTS(SELECT 1 FROM sys.foreign_keys WHERE parent_object_id = OBJECT_ID(N'dbo.Response'))
 BEGIN 

ALTER TABLE [dbo].[Response] DROP CONSTRAINT [FK_Response_Request]  

ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request]  FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE CASCADE
END

ELSE

 BEGIN 
 ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request]  FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE CASCADE
END

ที่สองในการปิดการใช้งานคุณสมบัติ ONCascade:

1. ลดข้อ จำกัด foreign key ที่มีอยู่

2. เพิ่มรายการใหม่ที่เปิดใช้งานการตั้งค่า ON DELETE NO ACTION

Ex:

IF EXISTS(SELECT 1 FROM sys.foreign_keys WHERE parent_object_id = OBJECT_ID(N'dbo.Response'))
 BEGIN 
ALTER TABLE [dbo].[Response] DROP CONSTRAINT [FK_Response_Request]  

ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request]  FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE CASCADE
END

ELSE

 BEGIN 
 ALTER TABLE [dbo].[Response] WITH CHECK ADD CONSTRAINT [FK_Response_Request]  FOREIGN KEY([RequestId])
REFERENCES [dbo].[Request] ([RequestId])
ON DELETE NO ACTION 
END

15

ON DELETE CASCADE
มันระบุว่าข้อมูลเด็กจะถูกลบเมื่อข้อมูลผู้ปกครองจะถูกลบ

CREATE TABLE products
( product_id INT PRIMARY KEY,
  product_name VARCHAR(50) NOT NULL,
  category VARCHAR(25)
);

CREATE TABLE inventory
( inventory_id INT PRIMARY KEY,
  product_id INT NOT NULL,
  quantity INT,
  min_level INT,
  max_level INT,
  CONSTRAINT fk_inv_product_id
    FOREIGN KEY (product_id)
    REFERENCES products (product_id)
    ON DELETE CASCADE
);

สำหรับคีย์ต่างประเทศนี้เราได้ระบุON DELETE CASCADEส่วนที่บอกให้ SQL Server ลบระเบียนที่เกี่ยวข้องในตารางลูกเมื่อข้อมูลในตารางแม่จะถูกลบ ดังนั้นในตัวอย่างนี้หากค่า product_id ถูกลบออกจากตารางผลิตภัณฑ์บันทึกที่เกี่ยวข้องในตารางสินค้าคงคลังที่ใช้ product_id นี้จะถูกลบด้วย


-2

หากความสัมพันธ์แบบหนึ่งต่อหลายคนมาจาก T1 ถึง T2 แสดงว่ามันไม่ได้เป็นตัวแทนของฟังก์ชั่นดังนั้นจึงไม่สามารถใช้เพื่ออนุมานหรืออนุมานฟังก์ชันผกผันที่รับประกันได้ว่าค่า T2 ที่ได้จะไม่ตัดกับ tuples ของ T1 เข้าร่วม T2 เนื่องจากไม่มีฟังก์ชันผกผันที่ใช้งานได้ (ฟังก์ชั่นที่แสดงถึงวัตถุประสงค์ของคีย์หลัก) คำตอบใน SQL คิดว่าใช่คุณสามารถทำได้ คำตอบในการคิดเชิงสัมพันธ์คือคุณไม่สามารถทำได้ ดูจุดที่คลุมเครือใน Codd 1970 ความสัมพันธ์จะต้องมีหลายต่อหนึ่งจาก T1 ถึง T2


-10

ฉันคิดว่าคุณไม่สามารถลบคุณสมบัติของตารางได้ถ้าเป็นข้อมูลการผลิตจริงเพียงแค่ลบเนื้อหาที่ไม่มีผลกับ schema ของตาราง

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