2

I've list of tables (around 100++) that need to be dropped from SQL Server. Below is the sample code that I would use

IF OBJECT_ID('dbo.DS_Area_TBL', 'U') IS NOT NULL
drop table dbo.DS_Area_TBL
Print 'dbo.DS_Area_TBL has been dropped'

I need to replace table name 100++ time with other table name. How to write a dynamic sql script that can auto generate list of queries?

jarlh
  • 42,561
  • 8
  • 45
  • 63
user664481
  • 2,141
  • 9
  • 25
  • 31

2 Answers2

3
DECLARE @SQL NVARCHAR(MAX)

SELECT @SQL = (
    SELECT '
IF OBJECT_ID(''' + obj + ''', ''U'') IS NOT NULL BEGIN
    DROP TABLE ' + obj + '
    PRINT ''' + obj + ' has been dropped''
END
'
    FROM (
        SELECT obj = QUOTENAME(s.name) + '.' + QUOTENAME(o.name)
        FROM sys.objects o
        JOIN sys.schemas s ON o.[schema_id] = s.[schema_id]
        WHERE o.[type] = 'U'
            --AND o.name LIKE 'table%'
            --AND s.name IN ('dbo')
    ) t
    FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')

PRINT @SQL
--EXEC sys.sp_executesql @SQL

Output -

IF OBJECT_ID('[dbo].[user_data]', 'U') IS NOT NULL BEGIN
    DROP TABLE [dbo].[user_data]
    PRINT '[dbo].[user_data] has been dropped'
END

IF OBJECT_ID('[dbo].[formatter_options]', 'U') IS NOT NULL BEGIN
    DROP TABLE [dbo].[formatter_options]
    PRINT '[dbo].[formatter_options] has been dropped'
END
Devart
  • 119,203
  • 23
  • 166
  • 186
2

You could first generate script then execute with dynamic sql:

CREATE TABLE a(a INT);
CREATE TABLE b(a INT);
CREATE TABLE c(a INT);
CREATE TABLE d(a INT);
CREATE TABLE e(a INT);

CREATE TABLE tab(tab_name SYSNAME);   -- here are table names stored
INSERT INTO tab VALUES ('a'),('b'),('c'),('d'),('e');


-- main part
DECLARE @sql NVARCHAR(MAX);

SELECT @sql = STUFF((SELECT ' ' +  FORMATMESSAGE(
'IF OBJECT_ID(''%s'', ''U'') IS NOT NULL 
BEGIN
   DROP TABLE %s;
   PRINT ''%s has been dropped '';
END
', QUOTENAME(tab_name),QUOTENAME(tab_name),QUOTENAME(tab_name))
                   FROM tab
                   FOR XML PATH('')), 1, 1, '');

PRINT @sql;   -- for debug

EXEC [dbo].[sp_executesql]
    @sql;

If you use version of SQL Server lower than 2012 you need to change FORMATMESSAGE with string concatenation +.

You could easily extend this script with custom schema and so on by modifying template:

'IF OBJECT_ID(''%s'', ''U'') IS NOT NULL 
    BEGIN
       DROP TABLE %s;
       PRINT ''%s has been dropped '';
    END
'

Output:

IF OBJECT_ID('[a]', 'U') IS NOT NULL 
BEGIN
   DROP TABLE [a];
   PRINT '[a] has been dropped ';
END
 IF OBJECT_ID('[b]', 'U') IS NOT NULL 
BEGIN
   DROP TABLE [b];
   PRINT '[b] has been dropped ';
END
 IF OBJECT_ID('[c]', 'U') IS NOT NULL 
BEGIN
   DROP TABLE [c];
   PRINT '[c] has been dropped ';
END
 IF OBJECT_ID('[d]', 'U') IS NOT NULL 
BEGIN
   DROP TABLE [d];
   PRINT '[d] has been dropped ';
END
 IF OBJECT_ID('[e]', 'U') IS NOT NULL 
BEGIN
   DROP TABLE [e];
   PRINT '[e] has been dropped ';
END

EDIT:
How it works:

  1. XML + STUFF for string concatenation is common idiom with SQL Server, works like GROUP_CONCAT in MySQL. You can think about it as a way to combine multiple IF BEGIN END chunks into one string.
  2. FORMATMESSAGE will replace %s with actual table names(quoted to avoid SQL Injection attacks)
  3. PRINT is for debug to check generated query, can be commented
  4. sp_executesql will execute SQL string
Lukasz Szozda
  • 162,964
  • 23
  • 234
  • 275
  • 2
    Quoting is a very appreciated ;) – Devart Jan 11 '16 at 11:31
  • Thanks for the answer !!! Would you mind explain to me how actually this statement generate the code ? STUFF((SELECT ' ' + FORMATMESSAGE( 'IF OBJECT_ID(''%s'', ''U'') IS NOT NULL BEGIN DROP TABLE %s; PRINT ''%s has been dropped ''; END ', QUOTENAME(tab_name),QUOTENAME(tab_name),QUOTENAME(tab_name)) FROM tab FOR XML PATH('')), 1, 1, ''); – user664481 Jan 11 '16 at 13:51