Contrainte de clé étrangère SQL DROP TABLE


154

Si je veux supprimer toutes les tables de ma base de données de cette manière, prendra-t-il en charge la contrainte de clé étrangère? Sinon, comment puis-je m'en occuper en premier?

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
Vérifiez cette réponse, cela m'a aidé;) stackoverflow.com/a/5488670/2205144
xatz

Réponses:


335

Non, cela ne supprimera pas votre table s'il existe effectivement des clés étrangères la référençant.

Pour obtenir toutes les relations de clé étrangère faisant référence à votre table, vous pouvez utiliser ce SQL (si vous utilisez SQL Server 2005 et versions ultérieures):

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

et s'il y en a, avec cette instruction ici, vous pouvez créer des instructions SQL pour supprimer ces relations 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')

Remarque: la table générée contient les instructions pour supprimer les contraintes individuelles à exécuter dans une requête différente. Cela a fonctionné à merveille dans mon cas, car je devais me débarrasser d'une table inutile (à des fins de test) tout en conservant le reste des tables contenant FK intact.
Mauricio Quintana

1
J'ai dû utiliser parent_object_id au lieu de referenced_object_id
Tom Robinson

2
Une alternative à l'instruction SELECT pour obtenir toutes les tables de référence est: EXEC sp_fkeys 'Student';
Buggieboy

petit ajustement cette requête SELECT 'ALTER TABLE' + OBJECT_SCHEMA_NAME (parent_object_id) + '. [' + OBJECT_NAME (parent_object_id) + '] DROP CONSTRAINT [nom]' FROM sys.foreign_keys WHERE referenced_object_id = object_id ('Student') replace [nom] avec le nom CONSTRAINT
Stas Svishov

1
Comment affecter votre dernière sélection en tant que variable et l'exécuter?
Hrvoje T

44

Dans SQL Server Management Studio 2008 (R2) et plus récent, vous pouvez faire un clic droit sur le

DB -> Tâches -> Générer des scripts

  • Sélectionnez les tables que vous souhaitez SUPPRIMER.

  • Sélectionnez "Enregistrer dans une nouvelle fenêtre de requête".

  • Cliquez sur le bouton Avancé.

  • Définissez Script DROP et CREATE sur Script DROP.

  • Définissez les clés étrangères de script sur True.

  • Cliquez sur OK.

  • Cliquez sur Suivant -> Suivant -> Terminer.

  • Affichez le script, puis exécutez.


12
toujours le même 'Impossible de supprimer l'objet' ma_table 'car il est référencé par une contrainte FOREIGN KEY.
FrenkyB

6
Comment cette réponse a une note de 28 + me dépasse ... ne fonctionne toujours pas
mec

1
Bien qu'il génère le script - ce script ne résout pas le problème, ce qui est de supprimer la table référencée par les contraintes de clé étrangère.
Alexey Shevelyov

A fonctionné à merveille pour moi.
Johan le

21

Si vous supprimez d'abord la table «enfant», la clé étrangère sera également supprimée. Si vous essayez d'abord de supprimer la table "parent", vous obtiendrez un message "Impossible de supprimer l'objet 'a' car il est référencé par une contrainte FOREIGN KEY." Erreur.


2
C'est vrai, mais pas de solution. L'enfant peut avoir des clés étrangères vers d'autres tables et / ou vous ne voudrez peut-être pas le supprimer en premier lieu.
MaR

4
Vrai, et une solution si l'objectif est, comme indiqué, "Si je veux supprimer toutes les tables de ma base de données ..."
Philip Kelley

4
c'est une bien meilleure réponse que celle acceptée, étant donné que l'
interlocuteur

17

Voici une autre façon de supprimer toutes les tables correctement, en utilisant la sp_MSdropconstraintsprocédure. Le code le plus court auquel je puisse penser:

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

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

2

S'il s'agit de SQL Server, vous devez supprimer la contrainte avant de pouvoir supprimer la table.


2

Version légèrement plus générique de ce que @mark_s a publié, cela m'a aidé

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

branchez simplement le nom de votre table et exécutez le résultat.


1
Salut, j'ai essayé de supprimer mes contraintes de clé étrangère par ce qui précède, mais quand je vais supprimer une table par la suite, il continue à dire "Impossible de supprimer l'objet car il est toujours référencé par une contrainte de clé étrangère ... des idées? Merci d'avance.
daniness

1

Voici une autre façon de supprimer toutes les contraintes suivies par les tables elles-mêmes, en utilisant une astuce de concaténation impliquant FOR XML PATH('')qui permet de fusionner plusieurs lignes d'entrée en une seule ligne de sortie. Devrait fonctionner sur quoi que ce soit SQL 2005 et plus tard.

J'ai laissé les commandes EXECUTE commentées pour des raisons de sécurité.

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)

Cela ne fonctionne pas bien car tous les FK ne seront pas supprimés (uniquement ceux où nos tables sont utilisées comme parent, où nous devrions également supprimer la contrainte où notre table a été utilisée comme "référencée").
Roman Pokrovskij

Roman, l'article original concerne la suppression des contraintes de clé étrangère. Ma réponse ne vise pas à couvrir autre chose.
Warren Rumak

1

Voici un script complet pour implémenter une solution:

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

À l'aide de SQL Server Manager, vous pouvez supprimer les contraintes de clé étrangère de l'interface utilisateur. Si vous souhaitez supprimer la table Diarymais que la table User a une clé étrangère DiaryIdpointant vers la Diarytable, vous pouvez développer (à l'aide du symbole plus) la Usertable, puis développer la Foreign Keyssection. Cliquez avec le bouton droit de la souris sur la clé étrangère qui pointe vers le tableau du journal, puis sélectionnez Delete. Vous pouvez ensuite développer la Columnssection, cliquer avec le bouton droit de la souris et supprimer la colonne DiaryIdégalement. Ensuite, vous pouvez simplement exécuter:

drop table Diary

Je sais que votre question réelle concerne la suppression de toutes les tables, donc cela peut ne pas être utile dans ce cas. Cependant, si vous souhaitez simplement supprimer quelques tables, c'est utile, je pense (le titre ne mentionne pas explicitement la suppression de toutes les tables).


0

Si vous êtes sur un serveur mysql et que cela ne vous dérange pas de perdre vos tables, vous pouvez utiliser une simple requête pour supprimer plusieurs tables à la fois:

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

De cette façon, l'ordre dans lequel vous utilisez la table dans votre requête n'a pas d'importance.

Si quelqu'un veut dire quelque chose sur le fait que ce n'est pas une bonne solution si vous avez une base de données avec de nombreuses tables: je suis d'accord!


Je reçoisIncorrect syntax near '='. (102) (SQLExecDirectW)
Matt

@Matt Bit difficile de deviner à quel '=' vous obtenez cette erreur.
Els den Iep

3
foreign_key_checksne fonctionnera pas sur le serveur MSSQL. Je pense que c'est une variable spécifique à MySql.
ooXei1sh

1
@ ooXei1sh Non pas sur MSSQL. C'est pourquoi je dis au début de mon message: "Si vous êtes sur un serveur MYSQL".
Els den Iep

0

exécutez le code ci-dessous pour obtenir le nom de la contrainte de clé étrangère qui bloque votre dépôt. Par exemple, je prends la rolestable.

      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'

vous obtiendrez le nom FK comme ci-dessous: FK__Table1__roleId__1X1H55C1

exécutez maintenant le code ci-dessous pour supprimer la référence FK obtenue par le haut.

ALTER TABLE dbo.users drop CONSTRAINT FK__Table1__roleId__1X1H55C1;

Terminé!


-4

Si je veux supprimer toutes les tables de ma base de données

Ensuite, il est beaucoup plus facile de supprimer toute la base de données:

DROP DATABASE WorkerPensions

71
Vous donner un -1 pour cela car ce n'est pas une réponse valide à la question, pour deux raisons importantes: 1) Cela supprime beaucoup plus que des tableaux! Les procédures stockées, les fonctions, les UDT, la sécurité, les assemblys .NET, etc. disparaissent tous avec une DROP DATABASE. 2) Il se peut que vous ne soyez pas autorisé à créer des bases de données, par exemple un environnement de développement géré de manière centralisée dans lequel les bases de données sont provisionnées par le service informatique et ont des exigences supplémentaires au moment de la création dont vous n'avez pas connaissance.
Warren Rumak

-4

Si vous voulez DROPune table qui a été référencée par une autre table à l'aide de la clé étrangère, utilisez

DROP TABLE *table_name* CASCADE CONSTRAINTS;
Je pense que cela devrait fonctionner pour vous.


1
il n'y a pas cascade constraintsde serveur SQL
JackyJohnson
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.