SQL DROP TABLE Fremdschlüsseleinschränkung

154

Wenn ich alle Tabellen in meiner Datenbank auf diese Weise löschen möchte, wird dann die Fremdschlüsseleinschränkung berücksichtigt? Wenn nicht, wie kümmere ich mich zuerst darum?

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]
Sam
quelle
2
Überprüfen Sie diese Antwort, es hat mir geholfen;) stackoverflow.com/a/5488670/2205144
xatz

Antworten:

335

Nein, dies wird Ihre Tabelle nicht löschen, wenn tatsächlich Fremdschlüssel darauf verweisen.

Um alle Fremdschlüsselbeziehungen abzurufen, die auf Ihre Tabelle verweisen, können Sie dieses SQL verwenden (wenn Sie SQL Server 2005 oder höher verwenden):

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

und wenn es welche gibt, können Sie mit dieser Anweisung hier SQL-Anweisungen erstellen, um diese FK-Beziehungen tatsächlich zu löschen:

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')
marc_s
quelle
Hinweis: Die generierte Tabelle enthält die Anweisungen zum Löschen der einzelnen Einschränkungen, die in einer anderen Abfrage ausgeführt werden sollen. In meinem Fall wirkte es Wunder, da ich eine nutzlose Tabelle (zu Testzwecken) entfernen musste, während der Rest der Tabellen, an denen FK vorhanden war, intakt blieb.
Mauricio Quintana
1
Ich musste parent_object_id anstelle von referenced_object_id verwenden
Tom Robinson
2
Eine Alternative zur SELECT-Anweisung zum Abrufen aller Referenzierungstabellen ist: EXEC sp_fkeys 'Student';
Buggieboy
kleine Anpassung dieser Abfrage 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') replace [name] mit dem Namen CONSTRAINT
Stas Svishov
1
Wie ordne ich deine letzte Auswahl als Variable zu und führe sie aus?
Hrvoje T
44

In SQL Server Management Studio 2008 (R2) und höher können Sie mit der rechten Maustaste auf klicken

DB -> Aufgaben -> Skripte generieren

  • Wählen Sie die Tabellen aus, die Sie fallen lassen möchten.

  • Wählen Sie "In neuem Abfragefenster speichern".

  • Klicken Sie auf die Schaltfläche Erweitert.

  • Setzen Sie Script DROP und CREATE auf Script DROP.

  • Setzen Sie Script Foreign Keys auf True.

  • OK klicken.

  • Klicken Sie auf Weiter -> Weiter -> Fertig stellen.

  • Zeigen Sie das Skript an und führen Sie es aus.

Riaan
quelle
12
immer noch das gleiche 'Objekt' my_table 'konnte nicht gelöscht werden, da es durch eine FOREIGN KEY-Einschränkung referenziert wird.
FrenkyB
6
Wie diese Antwort 28 + Bewertung hat, ist mir ein
Rätsel
1
Während das Skript generiert wird, löst dieses Skript das Problem nicht. Dabei wird die Tabelle gelöscht, auf die durch Fremdschlüsseleinschränkungen verwiesen wird.
Alexey Shevelyov
Arbeitete wie ein Zauber für mich.
Johan
21

Wenn Sie zuerst die "untergeordnete" Tabelle löschen, wird auch der Fremdschlüssel gelöscht. Wenn Sie versuchen, die "übergeordnete" Tabelle zuerst zu löschen, erhalten Sie die Meldung "Objekt 'a' konnte nicht gelöscht werden, da es durch eine FOREIGN KEY-Einschränkung referenziert wird." Error.

Philip Kelley
quelle
2
Stimmt, aber keine Lösung. Das Kind kann Fremdschlüssel für andere Tabellen haben und / oder Sie möchten diese möglicherweise gar nicht erst löschen.
MaR
4
Richtig, und eine Lösung, wenn das Ziel wie angegeben lautet: "Wenn ich alle Tabellen in meiner Datenbank löschen möchte ..."
Philip Kelley
4
Dies ist eine viel bessere Antwort als die akzeptierte, da der Fragesteller "alle Tabellen in meiner Datenbank löschen" möchte
lukkea
17

Hier ist eine andere Möglichkeit, alle Tabellen mithilfe der sp_MSdropconstraintsProzedur korrekt zu löschen. Der kürzeste Code, den ich mir vorstellen kann:

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

Wenn es sich um SQL Server handelt, müssen Sie die Einschränkung löschen, bevor Sie die Tabelle löschen können.

Shiraz Bhaiji
quelle
2

Etwas allgemeinere Version von dem, was @mark_s gepostet hat, das hat mir geholfen

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

Stecken Sie einfach Ihren Tabellennamen ein und führen Sie das Ergebnis aus.

Stas Svishov
quelle
1
Hallo, ich habe versucht, meine Fremdschlüsseleinschränkungen durch das oben Gesagte zu löschen, aber wenn ich danach eine Tabelle lösche, heißt es immer wieder: "Das Objekt konnte nicht gelöscht werden, da es immer noch durch eine Fremdschlüsseleinschränkung referenziert wird ...
Irgendwelche
1

Hier ist eine andere Möglichkeit, alle Einschränkungen, denen die Tabellen selbst folgen, mithilfe eines Verkettungstricks zu löschen, bei FOR XML PATH('')dem mehrere Eingabezeilen in einer einzigen Ausgabezeile zusammengeführt werden. Sollte mit SQL 2005 und höher funktionieren.

Ich habe die EXECUTE-Befehle aus Sicherheitsgründen auskommentiert.

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)
Warren Rumak
quelle
Dies funktioniert nicht gut, da nicht alle FK gelöscht werden (nur diejenigen, bei denen unsere Tabellen als übergeordnetes Element verwendet werden, bei denen wir auch Einschränkungen löschen sollten, bei denen unsere Tabelle als "referenziert" verwendet wurde).
Roman Pokrovskij
Roman, im ursprünglichen Beitrag geht es darum, Fremdschlüsseleinschränkungen zu löschen. Meine Antwort zielt nicht darauf ab, etwas darüber hinaus abzudecken.
Warren Rumak
1

Hier ist ein vollständiges Skript zum Implementieren einer Lösung:

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
Roman Pokrovskij
quelle
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.
CodeTzu
quelle
0

Mit SQL Server Manager können Sie Fremdschlüsseleinschränkungen von der Benutzeroberfläche entfernen. Wenn Sie die Tabelle löschen möchten, Diarydie Benutzertabelle jedoch einen Fremdschlüssel hat DiaryId, der auf die DiaryTabelle verweist, können Sie die Tabelle erweitern (mithilfe des Plus-Symbols) Userund anschließend den Foreign KeysAbschnitt erweitern. Klicken Sie mit der rechten Maustaste auf den Fremdschlüssel, der auf die Tagebuch-Tabelle zeigt, und wählen Sie dann aus Delete. Sie können dann den ColumnsAbschnitt erweitern, mit der rechten Maustaste klicken und die Spalte DiaryIdebenfalls löschen . Dann können Sie einfach laufen:

drop table Diary

Ich weiß, dass Ihre eigentliche Frage das Löschen aller Tabellen betrifft, daher ist dies in diesem Fall möglicherweise nicht hilfreich. Wenn Sie jedoch nur einige Tabellen löschen möchten, ist dies meines Erachtens nützlich (der Titel erwähnt nicht ausdrücklich das Löschen aller Tabellen).

Hazza
quelle
0

Wenn Sie sich auf einem MySQL-Server befinden und es Ihnen nichts ausmacht, Ihre Tabellen zu verlieren, können Sie mit einer einfachen Abfrage mehrere Tabellen gleichzeitig löschen:

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

Auf diese Weise spielt es keine Rolle, in welcher Reihenfolge Sie die Tabelle in Ihrer Abfrage verwenden.

Wenn jemand etwas darüber sagen will, dass dies keine gute Lösung ist, wenn Sie eine Datenbank mit vielen Tabellen haben: Ich stimme zu!

Els den Iep
quelle
Ich bekommeIncorrect syntax near '='. (102) (SQLExecDirectW)
Matt
@Matt Etwas schwer zu erraten, bei welchem ​​'=' dieser Fehler auftritt.
Els den Iep
3
foreign_key_checksfunktioniert nicht auf MSSQL Server. Ich denke, das ist eine MySql-spezifische Variable.
ooXei1sh
1
@ ooXei1sh Nein, nicht unter MSSQL. Deshalb sage ich zu Beginn meines Beitrags: "Wenn Sie sich auf einem MYSQL-Server befinden".
Els den Iep
0

Führen Sie den folgenden Code aus, um den Namen der Fremdschlüsseleinschränkung zu erhalten, der Ihre Ablage blockiert. Zum Beispiel nehme ich den rolesTisch.

      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'

Sie erhalten den FK-Namen wie folgt: FK__Table1__roleId__1X1H55C1

Führen Sie nun den folgenden Code aus, um die von oben erhaltene FK-Referenz zu entfernen.

ALTER TABLE dbo.users drop CONSTRAINT FK__Table1__roleId__1X1H55C1;

Getan!

Jithil
quelle
-4

Wenn ich alle Tabellen in meiner Datenbank löschen möchte

Dann ist es viel einfacher, die gesamte Datenbank zu löschen:

DROP DATABASE WorkerPensions
Andomar
quelle
71
Geben Sie dafür eine -1, da dies aus zwei wichtigen Gründen keine gültige Antwort auf die Frage ist: 1) Es werden viel mehr als nur Tabellen gelöscht! Gespeicherte Prozeduren, Funktionen, UDTs, Sicherheit, .NET-Assemblys usw. werden mit einer DROP-DATENBANK entfernt. 2) Möglicherweise dürfen Sie keine Datenbanken erstellen, z. B. eine zentral verwaltete Entwicklungsumgebung, in der Datenbanken von der IT bereitgestellt werden und zum Zeitpunkt der Erstellung zusätzliche Anforderungen gelten, die Ihnen nicht bekannt sind.
Warren Rumak
-4

Wenn Sie DROPeine Tabelle verwenden möchten, auf die von einer anderen Tabelle mit dem Fremdschlüssel verwiesen wurde, verwenden Sie

DROP TABLE *table_name* CASCADE CONSTRAINTS;
Ich denke, es sollte für dich funktionieren.

Nitish
quelle
1
Es gibt keine cascade constraintsin SQL Server
JackyJohnson