Kısıtlamaları geçici olarak kapatma (MS SQL)


208

Geçici olarak tüm DB kısıtlamaları (örneğin tablo ilişkileri) kapatmak için bir yol arıyorum.

(INSERTs kullanarak) bir DB tablolarını başka bir DB kopyalamak gerekiyor. Bunu komutları düzgün bir şekilde (ilişkileri bozmamak için) yürüterek başarabileceğimi biliyorum.

Ancak kısıtlamaları kontrol etmeyi geçici olarak kapatabilir ve işlem bittikten sonra tekrar açabilirsem daha kolay olurdu.

Mümkün mü?


3
Bu tam bir kopya değil Sadece aradaki seçili tabloları kopyalamak istiyorum
Maciej

Bunu yapma konusundaki endişem, bunun sadece siz değil herkes için kısıtlamaları ortadan kaldırmasıdır. Bunu yapmanız gerekiyorsa, önce veritabanını tek kullanıcı moduna getirin. Aksi takdirde veri bütünlüğü sorunlarına neden olabilirsiniz.
HLGEM

13
Gelecekten gelen sevgili insanlar: Veritabanındaki tüm kısıtlamaları bir kerede devre dışı bırakıp yeniden etkinleştirebilirsiniz; bkz. stackoverflow.com/a/161410
brichins

1
İşiniz bittiğinde kısıtlamaları etkinleştirmeyi unutmayın!
Mike Christian

1
@NicolasBarbulesco yeterince adil; sql-serverVe sql-server-2005etiketleri gidiyordum . Verdiğim bağlantı SQL Server içindir, ancak aynı şeyi Oracle'da da yapabilirsiniz - buraya ve buraya bakın . PostgreSQL'de de yapabilirsiniz .
brichins

Yanıtlar:


214

FK ve CHECK kısıtlamalarını yalnızca SQL 2005 ve sonraki sürümlerinde devre dışı bırakabilirsiniz . Bakınız ALTER TABLOSU

ALTER TABLE foo NOCHECK CONSTRAINT ALL

veya

ALTER TABLE foo NOCHECK CONSTRAINT CK_foo_column

Birincil anahtarlar ve benzersiz kısıtlamalar devre dışı bırakılamaz, ancak sizi doğru anladıysam bu iyi olmalıdır.


10
Ancak bu geçici değildir.
Nicolas Barbulesco

@NicolasBarbulesco: duruma göre değişir. Evet, DROP / CREATE ile onları yeniden etkinleştirebilirsiniz
gbn

Bu cevap bir çözümün sadece ilk yarısıdır. Kısıtlamaları geçici olarak kapatmanın basit bir yolunu arıyordum ve Oracle'da var olmadığı sonucuna vardım.
Nicolas Barbulesco

PK'lerin ve benzersiz kısıtlamanın devre dışı bırakılamayacağı doğru değildir. En azından SQL Server'ın daha yeni sürümünde çalışır. Örneğin, bkz: techonthenet.com/sql_server/primary_keys.php
Dejan

1
Oracle'da @NicolasBarbulesco? ALTER TABLE some_table DISABLE CONSTRAINT some_table_fk1; // kısıtlamaları ihlal edecek bazı şeyler yapın ALTER TABLE some_table ENABLE 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. Tutarlı olduğunuz sürece önemli değil.
Po-ta-toe

2
Alıntılanan tanımlayıcıları kullanmak, ANSI standart ayarına inanıyorum, bu da onları dizeler için kullanmamanız gerektiği anlamına geliyor. Tutarlı olmakla ilgisi yoktur. bkz. stackoverflow.com/questions/1992314/…
kevinc

1
Prosedür için teşekkürler! Ve BTW doğru kasa "sp_MSforeachtable" (MS büyük harf). Teşekkürler!
Sielu

3
Bu, soruyu tamamen cevapladığı için doğru cevap olarak işaretlenmiş olmalıdır. Sadece bu değil, ama @Donal benim için çok yararlı bir joker sürümü dahil.
Matt Jackson

2
Yeniden etkinleştirme biti için teşekkürler. Özellikle check checkbirçok millet unutmak çift !!
Alex

57

Ve eğer ilişkilerinizi bozmadığınızı ve yetimleri tanımadığınızı doğrulamak istiyorsanız, çeklerinizi yeniden silahlandırdıktan sonra, yani

ALTER TABLE foo CHECK CONSTRAINT ALL

veya

ALTER TABLE foo CHECK CONSTRAINT FK_something

ardından geri dönebilir ve işaretli sütunlara karşı bir güncelleme yapabilirsiniz:

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

Ve bu noktadaki hatalar, kısıtlamalara uyulmamasından kaynaklanacaktır.


11
Daha iyi bir yol, DENETİM KONTROLÜ İLE ALTER TABLO YEMEK FK_something
Cody Konior

1
ALTER TABLE foo CHECK CONSTRAINT TÜMÜNÜ veya ALTER TABLE foo CHECK CONSTRAINT FK_something kısıtlamaları etkinleştirir, ancak verileri kontrol etmeden ve bu, kısıtlamanın güvenilmeyeceği anlamına gelir (is_no_trusted = 1, is_disabled = 0).
Bogdan Sahlean


0

Tüm Yabancı Anahtarları Devre Dışı Bırakma ve Etkinleştirme

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

İlk olarak, foreignKeyCursor imleci yabancı anahtarların listesini ve tablo adlarını toplayan SELECT ifadesi olarak bildirilir. Ardından, imleç açılır ve ilk FETCH deyimi yürütülür. Bu FETCH deyimi, ilk satırın verilerini @foreignKeyName ve @tableName yerel değişkenlerine okur. Bir imleç arasında geçiş yaparken, @@ FETCH_STATUS değerinde 0 değerini kontrol edebilirsiniz, bu getirme işleminin başarılı olduğunu gösterir. Bu, döngüün art arda gelen her yabancı anahtarı satır kümesinden alabilmesi için ilerlemeye devam edeceği anlamına gelir. @@ FETCH_STATUS bağlantıdaki tüm imleçler tarafından kullanılabilir. Bu nedenle, birden çok imleç arasında döngü yapıyorsanız, FETCH deyimini hemen takip eden ifadede @@ FETCH_STATUS değerini kontrol etmek önemlidir. @@ FETCH_STATUS, bağlantıdaki en son FETCH işleminin durumunu yansıtır. @@ FETCH_STATUS için geçerli değerler:

0 = FETCH başarılı oldu
-1 = FETCH başarısız oldu
-2 = getirilen satır eksik

Döngünün içinde, kod, yabancı anahtar kısıtlamasını devre dışı bırakma veya etkinleştirme amacına bağlı olarak (CHECK veya NOCHECK anahtar sözcüğünü kullanarak) ALTER TABLE komutunu farklı şekilde oluşturur. İfade daha sonra bir mesaj olarak yazdırılır, böylece ilerlemesi gözlemlenebilir ve ardından ifade yürütülür. Son olarak, tüm satırlar yinelendiğinde, saklı yordam imleci kapatır ve yeniden konumlandırır.

bkz . MSDN Magazine'den Kısıtlamaları ve Tetikleyicileri Devre Dışı Bırakma

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.