Vincolo chiave esterna SQL DROP TABLE


154

Se voglio eliminare tutte le tabelle nel mio database in questo modo, si occuperà del vincolo di chiave esterna? In caso contrario, come posso occuparmene prima?

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
Controllare questa risposta, mi ha aiutato;) stackoverflow.com/a/5488670/2205144
xatz

Risposte:


335

No, questo non lascerà cadere la tua tabella se ci sono davvero chiavi esterne che lo fanno riferimento.

Per ottenere tutte le relazioni di chiave esterna che fanno riferimento alla tabella, è possibile utilizzare questo SQL (se si utilizza SQL Server 2005 e versioni successive):

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

e se ce ne sono, con questa affermazione qui, è possibile creare istruzioni SQL per eliminare effettivamente quelle relazioni FK:

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

Nota: la tabella generata contiene le istruzioni per eliminare i singoli vincoli da eseguire in una query diversa. Nel mio caso ha funzionato a meraviglia poiché avevo bisogno di sbarazzarmi di una tabella inutile (a scopo di test) mantenendo intatto il resto delle tabelle che avevano FK.
Mauricio Quintana,

1
Ho dovuto usare parent_object_id invece di referenced_object_id
Tom Robinson,

2
Un'alternativa all'istruzione SELECT per ottenere tutte le tabelle di riferimento è: EXEC sp_fkeys 'Student';
Buggieboy,

piccola regolazione questa query SELEZIONA 'ALTER TABLE' + OBJECT_SCHEMA_NAME (parent_object_id) + '. [' + OBJECT_NAME (parent_object_id) + '] DROP CONSTRAINT [nome]' DA sys.foreign_keys DOVE referenced_object_id = object_id ('Student') sostituisci [nome] con nome
VINCITORE

1
Come assegnare l'ultima selezione come variabile ed eseguirla?
Hrvoje T

44

In SQL Server Management Studio 2008 (R2) e versioni successive, è possibile fare clic con il tasto destro del mouse su

DB -> Attività -> Genera script

  • Seleziona le tabelle che vuoi DROP.

  • Seleziona "Salva nella nuova finestra della query".

  • Fai clic sul pulsante Avanzate.

  • Impostare Script DROP e CREATE su Script DROP.

  • Impostare le chiavi esterne dello script su True.

  • Clicca OK.

  • Fai clic su Avanti -> Avanti -> Fine.

  • Visualizza lo script e quindi Esegui.


12
sempre lo stesso 'Impossibile rilasciare l'oggetto' my_table 'perché a cui fa riferimento un vincolo FOREIGN KEY.
FrenkyB,

6
In che modo questa risposta ha un punteggio di
28+

1
Mentre genera lo script, tale script non risolve il problema, ovvero l'eliminazione della tabella a cui fanno riferimento i vincoli della chiave esterna.
Alexey Shevelyov,

Ha funzionato benissimo per me.
Johan

21

Se si elimina prima la tabella "figlio", anche la chiave esterna verrà eliminata. Se si tenta di eliminare prima la tabella "padre", verrà visualizzato il messaggio "Impossibile rilasciare l'oggetto" a "perché a cui fa riferimento un vincolo FOREIGN KEY". errore.


2
Vero, ma nessuna soluzione. Il bambino può avere chiavi esterne per le sue tabelle e / o potresti non volerlo rilasciare in primo luogo.
MaR

4
Vero, e una soluzione se l'obiettivo è, come affermato, "Se voglio eliminare tutte le tabelle nel mio database ..."
Philip Kelley,

4
questa è una risposta molto migliore di quella accettata, dato che l'interrogante vuole "cancellare tutte le tabelle nel mio database"
lukkea,

17

Ecco un altro modo per eliminare correttamente tutte le tabelle, usando la sp_MSdropconstraintsprocedura. Il codice più breve che mi viene in mente:

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

Uomo fantastico ............
edCoder il

2

Se si tratta di SQL Server, è necessario eliminare il vincolo prima di poter eliminare la tabella.


2

Versione leggermente più generica di ciò che ha pubblicato @mark_s, questo mi ha aiutato

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

basta inserire il nome della tabella ed eseguirne il risultato.


1
Ciao, ho cercato di eliminare i miei vincoli di chiave esterna da quanto sopra, ma quando vado a eliminare una tabella in seguito, continua a dire "Impossibile eliminare l'oggetto perché viene ancora indicato da un vincolo di chiave esterna ... qualche idea? Grazie in anticipo.
daniness

1

Ecco un altro modo per eliminare tutti i vincoli seguiti dalle tabelle stesse, usando un trucco di concatenazione FOR XML PATH('')che consente di unire più righe di input in una singola riga di output. Dovrebbe funzionare su qualsiasi SQL 2005 e versioni successive.

Ho lasciato i comandi EXECUTE commentati per sicurezza.

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)

Questo non funziona bene perché non tutti gli FK verranno eliminati (solo quelli in cui le nostre tabelle vengono utilizzate come parent, dove dovremmo eliminare anche i vincoli in cui la nostra tabella è stata utilizzata come "referenziata").
Roman Pokrovskij,

Romano, il post originale riguarda l'eliminazione dei vincoli di chiave esterna. La mia risposta non mira a coprire nulla oltre a quello.
Warren Rumak,

1

Ecco uno script completo per implementare una soluzione:

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

Utilizzando SQL Server Manager è possibile eliminare i vincoli di chiave esterna dall'interfaccia utente. Se si desidera eliminare la tabella Diaryma la tabella Utente ha una chiave esterna che DiaryIdpunta alla Diarytabella, è possibile espandere (utilizzando il simbolo più) la Usertabella e quindi espandere la Foreign Keyssezione. Fare clic con il tasto destro del mouse sulla chiave esterna che punta alla tabella del diario, quindi selezionare Delete. È quindi possibile espandere la Columnssezione, fare clic con il tasto destro ed eliminare anche la colonna DiaryId. Quindi puoi semplicemente eseguire:

drop table Diary

So che la tua vera domanda riguarda l'eliminazione di tutte le tabelle, quindi questo potrebbe non essere utile per quel caso. Tuttavia, se si desidera eliminare solo alcune tabelle, ciò è utile, credo (il titolo non menziona esplicitamente l'eliminazione di tutte le tabelle).


0

Se sei su un server mysql e se non ti dispiace perdere le tue tabelle, puoi utilizzare una semplice query per eliminare più tabelle contemporaneamente:

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

In questo modo non importa in quale ordine usi la tabella nella tua query.

Se qualcuno dirà qualcosa sul fatto che questa non è una buona soluzione se si dispone di un database con molte tabelle: sono d'accordo!


RicevoIncorrect syntax near '='. (102) (SQLExecDirectW)
Matt,

@Matt Bit difficile indovinare a quale '=' si ottiene quell'errore.
Els den Iep

3
foreign_key_checksnon funzionerà sul server MSSQL. Penso che sia una variabile specifica di MySql.
ooXei1sh,

1
@ ooXei1sh No, non su MSSQL. Ecco perché dico all'inizio del mio post: "Se sei su un server MYSQL".
Els den Iep

0

eseguire il codice seguente per ottenere il nome del vincolo di chiave esterna che blocca il rilascio. Ad esempio, prendo il rolestavolo.

      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'

otterrai il nome FK come di seguito: FK__Table1__roleId__1X1H55C1

ora esegui il codice seguente per rimuovere il riferimento FK ottenuto dall'alto.

ALTER TABLE dbo.users drop CONSTRAINT FK__Table1__roleId__1X1H55C1;

Fatto!


-4

Se voglio cancellare tutte le tabelle nel mio database

Quindi è molto più semplice eliminare l'intero database:

DROP DATABASE WorkerPensions

71
Dandoti un -1 per questo in quanto non è una risposta valida alla domanda, per due motivi importanti: 1) Elimina molto più delle tabelle! Stored procedure, funzioni, UDT, sicurezza, assembly .NET, ecc. Vanno tutti via con un DROP DATABASE. 2) Potrebbe non essere consentito creare database, ad esempio un ambiente di sviluppo gestito centralmente in cui i database sono forniti dall'IT e hanno requisiti aggiuntivi al momento della creazione di cui non si è a conoscenza.
Warren Rumak,

-4

Se si desidera DROPuna tabella a cui fa riferimento un'altra tabella utilizzando la chiave esterna utilizzare

DROP TABLE *table_name* CASCADE CONSTRAINTS;
Penso che dovrebbe funzionare per te.


1
non esiste un cascade constraintsserver sql
JackyJohnson,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.