在MSSQL里有许多不公开的系统存储过程,其中可能常用的sp_MSforeachtable和sp_MSforeachdb有这2个。
分别用于遍历某数据库的每个用户表、每个数据库。

sp_MSforeachtable

create proc sp_MSforeachtable
    @command1 nvarchar(2000),             --第一条运行的T-SQL
    @replacechar nchar(1) = N'?',          --指定的占位符
    @command2 nvarchar(2000) = null,      --第二条运行的T-SQL   
    @command3 nvarchar(2000) = null,      --第三条运行的T-SQL
    @whereand nvarchar(2000) = null,      --表的选择条件
    @precommand nvarchar(2000) = null,    --在表前执行的指令
    @postcommand nvarchar(2000) = null    --在表后执行的指令
as
    /* This proc returns one or more rows for each table (optionally, matching @where), with each table defaulting to its own result set */
    /* @precommand and @postcommand may be used to force a single result set via a temp table. */
    /* Preprocessor won't replace within quotes so have to use str(). */
    declare @mscat nvarchar(12)
    select @mscat = ltrim(str(convert(int, 0x0002)))

if (@precommand is not null)
        exec(@precommand)

/* Create the select */
     exec(N'declare hCForEach cursor global for
     select ''['' + REPLACE(user_name(uid), N'']'', N'']]'') + '']'' + ''.'' + ''['' + REPLACE(object_name(id), N'']'', N'']]'') + '']'' from dbo.sysobjects o '
     + N' where OBJECTPROPERTY(o.id, N''IsUserTable'') = 1 ' + N' and o.category & ' + @mscat + N' = 0 '
     + @whereand)
    --上面的代码,就是定义游标根据系统表sysobjects获取用户表,@whereand就确定 sysobjects的where条件
    declare @retval int
    select @retval = @@error
    if (@retval = 0)
        --调用sp_MSforeach_worker 执行游标遍历
        --sp_MSforeach_worker存储过程见最后
        exec @retval = sp_MSforeach_worker @command1, @replacechar, @command2, @command3

if (@retval = 0 and @postcommand is not null)
        exec(@postcommand)

return @retval

go
--统计数据库里每个表的详细情况
exec sp_MSforeachtable 'sp_spaceused ''?'''
--获得每个表的记录数和容量
exec sp_MSforeachtable 'select ''?''','?', 'sp_spaceused ''?''', 'SELECT count(*) FROM ? '
--获得所有的数据库的存储空间
exec sp_MSforeachdb  'select  ''?''','?','sp_spaceused '
--检查所有的数据库
exec sp_MSforeachdb  @command1="print '?'",'DBCC CHECKDB (?) '
--更新PUBS数据库中已t开头的所有表的统计
exec sp_MSforeachtable
       'print ''*'' update statistics * ',
       '*',
       null,
       null,
       ' and name like ''t%''',
       'print ''Updating Statistics.....''',
       'print ''Complete Update Statistics!'''

--删除当前数据库所有表中的数据
sp_MSforeachtable 'Delete from ?'
sp_MSforeachtable 'Truncate Table ?'

--更新Table1/Table2中note列为NULL的值
sp_MSforeachtable 'Update ? Set note='''' Where note is null',null,null,null,' AND o.name in (''Table1'',''Table2'')

sp_MSforeachdb 在应用上与sp_MSforeachTable一样,只是没有@whereand 这个条件变量而已
/*
 * The following table definition will be created by SQLDMO at start of each connection.
 * We don't create it here temporarily because we need it in Exec() or upgrade won't work.
 */
Create proc sp_MSforeachdb
    @command1 nvarchar(2000),
    @replacechar nchar(1) = N'?',
    @command2 nvarchar(2000) = null,
    @command3 nvarchar(2000) = null,
    @precommand nvarchar(2000) = null,
    @postcommand nvarchar(2000) = null
as
    set deadlock_priority low
    /* This proc returns one or more rows for each accessible db, with each db defaulting to its own result set */
    /* @precommand and @postcommand may be used to force a single result set via a temp table. */
    /* Preprocessor won't replace within quotes so have to use str(). */
    declare @inaccessible nvarchar(12), @invalidlogin nvarchar(12), @dbinaccessible nvarchar(12)
    select @inaccessible = ltrim(str(convert(int, 0x03e0), 11))
    select @invalidlogin = ltrim(str(convert(int, 0x40000000), 11))
    select @dbinaccessible = N'0x80000000'        /* SQLDMODbUserProf_InaccessibleDb; the negative number doesn't work in convert() */

if (@precommand is not null)        exec(@precommand)

declare @origdb nvarchar(128)
    select @origdb = db_name()

/* If it's a single user db and there's an entry for it in sysprocesses who isn't us, we can't use it. */
    /* Create the select */
    exec(N'declare hCForEach cursor global for select name from master.dbo.sysdatabases d ' +
            N' where (d.status & ' + @inaccessible + N' = 0)' +
            N' and ((DATABASEPROPERTY(d.name, ''issingleuser'') = 0 and (has_dbaccess(d.name) = 1)) or ' +
            N' ( DATABASEPROPERTY(d.name, ''issingleuser'') = 1 and not exists ' +
            N' (select * from master.dbo.sysprocesses p where dbid = d.dbid and p.spid <> @@spid)))' )

declare @retval int
    select @retval = @@error
    if (@retval = 0)
        exec @retval = sp_MSforeach_worker @command1, @replacechar, @command2, @command3

if (@retval = 0 and @postcommand is not null)
        exec(@postcommand)

declare @tempdb nvarchar(258)
       SELECT @tempdb = REPLACE(@origdb, N']', N']]')
       exec (N'use ' + N'[' + @tempdb + N']')

return @retval

go

sp_MSforeach_worker
/*
 * This is the worker proc for all of the "for each" type procs.  Its function is to read the
 * next replacement name from the cursor (which returns only a single name), plug it into the
 * replacement locations for the commands, and execute them.  It assumes the cursor "hCForEach"
 * has already been opened by its caller.
 */
create proc sp_MSforeach_worker
    @command1 nvarchar(2000),
    @replacechar nchar(1) = N'?',
    @command2 nvarchar(2000) = null,
    @command3 nvarchar(2000) = null
as

create table #qtemp (    /* Temp command storage */
        qnum                int                NOT NULL,
        qchar                nvarchar(2000)    COLLATE database_default NULL
    )

set nocount on
    declare @name nvarchar(517), @namelen int, @q1 nvarchar(2000), @q2 nvarchar(2000)
    declare @q3 nvarchar(2000), @q4 nvarchar(2000), @q5 nvarchar(2000)
    declare @q6 nvarchar(2000), @q7 nvarchar(2000), @q8 nvarchar(2000), @q9 nvarchar(2000), @q10 nvarchar(2000)
    declare @cmd nvarchar(2000), @replacecharindex int, @useq tinyint, @usecmd tinyint, @nextcmd nvarchar(2000)
    declare @namesave nvarchar(517), @nametmp nvarchar(517), @nametmp2 nvarchar(258)

open hCForEach
    fetch hCForEach into @name
    /* Loop for each database */
    while (@@fetch_status >= 0)
    begin
        /* Initialize. */
        /* save the original dbname */
        select @namesave = @name
        select @useq = 1, @usecmd = 1, @cmd = @command1, @namelen = datalength(@name)
        while (@cmd is not null)
        begin        /* Generate @q* for exec() */
            /*
             * Parse each @commandX into a single executable batch.
             * Because the expanded form of a @commandX may be > OSQL_MAXCOLLEN_SET, we'll need to allow overflow.
             * We also may append @commandX's (signified by '++' as first letters of next @command).
             */
            select @replacecharindex = charindex(@replacechar, @cmd)
            while (@replacecharindex <> 0)
            begin

/* 7.0, if name contains ' character, and the name has been single quoted in command, double all of them in dbname */
                    /* if the name has not been single quoted in command, do not doulbe them */
                    /* if name contains ] character, and the name has been [] quoted in command, double all of ] in dbname */
                    select @name = @namesave
                    select @namelen = datalength(@name)
                    declare @tempindex int
                    if (substring(@cmd, @replacecharindex - 1, 1) = N'''')
                     begin
                       /* if ? is inside of '', we need to double all the ' in name */
                       select @name = REPLACE(@name, N'''', N'''''')
                    end
                    else if (substring(@cmd, @replacecharindex - 1, 1) = N'[')
                    begin
                       /* if ? is inside of [], we need to double all the ] in name */
                       select @name = REPLACE(@name, N']', N']]')
                    end
                    else if ((@name LIKE N'%].%]') and (substring(@name, 1, 1) = N'['))
                    begin
                       /* ? is NOT inside of [] nor '', and the name is in [owner].[name] format, handle it */
                       /* !!! work around, when using LIKE to find string pattern, can't use '[', since LIKE operator is treating '[' as a wide char */
                       select @tempindex = charindex(N'].[', @name)
                       select @nametmp  = substring(@name, 2, @tempindex-2 )
                       select @nametmp2 = substring(@name, @tempindex+3, len(@name)-@tempindex-3 )
                       select @nametmp  = REPLACE(@nametmp, N']', N']]')
                       select @nametmp2 = REPLACE(@nametmp2, N']', N']]')
                       select @name = N'[' + @nametmp + N'].[' + @nametmp2 + ']'
                    end
                    else if ((@name LIKE N'%]') and (substring(@name, 1, 1) = N'['))
                    begin
                       /* ? is NOT inside of [] nor '', and the name is in [name] format, handle it */
                       /* j.i.c., since we should not fall into this case */
                       /* !!! work around, when using LIKE to find string pattern, can't use '[', since LIKE operator is treating '[' as a wide char */
                         select @nametmp = substring(@name, 2, len(@name)-2 )
                         select @nametmp = REPLACE(@nametmp, N']', N']]')
                         select @name = N'[' + @nametmp + N']'
                    end
                    /* Get the new length */
                    select @namelen = datalength(@name)
                    /* start normal process */
                    if (datalength(@cmd) + @namelen - 1 > 2000)
                    begin
                    /* Overflow; put preceding stuff into the temp table */
                        if (@useq > 9)
                        begin
                            raiserror 55555 N'sp_MSforeach_worker assert failed:  command too long'
                            close hCForEach deallocate hCForEach
                            return 1
                        end
                        if (@replacecharindex < @namelen) begin
                        /* If this happened close to beginning, make sure expansion has enough room. */
                        /* In this case no trailing space can occur as the row ends with @name. */
                        select @nextcmd = substring(@cmd, 1, @replacecharindex)
                        select @cmd = substring(@cmd, @replacecharindex + 1, 2000)
                        select @nextcmd = stuff(@nextcmd, @replacecharindex, 1, @name)
                        select @replacecharindex = charindex(@replacechar, @cmd)
                        insert #qtemp values (@useq, @nextcmd)
                        select @useq = @useq + 1
                        continue
                    end
                    /* Move the string down and stuff() in-place. */
                    /* Because varchar columns trim trailing spaces, we may need to prepend one to the following string. */
                    /* In this case, the char to be replaced is moved over by one. */
                    insert #qtemp values (@useq, substring(@cmd, 1, @replacecharindex - 1))
                    if (substring(@cmd, @replacecharindex - 1, 1) = N' ')
                    begin
                        select @cmd = N' ' + substring(@cmd, @replacecharindex, 2000)
                        select @replacecharindex = 2
                    end
                    else
                    begin
                        select @cmd = substring(@cmd, @replacecharindex, 2000)
                        select @replacecharindex = 1
                    end
                    select @useq = @useq + 1
                end
                select @cmd = stuff(@cmd, @replacecharindex, 1, @name)
                select @replacecharindex = charindex(@replacechar, @cmd)
            end
            /* Done replacing for current @cmd.  Get the next one and see if it's to be appended. */
            select @usecmd = @usecmd + 1
            select @nextcmd = case (@usecmd) when 2 then @command2 when 3 then @command3 else null end
            if (@nextcmd is not null and substring(@nextcmd, 1, 2) = N'++')
            begin
                insert #qtemp values (@useq, @cmd)
                select @cmd = substring(@nextcmd, 3, 2000), @useq = @useq + 1
                continue
            end
            /* Now exec() the generated @q*, and see if we had more commands to exec().  Continue even if errors. */
            /* Null them first as the no-result-set case won't. */
           select @q1 = null, @q2 = null, @q3 = null, @q4 = null, @q5 = null, @q6 = null, @q7 = null, @q8 = null, @q9 = null, @q10 = null
            select @q1 = qchar from #qtemp where qnum = 1
            select @q2 = qchar from #qtemp where qnum = 2
            select @q3 = qchar from #qtemp where qnum = 3
            select @q4 = qchar from #qtemp where qnum = 4
            select @q5 = qchar from #qtemp where qnum = 5
            select @q6 = qchar from #qtemp where qnum = 6
            select @q7 = qchar from #qtemp where qnum = 7
            select @q8 = qchar from #qtemp where qnum = 8
            select @q9 = qchar from #qtemp where qnum = 9
            select @q10 = qchar from #qtemp where qnum = 10
            truncate table #qtemp
            exec (@q1 + @q2 + @q3 + @q4 + @q5 + @q6 + @q7 + @q8 + @q9 + @q10 + @cmd)
            select @cmd = @nextcmd, @useq = 1
        end
        /* while @cmd is not null, generating @q* for exec() */
        /* All commands done for this name.  Go to next one. */
        fetch hCForEach into @name
    end
    /* while FETCH_SUCCESS */
    close hCForEach deallocate hCForEach
    return 0

其他一些sql中的扩展存储的总结:

xp_availablemedia    (无)      显示系统上可用的盘符'C:\' xp_availablemedia
xp_enumgroups                     列出当前系统的使用群组及其说明 xp_enumgroups
xp_enumdsn            (无)      列出系统上已经设置好的ODBC数据源名称 xp_enumdsn
xp_dirtree            (无)      显示某个目录下的子目录与文件架构 xp_dirtree 'C:\inetpub\wwwroot\'
xp_getfiledetails    (无)      获取某文件的相关属性 xp_getfiledetails 'C:\inetpub\wwwroot.asp'
dbp.xp_makecab        (无)     将目标计算机多个档案压缩到某个档案里所压缩的档案都可以接在参数的后面用豆号隔开             dbp.xp_makecab 'C:\lin.cab','evil',1,'C:\inetpub\mdb.asp'
xp_unpackcab           (无)      解压缩 xp_unpackcab 'C:\hackway.cab','C:\temp',1
xp_ntsec_enumdomains  (无)      列出服务器域名 xp_ntsec_enumdomains
xp_servicecontrol     (无)      停止或者启动某个服务 xp_servicecontrol 'stop','schedule'
xp_terminate_process  (无)     用pid来停止某个执行中的程序 xp_terminate_process 123
dbo.xp_subdirs        (无)      只列某个目录下的子目录 dbo.xp_subdirs 'C:\'

网络上有个存储过程sp_MSforeachObject,这是根据sp_MSforeachtable延伸出来的一个存储过程,扩展了应用。个人感觉很有用,这里推荐下。
USE MASTER
GO
--=============================================================
--@objectType 对象类型
--1  IsUserTable
--2  IsView
--3  IsTrigger
--4  IsProcedure
--5  IsDefault
--6  IsForeignKey
--7  IsScalarFunction
--8  IsInlineFunction
--9  IsPrimaryKey
--10 IsExtendedProc
--11 IsReplProc
--12 IsRule
--=============================================================
Create proc sp_MSforeachObject
     @objectType int=1,
     @command1 nvarchar(2000),
     @replacechar nchar(1) = N'?',
     @command2 nvarchar(2000) = null,
     @command3 nvarchar(2000) = null,
     @whereand nvarchar(2000) = null,
     @precommand nvarchar(2000) = null,
     @postcommand nvarchar(2000) = null
as
/* This proc returns one or more rows for each table (optionally, matching @where), with each table defaulting to its
own result set */
/* @precommand and @postcommand may be used to force a single result set via a temp table. */
/* Preprocessor won't replace within quotes so have to use str(). */
declare @mscat nvarchar(12)
select @mscat = ltrim(str(convert(int, 0x0002)))
if (@precommand is not null)
exec(@precommand)
/* Defined @isobject for save object type */
Declare @isobject varchar(256)
select @isobject= case @objectType when 1 then 'IsUserTable'
     when 2 then 'IsView'
     when 3 then 'IsTrigger'
     when 4 then 'IsProcedure'
     when 5 then 'IsDefault'
     when 6 then 'IsForeignKey'
     when 7 then 'IsScalarFunction'
     when 8 then 'IsInlineFunction'
     when 9 then 'IsPrimaryKey'
     when 10 then 'IsExtendedProc'
     when 11 then 'IsReplProc'
     when 12 then 'IsRule'
end
/* Create the select */
/* Use @isobject variable isstead of IsUserTable string */
EXEC(N'declare hCForEach cursor global for select ''['' + REPLACE(user_name(uid), N'']'', N'']]'') + '']'' + ''.'' + ''['' +
REPLACE(object_name(id), N'']'', N'']]'') + '']'' from dbo.sysobjects o '
    + N' where OBJECTPROPERTY(o.id, N'''+@isobject+''') = 1 '+N' and o.category & ' + @mscat + N' = 0 '
    + @whereand)
     declare @retval int
     select @retval = @@error
     if (@retval = 0)
           exec @retval = sp_MSforeach_worker @command1, @replacechar, @command2, @command3
     if (@retval = 0 and @postcommand is not null)
           exec(@postcommand)
     return @retval
GO

--下面2个例子:第一个 所有存储过程源代码,第2个修改所有表的所有者为dbo
sp_MSforeachObject 4,'sp_helptext ''?'''
sp_MSforeachObject 1,'sp_changeobjectowner ''?'', ''dbo'''  --当然这个可以应用sp_MSforeachtable 来完成

sp_MSforeachtable 与 sp_MSforeachdb的更多相关文章

  1. sp_Msforeachtable与sp_Msforeachdb详解

      一.简要介绍: 系统存储过程sp_MSforeachtable和sp_MSforeachdb,是微软提供的两个不公开的存储过程.从mssql6.5开始,存放在SQL Server的MASTER数据 ...

  2. sp_MSforeachtable使用方法

    1)说明系统存储过程sp_MSforeachtable和sp_MSforeachdb,是微软提供的两个不公开的存储过程,从ms sql 6.5开始.存放在SQL Server的MASTER数据库中. ...

  3. sp_MSforeachtable使用方法 查看库中所有表的空间大小

    sp_MSforeachtable使用方法 1)说明系统存储过程sp_MSforeachtable和sp_MSforeachdb,是微软提供的两个不公开的存储过程,从ms sql 6.5开始.存放在S ...

  4. SQL 笔记 By 华仔

    -------------------------------------读书笔记------------------------------- 笔记1-徐 最常用的几种备份方法 笔记2-徐 收缩数据 ...

  5. 最简单删除SQL Server中所有数据的方法

     最简单删除SQL Server中所有数据的方法 编写人:CC阿爸 2014-3-14 其实删除数据库中数据的方法并不复杂,为什么我还要多此一举呢,一是我这里介绍的是删除数据库的所有数据,因为数据之间 ...

  6. MSSQL数据库统计所有表的记录数

    今天需要筛选出来库中行数不为零的表,于是动手写下了如下存储过程. CREATE PROCEDURE TableCount AS BEGIN SET NOCOUNT ON ),RowsCount INT ...

  7. 分享一下我研究SQLSERVER以来收集的笔记

    分享一下我研究SQLSERVER以来收集的笔记 前言 为什麽分享??因为像现在网上很多人攻城师那样,转行去卖水果,卖早餐,总有一日我也会离开这个行业的 由于本人不是在大公司上班工资很低,我希望有一天存 ...

  8. Atitit.mssql 数据库表记录数and 表体积大小统计

    Atitit.mssql 数据库表记录数and 表体积大小统计 1. EXEC   sp_MSforeachtable   "EXECUTE   sp_spaceused   '?'&quo ...

  9. SQL Server 批量完整备份

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 实现代码(SQL Codes) 实现方式一(One) 实现方式二(Two) 实现方式三(Thr ...

随机推荐

  1. VMware与virtualbox安装centos7连接网络不可达问题解决笔记(连接网络)

    我最初是安装vmware遇到访问不到网络,按网上的配置方法都不能解决.然后我感觉可能跟系统有关,我装的是centos,然后我试着在virtualbox上安装看遇到什么问题. 用virtualbox安装 ...

  2. Android-简单拨号器案例

    Android [19]简单电话拨号器 @方法步骤 1.新建一个android程序,项目名设置为 phone  ,然后打开  phone->res->layout->activity ...

  3. C++中 引入虚基类的作用

    当某类的部分或全部直接基类是从另一个基类共同派生而来时,这直接基类中,从上一级基类继承来的成员就拥有相同的名称,派生类的对象的这些同名成员在内存中同时拥有多个拷贝,同一个函数名有多个映射.可以使用作用 ...

  4. javascript循环和数组的基础练习

    九九乘法表 <script> //外层循环行数 for(var i=0; i<=9; i++){ //内曾循环控制每一行的列数 for(var j=0;j<=i; j++){ ...

  5. 一起来做webgame,《卡片魔兽》(一)基础战斗

    写在前面的话 这不是教程,只是博主在娱乐过程中的一些小结记录.博主水平有限,没有什么高级的东西,只是将一些小的知识点结合一下,做这么一个养成类型的卡片页面游戏(=.=!有点绕).做一个完整的游戏,涉及 ...

  6. Update Request

    public function update(UpdateAppointmentRequest $request) { try { $data = array_filter($request-> ...

  7. CocoaPods for Xcode

    http://www.cnblogs.com/MrRed/p/5728933.html 非常方便的Xcode pods插件.可以很方便的在Xcode通过pods安装各种objective-c第三方库, ...

  8. 使用JSON.Net(Newtonsoft.Json)作为ASP.Net MVC的json序列化和反序列化工具

    ASP.Net MVC默认的JSON序列化使用的是微软自己的JavaScriptSerializer.性能低不说,最让人受不了的是Dictionary<,>和Hashtable类型居然对应 ...

  9. tensorfolw配置过程中遇到的一些问题及其解决过程的记录(配置SqueezeDet: Unified, Small, Low Power Fully Convolutional Neural Networks for Real-Time Object Detection for Autonomous Driving)

    今天看到一篇关于检测的论文<SqueezeDet: Unified, Small, Low Power Fully Convolutional Neural Networks for Real- ...

  10. 自动更新补丁Security Update for Internet Explorer 10 for Windows Server 2008 R2 x64 Edition (KB2964358)失败

    下载http://www.microsoft.com/zh-CN/download/details.aspx?id=42581手动安装成功.