[翻译]SQL Server 未公开的两个存储过程sp_MSforeachtable 和 sp_MSforeachdb
SQL Server 未公開的兩個存儲過程sp_MSforeachtable 和 sp_MSforeachdb
您是否曾經寫過代碼來處理數據庫中的所有表?處理一個 SQL Server實例中的所有數據庫的代碼又該如何寫?然則,您是否知道有多種方法可以解決這問題?您可以創(chuàng)建一個游標cursor包含所有數據表,或者包含SQL Server實例的所有數據庫;或者使用非公開(undocumented)的存儲過程。本文將向您闡述非公開的存儲過程的工作方式,以及應用實例向您展示如何使用它們。非公開的存儲過程比之游標更易用。
概述
Microsoft 提供了兩個非公開化的存儲過程,讓您可以迭代處理數據庫中的所有表,或者SQL Server 實例中的所有數據庫。第一個存儲過程是"sp_MSforeachtable",讓您可以輕易地使用代碼處理數據庫中的所有表;另一個是"sp_MSforeachdb",處理SQL Server 實例中的所有數據庫。讓我們深入地了解這兩個存儲過程。
sp_MSforeachtable
"sp_MSforeachtable"沒有在在線文檔中出現,它存在于master數據庫中,可以對給定數據庫的所有表執(zhí)行單條或多條T-SQL命令,請看下面的例子。
假如,您需要創(chuàng)建一個臨時表,記錄當前數據庫擁有的表的表名、行記錄數。為了實現此功能,您需要執(zhí)行這樣的命令:"select '<mytable>', count(*) from <mytable>"。其中"<mytable>"替換為數據庫中的每個表名,并將結果插入到臨時表。下面我們用游標與非公開的"sp_MSforeachtable"來分別實現。
使用游標的方式:
下面是輸出結果:
下面代碼應用非公開的"sp_MSforeachtable"生成相同的結果:
下面是結果:
可見,使用游標與sp_MSforeachtable可生成相同的結果,您認為哪種方式更具可讀性,更簡單?下面來詳細介紹sp_MSforeachtable的語法:
exec @RETURN_VALUE=sp_MSforeachtable @command1, @replacechar, @command2,
@command3, @whereand, @precommand, @postcommand
說明:
- @RETURN_VALUE – 返回值
- @command1 – 類型是nvarchar(2000),sp_MSforeachtable最先執(zhí)行的命令
- @replacechar – 處理過程中,將命令行的這個字符替換為具體的表名(默認是"?")
- @command2\@command3:對每個數據表,都會執(zhí)行這兩條命令,@command2在@command1之后執(zhí)行,@command3在@command2之后執(zhí)行
- @whereand – 類型是varchar(2000),提供額外的約束來過濾 sysobjects 表的行
- @precommand - 類型是varchar(2000),在處理任何表之前執(zhí)行此命令
- @postcommand - 類型是varchar(2000),在處理完所有表之后執(zhí)行此命令
下面幾個例子演示此存儲過程的用法,處理所有表或者部分表。
下面查詢以字母 p 開頭的表,使用參數 @whereand 設置過濾條件,代碼如下:
下面是結果:
上面的代碼使用了參數 @command1 與 @whereand,參數 @whereand 用來設置 WHERE 條件,篩選出以字母 p 開頭的表名,我設置了參數值為"and o.name like ''p%''"。如果您希望使用多個條件約束,如以 p 開頭或者以 a 開頭,設置參數值為:
and o.name like ''p%'' or o.name like ''a%''
?
如果語句有問題,將 name 的前綴去掉,如下:
?
and name like ''p%'' or name like ''a%''
?
注意,上面例子的參數 @command1 使用了"?",它叫做替換字符(replacement character),默認被所有表名替換。如果您需要在命令中使用"?"作為內容而不是被表名替換的替換字符,那么可以使用參數 @replacechar 來設置替換字符。下面例子使用"{"作為替換字符。
下面是結果:
還有兩個參數 @precommand 與 @postcommand,看下面例子,把上面例子中的所有語句整合為一個簡潔的存儲過程調用。
注意上面例子用了全局臨時表 ##rowcount,如果用臨時表 #rowcount會報錯。參數 @precommand 創(chuàng)建全局臨時表,只執(zhí)行了一次,并先于 @command1 的語句執(zhí)行。@postcommmand 的語句待迭代處理完所有表后執(zhí)行,也僅執(zhí)行一次,用于顯示結果并刪除臨時表。
?
sp_MSforeachdb
sp_MSforeachdb 同樣也是在 master 數據庫中,它迭代SQL Server 實例中的每個數據庫,以執(zhí)行T-SQL 語句,如"DBCCCHECKDB",在看看它的語法
exec @RETURN_VALUE = sp_MSforeachdb @command1, @replacechar,
@command2, @command3, @precommand, @postcommand
說明:
- @RETURN_VALUE – 返回值
- @command1 – 類型是 nvarchar(2000),最先執(zhí)行的命令
- @replacechar – 替換字符,命令字符串中被替換為實際的數據庫名(默認是"?")
- @command2\@command3:對每個數據庫,都會執(zhí)行這兩條命令,@command2在@command1之后執(zhí)行,@command3在@command2之后執(zhí)行
- @precommand - 類型是varchar(2000),在處理任何數據庫之前執(zhí)行此命令
- @postcommand - 類型是varchar(2000),在處理完所有數據庫之后執(zhí)行此命令
sp_MSforeachdb 的參數與sp_MSforeachtable 的參數類似,因此,不再特意介紹這些參數。
請看下面的簡單例子,此例子將進行數據庫備份,然后對每個數據庫做"DBCC CHECKDB":
這里我用了三條不同的命令,第一條打印正在處理的數據庫名。sp_MSforeachtable 有一個參數用來過濾需要處理的數據表,但是sp_MSforeachdb沒有類似的過濾參數。由于SQL Server 不支持對 tempdb 的備份,因此我要跳過tempdb,這是我在每條命令使用 IF 的原因。第二條命令進行數據庫備份,最后一條命令對除 tempdb 之外的數據庫運行"DBCC CHECKDB"。
運行上面命令之前要先創(chuàng)建目錄"c:\temp",下面是部分輸出結果:
?
使用SQL Server非公開存儲過程的說明
當使用這些非公開的存儲過程時您須小心,并進行測試。由于未公開,意味著Microsoft在任何版本的升級或者補丁包都可能對它們進行修改,并且不做任何告知。因此,您需要在所有的SQL Server版本做全面的測試,測試以驗證您的代碼是否在新版本中仍然正常運行。
結語
正如您所見,這兩個非公開的存儲過程比游標易用,以后您可以用它們來迭代處理數據表或數據庫。但是請謹記,這兩個存儲過程是非公開的,Microsoft很可能會隨時改變它們的功能。
參考
SQL Server Undocumented Stored Procedures sp_MSforeachtable and sp_MSforeachdb
sp_MSforeachtable
?
轉載于:https://www.cnblogs.com/feixian49/archive/2011/05/10/2042733.html
總結
以上是生活随笔為你收集整理的[翻译]SQL Server 未公开的两个存储过程sp_MSforeachtable 和 sp_MSforeachdb的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: win7NVIDIA显卡驱动升级时卡住
- 下一篇: ovnif摄像头修改ip