SQL Server中的CLR编程——用.NET为SQL Server编写存储过程和函数
2012-05-12 19:23
483 查看
转载来自周公的blog.....
很早就知道可以用.NET为SQL Server2005及以上版本编写存储过程、触发器和存储过程的,不过之前开发的系统要么因为历史原因用的是SQL2000要么根本用不着在SQL Server中启用CLR,所以一直没有尝试。最近因为项目的原因,在这方面做了一个调研,现在在这里分享一下心得。
首先要说明的是要在SQL Server中启用CLR必须是在SQL Server2005及以上版本,其次在默认情况下是没有启用CLR的,必须要显示设置为启用。比如我们要在ArticleCollectorDB数据库中运行用.NET编写的函数或者存储过程,至少先要进行下面的SQL语句:
[sql]
view plaincopyprint?
exec sp_configure 'clr enabled', 1;--在SQL Server中启用CLR
reconfigure;
go
--在ArticleCollectorDB数据库中设置TRUSTWORTHY为ON
ALTER DATABASE [ArticleCollectorDB] SET TRUSTWORTHY ON
编译通过之后,记住类库的物理全路径,比如:F:\VS2008\netskycn\NetSkycn.Data\bin\Release\NetSkycn.Data.dll,在这里要强调几点:一、对于将来提供给SQL Server调用的函数或者存储过程必须是静态方法,并且还必须带有SqlFunction或者SqlProcedure属性;二、对于一些需要访问外部网络资源和安全属性的还必须添加响应的属性(如本例中的SendMail方法,如果没有添加响应的属性在创建SQL Function/Procedure时会出现错误提示)。
现在我们开始遵循先为SQL Server创建程序集、后创建函数或者存储过程的顺序来操作,在操作过程中用到的SQL语句如下:
[sql]
view plaincopyprint?
--在ArticleCollectorDB数据库中设置TRUSTWORTHY为ON
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
--如果已经存在SqlCLR程序集则删除该程序集
IF EXISTS(SELECT * FROM SYS.ASSEMBLIES WHERE NAME='SqlCLR')
DROP ASSEMBLY SqlCLR
--在SQL Server中创建程序集,,创建的程序集名为SqlCLR
CREATE ASSEMBLY SqlCLR FROM 'F:\VS2008\netskycn\NetSkycn.Data\bin\Release\NetSkycn.Data.dll' WITH PERMISSION_SET = UNSAFE
GO
--从CLR程序集中创建函数,函数名为IsMatch,有三个参数,
--[SqlCLR]是SQL Server中程序集名
--[NetSkycn.Data.SqlCLR]是.NET中的类的全名(命名空间及类名)
--[IsMatch]是.NET中类的函数名
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
--从CLR程序集中创建函数,函数名为IsMatch,有三个参数,
--[SqlCLR]是SQL Server中程序集名
--[NetSkycn.Data.SqlCLR]是.NET中的类的全名(命名空间及类名)
--[SendMail]是.NET中类的函数名
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语句:
[csharp]
view plaincopyprint?
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'
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语句写的存储过程和函数没有区别,极大地方便了编程。
很早就知道可以用.NET为SQL Server2005及以上版本编写存储过程、触发器和存储过程的,不过之前开发的系统要么因为历史原因用的是SQL2000要么根本用不着在SQL Server中启用CLR,所以一直没有尝试。最近因为项目的原因,在这方面做了一个调研,现在在这里分享一下心得。
首先要说明的是要在SQL Server中启用CLR必须是在SQL Server2005及以上版本,其次在默认情况下是没有启用CLR的,必须要显示设置为启用。比如我们要在ArticleCollectorDB数据库中运行用.NET编写的函数或者存储过程,至少先要进行下面的SQL语句:
[sql]
view plaincopyprint?
exec sp_configure 'clr enabled', 1;--在SQL Server中启用CLR
reconfigure;
go
--在ArticleCollectorDB数据库中设置TRUSTWORTHY为ON
ALTER DATABASE [ArticleCollectorDB] SET TRUSTWORTHY ON
[csharp] view plaincopyprint? 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 { /// <summary> /// 在SQL Server环境中执行的CLR方法,注意提供给SQL Server调用的方法必须有SqlFunction/SqlProcedure Attribute /// 作者:周公 /// 创建日期:2012-05-09 /// 博客地址:http://blog.csdn.net/zhoufoxcn http://zhoufoxcn.blog.51cto.com /// 新浪微博地址:http://weibo.com/zhoufoxcn /// </summary> public sealed class SqlCLR { /// <summary> /// 判断字符串是否匹配正则表达式 /// </summary> /// <param name="source">要匹配的文本</param> /// <param name="pattern">进行匹配的正则表达式</param> /// <param name="options">正则表达式匹配选项,1为忽略大小写,2为多行匹配,3为忽略大小写且多行匹配</param> /// <returns></returns> [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)); } /// <summary> /// 发送邮件 /// </summary> /// <param name="to">收件人邮件地址</param> /// <param name="from">发件人邮件地址</param> /// <param name="subject">邮件主题</param> /// <param name="body">邮件内容</param> /// <param name="username">登录smtp主机时用到的用户名,注意是邮件地址'@'以前的部分</param> /// <param name="password">登录smtp主机时用到的用户密码</param> /// <param name="smtpHost">发送邮件用到的smtp主机</param> [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;//设置邮件正文为html格式 message.Body = body;//设置邮件内容 SmtpClient client = new SmtpClient(smtpHost); //设置发送邮件身份验证方式 //注意如果发件人地址是abc@def.com,则用户名是abc而不是abc@def.com client.Credentials = new NetworkCredential(userName, password); client.Send(message); } } } 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 { /// <summary> /// 在SQL Server环境中执行的CLR方法,注意提供给SQL Server调用的方法必须有SqlFunction/SqlProcedure Attribute /// 作者:周公 /// 创建日期:2012-05-09 /// 博客地址:http://blog.csdn.net/zhoufoxcn http://zhoufoxcn.blog.51cto.com /// 新浪微博地址:http://weibo.com/zhoufoxcn /// </summary> public sealed class SqlCLR { /// <summary> /// 判断字符串是否匹配正则表达式 /// </summary> /// <param name="source">要匹配的文本</param> /// <param name="pattern">进行匹配的正则表达式</param> /// <param name="options">正则表达式匹配选项,1为忽略大小写,2为多行匹配,3为忽略大小写且多行匹配</param> /// <returns></returns> [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)); } /// <summary> /// 发送邮件 /// </summary> /// <param name="to">收件人邮件地址</param> /// <param name="from">发件人邮件地址</param> /// <param name="subject">邮件主题</param> /// <param name="body">邮件内容</param> /// <param name="username">登录smtp主机时用到的用户名,注意是邮件地址'@'以前的部分</param> /// <param name="password">登录smtp主机时用到的用户密码</param> /// <param name="smtpHost">发送邮件用到的smtp主机</param> [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;//设置邮件正文为html格式 message.Body = body;//设置邮件内容 SmtpClient client = new SmtpClient(smtpHost); //设置发送邮件身份验证方式 //注意如果发件人地址是abc@def.com,则用户名是abc而不是abc@def.com 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语句如下:
[sql]
view plaincopyprint?
--在ArticleCollectorDB数据库中设置TRUSTWORTHY为ON
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
--如果已经存在SqlCLR程序集则删除该程序集
IF EXISTS(SELECT * FROM SYS.ASSEMBLIES WHERE NAME='SqlCLR')
DROP ASSEMBLY SqlCLR
--在SQL Server中创建程序集,,创建的程序集名为SqlCLR
CREATE ASSEMBLY SqlCLR FROM 'F:\VS2008\netskycn\NetSkycn.Data\bin\Release\NetSkycn.Data.dll' WITH PERMISSION_SET = UNSAFE
GO
--从CLR程序集中创建函数,函数名为IsMatch,有三个参数,
--[SqlCLR]是SQL Server中程序集名
--[NetSkycn.Data.SqlCLR]是.NET中的类的全名(命名空间及类名)
--[IsMatch]是.NET中类的函数名
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
--从CLR程序集中创建函数,函数名为IsMatch,有三个参数,
--[SqlCLR]是SQL Server中程序集名
--[NetSkycn.Data.SqlCLR]是.NET中的类的全名(命名空间及类名)
--[SendMail]是.NET中类的函数名
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] view plaincopyprint? select * from article where dbo.IsMatch(Title,'^[\u4e00-\u9fa5]{3,5}$',3)=1 select * from article where dbo.IsMatch(Title,'^[\u4e00-\u9fa5]{3,5}$',3)=1
测试创建存储过程的SQL语句:
[csharp]
view plaincopyprint?
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'
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语句写的存储过程和函数没有区别,极大地方便了编程。
相关文章推荐
- SQL Server中的CLR编程——用.NET为SQL Server编写存储过程和函数
- SQL Server中的CLR编程——用.NET为SQL Server编写存储过程和函数
- SQL Server中的CLR编程——用.NET为SQL Server编写存储过程和函数
- SQL Server中的CLR编程——用.NET为SQL Server编写存储过程和函数
- SQL Server中的CLR编程——用.NET为SQL Server编写存储过程和函数
- SQL Server中的CLR编程——用.NET为SQL Server编写存储过程和函数
- SQL Server中的CLR编程——用.NET为SQL Server编写存储过程和函数
- SQL Server中的CLR编程――用.NET为SQL Server编写存储过程和函数
- SQL Server 存储过程编写经验和优化措施
- SQL Server在存储过程中编写事务处理代码的三种方法
- SQL Server 2005 - 如何实作CLR存储过程来传回讯息
- SQL Server ->> SQL Server 2016新特性之 -- sp_set_session_context存储过程和SESSION_CONTEXT函数
- SQL Server在存储过程中编写事务处理代码的三种方法
- 使用sql server CLR项目生成的存储过程不返回值问题
- 优化SQL Server存储过程极其编写 教程作者:佚名 教程来源:不详 教程栏目:Mysql教程
- SQL Server存储过程中编写事务处理的方法小结
- SQL Server 2005 - 实作CLR存储过程
- 刷新SQL SERVER所有视图、函数、存储过程
- SQL Server存储过程中编写事务处理的方法小结
- Oracle编程学习存储过程、函数、游标