SQL DROP TABEL kendala kunci asing


154

Jika saya ingin menghapus semua tabel dalam database saya seperti ini, apakah ini akan menangani batasan kunci asing? Jika tidak, bagaimana saya mengatasinya terlebih dahulu?

GO
IF OBJECT_ID('dbo.[Course]','U') IS NOT NULL
    DROP TABLE dbo.[Course]
GO
IF OBJECT_ID('dbo.[Student]','U') IS NOT NULL
    DROP TABLE dbo.[Student]


2
Periksa jawaban ini, itu membantu saya;) stackoverflow.com/a/5488670/2205144
xatz

Jawaban:


335

Tidak, ini tidak akan menjatuhkan meja Anda jika memang ada kunci asing yang merujuknya.

Untuk mendapatkan semua hubungan kunci asing yang merujuk tabel Anda, Anda bisa menggunakan SQL ini (jika Anda menggunakan SQL Server 2005 dan lebih tinggi):

SELECT * 
FROM sys.foreign_keys
WHERE referenced_object_id = object_id('Student')

dan jika ada, dengan pernyataan ini di sini, Anda dapat membuat pernyataan SQL untuk benar-benar menghentikan hubungan FK tersebut:

SELECT 
    'ALTER TABLE [' +  OBJECT_SCHEMA_NAME(parent_object_id) +
    '].[' + OBJECT_NAME(parent_object_id) + 
    '] DROP CONSTRAINT [' + name + ']'
FROM sys.foreign_keys
WHERE referenced_object_id = object_id('Student')

Catatan: tabel yang dihasilkan berisi pernyataan untuk menghapus batasan individual untuk dijalankan dalam kueri yang berbeda. Ini bekerja sangat baik dalam kasus saya karena saya harus menyingkirkan meja yang tidak berguna (untuk tujuan pengujian) sambil mempertahankan sisa tabel yang memiliki FK untuk itu tetap utuh.
Mauricio Quintana

1
Saya harus menggunakan parent_object_id alih-alih referenced_object_id
Tom Robinson

2
Alternatif untuk pernyataan SELECT untuk mendapatkan semua tabel referensi adalah: EXEC sp_fkeys 'Student';
Buggieboy

sesuaikan kecil permintaan ini SELECT 'ALTER TABLE' + OBJECT_SCHEMA_NAME (parent_object_id) + '. [' + OBJECT_NAME (parent_object_id) + '] DROP CONSTRAINT [nama]' FROM sys.foreign_keys WHERE referenced_object_id = object_id [ganti nama] 'siswa dengan nama CONSTRAINT
Stas Svishov

1
Bagaimana cara menetapkan pilihan terakhir Anda sebagai variabel dan menjalankannya?
Hrvoje T

44

Di SQL Server Management Studio 2008 (R2) dan yang lebih baru, Anda bisa Klik kanan pada

DB -> Tugas -> Hasilkan Skrip

  • Pilih tabel yang ingin Anda DROP.

  • Pilih "Simpan ke jendela permintaan baru".

  • Klik pada tombol Advanced.

  • Tetapkan Script DROP dan BUAT ke Script DROP.

  • Tetapkan Script Foreign Keys ke True.

  • Klik OK.

  • Klik Berikutnya -> Selanjutnya -> Selesai.

  • Lihat skrip dan kemudian Jalankan.


12
masih sama 'Tidak bisa drop objek' my_table 'karena direferensikan oleh batasan KUNCI ASING.
FrenkyB

6
Bagaimana jawaban ini memiliki 28 + peringkat di luar saya ... masih tidak berfungsi pasangan
AltF4_

1
Meskipun itu menghasilkan skrip - skrip itu tidak menyelesaikan masalah, yaitu menjatuhkan tabel yang dirujuk oleh batasan Kunci Asing.
Alexey Shevelyov

Bekerja seperti pesona bagi saya.
Johan

21

Jika Anda menjatuhkan tabel "child" terlebih dahulu, kunci asing akan dijatuhkan juga. Jika Anda mencoba untuk menjatuhkan tabel "induk" terlebih dahulu, Anda akan mendapatkan "Tidak dapat menjatuhkan objek 'a' karena direferensikan oleh batasan KUNCI ASING." kesalahan.


2
Benar, tetapi tidak ada solusi. Anak dapat memiliki kunci asing ke meja lainnya dan / atau Anda mungkin tidak ingin meletakkannya di tempat pertama.
MaR

4
Benar, dan solusi jika tujuannya adalah, seperti yang dinyatakan, "Jika saya ingin menghapus semua tabel dalam database saya ..."
Philip Kelley

4
ini adalah jawaban yang jauh lebih baik daripada yang diterima, mengingat si penanya ingin "menghapus semua tabel di basis data saya"
lukkea

17

Berikut ini cara lain untuk menjatuhkan semua tabel dengan benar, menggunakan sp_MSdropconstraintsprosedur. Kode terpendek yang dapat saya pikirkan:

exec sp_MSforeachtable "declare @name nvarchar(max); set @name = parsename('?', 1); exec sp_MSdropconstraints @name";
exec sp_MSforeachtable "drop table ?";

Pria yang luar biasa ............
edCoder

2

Jika itu SQL Server, Anda harus membuang kendala sebelum Anda bisa menjatuhkan tabel.


2

Versi yang sedikit lebih umum dari apa yang diposting @mark_s, ini membantu saya

SELECT 
'ALTER TABLE ' +  OBJECT_SCHEMA_NAME(k.parent_object_id) +
'.[' + OBJECT_NAME(k.parent_object_id) + 
'] DROP CONSTRAINT ' + k.name
FROM sys.foreign_keys k
WHERE referenced_object_id = object_id('your table')

cukup tancapkan nama tabel Anda, dan jalankan hasilnya.


1
Hai, saya sudah mencoba untuk menjatuhkan batasan kunci asing saya dengan yang di atas, tetapi ketika saya pergi untuk menjatuhkan tabel setelah itu, ia terus berkata "Tidak bisa menjatuhkan objek karena masih sedang dirujuk oleh batasan kunci asing ... ada ide? Terima kasih sebelumnya.
daniness

1

Berikut cara lain untuk menghapus semua kendala yang diikuti oleh tabel itu sendiri, menggunakan trik gabungan yang melibatkan FOR XML PATH('') yang memungkinkan penggabungan beberapa baris input menjadi satu baris output tunggal. Harus bekerja pada apa pun SQL 2005 & yang lebih baru.

Saya telah meninggalkan perintah EXECUTE untuk keamanan.

DECLARE @SQL NVARCHAR(max)
;WITH fkeys AS (
    SELECT quotename(s.name) + '.' + quotename(o.name) tablename, quotename(fk.name) constraintname 
    FROM sys.foreign_keys fk
    JOIN sys.objects o ON fk.parent_object_id = o.object_id
    JOIN sys.schemas s ON o.schema_id = s.schema_id
)
SELECT @SQL = STUFF((SELECT '; ALTER TABLE ' + tablename + ' DROP CONSTRAINT ' + constraintname
FROM fkeys
FOR XML PATH('')),1,2,'')

-- EXECUTE(@sql)

SELECT @SQL = STUFF((SELECT '; DROP TABLE ' + quotename(TABLE_SCHEMA) + '.' + quotename(TABLE_NAME) 
FROM INFORMATION_SCHEMA.TABLES 
FOR XML PATH('')),1,2,'')

-- EXECUTE(@sql)

Ini tidak berfungsi dengan baik karena tidak semua FK akan dihapus (hanya yang mana tabel kami digunakan sebagai orangtua, di mana kami harus menjatuhkan juga batasan di mana tabel kami digunakan sebagai "direferensikan").
Roman Pokrovskij

Roman, posting asli adalah tentang menghapus batasan kunci asing. Jawaban saya tidak bertujuan untuk menutupi apa pun selain itu.
Warren Rumak

1

Berikut ini adalah skrip lengkap untuk mengimplementasikan solusi:

create Procedure [dev].DeleteTablesFromSchema
(
    @schemaName varchar(500)
)
As 
begin
    declare @constraintSchemaName nvarchar(128), @constraintTableName nvarchar(128),  @constraintName nvarchar(128)
    declare @sql nvarchar(max)
    -- delete FK first
    declare cur1 cursor for
    select distinct 
    CASE WHEN t2.[object_id] is NOT NULL  THEN  s2.name ELSE s.name END as SchemaName,
    CASE WHEN t2.[object_id] is NOT NULL  THEN  t2.name ELSE t.name END as TableName,
    CASE WHEN t2.[object_id] is NOT NULL  THEN  OBJECT_NAME(d2.constraint_object_id) ELSE OBJECT_NAME(d.constraint_object_id) END as ConstraintName
    from sys.objects t 
        inner join sys.schemas s 
            on t.[schema_id] = s.[schema_id]
        left join sys.foreign_key_columns d 
            on  d.parent_object_id = t.[object_id]
        left join sys.foreign_key_columns d2 
            on  d2.referenced_object_id = t.[object_id]
        inner join sys.objects t2 
            on  d2.parent_object_id = t2.[object_id]
        inner join sys.schemas s2 
            on  t2.[schema_id] = s2.[schema_id]
    WHERE t.[type]='U' 
        AND t2.[type]='U'
        AND t.is_ms_shipped = 0 
        AND t2.is_ms_shipped = 0 
        AND s.Name=@schemaName
    open cur1
    fetch next from cur1 into @constraintSchemaName, @constraintTableName, @constraintName
    while @@fetch_status = 0
    BEGIN
        set @sql ='ALTER TABLE ' + @constraintSchemaName + '.' + @constraintTableName+' DROP CONSTRAINT '+@constraintName+';'
        exec(@sql)
        fetch next from cur1 into @constraintSchemaName, @constraintTableName, @constraintName
    END
    close cur1
    deallocate cur1

    DECLARE @tableName nvarchar(128)
    declare cur2 cursor for
    select s.Name, p.Name
    from sys.objects p
        INNER JOIN sys.schemas s ON p.[schema_id] = s.[schema_id]
    WHERE p.[type]='U' and is_ms_shipped = 0 
    AND s.Name=@schemaName
    ORDER BY s.Name, p.Name
    open cur2

    fetch next from cur2 into @schemaName,@tableName
    while @@fetch_status = 0
    begin
        set @sql ='DROP TABLE ' + @schemaName + '.' + @tableName
        exec(@sql)
        fetch next from cur2 into @schemaName,@tableName
    end

    close cur2
    deallocate cur2

end
go

1
Removing Referenced FOREIGN KEY Constraints
Assuming there is a parent and child table Relationship in SQL Server:

--First find the name of the Foreign Key Constraint:
  SELECT * 
  FROM sys.foreign_keys
  WHERE referenced_object_id = object_id('States')

--Then Find foreign keys referencing to dbo.Parent(States) table:
   SELECT name AS 'Foreign Key Constraint Name', 
           OBJECT_SCHEMA_NAME(parent_object_id) + '.' + OBJECT_NAME(parent_object_id) AS 'Child Table'
   FROM sys.foreign_keys 
   WHERE OBJECT_SCHEMA_NAME(referenced_object_id) = 'dbo' AND 
              OBJECT_NAME(referenced_object_id) = 'dbo.State'

 -- Drop the foreign key constraint by its name 
   ALTER TABLE dbo.cities DROP CONSTRAINT FK__cities__state__6442E2C9;

 -- You can also use the following T-SQL script to automatically find 
 --and drop all foreign key constraints referencing to the specified parent 
 -- table:

 BEGIN

DECLARE @stmt VARCHAR(300);

-- Cursor to generate ALTER TABLE DROP CONSTRAINT statements  
 DECLARE cur CURSOR FOR
 SELECT 'ALTER TABLE ' + OBJECT_SCHEMA_NAME(parent_object_id) + '.' + 
 OBJECT_NAME(parent_object_id) +
                ' DROP CONSTRAINT ' + name
 FROM sys.foreign_keys 
 WHERE OBJECT_SCHEMA_NAME(referenced_object_id) = 'dbo' AND 
            OBJECT_NAME(referenced_object_id) = 'states';

 OPEN cur;
 FETCH cur INTO @stmt;

 -- Drop each found foreign key constraint 
  WHILE @@FETCH_STATUS = 0
  BEGIN
    EXEC (@stmt);
    FETCH cur INTO @stmt;
  END

  CLOSE cur;
  DEALLOCATE cur;

  END
  GO

--Now you can drop the parent table:

 DROP TABLE states;
--# Command(s) completed successfully.

0

Menggunakan SQL Server Manager Anda bisa menghilangkan batasan kunci asing dari UI. Jika Anda ingin menghapus tabel Diarytetapi tabel pengguna memiliki kunci asing yang DiaryIdmenunjuk ke Diarytabel, Anda bisa memperluas (menggunakan simbol plus) Usertabel dan kemudian memperluas Foreign Keysbagian. Klik kanan pada kunci asing yang menunjuk ke tabel buku harian lalu pilih Delete. Anda kemudian dapat memperluas Columnsbagian, klik kanan dan hapus kolom DiaryIdjuga. Maka Anda bisa menjalankan:

drop table Diary

Saya tahu pertanyaan Anda yang sebenarnya adalah tentang menghapus semua tabel, jadi ini mungkin tidak berguna untuk kasus itu. Namun, jika Anda hanya ingin menghapus beberapa tabel, ini berguna, saya yakin (judulnya tidak menyebutkan secara eksplisit menghapus semua tabel).


0

Jika Anda menggunakan server mysql dan jika Anda tidak keberatan kehilangan tabel, Anda dapat menggunakan kueri sederhana untuk menghapus beberapa tabel sekaligus:

SET foreign_key_checks = 0;
DROP TABLE IF EXISTS table_a,table_b,table_c,table_etc;
SET foreign_key_checks = 1;

Dengan cara ini tidak masalah dalam urutan apa Anda menggunakan tabel dalam kueri Anda.

Jika ada yang akan mengatakan sesuatu tentang fakta bahwa ini bukan solusi yang baik jika Anda memiliki database dengan banyak tabel: Saya setuju!


Saya mendapatkanIncorrect syntax near '='. (102) (SQLExecDirectW)
Matt

@ Mat agak sulit untuk menebak di mana '=' Anda mendapatkan kesalahan itu.
Els den Iep

3
foreign_key_checkstidak akan bekerja di server MSSQL. Saya pikir itu adalah variabel spesifik MySql.
ooXei1sh

1
@ ooXei1sh Tidak bukan di MSSQL. Itu sebabnya saya katakan di awal posting saya: "Jika Anda berada di server MYSQL".
Els den Iep

0

jalankan kode di bawah ini untuk mendapatkan nama batasan kunci asing yang memblokir drop Anda. Sebagai contoh, saya mengambil rolestabel.

      SELECT *
      FROM sys.foreign_keys
      WHERE referenced_object_id = object_id('roles');

      SELECT name AS 'Foreign Key Constraint Name',
      OBJECT_SCHEMA_NAME(parent_object_id) + '.' + OBJECT_NAME(parent_object_id)
      AS 'Child Table' FROM sys.foreign_keys
      WHERE OBJECT_SCHEMA_NAME(referenced_object_id) = 'dbo'
      AND OBJECT_NAME(referenced_object_id) = 'dbo.roles'

Anda akan mendapatkan nama FK seperti di bawah ini: FK__Table1__roleId__1X1H55C1

sekarang jalankan kode di bawah ini untuk menghapus referensi FK yang didapat dari atas.

ALTER TABLE dbo.users drop CONSTRAINT FK__Table1__roleId__1X1H55C1;

Selesai!


-4

Jika saya ingin menghapus semua tabel di database saya

Maka jauh lebih mudah untuk menghapus seluruh basis data:

DROP DATABASE WorkerPensions

71
Memberi Anda -1 untuk ini karena itu bukan jawaban yang valid untuk pertanyaan, karena dua alasan penting: 1) Ini menghapus lebih banyak daripada tabel! Menyimpan prosedur, fungsi, UDT, keamanan, rakitan .NET, dll. Semuanya hilang dengan DATABASE DROP. 2) Anda mungkin tidak diizinkan untuk membuat basis data, misalnya lingkungan pengembang yang dikelola secara terpusat di mana basis data disediakan oleh IT dan memiliki persyaratan tambahan pada waktu pembuatan yang tidak Anda ketahui.
Warren Rumak

-4

Jika Anda ingin DROPtabel yang telah dirujuk oleh tabel lain menggunakan penggunaan kunci asing

DROP TABLE *table_name* CASCADE CONSTRAINTS;
Saya pikir itu akan berhasil untuk Anda.


1
tidak ada cascade constraintsdalam server sql
JackyJohnson
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.