我的维护程序遇到问题,需要创建第二个维护程序,在该程序中我声明一个带有数据库ID列表的游标,然后将它们传递给另一个游标以获取每个数据库的表列表。
当前的问题是,即使内部游标运行,它也使用[database_name],当我声明并指定查询时,它会从master数据库中选择表。它不会在进入内部游标之前更改数据库上下文。
DECLARE @db varchar(128)
declare @cmd varchar(1024)
declare @table varchar(255)
declare @cmd2 varchar(1024)
DECLARE crDB CURSOR global FORWARD_only FOR
SELECT [name] FROM sys.databases WHERE database_id > 4
and database_id in (33) ORDER BY [name]
OPEN crDB
FETCH crDB INTO @db
WHILE @@FETCH_STATUS = 0
BEGIN
SET @cmd = 'USE [' + @db +']'
EXEC (@cmd)
DECLARE crTB CURSOR LOCAL FAST_FORWARD FOR
select [name] from sys.objects where type = 'u' ORDER BY [name]
OPEN crTB
FETCH crTB INTO @table
WHILE @@FETCH_STATUS = 0
BEGIN
SET @cmd2 = 'Update Statistics ' + @table + CHAR(13)
PRINT @cmd2
EXEC (@cmd2)
end
CLOSE crTB
DEALLOCATE crTB
FETCH crDB INTO @db
END
CLOSE crDB
DEALLOCATE crDB
GO
答案 0 :(得分:1)
内部游标的问题是范围。您可以在这里做两件事。您必须在USE [' + @db
之后向右移动内部光标,例如:
DECLARE @db VARCHAR(128);
DECLARE @cmd VARCHAR(1024);
DECLARE @table VARCHAR(255);
DECLARE @cmd2 VARCHAR(1024);
DECLARE crDB CURSOR GLOBAL READ_ONLY FORWARD_ONLY FOR
SELECT name
FROM sys.databases
WHERE database_id > 4
AND database_id IN (33)
ORDER BY name;
OPEN crDB;
FETCH crDB
INTO @db;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @cmd = 'USE [' + @db + ']
GO;
DECLARE crTB CURSOR LOCAL FAST_FORWARD FOR
SELECT name
FROM sys.objects
WHERE type = ''u'';
ORDER BY name;
OPEN crTB;
FETCH NEXT FROM crTB
INTO @table;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @cmd2 = ''Update Statistics '' + @table + CHAR(13);
PRINT @cmd2;
EXEC (@cmd2);
END;
CLOSE crTB;
DEALLOCATE crTB;
';
EXEC (@cmd);
FETCH NEXT FROM crDB
INTO @db;
END;
CLOSE crDB;
DEALLOCATE crDB;
或者您可以完全摆脱内部游标,并使用sys.sp_MSforeachtable:
WHILE @@FETCH_STATUS = 0
BEGIN
SET @cmd = 'USE [' + @db + ']
GO;
EXEC sys.sp_MSforeachtable @command1 = ''UPDATE STATISTICS ?;''';
EXEC (@cmd);