天天看點

SQL Server 在多個資料庫中建立同一個存儲過程(Create Same Stored Procedure in All Databases)一.本文所涉及的内容(Contents)二.背景(Contexts)三.遇到的問題(Problems)四.實作代碼(SQL Codes)五.參考文獻(References)

<a href="#_labelContents">本文所涉及的内容(Contents)</a>

<a href="#_labelContexts">背景(Contexts)</a>

<a href="#_labelProblems">遇到的問題(Problems)</a>

<a href="#_labelSQLCodes">實作代碼(SQL Codes)</a>

<a href="#_labelOne">方法一:拼接SQL;</a>

<a href="#_labelTwo">方法二:調用模闆存儲過程建立存儲過程;</a>

<a href="#_labelThree">總結</a>

<a href="#_labelFour">擴充閱讀</a>

<a href="#_labelReferences">參考文獻(References)</a>

  在我的資料庫伺服器上,同一個執行個體下面挂載着許多相同結構的資料庫,他們為不同公司提供着服務,在許多時候我需要同時建立、修改、删除一些對象,存儲過程就是其中一個,但是想要批量建立存儲,這有些特殊,下面就教你如何實作在多個資料庫中建立同一個存儲過程(Create Same Stored Procedure in All Databases)。

  在之前的文章中多次談到使用遊标的方式處理的各種問題:

<a href="http://www.cnblogs.com/gaizai/archive/2013/05/08/3066918.html">SQL Server 遊标運用:檢視所有資料庫所有表大小資訊(Sizes of All Tables in All Database)</a>

<a href="http://www.cnblogs.com/gaizai/archive/2013/05/07/3064489.html">SQL Server 遊标運用:檢視一個資料庫所有表大小資訊(Sizes of All Tables in a Database)</a>

  如果使用遊标來批量建立存儲過程,可能你會遇到下面的一些問題,假設我們需要在多個資料庫(當然可以過濾掉部分資料庫)中建立同樣一個存儲過程sp_GetId,存儲過程的腳本如下Script1所示:

  根據前面提到使用遊标方式,我們可能會寫出類似下面的代碼,錯誤代碼Script2示例:

執行上面的代碼你會遇到這樣的錯誤資訊:

SQL Server 在多個資料庫中建立同一個存儲過程(Create Same Stored Procedure in All Databases)一.本文所涉及的内容(Contents)二.背景(Contexts)三.遇到的問題(Problems)四.實作代碼(SQL Codes)五.參考文獻(References)

(Figure1:錯誤資訊1)

根據錯誤資訊修改上面的SQL代碼,把”GO”改成“;”但還是會出現下圖Figure2的錯誤資訊:

SQL Server 在多個資料庫中建立同一個存儲過程(Create Same Stored Procedure in All Databases)一.本文所涉及的内容(Contents)二.背景(Contexts)三.遇到的問題(Problems)四.實作代碼(SQL Codes)五.參考文獻(References)

(Figure2:錯誤資訊2)

既然這樣行不通,也許你還會嘗試在[dbo].[sp_GetId]前面加上資料庫名的變量,但是卻出現下圖Figure3的錯誤資訊:

SQL Server 在多個資料庫中建立同一個存儲過程(Create Same Stored Procedure in All Databases)一.本文所涉及的内容(Contents)二.背景(Contexts)三.遇到的問題(Problems)四.實作代碼(SQL Codes)五.參考文獻(References)

(Figure3:錯誤資訊3)

  上面的3個錯誤讓我們陷入了困境,也許你想過放棄了,但是經過努力,我通過2種方式實作了在多個資料庫中建立同一個存儲過程(大家可認為是批量建立存儲過程),下面是實作的2種方式概述:

  1. 通過修改過的系統存儲過程[dbo].[sp_MSforeachdb_Filter]和拼接SQL;

  2. 通過建立一個模闆存儲過程,由系統存儲過程sp_MSForEachDB循環調用另外一個建立存儲過程的存儲來建立模闆存儲過程(這也許聽起來很拗口,看後面的實作腳本Script7,你就會了解了)。

  1) 首先我們需要在master資料庫中建立一個存儲過程[dbo].[sp_MSforeachdb_Filter],這是通過修改系統存儲過程sp_MSforeachdb得來的,做的改進主要是可以過濾資料庫,建立的SQL代碼如下Script3所示:

  2) 接着在master資料庫中執行下面的SQL在多個資料庫中建立同一個存儲過程,其實是把需要建立的存儲過程通過拼接儲存在@SQL變量中,使用[sp_MSforeachdb_Filter]來過濾資料庫,并在符合條件的每個資料庫中執行@SQL中的語句,SQL代碼如下Script4所示:

  3) 執行上面的SQL腳本之後,除了('tempdb','master','model','msdb')4個資料庫之外的資料庫都會建立了存儲過程sp_GetId,為了快速驗證,可以使用下面的SQL腳本進行驗證:

執行上面的SQL腳本的結果如下圖Figure4所示:

SQL Server 在多個資料庫中建立同一個存儲過程(Create Same Stored Procedure in All Databases)一.本文所涉及的内容(Contents)二.背景(Contexts)三.遇到的問題(Problems)四.實作代碼(SQL Codes)五.參考文獻(References)

(Figure4:建立了sp_GetId存儲過程的資料庫清單)

  1) 為了能看到方式2的實際效果,我們需要把存在sp_GetId存儲過程的資料庫中批量删除這個存儲過程,通過下面的腳本Script6來實作:

  2) 通過Script5确認所有資料庫都不存在sp_GetId存儲過程;

  4) 再接着建立一個存儲過程CreateProcedure,這個存儲過程的作用就是建立存儲過程,在這個存儲過程CreateProcedure利用系統表傳回sp_GetId存儲過程的内容,儲存在變量@proc_text中,查詢出如下所示:

  5) 準備完上面的步驟,隻需要下面的一條SQL語句就能批量建立存儲過程sp_GetId:

執行上面的SQL腳本的結果如下圖Figure5所示,與Figure4的差別就是在master資料庫中多了一個模闆存儲過程sp_GetId。

SQL Server 在多個資料庫中建立同一個存儲過程(Create Same Stored Procedure in All Databases)一.本文所涉及的内容(Contents)二.背景(Contexts)三.遇到的問題(Problems)四.實作代碼(SQL Codes)五.參考文獻(References)

  上面已經通過兩種方式實作了在多個資料庫中建立同一個存儲過程,如果存儲過程sp_GetId屬于比較簡單的,使用方式1實作會比較快捷,如果sp_GetId比較複雜了,比如存儲過程裡面還包含單引号或者代碼比較多的情況下,建議使用方式2,雖然方式2的步驟會多一點,但是隻要建立好模闆存儲過程,其它的根本不會因為存儲過程sp_GetId而變得複雜;

  在實際運用中,很多時候你需要的并不單單是在多個資料庫中建立同一個存儲過程,可能還需要修改同一個存儲過程,通過上面的閱讀你也許猜到修改存儲過程,可以先删除,再建立,對的,這是沒有問題的,不過也可以直接修改,下面提供SQL代碼:

  1) 首先修改下master資料庫的模闆存儲過程sp_GetId,在存儲過程裡面中加入一個變量@id:

  2) 接着建立一個修改存儲過程的存儲過程AlterProcedure,隻需要把變量@proc_text裡面的“CREATE PROC”替換成“ALTER PROC”就可以了:

  3) 準備完上面的步驟,再把Script8的腳本中調用存儲過程CreateProcedure改成調用存儲過程AlterProcedure,通過下面的一條SQL語句批量修改存儲過程sp_GetId:

  4) 建立完成後,剩下的就是驗證下資料庫中存儲過程sp_GetId的内容了;

<a href="http://www.kodyaz.com/articles/create-stored-procedure-using-sp_msforeachdb-on-all-databases.aspx">Create Same Stored Procedure on All Databases using sp_MSForEachDB T-SQL Example</a>