很早就知道可以用.NET為SQL Server2005及以上版本編寫存儲過程、觸發器和存儲過程的,不過之前開發的系統要么因為歷史原因用的是SQL2000要么根本用不著在SQL Server中啟用CLR,所以一直沒有嘗試。最近因為項目的原因,在這方面做了一個調研,現在在這里分享一下心得。
首先要說明的是要在SQL Server中啟用CLR必須是在SQL Server2005及以上版本,其次在默認情況下是沒有啟用CLR的,必須要顯示設置為啟用。比如我們要在ArticleCollectorDB數據庫中運行用.NET編寫的函數或者存儲過程,至少先要進行下面的SQL語句:
exec?sp_configure?'clr?enabled',?1;?reconfigure;?go??ALTER?DATABASE?[ArticleCollectorDB]?SET?TRUSTWORTHY?ON?
這時可能會得到提示要重新啟動SQL Server,如果有此提示則重新啟動一下。
接著我們在VS中進行編碼,在這里我們將分別編寫一個名為IsMatch的函數和一個名為SendMail存儲過程。在VS中創建一個名為NetSkycn.Data的類庫項目,添加一個SqlCLR的類,代碼如下:
using?System.Data.SqlTypes;?using?System.Net;?using?System.Net.Mail;?using?System.Security.Permissions;?using?System.Text.RegularExpressions;?using?Microsoft.SqlServer.Server;??namespace?NetSkycn.Data?{????????public?sealed?class?SqlCLR?{????????[SqlFunction(IsDeterministic?=?true,?DataAccess?=?DataAccessKind.None)]?public?static?SqlBoolean?IsMatch(string?source,?string?pattern,int?options)?{?if?(string.IsNullOrEmpty(source)?||?string.IsNullOrEmpty(pattern))?{?return?SqlBoolean.False;?}?RegexOptions?regexOptions=RegexOptions.None;?int?optionIgnoreCase?=?1;?int?optionMultiline?=?2;?if?((options?&?optionIgnoreCase)?!=?0)?{?regexOptions?=?regexOptions?|?RegexOptions.IgnoreCase;?}??if?((options?&?optionMultiline)?!=?0)?{?regexOptions?=?regexOptions?|?RegexOptions.Multiline;?}??return?(SqlBoolean)(Regex.IsMatch(source,?pattern,?regexOptions));?}???????????[SqlProcedure]?[SmtpPermission(SecurityAction.Assert)]?[SecurityPermission(SecurityAction.Assert)]?public?static?void?SendMail(string?to,?string?from,?string?subject,?string?body,?string?userName,?string?password,?string?smtpHost)?{?MailAddress?addressFrom?=?new?MailAddress(from);?MailAddress?addressTo?=?new?MailAddress(to);?MailMessage?message?=?new?MailMessage(addressFrom,?addressTo);?message.Subject?=?subject;?message.IsBodyHtml?=?true;?message.Body?=?body;??SmtpClient?client?=?new?SmtpClient(smtpHost);????client.Credentials?=?new?NetworkCredential(userName,?password);?client.Send(message);?}??}?}?
編譯通過之后,記住類庫的物理全路徑,比如:F:\VS2008\netskycn\NetSkycn.Data\bin\Release\NetSkycn.Data.dll,在這里要強調幾點:一、對于將來提供給SQL Server調用的函數或者存儲過程必須是靜態方法,并且還必須帶有SqlFunction或者SqlProcedure屬性;二、對于一些需要訪問外部網絡資源和安全屬性的還必須添加響應的屬性(如本例中的SendMail方法,如果沒有添加響應的屬性在創建SQL Function/Procedure時會出現錯誤提示)。
現在我們開始遵循先為SQL Server創建程序集、后創建函數或者存儲過程的順序來操作,在操作過程中用到的SQL語句如下:
?ALTER?DATABASE?[ArticleCollectorDB]?SET?TRUSTWORTHY?ON???IF?EXISTS(SELECT?*?FROM?SYS.SYSOBJECTS?WHERE?NAME='SendMail'?AND?XTYPE='PC')??DROP?PROCEDURE?SendMail???IF?EXISTS(SELECT?*?FROM?SYS.SYSOBJECTS?WHERE?NAME='IsMatch'?AND?XTYPE='FS')??DROP?FUNCTION?IsMatch???IF?EXISTS(SELECT?*?FROM?SYS.ASSEMBLIES?WHERE?NAME='SqlCLR')??DROP?ASSEMBLY?SqlCLR???CREATE?ASSEMBLY?SqlCLR?FROM?'F:\VS2008\netskycn\NetSkycn.Data\bin\Release\NetSkycn.Data.dll'?WITH?PERMISSION_SET?=?UNSAFE?GO??????CREATE?FUNCTION?[dbo].[IsMatch]??(??@source?AS?NVARCHAR(200),?@pattern?AS?NVARCHAR(200),?@option?INT=3?)??RETURNS?BIT??AS??EXTERNAL?NAME?[SqlCLR].[NetSkycn.Data.SqlCLR].[IsMatch];??GO??????CREATE?PROCEDURE?[dbo].[SendMail]??(??@to?AS?NVARCHAR(200),?@from?AS?NVARCHAR(200),?@subject?AS?NVARCHAR(200),?@body?AS?NVARCHAR(MAX),?@userName?AS?NVARCHAR(200),?@password?AS?NVARCHAR(200),?@smtpHost?AS?NVARCHAR(200)?)?AS??EXTERNAL?NAME?[SqlCLR].[NetSkycn.Data.SqlCLR].[SendMail];??GO?
如果沒有得到任何錯誤提示,則表示創建函數和存儲過程成功。至此我們會看到如下情形:
這表示創建成功。
測試創建函數的SQL語句(查找article表中title字段是3至5個字段的數據):
select?*?from?article?where?dbo.IsMatch(Title,'^[\u4e00-\u9fa5]{3,5}$',3)=1?
測試創建存儲過程的SQL語句:
exec?[dbo].SendMail?@to='test@qq.com',@from='webmaster@qq.com',@subject='test',@body='This?mail?was?sent?by?SQL?Procedure',@userName='webmaster',@password='123',@smtpHost='smtp.qq.com'?
以上代碼在SQL Server 2005中文企業版、SQL Server 2008英文企業版測試通過。
可以看出在一些SQL語句不夠靈活的情況下,可以使用.NET來編寫存儲過程和函數,通過以上步驟之后和調用SQL語句寫的存儲過程和函數沒有區別,極大地方便了編程。
周公
2012-05-12
?
總結
以上是生活随笔為你收集整理的SQL Server中的CLR编程——用.NET为SQL Server编写存储过程和函数的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。