SQL DÜŞME TABLOSU yabancı anahtar kısıtı


154

Veritabanımdaki tüm tabloları bu şekilde silmek istersem, yabancı anahtar kısıtlamasına dikkat eder mi? Değilse, ilk önce bununla nasıl ilgilenirim?

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
Bu yanıtı kontrol edin, bana yardımcı oldu;) stackoverflow.com/a/5488670/2205144
xatz

Yanıtlar:


335

Hayır, gerçekten referans veren yabancı anahtarlar varsa masanızı düşürmez.

Tablonuzla ilgili tüm yabancı anahtar ilişkilerini almak için bu SQL'i kullanabilirsiniz (SQL Server 2005 ve sonraki sürümlerde iseniz):

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

ve varsa, bu ifadeyle, bu FK ilişkilerini gerçekten bırakmak için SQL ifadeleri oluşturabilirsiniz:

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')

Not: oluşturulan tablo, farklı bir sorguda çalıştırılacak bağımsız kısıtlamaları silmek için ifadeler içerir. Ona FK olan tabloların geri kalanını korurken işe yaramaz bir tablodan (test amaçlı) kurtulmam gerektiğinden benim durumumda harikalar yarattı.
Mauricio Quintana

1
Referans_object_id yerine parent_object_id kullanmak zorunda kaldım
Tom Robinson

2
Tüm referans tablolarını almak için SELECT deyiminin bir alternatifi: EXEC sp_fkeys 'Student';
Buggieboy

küçük sorgu bu sorguyu SEÇ 'ALTER TABLE' + OBJECT_SCHEMA_NAME (parent_object_id) + '. [' + OBJECT_NAME (parent_object_id) + '] DAMLA SÖZLEŞMESİ [ad]' FROM sys.foreign_keys WHERE referans_object_id = object_id ('Öğrenci') [name] yerine CONSTRAINT adıyla
Stas Svishov

1
Son seçiminizi değişken olarak nasıl atayabilir ve uygulayabilirsiniz?
Hrvoje T

44

SQL Server Management Studio 2008 (R2) ve daha yeni sürümlerde,

DB -> Görevler -> Komut Dosyaları Oluştur

  • DAMLA yapmak istediğiniz tabloları seçin.

  • "Yeni sorgu penceresine kaydet" i seçin.

  • Gelişmiş düğmesine tıklayın.

  • Komut Dosyası DROP'u ve CREATE değerini Komut Dosyası DROP'u olarak ayarlayın.

  • Komut Dosyası Yabancı Anahtarlarını True olarak ayarlayın.

  • Tamam'ı tıklayın.

  • İleri -> İleri -> Son'u tıklayın.

  • Komut dosyasını görüntüleyin ve ardından Yürütün.


12
yine aynı 'FOREIGN KEY kısıtlaması tarafından başvurulduğundan' my_table 'nesnesi bırakılamadı.
FrenkyB

6
Bu cevabın nasıl 28 + puanı var benim ötesinde ... hala çalışmıyor dostum
AltF4_

1
Komut dosyasını oluştururken - bu komut dosyası, Yabancı Anahtar kısıtlamaları tarafından başvurulan tabloyu bırakan sorunu çözmez.
Alexey Shevelyov

Benim için bir cazibe gibi çalıştı.
Johan

21

Önce "alt" tabloyu düşürürseniz, yabancı anahtar da kaldırılır. Önce "üst" tabloyu bırakmaya çalışırsanız, bir "FOREIGN KEY kısıtlaması tarafından başvuruda bulunduğundan" a nesnesi bırakılamadı "iletisini alırsınız. hata.


2
Doğru, ama çözüm yok. Çocuğun masaları çevirmek için yabancı anahtarları olabilir ve / veya ilk etapta düşürmek istemeyebilirsiniz.
MaR

4
Doğru ve hedef, "Veritabanımdaki tüm tabloları silmek istiyorum ..."
Philip Kelley

4
sorgulayanın "veri
tabanımdaki

17

sp_MSdropconstraintsYordamı kullanarak tüm tabloları doğru bir şekilde bırakmanın başka bir yolu . Aklıma gelen en kısa kod:

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

Awesome man ............
edCoder

2

SQL Server ise, tabloyu bırakmadan önce kısıtlamayı bırakmanız gerekir.


2

@Mark_s'ın yayınladığı şeyin biraz daha genel bir sürümü, bu bana yardımcı oldu

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')

sadece tablo adınızı takın ve sonucunu yürütün.


1
Merhaba, Yukarıdaki benim yabancı anahtar kısıtlamaları düşürmek için çalışıyorum, ama daha sonra bir tablo bıraktığınızda, "Nesne düşürülemedi çünkü hala bir yabancı anahtar kısıtlaması tarafından başvuruluyor ... Şimdiden teşekkürler
daniness

1

İşte bir kısıtlama hilesi kullanarak tabloların ardından gelen tüm kısıtlamaları silmenin başka bir yolu FOR XML PATH('') birden çok giriş satırının tek bir çıkış satırında birleştirilmesine izin veren . SQL 2005 ve üzeri herhangi bir şey üzerinde çalışmalıdır.

Ben EXECUTE komutları güvenlik için yorum yaptı bıraktım.

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)

Tüm FK bırakılmayacağı için bu iyi çalışmaz (yalnızca tablolarımızın üst öğe olarak kullanıldığı yerler, burada da tablonuzun "referans" olarak kullanıldığı yerde kısıtlama bırakmamız gerekir).
Roman Pokrovskij

Roman, orijinal yazı yabancı anahtar kısıtlamalarını silmekle ilgili. Cevabım bunun ötesinde hiçbir şeyi kapsamayı amaçlamıyor.
Warren Rumak

1

İşte bir çözüm uygulamak için tam bir komut dosyası:

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

SQL Server Manager'ı kullanarak kullanıcı arayüzünden yabancı anahtar kısıtlamaları bırakabilirsiniz. Tabloyu silmek istiyorsanız, Diaryancak Kullanıcı tablosunda tabloya DiaryIdişaret eden bir yabancı anahtar Diaryvarsa , tabloyu genişletebilir (artı sembolünü kullanarak) Userve sonra Foreign Keysbölümü genişletebilirsiniz . Günlük tablosunu gösteren yabancı tuşa sağ tıklayın ve ardından öğesini seçin Delete. Daha sonra Columnsbölümü genişletebilir , sütunu sağ tıklayıp silebilirsiniz DiaryId. Sonra sadece çalıştırabilirsiniz:

drop table Diary

Asıl sorunuzun tüm tabloları silmekle ilgili olduğunu biliyorum, bu yüzden bu durum için yararlı olmayabilir. Ancak, sadece birkaç tablo silmek istiyorsanız bu yararlı olduğunu düşünüyorum (başlık açıkça tüm tabloları silme bahsetmiyor).


0

Bir mysql sunucusundaysanız ve tablolarınızı kaybetmenin bir sakıncası yoksa, aynı anda birden çok tabloyu silmek için basit bir sorgu kullanabilirsiniz:

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

Bu şekilde sorgunuzda tabloyu hangi sırayla kullandığınız önemli değildir.

Eğer birçok tablo içeren bir veritabanınız varsa, bunun iyi bir çözüm olmadığı gerçeği hakkında bir şeyler söyleyecek olursa: Kabul ediyorum!


AnladımIncorrect syntax near '='. (102) (SQLExecDirectW)
Matt

@Matt Bu hatayı hangi '=' aldığınızı tahmin etmek biraz zor.
Els den Iep

3
foreign_key_checksMSSQL sunucusunda çalışmaz. Bence bu MySql'e özgü bir değişken.
ooXei1sh

1
@ ooXei1sh MSSQL üzerinde değil. Bu yüzden yazımın başında "MYSQL sunucusuysanız" diyorum.
Els den Iep

0

bırakma işleminizi engelleyen yabancı anahtar kısıtlama adını almak için aşağıdaki kodu yürütün. Mesela rolesmasayı alıyorum .

      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'

FK adını aşağıdaki gibi bir şey alırsınız: FK__Table1__roleId__1X1H55C1

şimdi yukarıdan alınan FK referansını kaldırmak için aşağıdaki kodu çalıştırın.

ALTER TABLE dbo.users drop CONSTRAINT FK__Table1__roleId__1X1H55C1;

Bitti!


-4

Veritabanımdaki tüm tabloları silmek istersem

Sonra tüm veritabanını bırakmak çok daha kolay:

DROP DATABASE WorkerPensions

71
Bunun için -1 vermek, iki önemli nedenden dolayı sorunun geçerli bir cevabı değildir: 1) Tablolardan çok daha fazlasını siler! Saklı yordamlar, işlevler, UDT'ler, güvenlik, .NET derlemeleri vb. Bir DROP DATABASE ile ortadan kalkar. 2) Veritabanları oluşturmanıza izin verilmeyebilir, örneğin, veritabanlarının BT tarafından sağlandığı ve farkında olmadığınız oluşturma zamanında ek gereksinimlere sahip olduğu merkezi olarak yönetilen geliştirme ortamı.
Warren Rumak

-4

DROPYabancı anahtar kullanımı kullanılarak başka bir tablo tarafından başvurulan bir tablo istiyorsanız

DROP TABLE *table_name* CASCADE CONSTRAINTS;
Bence senin için işe yaramalı.


1
Hiçbir yoktur cascade constraintssql sunucusunda
JackyJohnson
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.