原文:SQL Server中的CLR编程——用.NET为SQL Server编写存储过程和函数

很早就知道可以用.NET为SQL Server2005及以上版本编写存储过程、触发器和存储过程的,不过之前开发的系统要么因为历史原因用的是SQL2000要么根本用不着在SQL Server中启用CLR,所以一直没有尝试。最近因为项目的原因,在这方面做了一个调研,现在在这里分享一下心得。

首先要说明的是要在SQL Server中启用CLR必须是在SQL Server2005及以上版本,其次在默认情况下是没有启用CLR的,必须要显示设置为启用。比如我们要在ArticleCollectorDB数据库中运行用.NET编写的函数或者存储过程,至少先要进行下面的SQL语句:

exec sp_configure 'clr enabled', 1;--在SQL Server中启用CLR
reconfigure;
go
--在ArticleCollectorDB数据库中设置TRUSTWORTHY为ON
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
{
/// <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语句如下:

--在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语句(查找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编写存储过程和函数的更多相关文章

  1. 在SQL Server中使用CLR调用.NET方法

    介绍    我们一起来做个示例,在.NET中新建一个类,并在这个类里新建一个方法,然后在SQL Server中调用这个方法.按照微软所述,通过宿主 Microsoft .NET Framework 2 ...

  2. 在SQL Server中使用CLR调用.NET类库中的方法 (转载)

    在SQL Server中调用 .NET 类库的方法要分为下面几步来实现: 在.NET中新建一个类库项目,并在这个项目中添加一个类文件,并把要被SQL Server调用的方法定义为公有的,静态的方法. ...

  3. [转载]在SQL Server 中,如何实现DBF文件和SQL Server表之间的导入或者导出?

    原来使用SQL Server 2000数据库,通过DTS工具很方便地在SQL Server和DBF文件之间进行数据的导入和导出,现在安装了SQL Server2005之后,发现其提供的“SQL Ser ...

  4. SQL学习笔记七之MySQL视图、触发器、事务、存储过程、函数

    阅读目录 一 视图 二 触发器 三 事务 四 存储过程 五 函数 六 流程控制 一 视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用[名 ...

  5. 转 在SQL Server中创建用户角色及授权(使用SQL语句)

     目录 要想成功访问 SQL Server 数据库中的数据 我们需要两个方面的授权 完整的代码示例 使用存储过程来完成用户创建 实例 要想成功访问 SQL Server 数据库中的数据, 我们需要两个 ...

  6. 【转】在SQL Server中创建用户角色及授权(使用SQL语句)

    1. 首先在 SQL Server 服务器级别,创建登陆帐户(create login) --创建登陆帐户(create login) create login dba with password=' ...

  7. Sql server 中关闭ID自增字段(SQL取消ID自动增长)

    sql server在导入数据的时候,有时候要考虑id不变,就要先取消自动增长再导入数据,导完后恢复自增. 比如网站改版从旧数据库导入新数据库,数据库结构不相同,可能会使用insert into xx ...

  8. 在SQL Server中创建用户角色及授权(使用SQL语句)

    1. 首先在 SQL Server 服务器级别,创建登陆帐户(create login) --创建登陆帐户(create login) create login dba with password=' ...

  9. SQL Server ->> CLR编程问题汇总

    1) CLR不支持C#类方法重载(Method Overload) 今天打算写个枚举目录的C# CLR存储过程,结果发现原来CLR不支持方法重载. Msg 6572, Level 16, State ...

随机推荐

  1. ListView的cacheColorHint与listSelector物业和fragment里面onActivityResult问题没有响应

    fragment里面onActivityResult 如何才华被称之为.在使用时发现没反应,没注意这个问题谁. 多方法都不是非常方便.最终实验除了一个最简单的方法. startActivityForR ...

  2. Chrome 控制台不完全指南(转)

    Chrome的开发者工具已经强大到没朋友的地步了,特别是其功能丰富界面友好的console,使用得当可以有如下功效: 更高「逼格」更快「开发调试」更强「进阶级的Frontender」 Bug无处遁形「 ...

  3. struts开发步骤

    说来惭愧.这是一个简单的struts折腾了很长一段时间,几乎相同的时间量就花了三天时间来解决.下面的步骤总结一下我开发:(我使用的是MyEclipse); 1.新建一个Exercise3的web Pr ...

  4. 流动python - 自然装饰

    好多人搞非常复杂的装饰,其实本质easy. 首先,这是什么装饰?发现穿着在代码@xxx帽子,它是装饰. 它是由如何定制它装饰? 其实不管什么人需要一个参数callable用来做装饰器,比方函数和类.为 ...

  5. Nio学习4——EchoServer在IO,NIO,NIO.2中的实现

    堵塞IO实现: public class PlainEchoServer { public void serve(int port) throws IOException { final Server ...

  6. MEF初体验之七:Using Catalogs

    MEF特性化编程模型的价值主张之一是通过catalogs动态发现部件的能力.Catalogs允许应用程序很容易地消费那些通过[Export]已经自我注册的exports. Assembly Catal ...

  7. TFS:TF30042 数据库已满 处理方法

    原文:TFS:TF30042 数据库已满 处理方法 今天早上,公司打来电话,说TFS(Team Foundation Server)微软源代码管理软件签入不了,报错:TF30042 数据库已满. 经过 ...

  8. Docker系列之(一):10分钟玩转Docker(转)

    1.前言 进入云计算的时代,各大云提供商AWS,阿里云纷纷推出针对Docker的服务,现在Docker是十分火爆,那么Docker到底是什麽,让我们来体验一下. 2.Docker是什麽 Docker是 ...

  9. SDUT OJ 2463 学校password你必须学会科学计划

    #include<iostream> #include<string.h> #include<stdio.h> #define N 10010 #define M ...

  10. 记录一次有用的stackoverflow搜索

    经常逛stackoverflow有一段时间了,也遇到了不少问题 问题: 1.ckeditor中在source中输入如下代码 2.再点击source按钮,查看页面显示效果,不对啊 3.然后再检查源码,发 ...