ฉันจะวางข้อ จำกัด ทั้งหมดจากตารางทั้งหมดได้อย่างไร


30

ฉันต้องการปล่อยข้อ จำกัด เริ่มต้นทั้งหมดตรวจสอบข้อ จำกัด ข้อ จำกัด เฉพาะคีย์หลักและคีย์ต่างประเทศจากตารางทั้งหมดในฐานข้อมูล SQL Server ฉันรู้วิธีรับชื่อข้อ จำกัด ทั้งหมดsys.objectsแต่ฉันจะเติมALTER TABLEส่วนได้อย่างไร


แค่อยากรู้อยากเห็นบริบทของคำขอดังกล่าวคืออะไร? ฉันสงสัยว่าการอ้างอิงการทำงานนั้นได้รับการแก้ไขอย่างไร (เช่นมุมมองที่จัดทำดัชนีเหตุการณ์เรียงซ้อนบน FKs และ UQ ที่มี IGNORE_DUP_KEY = ON)
โซโลมอน Rutzky

3
@srutzky มันถูกถามใน Stack Overflowแต่ฉันตัดสินใจที่จะสร้างเวอร์ชั่นที่สะอาดกว่ามาตรฐานที่นี่ อย่างไรก็ตามมันเป็นคำขอทั่วไปซึ่งมักเป็นส่วนหนึ่งของงานที่มีขนาดใหญ่กว่าในการล้างฐานข้อมูล (เริ่มต้นใหม่ล้างวัตถุที่ใส่ผิดพลาดเป็นต้น) ฉันไม่เห็นว่าการพึ่งพาฟังก์ชั่นการทำงานเหล่านี้ได้รับผลกระทบจากการลดข้อ จำกัด - ในความเป็นจริงฉันสงสัยว่าในกรณีส่วนใหญ่ภาพใหญ่จะถูกตัดหรือวางตารางเช่นกัน การปล่อยข้อ จำกัด ก่อนอนุญาตให้ทำได้
Aaron Bertrand

คำตอบ:


36

คุณสามารถรับข้อมูลนี้ได้อย่างง่ายดายโดยการเข้าร่วมsys.tables.object_id = sys.objects.parent_object_idประเภทวัตถุเหล่านั้น

DECLARE @sql NVARCHAR(MAX);
SET @sql = N'';

SELECT @sql = @sql + N'
  ALTER TABLE ' + QUOTENAME(s.name) + N'.'
  + QUOTENAME(t.name) + N' DROP CONSTRAINT '
  + QUOTENAME(c.name) + ';'
FROM sys.objects AS c
INNER JOIN sys.tables AS t
ON c.parent_object_id = t.[object_id]
INNER JOIN sys.schemas AS s 
ON t.[schema_id] = s.[schema_id]
WHERE c.[type] IN ('D','C','F','PK','UQ')
ORDER BY c.[type];

PRINT @sql;
--EXEC sys.sp_executesql @sql;

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

เมื่อคุณพอใจกับผลลัพธ์EXECแล้ว


3
คุณอาจต้องการตรวจสอบให้แน่ใจว่าได้ลดข้อ จำกัด foreign key ก่อนคีย์หลัก; ORDER BY (CASE WHEN c.[type] IN ('PK', 'UQ') THEN 1 ELSE 0 END)
Daniel Hutmacher

1
@Daniel จุดที่ดี ORDER BY type น่าจะเพียงพอจนกว่า SQL Server จะแนะนำประเภทข้อ จำกัด ใหม่
Aaron Bertrand

6

ฉันเริ่มต้นด้วยคำตอบที่ยอมรับและปรับเปลี่ยนโครงสร้างเพื่อใช้ a while loop แทนที่จะสร้างคำสั่ง sql แบบเต็มใน sql แบบไดนามิก ฉันชอบสิ่งนี้ดีกว่าด้วยเหตุผลหลายประการ

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

Set NoCount ON

Declare @schemaName varchar(200)
set @schemaName=''
Declare @constraintName varchar(200)
set @constraintName=''
Declare @tableName varchar(200)
set @tableName=''

While exists
(   
    SELECT c.name
    FROM sys.objects AS c
    INNER JOIN sys.tables AS t
    ON c.parent_object_id = t.[object_id]
    INNER JOIN sys.schemas AS s 
    ON t.[schema_id] = s.[schema_id]
    WHERE c.[type] IN ('D','C','F','PK','UQ')
    and t.[name] NOT IN ('__RefactorLog', 'sysdiagrams')
    and c.name > @constraintName
)

Begin   
    -- First get the Constraint
    SELECT 
        @constraintName=min(c.name)
    FROM sys.objects AS c
    INNER JOIN sys.tables AS t
    ON c.parent_object_id = t.[object_id]
    INNER JOIN sys.schemas AS s 
    ON t.[schema_id] = s.[schema_id]
    WHERE c.[type] IN ('D','C','F','PK','UQ')
    and t.[name] NOT IN ('__RefactorLog', 'sysdiagrams')
    and c.name > @constraintName

    -- Then select the Table and Schema associated to the current constraint
    SELECT 
        @tableName = t.name,
        @schemaName = s.name
    FROM sys.objects AS c
    INNER JOIN sys.tables AS t
    ON c.parent_object_id = t.[object_id]
    INNER JOIN sys.schemas AS s 
    ON t.[schema_id] = s.[schema_id]
    WHERE c.name = @constraintName

    -- Then Print to the output and drop the constraint
    Print 'Dropping constraint ' + @constraintName + '...'
    Exec('ALTER TABLE [' + @schemaName + N'].[' + @tableName + N'] DROP CONSTRAINT [' + @constraintName + ']')
End

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