代码之家  ›  专栏  ›  技术社区  ›  Alen

需要用声明中的变量声明光标

  •  0
  • Alen  · 技术社区  · 6 年前

    我在维护过程中遇到了问题,需要创建第二个过程,在这里我用数据库ID列表声明一个游标,并将它们传递到另一个游标中,以获取每个数据库的表列表。

    当前的问题是,在内部光标中,即使它运行,当我声明它并指定查询时,它也会从主数据库中选择表。它不会在进入内部光标之前更改数据库上下文。

    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
    

    1 回复  |  直到 6 年前
        1
  •  1
  •   Thailo    6 年前

    内部光标的问题是范围。你可以在这里做两件事。您必须将内部光标移到 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);