我们用过SQL SERVER的都知道,SQL SERVER它本身是不自带正则表达式的,因为没有,所以基本都没用过啊,

但我们在C#中对文本匹配用正则的方式处理非常好用,省得你写一堆代码实现匹配,多简洁啊,

那么是否想过,在SQL SERVER中也使用正则,可能吗?

答案:当然啦,

自从微软发布SQL SERVER 2008就支持CLR了,这里就是突破口了,可以用C#写正则函数给SQL函数调用了,

这里实现的方法说明如下

一.先说一下工作中实际遇到的问题

PCB流程是顺序结构,流程的顺序是有着严格的要求的,顺序不能错,流程也不能多,更不能少,

所以要保证流程顺序正确,需要检测:流程工序顺序上下顺序是否正确,而SQL SERVER本身是不支持数组的,要实现上下行数据对比,很困难的。

如果实现起来需要堆N多行代码来实现它,这样增加了程序代码实现的复杂度了,而且后面维护的人看这样的代码也吐血,

从这个出发点思考一种新的方式,是否可以写出一种更加简洁的代码来解决此问题呢,大家都能看懂的。

接下来后面讲了就是解决此问题的方法了。

目前的问题点: 我们要检测【钻孔】前工序是否存在【磨边】,同时【钻孔】后第2个工序是否存在【沉铜】工序

对于这样的问题,纯SQL来实现的话,不写N行代码解决不了是吧

二.C# 写SQL SERVER 正则函数代码

这里将常用的4个正则匹配移值到SQL SERVER中,目前想想应该是够用了

  1. /// <summary>
  2. /// 正则匹配
  3. /// </summary>
  4. /// <param name="regex">正则表达式</param>
  5. /// <param name="input">文本</param>
  6. /// <returns></returns>
  7. [Microsoft.SqlServer.Server.SqlFunction]
  8. public static SqlString RegexMatch(string regex, string input)
  9. {
  10. return string.IsNullOrEmpty(input) ? "" : Regex.Match(input, regex, RegexOptions.IgnoreCase).Value;
  11. }
  12. /// <summary>
  13. /// 正则匹配次数
  14. /// </summary>
  15. /// <param name="regex">正则表达式</param>
  16. /// <param name="input">文本</param>
  17. /// <returns></returns>
  18. [Microsoft.SqlServer.Server.SqlFunction]
  19. public static SqlInt32 RegexMatchsCount(string regex, string input)
  20. {
  21. return Regex.Matches(input, regex, RegexOptions.IgnoreCase).Count;
  22. }
  23. /// <summary>
  24. /// 正则替换
  25. /// </summary>
  26. /// <param name="regex">正则表达式</param>
  27. /// <param name="input">文本</param>
  28. /// <param name="replace">要替换的目标</param>
  29. /// <returns></returns>
  30. [Microsoft.SqlServer.Server.SqlFunction]
  31. public static SqlString RegexReplace(string regex, string input, string replace)
  32. {
  33. return string.IsNullOrEmpty(input) ? "" : Regex.Replace(input, regex, replace, RegexOptions.IgnoreCase);
  34. }
  35.  
  36. /// <summary>
  37. /// 正则校验
  38. /// </summary>
  39. /// <param name="regex">正则表达式</param>
  40. /// <param name="input">文本</param>
  41. /// <returns></returns>
  42. [Microsoft.SqlServer.Server.SqlFunction]
  43. public static SqlBoolean RegexIsMatch(string regex, string input)
  44. {
  45. return !string.IsNullOrEmpty(input) && Regex.IsMatch(input, regex, RegexOptions.IgnoreCase);
  46. }

三.SQL SERVER修改程序集与创建4个正则函数

  1. alter ASSEMBLY SQLfunctionAssembly
  2. FROM 'D:\SQLClr.dll' --改为自己C#写的dll路径填写
  3. WITH PERMISSION_SET = UNSAFE;
  4.  
  5. --正则匹配
  6. CREATE FUNCTION[dbo].[RegexMatch] (
  7. @regex NVARCHAR(max),
  8. @input NVARCHAR(max)
  9. )
  10. RETURNS NVARCHAR(max)
  11. WITH EXECUTE AS CALLER
  12. AS
  13. EXTERNAL NAME [SQLfunctionAssembly].[SQLClr.SQLfunction].[RegexMatch] --[SQL程序集名].[命名空间.类名].[方法名]
  14.  
  15. --正则匹配次数
  16. CREATE FUNCTION[dbo].[RegexMatchsCount] (
  17. @regex NVARCHAR(max),
  18. @input NVARCHAR(max)
  19. )
  20. RETURNS int
  21. WITH EXECUTE AS CALLER
  22. AS
  23. EXTERNAL NAME [SQLfunctionAssembly].[SQLClr.SQLfunction].[RegexMatchsCount] --[SQL程序集名].[命名空间.类名].[方法名]
  24.  
  25. --正则替换
  26. CREATE FUNCTION[dbo].[RegexReplace] (
  27. @regex NVARCHAR(max),
  28. @input NVARCHAR(max),
  29. @replace NVARCHAR(max)
  30. )
  31. RETURNS NVARCHAR(max)
  32. WITH EXECUTE AS CALLER
  33. AS
  34. EXTERNAL NAME [SQLfunctionAssembly].[SQLClr.SQLfunction].[RegexReplace] --[SQL程序集名].[命名空间.类名].[方法名]
  35.  
  36. --正则校验
  37. CREATE FUNCTION[dbo].[RegexIsMatch] (
  38. @regex NVARCHAR(max),
  39. @input NVARCHAR(max)
  40. )
  41. RETURNS bit
  42. WITH EXECUTE AS CALLER
  43. AS
  44. EXTERNAL NAME [SQLfunctionAssembly].[SQLClr.SQLfunction].[RegexIsMatch] --[SQL程序集名].[命名空间.类名].[方法名]

四.正则函数应用例子

应用场景1:

检测:【钻孔】前流程存在【开料】工序  同时后流程存在【外层前处理】工序

  1. DECLARE @reStr VARCHAR(MAX)
  2. SET @reStr = '流程指示,计划投料,开料,裁切,磨边,圆角,打标,烘板,钻孔,去毛刺,烘板,沉铜,负片电镀,磨板,外层前处理,贴膜,曝光,显影,酸性蚀刻,退膜,外层AOI,阻焊前处理,丝印,预烘,曝光,显影,字符,终固化,喷砂,板边包胶,沉金,水洗烘干,电子测试,铣板,成品清洗,功能检查,外观检查,内包装,入库,外包装,出库'
  3. SELECT dbo.RegexIsMatch('开料.*钻孔',@reStr)
  4. SELECT dbo.RegexMatch('开料.*钻孔',@reStr)

应用场景2:

检测:【钻孔】前一个流程存在【烘板】工序  同时后一个流程存在【去毛刺】工序

  1. DECLARE @reStr VARCHAR(MAX)
  2. SET @reStr = '流程指示,计划投料,开料,裁切,磨边,圆角,打标,烘板,钻孔,去毛刺,烘板,沉铜,负片电镀,磨板,外层前处理,贴膜,曝光,显影,酸性蚀刻,退膜,外层AOI,阻焊前处理,丝印,预烘,曝光,显影,字符,终固化,喷砂,板边包胶,沉金,水洗烘干,电子测试,铣板,成品清洗,功能检查,外观检查,内包装,入库,外包装,出库'
  3. SELECT dbo.RegexIsMatch('烘板,钻孔,去毛刺',@reStr)
  4. SELECT dbo.RegexMatch('烘板,钻孔,去毛刺',@reStr)

应用场景3:

检测:【钻孔】前流程存在【开料】工序  同时需满足,【开料】到【钻孔】之间的允许存在其这的工序,数量在3-6个之间

  1. DECLARE @reStr VARCHAR(MAX)
  2. SET @reStr = '流程指示,计划投料,开料,裁切,磨边,圆角,打标,烘板,钻孔,去毛刺,烘板,沉铜,负片电镀,磨板,外层前处理,贴膜,曝光,显影,酸性蚀刻,退膜,外层AOI,阻焊前处理,丝印,预烘,曝光,显影,字符,终固化,喷砂,板边包胶,沉金,水洗烘干,电子测试,铣板,成品清洗,功能检查,外观检查,内包装,入库,外包装,出库'
  3. SELECT dbo.RegexIsMatch('开料((,[\u4e00-\u9fa5]{1,8}){3,6}),钻孔',@reStr)
  4. SELECT dbo.RegexMatch('开料((,[\u4e00-\u9fa5]{1,8}){3,6}),钻孔',@reStr)

六.综合实例

1.重新封装一个函数,客户端只需传入生产型号检测与正则表达式,即可检测流程顺序是否符合要求

此实例用到了【JoinString】聚合函数,可以看下面这篇文章有说明   https://www.cnblogs.com/pcbren/p/9343602.html

  1. CREATE FUNCTION [dbo].[IsMatchPpeflowOrderno] (@regex VARCHAR(MAX),@isTechno bit,@pdctno varchar(50))
  2. RETURNS BIT
  3. AS
  4. BEGIN
  5. DECLARE @reStr varchar(5000)
  6. IF (@isTechno = 1)
  7. BEGIN
  8. SELECT @reStr = FP_EMSDB_PUB.dbo.JoinString(TechNo,',',GlobalOrder)
  9. FROM FP_EMS_DB.dbo.V_PPEFlow
  10. WHERE FlowLevel = 2 AND pdctno = @pdctno
  11. GROUP BY pdctno
  12. END
  13. ELSE
  14. BEGIN
  15. SELECT @reStr = FP_EMSDB_PUB.dbo.JoinString(techname,',',GlobalOrder)
  16. FROM FP_EMS_DB.dbo.V_PPEFlow
  17. WHERE FlowLevel = 2 AND pdctno = @pdctno
  18. GROUP BY pdctno
  19. END
  20. SET @reStr = ISNULL(@reStr,'')
  21. RETURN dbo.RegexIsMatch(@regex,@reStr)
  22. END

2.实际函数调用

检测:【钻孔】到前流程【开料】工序相隔5个工序,  同时需满足,【钻孔】到后流程【沉铜】工序相隔2个工序,

此是检测流程名称是汉字:正则式用[\u4e00-\u9fa5]     如果是流程编码:正则式改为:\w

  1. SELECT [dbo].[IsMatchPpeflowOrderno]('开料((,[\u4e00-\u9fa5]{1,8}){5,5}),钻孔((,[\u4e00-\u9fa5]{1,8}){2,2}),沉铜',0,'2G16G00LA0')

七.小结

首次将正则表达式移值到存储过程中来,和在C#中用法一样,效率方面可以接受,总体来说表现不错的.

在工作中有写存储过程可以直接嵌套此函数加以应用了哦,对文本处理对比SQL来写的话,更加简洁了;后续维护也方便。

这次移值进来表示非常满意,测试一次成功到位。

PCB SQL SERVER 正则应用实例的更多相关文章

  1. PCB SQL Server 触发器应用实例

    这里以实际例子对触发器的应用对触发器的理解与应用来得更实际 一.更新触发器(Update) 临时表:inserted表有数据(新数据)     Deleted表有数据(旧数据) 实例说明:当表更新时, ...

  2. 由于启动用户实例的进程时出错,导致无法生成 SQL Server 的用户实例。该连接将关闭。

    错误:由于启动用户实例的进程时出错,导致无法生成SQL Server的用户实例. 原因:添加安装SQLEXPRESS时,估计装在了不同的目录下: 解决方法:关闭Sqlserver及相关的程序,删除目录 ...

  3. 由于检索用户的本地应用程序数据路径时出错,导致无法生成 SQL Server 的用户实例

    /”应用程序中的服务器错误. 由于检索用户的本地应用程序数据路径时出错,导致无法生成 SQL Server 的用户实例.请确保该用户在此计算机上有本地用户配置文件.该连接将关闭. 堆栈跟踪: [Sql ...

  4. PCB SQL SERVER 位运算应用实例

    在PCB行业,一个产品可能同时在多个工厂生产,举例:一个产品一条主记录,这条记录中会对应多个工厂的产地,而这个工厂产地个数不确定, 那么如何设计表结构存储这个不确定的工厂呢?这里想到了4个方式存储 一 ...

  5. SQL SERVER 锁定的实例

    ---实例DB:AdventureWorks2014 --- 创建view DBLocks USE [AdventureWorks2014] GO /****** Object: View [dbo] ...

  6. 如何查看SQL Server的数据库实例名

    其实一般默认就是MSSQLSERVER  (注意,就是英文大写). 点击开始,运行,services.mcs 然后查阅所有SQL Server的项,其中括号中字符串的就是实例名 reference: ...

  7. Sql Server 服务器名称\实例名称 无法连接 Server Name\Instance Name

      解决步骤: 1:  Sql Server是否已经启动. 2:  检查Sql Server服务器是否开启TCP/IP协议. 侦听的默认端口为1433          3:     ping 数据库 ...

  8. 【Kettle】4、SQL SERVER到SQL SERVER数据转换抽取实例

    1.系统版本信息 System:Windows旗舰版 Service Pack1 Kettle版本:6.1.0.1-196 JDK版本:1.8.0_72 2.连接数据库 本次实例连接数据库时使用全局变 ...

  9. PCB SQL SERVER 发送邮件(异步改同步)

    采用SQL SERVER发送邮件是队列方式(异步)发送邮件,所以在我们执行发送邮件后,无法立即获取到邮件是否发送成功了,而在PCB行业实际应用中是需要立即获取发送邮件是否成功的状态来决定下一步逻辑该如 ...

随机推荐

  1. Vue.js 观察者(watch)

    Vue.js 观察者(watch) watch 属性用于监视 vue 实例上的数据变动,并相应的改变其他变量的值. 用法 实例 1 <!DOCTYPE html> <html> ...

  2. 模拟--P1427 小鱼的数字游戏

    题目描述 小鱼最近被要求参加一个数字游戏,要求它把看到的一串数字(长度不一定,以0结束,最多不超过100个,数字不超过2^32-1),记住了然后反着念出来(表示结束的数字0就不要念出来了).这对小鱼的 ...

  3. 字符串匹配「 KMP 算法 」

    引言 众所周知,字符串无论是在 OI 中还是别的计算机领域都占有比较大的比重,今天说的就是一个关于匹配字符串的算法——「 KMP 算法 」. 0x00 KMP 算法用于解决这样的一类问题:给定一个文本 ...

  4. UVA - 11212 Editing a Book (IDA*搜索)

    题目: 给出n(1<n<10)个数字组成的序列,每次操作可以选取一段连续的区间将这个区间之中的数字放到其他任意位置.问最少经过多少次操作可将序列变为1,2,3……n. 思路: 利用IDA* ...

  5. Re0:DP学习之路 01背包如何打印路径?

    伪代码 用二维数组记录,如果出现可以转移的dp那么记录bk[当前体积][装的物品]=1 输出的时候倒推,如果存在连通的边那么输出并且总共的体积减去输出的体积 代码(uva-624,目前wa不明所以,网 ...

  6. [BOI2008]Elect 选举

    背包. #include <algorithm> #include <iostream> #include <cstdlib> #include <cstri ...

  7. Oracle 常用目录结构(10g)

    大多数情况下,了解Oracle常用目录结构,将大大提高数据库管理与维护的工作效率,本文介绍了Oracle 10g 的常用目录. OFA: 下面给出Oracle 最优灵活体系结构OFA(Optimal ...

  8. redis+php+mysql处理高并发实例

    一.实验环境ubuntu.php.apache或nginx.mysql二.利用Redis锁解决高并发问题,需求现在有一个接口可能会出现并发量比较大的情况,这个接口使用php写的,做的功能是接收 用户的 ...

  9. buf.readUInt32BE()函数详解

    buf.readUInt32BE(offset[, noAssert]) buf.readUInt32LE(offset[, noAssert]) offset {Number} 0 noAssert ...

  10. this与const

    在普通非const成员函数中,this是const指针,而在const成员函数中,this是const对象的const指针. class Foo { Foo& get_self1(void) ...