Reputation: 11407
I have a bunch of db tables and I want to drop all but one. My script is as follows....however I have created an infinite loop when I run my attempt..
Any ideas how i can do this?
/* Drop all tables */
DECLARE @name VARCHAR(128)
DECLARE @SQL VARCHAR(254)
SELECT @name = (SELECT TOP 1 [name] FROM sysobjects
WHERE [type] = 'U' AND category = 0 ORDER BY [name])
WHILE @name IS NOT NULL
IF @name != 'tableNotToBeDropped'
BEGIN
SELECT @SQL = 'DROP TABLE [dbo].[' + RTRIM(@name) +']'
EXEC (@SQL)
PRINT 'Dropped Table: ' + @name
SELECT @name = (SELECT TOP 1 [name] FROM sysobjects
WHERE [type] = 'U' AND category = 0 AND [name] > @name
ORDER BY [name])
END
GO
Upvotes: 6
Views: 7872
Reputation: 175706
There is no need for loop at all. DROP TABLE
can drop multiple tables with one statement:
DECLARE @tables NVARCHAR(MAX) =
STUFF((SELECT ',' + QUOTENAME([table_name]) AS [text()]
FROM INFORMATION_SCHEMA.TABLES
WHERE table_schema = 'dbo'
AND TABLE_NAME <> 'tableNotToBeDropped'
FOR XML PATH('')),1,1,'');
DECLARE @sql NVARCHAR(MAX) = 'DROP TABLE ' + @tables;
-- debug
SELECT @sql;
EXEC sp_executesql @sql;
How it works:
Keep in mind that if your tables have defined foreign keys the order of dropping matters.
SQL Server 2017 version:
DECLARE @sql NVARCHAR(MAX) = 'DROP TABLE IF EXISTS '
+ (SELECT string_agg(QUOTENAME(table_name), ',')
FROM INFORMATION_SCHEMA.TABLES
WHERE table_schema = 'dbo'
AND TABLE_NAME <> 'tableNotToBeDropped'
AND TABLE_NAME LIKE 't%');
SELECT @sql;
EXEC sp_executesql @sql;
Upvotes: 12
Reputation: 15175
This one liner also works:
sp_MSforeachtable @command1='IF OBJECT_ID(''?'') NOT IN (OBJECT_ID(''TableToNotDelete'')) DROP TABLE ?'
Upvotes: 1
Reputation: 3993
I suggest you use a cursor instead and add the name not equals to the where clause of the cursor query.
http://www.kodyaz.com/articles/sql-cursor-example-tables-rows-count-using-sql-server-cursor.aspx
Upvotes: 0