Matikan kendala sementara (MS SQL)

208

Saya mencari cara untuk sementara waktu mematikan semua kendala DB (misalnya hubungan tabel).

Saya perlu menyalin (menggunakan INSERT) satu tabel DB ke DB lain. Saya tahu saya dapat mencapainya dengan menjalankan perintah dalam urutan yang benar (untuk tidak memutuskan hubungan).

Tetapi akan lebih mudah jika saya bisa mematikan memeriksa kendala untuk sementara waktu dan menyalakannya kembali setelah operasi selesai.

Apakah ini mungkin?

Maciej
sumber
3
Ini bukan salinan lengkap Saya hanya ingin menyalin tabel yang dipilih antara
Maciej
Kekhawatiran saya tentang melakukan ini adalah bahwa ini mematikan kendala bagi semua orang, bukan hanya Anda. Jika Anda harus melakukan ini, taruh basis data dalam mode pengguna tunggal terlebih dahulu. Kalau tidak, Anda bisa berakhir dengan masalah integritas data.
HLGEM
13
Orang-orang terkasih dari The Future: Anda dapat menonaktifkan dan mengaktifkan kembali semua kendala dalam database sekaligus; lihat stackoverflow.com/a/161410
brichins
1
Jangan lupa untuk mengaktifkan kendala, saat selesai!
Mike Christian
1
@NicolasBarbulesco cukup adil; Saya pergi sql-serverdan sql-server-2005tag. Tautan yang saya berikan adalah untuk SQL Server, tetapi Anda dapat melakukan hal yang sama di Oracle - lihat di sini dan di sini . Anda juga dapat melakukannya di PostgreSQL .
brichins

Jawaban:

214

Anda dapat menonaktifkan batasan FK dan PERIKSA hanya dalam SQL 2005+ . Lihat ALTER TABEL

ALTER TABLE foo NOCHECK CONSTRAINT ALL

atau

ALTER TABLE foo NOCHECK CONSTRAINT CK_foo_column

Kunci primer dan batasan unik tidak dapat dinonaktifkan, tetapi ini harus OK jika saya mengerti Anda dengan benar.

gbn
sumber
10
Tapi ini tidak sementara.
Nicolas Barbulesco
@NicolasBarbulesco: itu tergantung. Ya itu, karena Anda dapat mengaktifkannya kembali dengan DROP / BUAT
gbn
Jawaban ini hanya setengah dari solusi. Saya sedang mencari cara sederhana untuk mematikan kendala sementara, dan saya telah mencapai kesimpulan bahwa itu tidak ada, di Oracle.
Nicolas Barbulesco
Tidak benar bahwa PK dan batasan unik tidak dapat dinonaktifkan. Setidaknya dalam versi terbaru dari SQL Server berfungsi. Misalnya, lihat: techonthenet.com/sql_server/primary_keys.php
Dejan
1
@NicolasBarbulesco di Oracle? ALTER TABLE some_table DISABLE CONSTRAINT some_table_fk1; // lakukan beberapa hal yang akan melanggar batasan 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'
---------------------------------------------------------
Donal
sumber
1
@kevinc no. Selama Anda konsisten, itu tidak masalah.
Po-ta-toe
2
Menggunakan pengenal yang dikutip adalah saya percaya pengaturan standar ANSI, yang berarti Anda tidak boleh menggunakannya untuk string. Tidak ada hubungannya dengan konsisten. Lihat stackoverflow.com/questions/1992314/…
kevinc
1
Terima kasih untuk prosedurnya! Dan BTW, casing yang benar adalah "sp_MSforeachtable" (huruf besar MS). Terima kasih!
Sielu
3
Ini seharusnya ditandai sebagai jawaban yang benar karena menjawab pertanyaan sepenuhnya. Bukan hanya itu, tetapi @Donal menyertakan versi wildcard yang sangat membantu saya.
Matt Jackson
2
Terima kasih atas bit yang diaktifkan kembali. Terutama double check checkyang banyak orang lupakan !!
Alex
57

Dan, jika Anda ingin memverifikasi bahwa Anda belum memutuskan hubungan Anda dan memperkenalkan anak yatim, setelah Anda mempersenjatai ulang cek Anda, yaitu

ALTER TABLE foo CHECK CONSTRAINT ALL

atau

ALTER TABLE foo CHECK CONSTRAINT FK_something

maka Anda dapat menjalankan kembali dan melakukan pembaruan terhadap kolom yang diperiksa seperti:

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

Dan setiap kesalahan pada saat itu akan disebabkan oleh kegagalan untuk memenuhi kendala.

Michael K. Campbell
sumber
11
Cara yang lebih baik adalah ALTER TABLE FOO WITH CHECK CHECK CONSTRAINT FK_something
Cody Konior
1
ALTER TABLE foo PERIKSA KONSTRA SEMUA atau ALTER TABLE foo PERIKSA KONSTRAINT FK_something akan memungkinkan kendala tetapi tanpa memeriksa data dan ini berarti bahwa kendala akan tidak dipercaya (is_no_trusted = 1, is_disabled = 0).
Bogdan Sahlean
16

Anda benar-benar dapat menonaktifkan semua batasan database dalam satu perintah SQL dan mengaktifkannya kembali memanggil perintah tunggal lainnya. Lihat:

Saya saat ini bekerja dengan SQL Server 2005 tetapi saya hampir yakin bahwa pendekatan ini bekerja dengan SQL 2000 juga

kristof
sumber
0

Menonaktifkan dan Mengaktifkan Semua Kunci Asing

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

Pertama, kursor foreignKeyCursor dideklarasikan sebagai pernyataan SELECT yang mengumpulkan daftar kunci asing dan nama tabelnya. Selanjutnya, kursor dibuka dan pernyataan FETCH awal dieksekusi. Pernyataan FETCH ini akan membaca data baris pertama ke dalam variabel lokal @foreignKeyName dan @tableName. Saat memutar melalui kursor, Anda dapat memeriksa @@ FETCH_STATUS untuk nilai 0, yang menunjukkan bahwa pengambilan berhasil. Ini berarti loop akan terus bergerak maju sehingga bisa mendapatkan setiap kunci asing berturut-turut dari rowset. @@ FETCH_STATUS tersedia untuk semua kursor pada koneksi. Jadi jika Anda mengulangi beberapa kursor, penting untuk memeriksa nilai @@ FETCH_STATUS dalam pernyataan segera setelah pernyataan FETCH. @@ FETCH_STATUS akan mencerminkan status untuk operasi FETCH terbaru pada koneksi. Nilai yang valid untuk @@ FETCH_STATUS adalah:

0 = FETCH berhasil
-1 = FETCH tidak berhasil
-2 = baris yang diambil tidak ada

Di dalam loop, kode membuat perintah ALTER TABLE berbeda tergantung pada apakah niatnya untuk menonaktifkan atau mengaktifkan batasan kunci asing (menggunakan kata kunci PERIKSA atau NOCHECK). Pernyataan tersebut kemudian dicetak sebagai pesan sehingga kemajuannya dapat diamati dan kemudian pernyataan tersebut dieksekusi. Akhirnya, ketika semua baris telah diulangi, prosedur yang disimpan menutup dan mendelokasi kursor.

lihat Menonaktifkan Batasan dan Pemicu dari Majalah MSDN

0x49D1
sumber