需要在声明中声明带有变量的游标

时间:2019-02-04 20:38:09

标签: sql sql-server

我的维护程序遇到问题,需要创建第二个维护程序,在该程序中我声明一个带有数据库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

1 个答案:

答案 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);