下面我們討論的前提都是您有過一定的SQLServer存儲過程的編寫經(jīng)驗(yàn),下面的各種技巧如果沒有特別注明,則同時適用于SQLServer7.0和SQLServer2000。
1、使用OUTPUT類型參數(shù)的存儲過程的技巧
一般的存儲過程都是直接返回一段記錄集給調(diào)用者,但是有的時候我們只需要一些存儲過程返回的一些參數(shù)的值,這時候可以指定存儲過程的OUTPUT參數(shù),比如:
Create procedure GetName
@uid nvarchar(1),
@usernam nvarchar(10)=‘‘ output
AS
set @username=‘hongchao‘
GO
在上面的存儲過程當(dāng)中我們傳遞進(jìn)的參數(shù)是@uid,而參數(shù)@username則在調(diào)有的時候不需要傳遞進(jìn)去。這樣,存儲過程會返回給我們參數(shù)@username的值是‘hongchao’。上面的都比較的容易,需要注意的是,當(dāng)在SQL2000中的時候,如果你的存儲過程只有一個參數(shù),并且這個參數(shù)是OUTPUT類型的,你必須在調(diào)用這個存儲過程的時候給這個參數(shù)一個初始的值,否則會出現(xiàn)調(diào)用錯誤的情況!
2、在存儲過程中的書寫注意事項(xiàng)
這一點(diǎn)在SQLServer7.0和SQLServer2000中有些地方是不一樣的,也不
知道是不是微軟的遺漏,那就是有些系統(tǒng)的關(guān)鍵字在不同的版本之間有所不同,比如關(guān)鍵字level,同樣的一句話:
select * from users where level=1
在SQLServer7當(dāng)中的存儲過程當(dāng)中運(yùn)行沒有絲毫的問題,但是到了SQLServer2000當(dāng)中則會出現(xiàn)運(yùn)行的錯誤,原因就是在于在SQLServer2000中“level”被當(dāng)作了關(guān)鍵字(奇怪的是SQL7當(dāng)中也同樣是關(guān)鍵字,卻沒問題),所以在SQL2000當(dāng)中,上面的語句應(yīng)當(dāng)改為:
select * from users where [level]=1
從上面的例子中我們可以看到,在你編寫存儲過程的時候,最好在有可能和系統(tǒng)關(guān)鍵字的地方使用“[”和“]”將他包圍起來,以避免在移植過程中出現(xiàn)的運(yùn)行錯誤問題。
3、在存儲過程中使用系統(tǒng)存儲過程SP_Executesql的注意事項(xiàng)
我們在編寫自己的存儲過程的時候,往往在很多的情況下,會使用到系統(tǒng)的存儲過程SP_Execute。但是需要的注意的是,如果你在這個存儲過程的參數(shù)(一般是一段SQL語句)當(dāng)中進(jìn)行了臨時Table的操作,那末對于調(diào)用者來說,這個臨時Table是不可見的,也就是說你無法通過臨時Table來在調(diào)用者和被調(diào)用者之間傳遞值。解決的方法是使用全局臨時Table,也就是“##”開頭的Table。
4、在存儲過程中使用臨時Table和游標(biāo)的注意事項(xiàng)
如果我們的商業(yè)邏輯比較復(fù)雜,在存儲過程當(dāng)中,就需要一些媒介作為中轉(zhuǎn)臺,這時候臨時表j就發(fā)揮了作用,但是請務(wù)必記得在使用完之后,即時刪除使用到的臨時Table。
而在存儲過程當(dāng)中想要依次遍歷一個記錄集的唯一方法就是使用系統(tǒng)游標(biāo),同樣要注意的是,在使用完成之后及時關(guān)閉和銷毀游標(biāo)對象釋放他用到的資源。并且不在萬不得已的情況下,不要隨意使用游標(biāo),因?yàn)樗麜加幂^多的系統(tǒng)資源,尤其是對于大并發(fā)量的情況下,很容易使得系統(tǒng)資源耗盡而崩潰。
使用臨時Table和游標(biāo)各有利弊,在使用的過程中要適當(dāng)?shù)睦眉纯?
5、在存儲過程中調(diào)用外部的ActiveX DLL程序
有些特殊的情況下,我們可能會需要調(diào)用外部的ActiveX DLL程序,這個時候就需要使用到系統(tǒng)的存儲過程sp_OACreate以及其他的相關(guān)系統(tǒng)存儲過程,都是以sp_OA開頭的存儲過程,可以自由的在自己的存儲過程當(dāng)中調(diào)用ActiveX DLL的各種方法和屬性。比如下面的例子:
DECLARE @object int
DECLARE @hr int
DECLARE @property varchar(255)
DECLARE @return varchar(255)
DECLARE @src varchar(255), @desc varchar(255)
-- 建立一個對象(SQLDMO.SQLServer).
EXEC @hr = sp_OACreate ‘SQLDMO.SQLServer‘,
@object OUT
IF @hr <> 0
BEGIN
EXEC sp_OAGetErrorInfo @object, @src OUT, @desc OUT
SELECT hr=convert(varbinary(4),@hr),
Source=@src, Description=@desc
RETURN
END
-- 設(shè)置對象的屬性.
EXEC @hr = sp_OASetProperty @object, ‘HostName‘, ‘Gizmo‘
IF @hr <> 0
BEGIN
EXEC sp_OAGetErrorInfo @object, @src OUT, @desc OUT
SELECT hr=convert(varbinary(4),@hr),
Source=@src, Description=@desc
RETURN
END
-- 通過OUTPUT參數(shù)獲取對象的屬性值.
EXEC @hr = sp_OAGetProperty @object, ‘HostName‘, @property OUT
IF @hr <> 0
BEGIN
EXEC sp_OAGetErrorInfo @object, @src OUT, @desc OUT
SELECT hr=convert(varbinary(4),@hr), Source=@src, Description=@desc
RETURN
END
PRINT @property
-- 調(diào)用對象的方法
EXEC @hr = sp_OAMethod @object, ‘Connect‘, NULL, ‘my_server‘, ‘my_login‘, ‘my_password‘
IF @hr <> 0
BEGIN
EXEC sp_OAGetErrorInfo @object, @src OUT, @desc
OUT
SELECT hr=convert(varbinary(4),@hr), Source=@src, Description=@desc
RETURN
END
-- 銷毀已經(jīng)創(chuàng)建的ActiveX對象
EXEC @hr = sp_OADestroy @object
IF @hr <> 0
BEGIN
EXEC sp_OAGetErrorInfo @object, @src OUT, @desc
OUT
SELECT hr=convert(varbinary(4),@hr), Source=@src, Description=@desc
RETURN
END
6、在存儲過程中使用數(shù)據(jù)庫事務(wù)處理
在很多的情況下,我們在存儲過程中都會遇到需要同時操作多個表的情況,這時候就需要避免在操作的過程中由于以外而造成的數(shù)據(jù)的不一致性。這時候就需要將操作多個表的操作放入到事務(wù)中進(jìn)行處理。
但是需要注意的是,不能在事務(wù)中使用return語句強(qiáng)行退出,這樣會引發(fā)事務(wù)的非正常錯誤,不能保證數(shù)據(jù)的一致性。
并且,一旦將多個處理放入事務(wù)當(dāng)中,系統(tǒng)的處理速度會有所降低,所以應(yīng)當(dāng)將頻繁操作的多個可分割的處理過程放入到多個存儲過程當(dāng)中,這樣會大大提高系統(tǒng)的響應(yīng)速度,但是前提是不違背數(shù)據(jù)的一致性。
看完了上面的這些編寫SQL Server存儲過程當(dāng)中的技巧,相信對您或多或少會有些幫助,也希望通過上面的一些經(jīng)驗(yàn)總結(jié),可以使得您在應(yīng)用SQL Server存儲過程的時候,有意識的可以避免一些彎路