ปิดข้อ จำกัด ชั่วคราว (MS SQL)


208

ฉันกำลังมองหาวิธีที่จะปิดข้อ จำกัด ทั้งหมดของฐานข้อมูลชั่วคราว (เช่นความสัมพันธ์ของตาราง)

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

แต่มันจะง่ายขึ้นถ้าฉันสามารถปิดการตรวจสอบข้อ จำกัด ชั่วคราวและเปิดใหม่หลังจากการดำเนินการเสร็จสิ้น

เป็นไปได้ไหม


3
นี่ไม่ใช่การคัดลอกที่สมบูรณ์ฉันเพียงต้องการคัดลอกตารางที่เลือกไว้
Maciej

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

13
เรียนผู้คนจากอนาคต: คุณสามารถปิดใช้งานและเปิดใช้งานข้อ จำกัด ทั้งหมดอีกครั้งในฐานข้อมูลได้ในครั้งเดียว ดูstackoverflow.com/a/161410
brichins

1
อย่าลืมเปิดใช้งานข้อ จำกัด เมื่อเสร็จแล้ว!
Mike Christian

1
@ NicolasBarbulesco ยุติธรรมพอ; ฉันกำลังออกไปsql-serverและsql-server-2005แท็ก การเชื่อมโยงฉันให้เป็นสำหรับ SQL Server แต่คุณสามารถทำสิ่งเดียวกันใน Oracle - ดูที่นี่และที่นี่ นอกจากนี้คุณยังสามารถทำมันได้ในPostgreSQL
brichins

คำตอบ:


214

คุณสามารถปิด FK และตรวจสอบข้อ จำกัดเฉพาะใน SQL 2005 + ดูการเปลี่ยนแปลงตาราง

ALTER TABLE foo NOCHECK CONSTRAINT ALL

หรือ

ALTER TABLE foo NOCHECK CONSTRAINT CK_foo_column

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


10
แต่นี่ไม่ใช่ชั่วคราว
Nicolas Barbulesco

@ NicolasBarbulesco: มันขึ้นอยู่กับ ใช่แล้วคุณสามารถเปิดใช้งานได้อีกครั้งด้วย DROP / CREATE
gbn

คำตอบนี้เป็นเพียงครึ่งแรกของการแก้ปัญหา ฉันกำลังมองหาวิธีง่ายๆในการปิดข้อ จำกัด ชั่วคราวและฉันได้ข้อสรุปว่าไม่มีอยู่ใน Oracle
Nicolas Barbulesco

ไม่เป็นความจริงที่ PKs และข้อ จำกัด เฉพาะไม่สามารถปิดใช้งานได้ อย่างน้อยในเวอร์ชันล่าสุดของ SQL Server จะทำงานได้ ตัวอย่างเช่นโปรดดู: techonthenet.com/sql_server/primary_keys.php
Dejan

1
@NicolasBarbulesco บน Oracle หรือไม่ แก้ไขตาราง some_table ปิดการใช้งานข้อ จำกัด some_table_fk1; // ทำบางสิ่งที่ละเมิดข้อ จำกัด ALTER TABLE some_table เปิดใช้งาน CONSTRAINT some_table_fk1;
Steve Swinsburg

237
-- Disable the constraints on a table called tableName:
ALTER TABLE tableName NOCHECK CONSTRAINT ALL

-- Re-enable the constraints on a table called tableName:
ALTER TABLE tableName WITH CHECK CHECK CONSTRAINT ALL
---------------------------------------------------------

-- Disable constraints for all tables:
EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT all'

-- Re-enable constraints for all tables:
EXEC sp_msforeachtable 'ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all'
---------------------------------------------------------

1
@kevinc no ตราบใดที่คุณยินยอมก็ไม่เป็นไร
Po-ta-toe

2
การใช้ตัวระบุที่ยกมาคือฉันเชื่อว่าการตั้งค่ามาตรฐาน ANSI ซึ่งหมายความว่าคุณไม่ควรใช้มันสำหรับสตริง ไม่มีอะไรเกี่ยวข้องกับความสอดคล้อง ดูstackoverflow.com/questions/1992314/…
kevinc

1
ขอบคุณสำหรับขั้นตอน! และ BTW มันเป็นท่อที่ถูกต้องคือ "sp_MSforeachtable" (MS ตัวพิมพ์ใหญ่) ขอบคุณ!
Sielu

3
สิ่งนี้ควรถูกทำเครื่องหมายว่าเป็นคำตอบที่ถูกต้องเพราะมันตอบคำถามได้อย่างสมบูรณ์ ไม่เพียงแค่นั้น แต่ @Donal ยังรวมเวอร์ชันตัวแทนซึ่งเป็นประโยชน์กับฉันมาก
Matt Jackson

2
ขอบคุณสำหรับการเปิดใช้งานบิตอีกครั้ง โดยเฉพาะคู่check checkที่หลายคนลืม !!
อเล็กซ์

57

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

ALTER TABLE foo CHECK CONSTRAINT ALL

หรือ

ALTER TABLE foo CHECK CONSTRAINT FK_something

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

UPDATE myUpdatedTable SET someCol = someCol, fkCol = fkCol, etc = etc

และข้อผิดพลาดที่จุดนั้นจะเกิดจากความล้มเหลวในการปฏิบัติตามข้อ จำกัด


11
วิธีที่ดีกว่าคือแก้ไขตาราง FOO ด้วยการตรวจสอบตรวจสอบข้อ จำกัด FK_something
Cody Konior

1
ALTER TABLE foo CHECK CONSTRAINT ALL หรือ ALTER TABLE foo CHECK CONSTRAINT FK_something จะเปิดใช้งานข้อ จำกัด แต่ไม่มีการตรวจสอบข้อมูลและหมายความว่าข้อ จำกัด จะไม่น่าเชื่อถือ (is_no_trusted = 1, is_disabled = 0)
Bogdan Sahlean

16

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

ขณะนี้ฉันทำงานกับ SQL Server 2005 แต่ฉันเกือบจะแน่ใจว่าวิธีนี้ใช้ได้กับ SQL 2000 เช่นกัน


0

ปิดการใช้งานและเปิดใช้งานคีย์ต่างประเทศทั้งหมด

CREATE PROCEDURE pr_Disable_Triggers_v2
    @disable BIT = 1
AS
    DECLARE @sql VARCHAR(500)
        ,   @tableName VARCHAR(128)
        ,   @tableSchema VARCHAR(128)

    -- List of all tables
    DECLARE triggerCursor CURSOR FOR
        SELECT  t.TABLE_NAME AS TableName
            ,   t.TABLE_SCHEMA AS TableSchema
        FROM    INFORMATION_SCHEMA.TABLES t
        ORDER BY t.TABLE_NAME, t.TABLE_SCHEMA

    OPEN    triggerCursor
    FETCH NEXT FROM triggerCursor INTO @tableName, @tableSchema
    WHILE ( @@FETCH_STATUS = 0 )
    BEGIN

        SET @sql = 'ALTER TABLE ' + @tableSchema + '.[' + @tableName + '] '
        IF @disable = 1
            SET @sql = @sql + ' DISABLE TRIGGER ALL'
        ELSE
            SET @sql = @sql + ' ENABLE TRIGGER ALL'

        PRINT 'Executing Statement - ' + @sql
        EXECUTE ( @sql )

        FETCH NEXT FROM triggerCursor INTO @tableName, @tableSchema

    END

    CLOSE triggerCursor
    DEALLOCATE triggerCursor

ก่อนอื่นเคอร์เซอร์ foreignKeyCursor จะถูกประกาศเป็นคำสั่ง SELECT ที่รวบรวมรายการของ foreign key และชื่อตาราง ถัดไปเคอร์เซอร์จะถูกเปิดและคำสั่ง FETCH เริ่มต้นจะถูกดำเนินการ คำสั่ง FETCH นี้จะอ่านข้อมูลของแถวแรกลงในตัวแปรโลคัล @foreignKeyName และ @tableName เมื่อวนลูปผ่านเคอร์เซอร์คุณสามารถตรวจสอบ @@ FETCH_STATUS สำหรับค่า 0 ซึ่งบ่งชี้ว่าการดึงข้อมูลสำเร็จ ซึ่งหมายความว่าการวนซ้ำจะดำเนินต่อไปข้างหน้าเพื่อให้สามารถรับแต่ละคีย์ต่างประเทศที่ต่อเนื่องจาก rowset @@ FETCH_STATUS มีเคอร์เซอร์ทั้งหมดในการเชื่อมต่อ ดังนั้นหากคุณวนลูปผ่านเคอร์เซอร์หลายตัวสิ่งสำคัญคือต้องตรวจสอบค่าของ @@ FETCH_STATUS ในคำสั่งทันทีหลังจากคำสั่ง FETCH @@ FETCH_STATUS จะแสดงสถานะของการดำเนินการ FETCH ล่าสุดในการเชื่อมต่อ ค่าที่ถูกต้องสำหรับ @@ FETCH_STATUS คือ:

0 = FETCH สำเร็จ
-1 = FETCH ไม่สำเร็จ
-2 = แถวที่ดึงข้อมูลหายไป

ภายในลูปรหัสจะสร้างคำสั่ง ALTER TABLE แตกต่างกันไปขึ้นอยู่กับว่าตั้งใจจะปิดหรือเปิดใช้งานข้อ จำกัด foreign key (โดยใช้คีย์เวิร์ด CHECK หรือ NOCHECK) คำสั่งจะถูกพิมพ์เป็นข้อความเพื่อให้สามารถสังเกตความคืบหน้าของมันและจากนั้นคำสั่งจะถูกดำเนินการ ในที่สุดเมื่อทุกแถวได้รับการวนซ้ำขั้นตอนการจัดเก็บจะปิดและยกเลิกการจัดสรรเคอร์เซอร์

ดูการปิดการใช้งานข้อ จำกัด และทริกเกอร์จากนิตยสาร MSDN

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