删除所有数据库中的特定表

时间:2019-09-02 15:22:25

标签: sql-server tsql

我编写了一个脚本,可以从一个数据库中删除特定的表。

-- Declare variable
DECLARE @TableName VARCHAR(MAX)
DECLARE @DbName VARCHAR(MAX)
DECLARE @sql NVARCHAR(MAX)

-- Declare Cursor with Tables and load data into
DECLARE cursor_tables CURSOR FOR SELECT
    [name]
FROM sys.objects o
WHERE o.name LIKE '%bak%'
AND o.name NOT LIKE 'dms%'
AND o.create_date < GETDATE()-60
AND o.type = 'u'

-- Run through cursor
OPEN cursor_tables
FETCH NEXT FROM cursor_tables INTO @TableName

    WHILE @@fetch_status = 0
    BEGIN
        -- Create and run drop statement
        SET @sql = 'drop table ' + QUOTENAME(@TableName)
        EXEC sp_executesql @SQL
        FETCH NEXT FROM cursor_tables INTO @TableName
    END

-- Delete cursor
CLOSE cursor_tables
DEALLOCATE cursor_tables

现在,我想扩展该脚本,以便它从所有数据库中删除这些表。因此,我想将这段代码打包到另一个(嵌套的)游标中以循环遍历。

BEGIN TRY

    -- Declare variable
    DECLARE @TableName NVARCHAR(MAX)
    DECLARE @DbName NVARCHAR(MAX)
    DECLARE @sql NVARCHAR(MAX)
    DECLARE @sql_db NVARCHAR(MAX)

    -- Declare Cursors with databases and load data into
    DECLARE cursor_db CURSOR FOR SELECT 
        name 
    FROM sys.databases d
    WHERE name NOT IN ('master','model','msdb','tempdb') 

    OPEN cursor_db
    FETCH NEXT FROM cursor_db INTO @DbName

    WHILE @@fetch_status = 0
    BEGIN

        -- Declare Cursor with Tables and load data into
        DECLARE cursor_tables CURSOR FOR SELECT
            name
        FROM sys.objects o
        WHERE o.name LIKE '%bak%'
        AND o.name NOT LIKE 'dms%'
        AND o.create_date < GETDATE()-60
        AND o.type = 'u'

        SET @sql_db = 'use '+ QUOTENAME(@DbName) --+ CHAR(13) + 'go'
        EXEC sp_executesql @sql_db

        OPEN cursor_tables
        FETCH NEXT FROM cursor_tables INTO @TableName

        WHILE @@fetch_status = 0
        BEGIN

            SET @sql = 'drop table ' + QUOTENAME(@TableName)
            EXEC sp_executesql @SQL
            FETCH NEXT FROM cursor_tables INTO @TableName
        END

        CLOSE cursor_tables
        DEALLOCATE cursor_tables

        FETCH NEXT FROM cursor_tables INTO @DbName
    END;

    CLOSE cursor_db
    DEALLOCATE cursor_db

END TRY
BEGIN CATCH
    SELECT   
        ERROR_NUMBER() AS ErrorNumber  
        ,ERROR_MESSAGE() AS ErrorMessage
        --,ERROR_SEVERITY() AS ErrorSeverity  
        --,ERROR_STATE() AS ErrorState
        ,ERROR_LINE() AS ErrorLine;
END CATCH

不幸的是,我收到一条错误消息,指出我试图关闭该光标所在的行中不存在“ cursor_tables”。有人可以帮我吗?

提前 亚历克斯

1 个答案:

答案 0 :(得分:4)

我个人将使用Aaron Bertrand的dbo.sp_foreachdb(而不是Microsoft的内置版本),并传递一个已构建并运行的动态语句。这未经测试,但我相信这会起作用:

DECLARE @SQL nvarchar(MAX);

SET @SQL = N'USE ?' + NCHAR(13) + NCHAR(10) +
           N'SET @DSQL = STUFF((SELECT NCHAR(13) + NCHAR(10) + ' + NCHAR(13) + NCHAR(10) + 
           N'                          N''DROP TABLE '' + QUOTENAME(s.[name]) + N''.'' + QUOTENAME(t.[name]) + N'';''' + NCHAR(13) + NCHAR(10) + 
           N'                   FROM sys.schemas s' + NCHAR(13) + NCHAR(10) + 
           N'                        JOIN sys.tables t ON s.schema_id = t.schema_id' + NCHAR(13) + NCHAR(10) + 
           N'                   WHERE t.[name] LIKE N''%bak%''' + NCHAR(13) + NCHAR(10) + 
           N'                     AND t.[name] NOT LIKE N''dms%''' + NCHAR(13) + NCHAR(10) + 
           N'                     AND t.create_date < DATEADD(DAY, -60, GETDATE())' + NCHAR(13) + NCHAR(10) + 
           N'                     AND t.type = N''u''' + NCHAR(13) + NCHAR(10) + 
           N'                   FOR XML PATH(N''''),TYPE).value(''.'',''nvarchar(MAX)''),1,2,N'''');' + NCHAR(13) + NCHAR(10) + 
           N'EXEC sp_executesql @DSQL;';

EXEC master.dbo.sp_foreachdb @command = @SQL;

这看起来很混乱,但这实际上是在动态语句(针对每个User数据库运行)中的动态语句。

相关问题