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

本文涉及的产品
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
云数据库 RDS SQL Server,基础系列 2核4GB
简介:

很早就知道可以用.NET为SQL Server2005及以上版本编写存储过程、触发器和存储过程的,不过之前开发的系统要么因为历史原因用的是SQL2000要么根本用不着在SQL Server中启用CLR,所以一直没有尝试。最近因为项目的原因,在这方面做了一个调研,现在在这里分享一下心得。
首先要说明的是要在SQL Server中启用CLR必须是在SQL Server2005及以上版本,其次在默认情况下是没有启用CLR的,必须要显示设置为启用。比如我们要在ArticleCollectorDB数据库中运行用.NET编写的函数或者存储过程,至少先要进行下面的SQL语句:


 
 
  1. exec sp_configure 'clr enabled', 1;--在SQL Server中启用CLR 
  2. reconfigure; 
  3. go 
  4. --在ArticleCollectorDB数据库中设置TRUSTWORTHY为ON 
  5. ALTER DATABASE [ArticleCollectorDB] SET TRUSTWORTHY ON 


这时可能会得到提示要重新启动SQL Server,如果有此提示则重新启动一下。
接着我们在VS中进行编码,在这里我们将分别编写一个名为IsMatch的函数和一个名为SendMail存储过程。在VS中创建一个名为NetSkycn.Data的类库项目,添加一个SqlCLR的类,代码如下:


 
 
  1. using System.Data.SqlTypes; 
  2. using System.Net; 
  3. using System.Net.Mail; 
  4. using System.Security.Permissions; 
  5. using System.Text.RegularExpressions; 
  6. using Microsoft.SqlServer.Server; 
  7.  
  8. namespace NetSkycn.Data 
  9. /// <summary> 
  10. /// 在SQL Server环境中执行的CLR方法,注意提供给SQL Server调用的方法必须有SqlFunction/SqlProcedure Attribute 
  11. /// 作者:周公 
  12. /// 创建日期:2012-05-09 
  13. /// 博客地址:http://blog.csdn.net/zhoufoxcn http://zhoufoxcn.blog.51cto.com 
  14. /// 新浪微博地址:http://weibo.com/zhoufoxcn 
  15. /// </summary> 
  16. public sealed class SqlCLR 
  17. /// <summary> 
  18. /// 判断字符串是否匹配正则表达式 
  19. /// </summary> 
  20. /// <param name="source">要匹配的文本</param> 
  21. /// <param name="pattern">进行匹配的正则表达式</param> 
  22. /// <param name="options">正则表达式匹配选项,1为忽略大小写,2为多行匹配,3为忽略大小写且多行匹配</param> 
  23. /// <returns></returns> 
  24. [SqlFunction(IsDeterministic = true, DataAccess = DataAccessKind.None)] 
  25. public static SqlBoolean IsMatch(string source, string pattern,int options) 
  26. if (string.IsNullOrEmpty(source) || string.IsNullOrEmpty(pattern)) 
  27. return SqlBoolean.False; 
  28. RegexOptions regexOptions=RegexOptions.None; 
  29. int optionIgnoreCase = 1; 
  30. int optionMultiline = 2; 
  31. if ((options & optionIgnoreCase) != 0) 
  32. regexOptions = regexOptions | RegexOptions.IgnoreCase; 
  33.  
  34. if ((options & optionMultiline) != 0) 
  35. regexOptions = regexOptions | RegexOptions.Multiline; 
  36.  
  37. return (SqlBoolean)(Regex.IsMatch(source, pattern, regexOptions)); 
  38. /// <summary> 
  39. /// 发送邮件 
  40. /// </summary> 
  41. /// <param name="to">收件人邮件地址</param> 
  42. /// <param name="from">发件人邮件地址</param> 
  43. /// <param name="subject">邮件主题</param> 
  44. /// <param name="body">邮件内容</param> 
  45. /// <param name="username">登录smtp主机时用到的用户名,注意是邮件地址'@'以前的部分</param> 
  46. /// <param name="password">登录smtp主机时用到的用户密码</param> 
  47. /// <param name="smtpHost">发送邮件用到的smtp主机</param> 
  48. [SqlProcedure] 
  49. [SmtpPermission(SecurityAction.Assert)] 
  50. [SecurityPermission(SecurityAction.Assert)] 
  51. public static void SendMail(string to, string from, string subject, string body, string userName, string password, string smtpHost) 
  52. MailAddress addressFrom = new MailAddress(from); 
  53. MailAddress addressTo = new MailAddress(to); 
  54. MailMessage message = new MailMessage(addressFrom, addressTo); 
  55. message.Subject = subject;//设置邮件主题 
  56. message.IsBodyHtml = true;//设置邮件正文为html格式 
  57. message.Body = body;//设置邮件内容 
  58.  
  59. SmtpClient client = new SmtpClient(smtpHost); 
  60.  
  61. //设置发送邮件身份验证方式 
  62. //注意如果发件人地址是abc@def.com,则用户名是abc而不是abc@def.com 
  63. client.Credentials = new NetworkCredential(userName, password); 
  64. client.Send(message); 
  65.  


编译通过之后,记住类库的物理全路径,比如:F:\VS2008\netskycn\NetSkycn.Data\bin\Release\NetSkycn.Data.dll,在这里要强调几点:一、对于将来提供给SQL Server调用的函数或者存储过程必须是静态方法,并且还必须带有SqlFunction或者SqlProcedure属性;二、对于一些需要访问外部网络资源和安全属性的还必须添加响应的属性(如本例中的SendMail方法,如果没有添加响应的属性在创建SQL Function/Procedure时会出现错误提示)。
现在我们开始遵循先为SQL Server创建程序集、后创建函数或者存储过程的顺序来操作,在操作过程中用到的SQL语句如下:


 
 
  1. --在ArticleCollectorDB数据库中设置TRUSTWORTHY为ON 
  2. ALTER DATABASE [ArticleCollectorDB] SET TRUSTWORTHY ON 
  3.  
  4. --如果已经存在该对象则删除 
  5. IF EXISTS(SELECT * FROM SYS.SYSOBJECTS WHERE NAME='SendMail' AND XTYPE='PC')  
  6. DROP PROCEDURE SendMail 
  7.  
  8. --如果已经存在该对象则删除 
  9. IF EXISTS(SELECT * FROM SYS.SYSOBJECTS WHERE NAME='IsMatch' AND XTYPE='FS')  
  10. DROP FUNCTION IsMatch 
  11.  
  12. --如果已经存在SqlCLR程序集则删除该程序集 
  13. IF EXISTS(SELECT * FROM SYS.ASSEMBLIES WHERE NAME='SqlCLR')  
  14. DROP ASSEMBLY SqlCLR 
  15.  
  16. --在SQL Server中创建程序集,,创建的程序集名为SqlCLR 
  17. CREATE ASSEMBLY SqlCLR FROM 'F:\VS2008\netskycn\NetSkycn.Data\bin\Release\NetSkycn.Data.dll' WITH PERMISSION_SET = UNSAFE 
  18. GO 
  19.  
  20. --从CLR程序集中创建函数,函数名为IsMatch,有三个参数, 
  21. --[SqlCLR]是SQL Server中程序集名 
  22. --[NetSkycn.Data.SqlCLR]是.NET中的类的全名(命名空间及类名) 
  23. --[IsMatch]是.NET中类的函数名 
  24. CREATE FUNCTION [dbo].[IsMatch]  
  25. (  
  26. @source AS NVARCHAR(200), 
  27. @pattern AS NVARCHAR(200), 
  28. @option INT=3 
  29. )  
  30. RETURNS BIT  
  31. AS  
  32. EXTERNAL NAME [SqlCLR].[NetSkycn.Data.SqlCLR].[IsMatch];  
  33. GO 
  34.  
  35. --从CLR程序集中创建函数,函数名为IsMatch,有三个参数, 
  36. --[SqlCLR]是SQL Server中程序集名 
  37. --[NetSkycn.Data.SqlCLR]是.NET中的类的全名(命名空间及类名) 
  38. --[SendMail]是.NET中类的函数名 
  39. CREATE PROCEDURE [dbo].[SendMail]  
  40. (  
  41. @to AS NVARCHAR(200), 
  42. @from AS NVARCHAR(200), 
  43. @subject AS NVARCHAR(200), 
  44. @body AS NVARCHAR(MAX), 
  45. @userName AS NVARCHAR(200), 
  46. @password AS NVARCHAR(200), 
  47. @smtpHost AS NVARCHAR(200) 
  48. AS  
  49. EXTERNAL NAME [SqlCLR].[NetSkycn.Data.SqlCLR].[SendMail];  
  50. GO 


如果没有得到任何错误提示,则表示创建函数和存储过程成功。至此我们会看到如下情形:


这表示创建成功。
测试创建函数的SQL语句(查找article表中title字段是3至5个字段的数据):


 
 
  1. select * from article where dbo.IsMatch(Title,'^[\u4e00-\u9fa5]{3,5}$',3)=1 


测试创建存储过程的SQL语句:


 
 
  1. 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语句写的存储过程和函数没有区别,极大地方便了编程。














本文转自周金桥51CTO博客,原文链接: http://blog.51cto.com/zhoufoxcn/859245,如需转载请自行联系原作者

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS&nbsp;SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/sqlserver
相关文章
|
1月前
|
存储 SQL 数据库
SQL Server存储过程的优缺点
【10月更文挑战第18天】SQL Server 存储过程具有提高性能、增强安全性、代码复用和易于维护等优点。它可以减少编译时间和网络传输开销,通过权限控制和参数验证提升安全性,支持代码共享和复用,并且便于维护和版本管理。然而,存储过程也存在可移植性差、开发和调试复杂、版本管理问题、性能调优困难和依赖数据库服务器等缺点。使用时需根据具体需求权衡利弊。
|
1月前
|
SQL 开发框架 .NET
ASP.NET连接SQL数据库:详细步骤与最佳实践指南ali01n.xinmi1009fan.com
随着Web开发技术的不断进步,ASP.NET已成为一种非常流行的Web应用程序开发框架。在ASP.NET项目中,我们经常需要与数据库进行交互,特别是SQL数据库。本文将详细介绍如何在ASP.NET项目中连接SQL数据库,并提供最佳实践指南以确保开发过程的稳定性和效率。一、准备工作在开始之前,请确保您
187 3
|
1月前
|
传感器 数据采集 物联网
探索.NET nanoFramework:为嵌入式设备编程的新途径
探索.NET nanoFramework:为嵌入式设备编程的新途
42 7
|
1月前
|
存储 SQL 缓存
SQL Server存储过程的优缺点
【10月更文挑战第22天】存储过程具有代码复用性高、性能优化、增强数据安全性、提高可维护性和减少网络流量等优点,但也存在调试困难、移植性差、增加数据库服务器负载和版本控制复杂等缺点。
|
1月前
|
存储 SQL 数据库
Sql Server 存储过程怎么找 存储过程内容
Sql Server 存储过程怎么找 存储过程内容
63 1
|
1月前
|
存储 SQL 数据库
SQL Server存储过程的优缺点
【10月更文挑战第17天】SQL Server 存储过程是预编译的 SQL 语句集,存于数据库中,可重复调用。它能提高性能、增强安全性和可维护性,但也有可移植性差、开发调试复杂及可能影响数据库性能等缺点。使用时需权衡利弊。
|
1月前
|
存储 SQL 数据库
SQL Server 临时存储过程及示例
SQL Server 临时存储过程及示例
52 3
|
1月前
|
SQL 开发框架 .NET
ASP.NET连接SQL数据库:实现过程与关键细节解析an3.021-6232.com
随着互联网技术的快速发展,ASP.NET作为一种广泛使用的服务器端开发技术,其与数据库的交互操作成为了应用开发中的重要环节。本文将详细介绍在ASP.NET中如何连接SQL数据库,包括连接的基本概念、实现步骤、关键代码示例以及常见问题的解决方案。由于篇幅限制,本文不能保证达到完整的2000字,但会确保
|
1月前
|
SQL 数据库
执行 Transact-SQL 语句或批处理时发生了异常。 (Microsoft.SqlServer.ConnectionInfo)之解决方案
执行 Transact-SQL 语句或批处理时发生了异常。 (Microsoft.SqlServer.ConnectionInfo)之解决方案
253 0
|
3月前
|
Java Spring 自然语言处理
Spring 框架里竟藏着神秘魔法?国际化与本地化的奇妙之旅等你来揭开谜底!
【8月更文挑战第31天】在软件开发中,国际化(I18N)与本地化(L10N)对于满足不同地区用户需求至关重要。Spring框架提供了强大支持,利用资源文件和`MessageSource`实现多语言文本管理。通过配置日期格式和货币符号,进一步完善本地化功能。合理应用这些特性,可显著提升应用的多地区适应性和用户体验。
43 0
下一篇
无影云桌面