一.本文所涉及的内容(Contents)

  1. 本文所涉及的内容(Contents)
  2. 背景(Contexts)
  3. 实现代码(SQL Codes)
    1. 方法一:运用游标
    2. 方法二:运用系统存储过程
    3. 方法三:拼接SQL
  4. 参考文献(References)

二.背景(Contexts)

  在性能调优或者需要了解某数据库表信息的时候,最直观的方式就是罗列出这个数据所有表的信息,这些信息包括:表的记录数、数据记录占用空间、索引占用空间、未使用的空间等(如Figure1所示),有了这些信息你可以简单的判断这个数据库来自数据上的压力可能是某个表造成的。因为表数据越大,对数据库性能的影响越大。

  要实现某个数据库所有表的信息,可以通过游标的形式获取相应的数据,下图Figure1返回某数据库中所有表的信息:

(Figure1:某数据库所有表信息)

  也许你并不满足于Figure1的信息,你希望获取整个数据库实例中所有数据库所有表的信息(如Figure2所示),如果想了解里面的实现可以参考:SQL Server 查看所有数据库所有表大小信息(Sizes of All Tables in All Database)

(Figure2:所有数据库所有表信息)

三.实现代码(SQL Codes)

为了实现Figure1的效果,有三种方式可以实现:

  1. 运用游标循环每个表,调用系统存储过程sp_spaceused把结果保存到临时表,可以过滤表;

  2. 运用系统存储过程sp_MSforeachtable把结果保存到临时表,可以过滤表;

  3. 运用系统表INFORMATION_SCHEMA.TABLES与系统存储过程sp_spaceused结合起来,拼接出每个表的INSERT语句,把结果保存到临时表,可以过滤表;

(一) 运用游标循环每个表,调用系统存储过程sp_spaceused把结果保存到临时表,可以过滤表;

  首先定义一个临时表变量@tablespaceinfo用于保存表的信息,使用游标读取sys.tables中的表名称,再通过sp_spaceused获取这个表的相关数据插入到临时表变量@tablespaceinfo。下面是SQL脚本的实现,效果就如Figure1所示:

  1. --Script1:
  2. --查看某数据库所有表的信息
  3. DECLARE @tablespaceinfo TABLE (
  4. [name] SYSNAME,
  5. [rows] BIGINT,
  6. [reserved] VARCHAR(100),
  7. [data] VARCHAR(100),
  8. [index_size] VARCHAR(100),
  9. [unused] VARCHAR(100)
  10. )
  11.  
  12. DECLARE @tablename VARCHAR(255);
  13.  
  14. DECLARE Info_cursor CURSOR FOR
  15. SELECT '['+[name]+']' FROM sys.tables WHERE TYPE='U';
  16.  
  17. OPEN Info_cursor
  18. FETCH NEXT FROM Info_cursor INTO @tablename
  19.  
  20. WHILE @@FETCH_STATUS = 0
  21. BEGIN
  22. INSERT INTO @tablespaceinfo EXEC sp_spaceused @tablename
  23.  
  24. FETCH NEXT FROM Info_cursor INTO @tablename
  25. END
  26.  
  27. CLOSE Info_cursor
  28. DEALLOCATE Info_cursor
  29.  
  30. SELECT * FROM @tablespaceinfo
  31. ORDER BY Cast(Replace(reserved,'KB','') AS INT) DESC

(二) 运用系统存储过程sp_MSforeachtable把结果保存到临时表,可以过滤表;

  下面Script2脚本是通过使用系统存储过程sp_MSforeachtable,返回的结果如Figure1所示:

  1. --Script2:
  2. --查看某数据库所有表的信息
  3. DECLARE @tablespaceinfo TABLE (
  4. [name] SYSNAME,
  5. [rows] BIGINT,
  6. [reserved] VARCHAR(100),
  7. [data] VARCHAR(100),
  8. [index_size] VARCHAR(100),
  9. [unused] VARCHAR(100)
  10. )
  11.  
  12. INSERT INTO @tablespaceinfo EXEC sp_MSforeachtable @command1="sp_spaceused '?'"
  13.  
  14. SELECT * FROM @tablespaceinfo
  15. ORDER BY Cast(Replace(reserved,'KB','') AS INT) DESC

  1) 如果你想使用sp_MSforeachtable但是又想过滤掉一些表,你可以在查询@tablespaceinfo的时候加入Where条件(这种方式就不演示了);或者直接在开始使用sp_MSforeachtable的时候就进行过滤:

  1. --获取所有表信息
  2. EXEC sp_MSforeachtable @command1="sp_spaceused '?'"

如果我们加入@whereand参数进行过滤,但是会出现下图的错误信息:

  1. --过滤某些表
  2. EXEC sp_MSforeachtable @whereand="and [name] like 't%'", @command1="sp_spaceused '?'"

(Figure3:错误信息)

  经过查看sp_MSforeachtable的源代码,发现是有多个[name]字段的,所以指明字段,上面的错误就可以解决了,效果如下图所示。把下面的SQL代码替换Script2的部分代码就可以了。

  1. --过滤某些表
  2. EXEC sp_MSforeachtable @whereand="and o.[name] like 't%'", @command1="sp_spaceused '?'"
  3. --或者
  4. EXEC sp_MSforeachtable @whereand="and syso.[name] like 't%'", @command1="sp_spaceused '?'"

(Figure4:过滤返回的结果)

  2) 在sp_MSforeachtable系统存储过程,有@whereand的参数可以对表进行过滤,sp_MSForEachDB系统存储是否也有同样的功能呢?查看了sp_MSForEachDB的源码,我们发现是没有这个功能的,为实现这个功能,我对sp_MSForEachDB进行修改,重新命名为:sp_MSForEachDB_Filter

  1. --扩展sp_MSforeachdb
  2. create proc dbo.[sp_MSforeachdb_Filter]
  3. @command1 nvarchar(2000), @replacechar nchar(1) = N'?', @command2 nvarchar(2000) = null, @command3 nvarchar(2000) = null,
  4. @whereand nvarchar(2000) = null,@precommand nvarchar(2000) = null, @postcommand nvarchar(2000) = null
  5. as
  6. set deadlock_priority low
  7.  
  8. declare @inaccessible nvarchar(12), @invalidlogin nvarchar(12), @dbinaccessible nvarchar(12)
  9. select @inaccessible = ltrim(str(convert(int, 0x03e0), 11))
  10. select @invalidlogin = ltrim(str(convert(int, 0x40000000), 11))
  11. select @dbinaccessible = N'0x80000000'
  12.  
  13. if (@precommand is not null)
  14. exec(@precommand)
  15.  
  16. declare @origdb nvarchar(128)
  17. select @origdb = db_name()
  18. exec(N'declare hCForEachDatabase cursor global for select name from master.dbo.sysdatabases d ' +
  19. N' where (d.status & ' + @inaccessible + N' = 0)' +
  20. N' and (DATABASEPROPERTY(d.name, ''issingleuser'') = 0 and (has_dbaccess(d.name) = 1))' + @whereand)
  21.  
  22. declare @retval int
  23. select @retval = @@error
  24. if (@retval = 0)
  25. exec @retval = sys.sp_MSforeach_worker @command1, @replacechar, @command2, @command3, 1
  26.  
  27. if (@retval = 0 and @postcommand is not null)
  28. exec(@postcommand)
  29.  
  30. declare @tempdb nvarchar(258)
  31. SELECT @tempdb = REPLACE(@origdb, N']', N']]')
  32. exec (N'use ' + N'[' + @tempdb + N']')
  33.  
  34. return @retval

  上面的存储过程sp_MSforeachdb_Filter是依照sp_MSforeachtable进行简单修改的,创建之后就可以使用下面的SQL脚本进行过滤数据库了,效果如下图所示:

  1. --过滤数据库
  2. EXEC [sp_MSforeachdb_Filter] @command1="print '?'",
  3. @whereand=" and [name] not in('tempdb','master','model','msdb') "

(Figure5:过滤数据库)

(三) 运用系统表INFORMATION_SCHEMA.TABLES与系统存储过程sp_spaceused结合起来,拼接出每个表的INSERT语句,把结果保存到临时表,可以过滤表;

  一次偶然的机会看到一个同样能实现Figure1效果的SQL脚本,它使用了系统表INFORMATION_SCHEMA.TABLES,下面是我修改过的SQL脚本,区别就在于可以满足对不同架构表的查询。原文详情可以参考:How to get information about all databases without a loop

  1. --Script3:Sizes of All Tables in a Database
  2. --exec sp_MSforeachtable 'print ''?'' exec sp_spaceused ''?'''
  3. --在它的基础上做了些修改,适合不同的框架dbo
  4. IF OBJECT_ID('tempdb..#TablesSizes') IS NOT NULL
  5. DROP TABLE #TablesSizes
  6.  
  7. CREATE TABLE #TablesSizes (TableName sysname, Rows bigint, reserved varchar(100), data varchar(100), index_size varchar(100), unused varchar(100))
  8.  
  9. DECLARE @sql VARCHAR(MAX)
  10. SELECT @sql = COALESCE(@sql,'') + '
  11. INSERT INTO #TablesSizes execute sp_spaceused ''' + QUOTENAME(TABLE_SCHEMA,'[]') + '.' + QUOTENAME(Table_Name,'[]') + ''''
  12. FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE'
  13.  
  14. PRINT (@SQL)
  15. EXECUTE (@SQL)
  16.  
  17. SELECT * FROM #TablesSizes ORDER BY TableName

上面PRINT出来的脚本类似下图Figure6所示:

(Figure6:拼接的SQL代码)

四.参考文献(References)

与存储过程sp_MSforeachdb类似的存储过程sp_MSforeachdb

SQL Server数据库开发顶级技巧

sp_MSforeachtable使用方法

How to get information about all databases without a loop

关于quotename的用法

SQL Server 游标运用:查看数据库所有表大小信息的更多相关文章

  1. SQL Server 游标运用:查看所有数据库所有表大小信息(Sizes of All Tables in All Database)

    原文:SQL Server 游标运用:查看所有数据库所有表大小信息(Sizes of All Tables in All Database) 一.本文所涉及的内容(Contents) 本文所涉及的内容 ...

  2. SQL Server 游标运用:查看一个数据库所有表大小信息(Sizes of All Tables in a Database)

    原文:SQL Server 游标运用:查看一个数据库所有表大小信息(Sizes of All Tables in a Database) 一.本文所涉及的内容(Contents) 本文所涉及的内容(C ...

  3. SQL SERVER 判断是否存在数据库、表、列、视图

    SQL SERVER 判断是否存在数据库.表.列.视图 --1. 判断数据库是否存在 IF EXISTS (SELECT * FROM SYS.DATABASES WHERE NAME = '数据库名 ...

  4. mongodb查看数据库和表的信息

    mongodb查看数据库和表的方法比较简单,在为这里推荐使用stats的方法,直观并且详细. 1.查看数据库 db.stats();1输出: { "db" : "siri ...

  5. sql server DDL语句 建立数据库 定义表 修改字段等

    一.数据库:1.建立数据库 create database 数据库名;use 数据库名; create database exp1;use exp1; mysql同样 2.删除数据库 drop dat ...

  6. sql server 判断是否存在数据库,表,列,视图

    1 判断数据库是否存在if exists (select * from sys.databases where name = '数据库名')    drop database [数据库名] 2 判断表 ...

  7. sql server 2008 删除某数据库所有表

    /* ------sqlserver 2008 删除某数据库所有表-------- */ declare @tname varchar(8000) set @tname='' select @tnam ...

  8. mongodb 查看数据库和表大小

    1.查看数据库 > db.stats(); { "db" : "test", //当前数据库 "collections" : 3, / ...

  9. POSTGRESQL 查看数据库 数据表大小

    1.查看数据库大小: select pg_database_size('log_analysis'); select pg_database_size('log_analysis'); pg_data ...

随机推荐

  1. Spark On YARN 分布式集群安装

    一.导读 最近开始学习大数据分析,说到大数据分析,就必须提到Hadoop与Spark.要研究大数据分析,就必须安装这两个软件,特此记录一下安装过程.Hadoop使用V2版本,Hadoop有单机.伪分布 ...

  2. sqlite3 的一些整理和补充

    一,sqlite3数据库打开时的返回值及其所代表的含义 返回值 描述 返回值 描述 SQLITE_OK=0 返回成功 SQLITE_FULL=13 数据库满,插入失败 SQLITE_ERROR=1 S ...

  3. Python3基础 time.localtime 当前系统的年月日 时分秒

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  4. Go第十一篇之编译与工具

    Go 语言的工具链非常丰富,从获取源码.编译.文档.测试.性能分析,到源码格式化.源码提示.重构工具等应有尽有. 在 Go 语言中可以使用测试框架编写单元测试,使用统一的命令行即可测试及输出测试报告的 ...

  5. Sql Server 创建表添加说明

    http://bbs.csdn.net/topics/340184487 在此感谢 提供参考 CREATE TABLE ToPayFee (    Id INT IDENTITY(1,1) PRIMA ...

  6. animate动画回调函数

    对非动画的实现排队,比如这个css()是要放在回调函数里才能,让前面的动画执行完成后在进行实现 $('button').click(function(event) { $(this).next().a ...

  7. Intellij新建Spring项目引入用户目录下的Spring jar包

    首先,在IntelliJ IDEA中新建module,选择Spring应用:   在初次使用时,如果IDE检测到本地没有spring核心库,则会在新建过程中下载对应库文件,在使用spring框架时,可 ...

  8. 配置文件(Machine.config、Web.config、App.config)

    Machine.config1.该文件在Windows目录下\Microsoft.net\framework\[version]\Config\2.为了提高性能,该文件只包含不同于默认值的设置.并且定 ...

  9. java必背面试题

    JAVA必背面试题和项目面试通关要点 一 数据库 1.常问数据库查询.修改(SQL查询包含筛选查询.聚合查询和链接查询和优化问题,手写SQL语句,例如四个球队比赛,用SQL显示所有比赛组合:举例2:选 ...

  10. 51nod 1445 变色DNA(最短路变形)

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1445 题意: 思路: 挺好的一道题目,如果$colormap[i][j] ...