166

If I want to delete all the tables in my database like this, will it take care of the foreign key constraint? If not, how do I take care of that first?

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
  • 6,961
  • 15
  • 44
  • 63

14 Answers14

359

No, this will not drop your table if there are indeed foreign keys referencing it.

To get all foreign key relationships referencing your table, you could use this SQL (if you're on SQL Server 2005 and up):

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

and if there are any, with this statement here, you could create SQL statements to actually drop those FK relations:

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')
Community
  • 1
  • 1
marc_s
  • 675,133
  • 158
  • 1,253
  • 1,388
  • 1
    Note: the generated table contains the statements to delete the individual constraints to be run in a different query. It worked wonders in my case since I needed to get rid of an useless table (for testing purposes) while maintaining the rest of the tables that had FK to it intact. – Mauricio Quintana Jul 24 '13 at 18:07
  • 1
    I had to use parent_object_id instead of referenced_object_id – Tom Robinson Feb 03 '15 at 14:03
  • 2
    An alternative to the SELECT statement for getting all referencing tables is: EXEC sp_fkeys 'Student'; – Buggieboy May 15 '15 at 21:03
  • small adjustment this query 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] with CONSTRAINT name – Stas Svishov Jun 09 '15 at 12:55
  • works good thanks. (I got an error because I needed to put foreign key name into [ ] . ) – Vlad May 14 '16 at 10:59
  • Great solution marc_s. Alternatively one could use (not as nice, but easy to execute): `SET foreign_key_checks = 0; DROP TABLE IF EXISTS table_a,table_b,table_c,table_etc; SET foreign_key_checks = 1;` In this way it doesn't matter in what order you use the tables in your query. – Els den Iep Aug 08 '16 at 14:22
  • 2
    How to assign your last select as a variable and execute it? – Hrvoje T Mar 27 '19 at 13:24
45

In SQL Server Management Studio 2008 (R2) and newer, you can Right Click on the

DB -> Tasks -> Generate Scripts

  • Select the tables you want to DROP.

  • Select "Save to new query window".

  • Click on the Advanced button.

  • Set Script DROP and CREATE to Script DROP.

  • Set Script Foreign Keys to True.

  • Click OK.

  • Click Next -> Next -> Finish.

  • View the script and then Execute.

Stephan Bauer
  • 8,103
  • 4
  • 34
  • 56
Riaan
  • 589
  • 4
  • 2
24

If you drop the "child" table first, the foreign key will be dropped as well. If you attempt to drop the "parent" table first, you will get an "Could not drop object 'a' because it is referenced by a FOREIGN KEY constraint." error.

Philip Kelley
  • 37,039
  • 10
  • 52
  • 87
  • 3
    True, but no solution. Child can have foreign keys to oher tables and/or you might not want to drop it in the first place. – MaR Nov 21 '09 at 18:17
  • 4
    True, and a solution if the goal is, as stated, "If I want to delete all the tables in my database..." – Philip Kelley Nov 23 '09 at 02:25
  • 4
    this is a much better answer than the accepted one, given that the questioner wants to "delete all the tables in my database" – lukkea Jan 23 '12 at 08:43
19

Here is another way to drop all tables correctly, using sp_MSdropconstraints procedure. The shortest code I could think of:

exec sp_MSforeachtable "declare @name nvarchar(max); set @name = parsename('?', 1); exec sp_MSdropconstraints @name";
exec sp_MSforeachtable "drop table ?";
Krait
  • 191
  • 1
  • 2
  • 1
    This answers the original question "If I want to delete all the tables in my database" really with the help of this simple 2 lines. At least for my SQLServer 2019. Thanks. – Dominik Dec 03 '20 at 11:10
2

If it is SQL Server you must drop the constraint before you can drop the table.

Shiraz Bhaiji
  • 60,773
  • 31
  • 133
  • 239
2

Slightly more generic version of what @mark_s posted, this helped me

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

just plug your table name, and execute the result of it.

Stas Svishov
  • 491
  • 2
  • 5
  • 16
  • 1
    Hi, I've been trying to drop my foreign key constraints by the above, but when I go to drop a table afterwards, it keeps saying "Could not drop the object because it still is being referenced by a Foreign Key constraint...any ideas? Thanks in advance. – daniness Dec 12 '17 at 19:11
1

Here's another way to do delete all the constraints followed by the tables themselves, using a concatenation trick involving FOR XML PATH('') which allows merging multiple input rows into a single output row. Should work on anything SQL 2005 & later.

I've left the EXECUTE commands commented out for safety.

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
  • 3,666
  • 20
  • 30
  • This doesn't work well because of not all FK will be dropped (only those where our tables is used as parent, where we should drop also constraint where our table was used as "referenced" ). – Roman Pokrovskij Dec 27 '13 at 10:05
  • Roman, the original post is about deleting foreign key constraints. My answer doesn't aim to cover anything beyond that. – Warren Rumak Dec 27 '13 at 13:56
1

Here is a complete script to implement a 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
David Hoelzer
  • 14,530
  • 4
  • 39
  • 61
Roman Pokrovskij
  • 7,969
  • 14
  • 68
  • 119
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
  • 11
  • 3
0

Using SQL Server Manager you can drop foreign key constraints from the UI. If you want to delete the table Diary but the User table has a foreign key DiaryId pointing to the Diary table, you can expand (using the plus symbol) the User table and then expand the Foreign Keys section. Right click on the foreign key that points to the diary table then select Delete. You can then expand the Columns section, right click and delete the column DiaryId too. Then you can just run:

drop table Diary

I know your actual question is about deleting all tables, so this may not be a useful for that case. However, if you just want to delete a few tables this is useful I believe (the title does not explicitly mention deleting all tables).

Hazza
  • 6,023
  • 3
  • 21
  • 35
0

execute the below code to get the foreign key constraint name which blocks your drop. For example, I take the roles table.

      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'

you will get the FK name something as below : FK__Table1__roleId__1X1H55C1

now run the below code to remove the FK reference got from above.

ALTER TABLE dbo.users drop CONSTRAINT FK__Table1__roleId__1X1H55C1;

Done!

jithil
  • 651
  • 6
  • 8
-1

If you are on a mysql server and if you don't mind loosing your tables, you can use a simple query to delete multiple tables at once:

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

In this way it doesn't matter in what order you use the table in you query.

If anybody is going to say something about the fact that this is not a good solution if you have a database with many tables: I agree!

Els den Iep
  • 256
  • 2
  • 13
-5

If you want to DROP a table which has been referenced by other table using the foreign key use

DROP TABLE *table_name* CASCADE CONSTRAINTS;
I think it should work for you.

Musakkhir Sayyed
  • 6,208
  • 13
  • 37
  • 60
Nitish
  • 1
-8

If I want to delete all the tables in my database

Then it's a lot easier to drop the entire database:

DROP DATABASE WorkerPensions
Andomar
  • 216,619
  • 41
  • 352
  • 379
  • 74
    Giving you a -1 for this as it is not a valid answer to the question, for two important reasons: 1) It deletes a lot more than tables! Stored procedures, functions, UDTs, security, .NET assemblies, etc. all go away with a DROP DATABASE. 2) You may not be allowed to create databases, e.g. centrally-managed dev environment where databases are provisioned by IT and have additional requirements at create-time that you aren't aware of. – Warren Rumak Dec 12 '13 at 21:30