我编写了一个脚本,可以从一个数据库中删除特定的表。
-- 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”。有人可以帮我吗?
提前 亚历克斯
答案 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数据库运行)中的动态语句。