我有这个脚本,它会为我提供特定数据库的表大小。
我的问题是如何重写代码,以便它可以从SQL Server返回所有表大小信息,无论数据库是什么,这意味着我不需要更改use_db
。
[use_db]
SELECT t.name AS TableName,
p.rows AS RowCounts,
SUM(a.total_pages) * 8 AS TotalSpaceKB,
SUM(a.used_pages) * 8 AS UsedSpaceKB,
(SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB
FROM sys.tables t
INNER JOIN sys.indexes i ON t.object_id = i.object_id
INNER JOIN sys.partitions p ON i.object_id = p.object_id AND i.index_id = p.index_id
INNER JOIN sys.allocation_units a ON p.partition_id = a.container_id
WHERE t.name NOT LIKE 'dt%'
AND t.is_ms_shipped = 0
AND i.object_id > 255
GROUP BY t.name,
p.rows
ORDER BY t.name
答案 0 :(得分:4)
IF OBJECT_ID('tempdb.dbo.#space') IS NOT NULL
DROP TABLE #space
CREATE TABLE #space (
[db_name] SYSNAME
, obj_name SYSNAME
, total_pages BIGINT
, used_pages BIGINT
, total_rows BIGINT
)
DECLARE @SQL NVARCHAR(MAX)
SELECT @SQL = STUFF((
SELECT '
USE [' + d.name + ']
INSERT INTO #space ([db_name], obj_name, total_pages, used_pages, total_rows)
SELECT DB_NAME(), SCHEMA_NAME(o.[schema_id]) + ''.'' + o.name, t.total_pages, t.used_pages, t.total_rows
FROM (
SELECT
i.[object_id]
, total_pages = SUM(a.total_pages)
, used_pages = SUM(a.used_pages)
, total_rows = SUM(CASE WHEN i.index_id IN (0, 1) AND a.[type] = 1 THEN p.[rows] END)
FROM sys.indexes i
JOIN sys.partitions p ON i.[object_id] = p.[object_id] AND i.index_id = p.index_id
JOIN sys.allocation_units a ON p.[partition_id] = a.container_id
WHERE i.is_disabled = 0
AND i.is_hypothetical = 0
GROUP BY i.[object_id]
) t
JOIN sys.objects o ON t.[object_id] = o.[object_id]
WHERE o.name NOT LIKE ''dt%''
AND o.is_ms_shipped = 0
AND o.type = ''U''
AND o.[object_id] > 255;'
FROM sys.databases d
WHERE d.[state] = 0
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '')
EXEC sys.sp_executesql @SQL
SELECT
[db_name]
, obj_name
, total_rows
, total_space = CAST(total_pages * 8. / 1024 AS DECIMAL(18,2))
, used_space = CAST(used_pages * 8. / 1024 AS DECIMAL(18,2))
, unused_space = CAST((total_pages - used_pages) * 8. / 1024 AS DECIMAL(18,2))
FROM #space
输出 -
db_name obj_name total_rows total_space used_space unused_space
-------------------------- ---------------------------------- ----------- ------------- ------------ --------------
master dbo.Person 1000 0.20 0.13 0.08
master dbo.Building 4 0.03 0.03 0.00
ReportServer$SQL_2012 dbo.Keys 1 0.02 0.02 0.00
ReportServer$SQL_2012 dbo.History 0 0.00 0.00 0.00
ReportServer$SQL_2012 dbo.ConfigurationInfo 20 0.03 0.03 0.00
ReportServer$SQL_2012 dbo.Catalog 1 0.08 0.08 0.00
ReportServer$SQL_2012 dbo.UpgradeInfo 1 0.02 0.02 0.00
答案 1 :(得分:2)
有几种方法可以做到这一点。您可以使用未记录的SQL Server过程msForEachDb。它针对当前实例上的每个db执行传递的SQL语句。问号将替换为当前的数据库名称。
对于每个Db示例
/* Undocumented sp can loop over every db on the server.
*/
EXECUTE msdb..sp_msForEachDb
'
USE [?];
SELECT DB_NAME();
'
;
这种方法的问题在于它没有记录。这意味着MS可以随时撤回或更改SP。
另一种可能更安全的方法是查询系统目录。您可以使用它们来构建可以执行的动态SQL语句。
系统目录示例
/* Using system tables to obtain and query each db,
* via dynamic SQL statement.
*/
DECLARE @query NVARCHAR(MAX) = '';
SELECT
@query = @query + 'USE [' + Name + ']; SELECT DB_NAME();'
FROM
sys.databases
;
EXECUTE sp_ExecuteSql @query;
;