T-SQL在不使用游标

时间:2015-10-08 10:36:14

标签: sql-server tsql

使用SQL Server 2012.

使用为每个数据库存储的系统视图,我希望保留实例中所有索引的索引行为摘要。下面的代码收集一些统计信息并将它们放在一个表中供以后使用。问题是,我不得不使用游标来遍历实例中的数据库。任何人都可以建议一种更好的方法,而不必使用光标吗?

USE Master
GO

-- If the procedure already exists then update it. 
IF OBJECT_ID('sp_index_stats') IS NOT NULL 
    DROP PROCEDURE sp_index_stats
GO

CREATE PROCEDURE sp_index_stats AS
    DECLARE     @dbname     NVARCHAR(128) 
    DECLARE     @finalSQL   NVARCHAR(1024)

    -- Results of the query are put into a table in Demo_DB. 
    -- So empty it now for the new results. 

    TRUNCATE TABLE Demo_DB.dbo.index_stats

    -- Use a cursor to get a list of all the tables in the instance. 
    DECLARE database_cursor CURSOR LOCAL FOR
        SELECT  name
        FROM    Master.dbo.sysdatabases
        WHERE   name NOT IN ('master', 'model', 'msdb', 'tempdb')

    OPEN database_cursor

    FETCH NEXT FROM database_cursor INTO @dbname

    WHILE @@FETCH_STATUS = 0
    BEGIN
        -- Each database will contain the same structue, so I need
        -- to create a standard query just changing the database name.
        SET @finalSQL = 'INSERT INTO Demo_DB.dbo.index_stats '

        -- Sort out the select statement.
        SET @finalSQL = @finalSQL + 'SELECT sdb.name, st.name, si.name, si.type_desc, '
        SET @finalSQL = @finalSQL + 'si.is_primary_key, si.fill_factor, '
        SET @finalSQL = @finalSQL + 'sd.user_scans, sd.last_user_scan, '
        SET @finalSQL = @finalSQL + 'sd.user_updates, sd.last_user_update '

        -- The 'from' and 'joins' need to be adjusted slightly for each databse. 
        SET @finalSQL = @finalSQL + 'FROM ' + @dbname + '.sys.tables st '
        SET @finalSQL = @finalSQL + 'JOIN ' + @dbname + '.sys.indexes si ON (si.object_id = st.object_id) '
        SET @finalSQL = @finalSQL + 'JOIN ' + @dbname + '.sys.dm_db_index_usage_stats sd ON (si.object_id = sd.object_id) '
        SET @finalSQL = @finalSQL + 'JOIN ' + @dbname + '.sys.databases sdb ON (sdb.database_id = sd.database_id) ;'

        -- Ok, let's run that...
        EXEC (@finalSQL) 

        -- Get the next database in the instance..,
        FETCH NEXT FROM database_cursor INTO @dbname
    END
    CLOSE database_cursor
    DEALLOCATE database_cursor
GO

问候,

JC。

1 个答案:

答案 0 :(得分:0)

连接怎么样?

像这样的东西(没有复制整个存储过程,但希望你得到要点)

DECLARE @SQL VARCHAR(MAX)

SET @SQL = ''

SELECT @SQL = @SQL + 
'INSERT INTO Demo_DB.dbo.index_stats ' +
'SELECT sdb.name, st.name, si.name, si.type_desc, ' +
'si.is_primary_key, si.fill_factor, ' +
'sd.user_scans, sd.last_user_scan, ' +
'sd.user_updates, sd.last_user_update ' +
'FROM ' + name + '.sys.tables st ' +
'JOIN ' + name + '.sys.indexes si ON (si.object_id = st.object_id) ' +
'JOIN ' + name + '.sys.dm_db_index_usage_stats sd ON (si.object_id = sd.object_id) ' +
'JOIN ' + name + '.sys.databases sdb ON (sdb.database_id = sd.database_id) ;'  
FROM    Master.dbo.sysdatabases
WHERE   name NOT IN ('master', 'model', 'msdb', 'tempdb')

SELECT @SQL

(显然此时并未执行任何操作)。