编写 spaceused 存储过程的脚本来编辑它

Fal*_*ind -2 sql-server sql-server-2014

是否可以编写sp_spaceused存储过程的脚本,以便我可以编辑它以包含日志空间信息并创建我自己的自定义存储过程?

我想将结果放在一个临时表中,以便我可以在我正在处理的项目中使用它,因此我还需要将 2 个结果集压缩为一个结果集。

不知道从哪里开始。有没有更简单的方法来获取相同的数据?

Mol*_*pad 5

是的,你可以使用 sp_helptext @objname = 'sp_spaceused'

做你想做的事情会很繁琐......只是因为你需要取消存储过程并重新设计它,可以这么说。

我自己为 DBA 使用的内部 SQL 库存应用程序做了同样的事情。下面产生一个单一的结果集,它汇集了两个结果集,sp_spaceused并添加了一些来自DBCC SQLPERF (logspace)

它使用动态 SQL 来获取实例中所有数据库的数据。它可能不完全是你想要的,但它可能会为你做一些事情。

请注意,有时我们必须明确 COLLATE 连接,因此如果您遇到 COLLATION 错误,请告诉我,我会尝试以某种方式提供帮助。

剧本:

/* ---------------------- */
/* Drop temporary objects */
/* ---------------------- */
IF OBJECT_ID('tempdb..#tmpLogUsage') IS NOT NULL
    DROP TABLE #tmpLogUsage;

IF OBJECT_ID('tempdb..##spaceused') IS NOT NULL
    DROP TABLE ##spaceused

/* ---------------------- */
/*    Create Variables    */
/* ---------------------- */
CREATE TABLE ##spaceused (
    databasename VARCHAR(500)
    ,database_size VARCHAR(50)
    ,unallocated_space VARCHAR(50)
    ,reserved VARCHAR(50)
    ,data VARCHAR(50)
    ,index_size VARCHAR(50)
    ,unused VARCHAR(50)
    ,dbsize VARCHAR(50)
    ,logsize VARCHAR(50)
    )

DECLARE @databases AS TABLE (
    ID INT identity(1, 1)
    ,databasename VARCHAR(500)
    )

INSERT INTO @databases
SELECT '['+NAME+']'
FROM sys.databases
WHERE database_id > 4 AND state = 0

DECLARE @recordcount AS INT = (
        SELECT MAX(ID)
        FROM @databases
        )
DECLARE @whilecount AS INT = 1
DECLARE @sql AS VARCHAR(MAX)
DECLARE @databasename AS VARCHAR(500)

/* ---------------------- */
/*   Get Log Information  */
/* ---------------------- */
DECLARE @logspace AS TABLE (
    DatabaseName VARCHAR(500)
    ,LogSizeMB DECIMAL(16, 2)
    ,LogSpaceUsedPerc DECIMAL(16, 2)
    ,STATUS INT
    )

INSERT INTO @logspace
EXECUTE ('DBCC SQLPERF (logspace)')

SELECT ls.DatabaseName
    ,ls.LogSpaceUsedPerc
    ,ROUND((ls.LogSizeMB / 100) * ls.LogSpaceUsedPerc, 2) AS LogSizeActualMB
    ,db.log_reuse_wait_desc
    ,db.recovery_model_desc
INTO #tmpLogUsage
FROM @logspace ls
INNER JOIN sys.databases db ON ls.DatabaseName = db.NAME 

/* ------------------------------------------------ */
/*  Loop through databases and get space used data  */
/* ------------------------------------------------ */
WHILE @whilecount <= @recordcount
BEGIN
    SET @databasename = (
            SELECT databasename
            FROM @databases
            WHERE ID = @whilecount
            )
    SET @sql = (
            'USE ' + @databasename + 
            ' INSERT INTO ##spaceused SELECT
    db_name() AS [database_name]
    ,ltrim(str((convert(DEC(15, 2), sf.dbsize) + convert(DEC(15, 2), sf.logsize)) * 8192 / 1048576, 15, 2) + '' MB'') AS [database_size]
    ,ltrim(str((
                CASE 
                    WHEN sf.dbsize >= pages.reservedpages
                        THEN (convert(DEC(15, 2), sf.dbsize) - convert(DEC(15, 2), pages.reservedpages)) * 8192 / 1048576
                    ELSE 0
                    END
                ), 15, 2) + '' MB'') AS [unallocated space]
    ,ltrim(str(pages.reservedpages * 8192 / 1024., 15, 0) + '' KB'') AS [reserved]
    ,ltrim(str(pages.pages * 8192 / 1024., 15, 0) + '' KB'') AS data
    ,ltrim(str((pages.usedpages - pages.pages) * 8192 / 1024., 15, 0) + '' KB'') AS index_size
    ,ltrim(str((pages.reservedpages - pages.usedpages) * 8192 / 1024., 15, 0) + '' KB'') AS unused

    ,ltrim(str((convert(DEC(15, 2), sf.dbsize)) * 8192 / 1048576, 15, 2) + '' MB'') AS dbsize
    ,ltrim(str((convert(DEC(15, 2), sf.logsize)) * 8192 / 1048576, 15, 2) + '' MB'') AS logsize
FROM (
    SELECT sum(convert(BIGINT, CASE 
                    WHEN STATUS & 64 = 0
                        THEN size
                    ELSE 0
                    END)) AS dbsize
        ,sum(convert(BIGINT, CASE 
                    WHEN STATUS & 64 <> 0
                        THEN size
                    ELSE 0
                    END)) AS logsize
    FROM dbo.sysfiles
    ) sf
    ,(
        SELECT sum(a.total_pages) AS reservedpages
            ,sum(a.used_pages) AS usedpages
            ,sum(CASE 
                    WHEN it.internal_type IN (
                            202
                            ,204
                            ,211
                            ,212
                            ,213
                            ,214
                            ,215
                            ,216
                            )
                        THEN 0
                    WHEN a.type <> 1
                        THEN a.used_pages
                    WHEN p.index_id < 2
                        THEN a.data_pages
                    ELSE 0
                    END) AS pages
        FROM sys.partitions p
        JOIN sys.allocation_units a ON p.partition_id = a.container_id
        LEFT JOIN sys.internal_tables it ON p.object_id = it.object_id
        ) pages;'
            )

    EXECUTE (@sql);

    SET @whilecount += 1
END

/* ----------------- */
/*   Output Dataset  */
/* ----------------- */
SELECT su.databasename AS DatabaseName
    ,lu.recovery_model_desc AS DatabaseRecoveryModel
    ,su.database_size AS DatabaseSizeIncLog
    ,su.unallocated_space AS UnallocatedSpace
    ,su.reserved AS ReservedbySQLServer
    ,su.data AS DataSize
    ,su.index_size AS IndexSize
    ,su.unused AS AllocatedUnused
    ,su.dbsize AS DataFileSize
    ,su.logsize AS LogFileSize
    ,lu.LogSpaceUsedPerc
    ,lu.LogSizeActualMB
    ,lu.log_reuse_wait_desc AS LogWaitDescription
FROM ##spaceused su
INNER JOIN #tmpLogUsage lu ON su.databasename = lu.DatabaseName
Run Code Online (Sandbox Code Playgroud)