38

By using this statement in SQL Server:

EXEC sp_msforeachtable 'DROP TABLE ?'

I know it's possible to delete all tables at once.

Is there a similar statement for views? I tried this hoping to be lucky: EXEC sp_msforeachview 'DROP VIEW ?' but it doesn't work!

Arulkumar
  • 12,966
  • 14
  • 47
  • 68
Sam
  • 3,067
  • 19
  • 53
  • 55

7 Answers7

78

Here you have, no cursor needed:

DECLARE @sql VARCHAR(MAX) = ''
        , @crlf VARCHAR(2) = CHAR(13) + CHAR(10) ;

SELECT @sql = @sql + 'DROP VIEW ' + QUOTENAME(SCHEMA_NAME(schema_id)) + '.' + QUOTENAME(v.name) +';' + @crlf
FROM   sys.views v

PRINT @sql;
EXEC(@sql);
Yaroslav
  • 6,476
  • 10
  • 48
  • 89
  • If you have a view in another schema (other than dbo) this script will break. – MikeTeeVee Mar 14 '13 at 07:45
  • Also if you have special characters in your names, it will also break. – MikeTeeVee Mar 14 '13 at 07:52
  • 1
    Adding some square brackets will help to deal with spaces, special characters, etc. SELECT @sql=@sql+'DROP VIEW ['+name +'];' FROM sys.views; – user1316401 Apr 03 '13 at 02:21
  • Good point Ric.Net, do you have a suggestion on how to fix it? Some code maybe? That way I can improve my answer so its much more general and suit more cases – Yaroslav Nov 06 '14 at 21:52
  • Sorry to say @Ric.Net , ran couple of tests, doesn't matter if there are nested views, all will be dropped, no matter the order the `DROP` is run. Modified to take care of schemas. – Yaroslav Nov 06 '14 at 22:53
  • 1
    It depends, if you use 'Bind to Schema' you will run into trouble... See my [answer](http://stackoverflow.com/a/26797842/3294832) for a solution – Ric .Net Nov 07 '14 at 09:14
  • 1
    I love the simplicity of this over the various other looping solutions here, it might not be perfect but I still think it's great! Thanks for sharing. – Simon May 03 '17 at 22:16
10
declare @SQL nvarchar(max)

set @SQL = 
  (
  select 'drop view '+name+'; '
  from sys.views
  for xml path('')
  )

exec (@SQL)
Mikael Eriksson
  • 136,425
  • 22
  • 210
  • 281
5

I wanted a script to drop schema bound views in the correct dependency order, and I wanted it to run on sql azure where sys.dm_sql_referencing_entities is not available. I also wanted to be able to view the sql being run before I actually ran it - which you can't do with the script in the answer by @RicNet. So I wrote this recursive query that use the other answers here as a foundation

DECLARE @sql VARCHAR(MAX) = ''
DECLARE @crlf VARCHAR(2) = CHAR(13) + CHAR(10);

;WITH allviews as
( --just combining schema and name
SELECT
    object_id,
    '[' + SCHEMA_NAME(schema_id) + '].[' + name + ']' AS viewname
FROM sys.views
),
dependents AS
( 
SELECT
    referencing.viewname dependentname,
    referenced.viewname dependenton
FROM sys.sql_expression_dependencies r
    INNER JOIN allviews referencing
        ON referencing.object_id = r.referencing_id
    INNER JOIN allviews referenced
        ON referenced.object_id = r.referenced_id
)
,
nodependents 
AS
( 
SELECT
    viewname name
FROM allviews v
    LEFT JOIN dependents d
        ON d.dependentname = viewname
WHERE d.dependentname IS NULL
)
,hierarchy AS
( --the hierarchy recurses the dependencies
SELECT
    d.dependenton,
    d.dependentname,
    1 tier
FROM dependents d UNION ALL SELECT
    d.dependenton,
    d.dependentname,
    h.tier + 1
FROM dependents d
    INNER JOIN hierarchy h
        ON h.dependenton = d.dependentname
--best thing I could think to stop the recursion was to 
--stop when we reached an item with no dependents       
WHERE h.dependenton NOT IN (SELECT
    name
FROM nodependents)
    ),
combined as
( --need to add item with no dependents back in
SELECT
    0 tier,
    name
FROM nodependents UNION SELECT
    tier,
    dependentname
FROM hierarchy  
)
SELECT
    @sql = @sql + 'DROP VIEW ' + name + ';' + @crlf
FROM combined
GROUP BY name --need to group because of multiple dependency paths
ORDER BY MAX(tier) desc

PRINT @sql;

--commented out until I'm confident I want to run it
--EXEC(@sql)
Colin
  • 22,328
  • 17
  • 103
  • 197
4

All answers don't account for constraints between views. This script will take this into account:

SET @schemeName = 'dbo'

SELECT @name = 
(SELECT TOP 1 o.[name] 
 FROM sysobjects o
 inner join sys.views v ON o.id = v.object_id
 WHERE SCHEMA_NAME(v.schema_id) =@schemeName AND o.[type] = 'V' AND o.category = 0 AND o.[name] NOT IN
 (
    SELECT  referenced_entity_name
    FROM sys.sql_expression_dependencies AS sed
    INNER JOIN sys.objects AS o ON sed.referencing_id = o.object_id
    WHERE referenced_schema_name = @schemeName
 )
 ORDER BY [name])

 WHILE @name IS NOT NULL
BEGIN
    SELECT @SQL = 'DROP VIEW [' + @schemeName + '].[' + RTRIM(@name) +']'
    EXEC (@SQL)
    PRINT 'Dropped View: ' + @name
SELECT @name = 
(SELECT TOP 1 o.[name] 
 FROM sysobjects o
 inner join sys.views v ON o.id = v.object_id
 WHERE SCHEMA_NAME(v.schema_id) = @schemeName AND o.[type] = 'V' AND o.category = 0 AND o.[name] NOT IN
 (
    SELECT  referenced_entity_name
    FROM sys.sql_expression_dependencies AS sed
    INNER JOIN sys.objects AS o ON sed.referencing_id = o.object_id
    WHERE referenced_schema_name = @schemeName
 )
 ORDER BY [name])
END
GO

This loops to all views and selects the TOP 1 view that is not present in the references systable.

Ric .Net
  • 5,540
  • 1
  • 20
  • 39
2

Try this script

DECLARE @viewName varchar(500)
DECLARE cur CURSOR
      FOR SELECT [name] FROM sys.objects WHERE type = 'v'
      OPEN cur

      FETCH NEXT FROM cur INTO @viewName
      WHILE @@fetch_status = 0
      BEGIN
            EXEC('DROP VIEW ' + @viewName)
            FETCH NEXT FROM cur INTO @viewName
      END
      CLOSE cur
      DEALLOCATE cur

See here for more info

Prince Jea
  • 5,524
  • 7
  • 28
  • 46
2

But what about schema?
The below script will help you if the views are part of schema

DECLARE @sql VARCHAR(MAX)='';
SELECT @sql=@sql+'DROP VIEW '+name +';' FROM 
(
SELECT Name=[s].name  + '.' + [v].name FROM sys.views [v]
LEFT OUTER JOIN sys.schemas [s]
ON
(
    [v].[schema_id]=[s].[schema_id]
)
)
X
EXEC(@sql)
Appyks
  • 496
  • 3
  • 12
1

Since no one of the scripts I tried from the answers worked correctly in the case of multiple schemas I am including a working one.

--DBNAME, PUT YOU OWN ONE use SIPE_ISU

DECLARE @viewName varchar(500) DECLARE cur CURSOR FOR SELECT sk.name + '.'+so.name FROM sys.objects so inner join sys.schemas sk on sk.schema_id = so.schema_id WHERE type = 'v' OPEN cur FETCH NEXT FROM cur INTO @viewName WHILE @@fetch_status = 0 BEGIN EXEC('DROP VIEW ' + @viewName) FETCH NEXT FROM cur INTO @viewName END CLOSE cur DEALLOCATE cur

A. Lion
  • 673
  • 5
  • 12