需要更新我们服务器上的所有数据库,并在每个数据库上执行相同的逻辑。有问题的数据库都遵循一个通用的命名方案,如CorpDB1,CorpDB2等。而不是为每个有问题的数据库(超过50个)创建一个SQL代理作业,我考虑过使用游标迭代数据库列表然后在每个上执行一些动态sql。鉴于游标应该是最后手段的普遍观念;是否可以通过使用未记录的sp_MSforeachdb stored procedure来重写以获得更好的性能或以其他方式编写?
DECLARE @db VARCHAR(100) --current database name
DECLARE @sql VARCHAR(1000) --t-sql used for processing on each database
DECLARE db_cursor CURSOR FAST_FORWARD FOR
SELECT name
FROM MASTER.dbo.sysdatabases
WHERE name LIKE 'CorpDB%'
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @db
WHILE @@FETCH_STATUS = 0
BEGIN
SET @sql = 'USE ' + @db +
' DELETE FROM db_table --more t-sql processing'
EXEC(@sql)
FETCH NEXT FROM db_cursor INTO @db
END
CLOSE db_cursor
DEALLOCATE db_cursor
答案 0 :(得分:5)
当游标用于处理基于集合的过程代码问题时,它们很糟糕。我不认为游标在你的场景中不一定是坏主意。
当需要针对多个数据库运行操作(备份,完整性检查,索引维护等)时,使用游标没有问题。当然,您可以构建一个包含数据库名称的临时表并循环执行...但它仍然是一种程序方法。
对于您的具体情况,如果您未根据某些WHERE
条款标准删除这些表格中的行,请考虑使用TRUNCATE TABLE
代替DELETE FROM
。两个操作之间的差异解释了here。请注意,运行TRUNCATE TABLE
的用户需要ALTER
对受影响对象的权限。
答案 1 :(得分:2)
这将收集一组delete语句并以单个序列运行它们。这不一定是性能更好的,而只是另一种让猫皮肤化的方法。
DECLARE @sql NVARCHAR(MAX); -- if SQL Server 2000, use NVARCHAR(4000)
SET @sql = N'';
SELECT @sql = @sql + N';DELETE ' + name + '..db_table -- more t-sql'
FROM master.sys.databases
WHERE name LIKE N'CorpDB%';
SET @sql = STUFF(@sql, 1, 1, '');
EXEC sp_executesql @sql;
您可以考虑在游标内部以类似的方式构建字符串,而不是为每个命令在内部运行EXEC()
。如果您要继续使用游标,请使用以下声明:
DECLARE db_cursor CURSOR
LOCAL STATIC FORWARD_ONLY READ_ONLY
FOR
这将具有最少的锁定并且没有不必要的tempdb使用。