我们用过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中,目前想想应该是够用了

        /// <summary>
/// 正则匹配
/// </summary>
/// <param name="regex">正则表达式</param>
/// <param name="input">文本</param>
/// <returns></returns>
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString RegexMatch(string regex, string input)
{
return string.IsNullOrEmpty(input) ? "" : Regex.Match(input, regex, RegexOptions.IgnoreCase).Value;
}
/// <summary>
/// 正则匹配次数
/// </summary>
/// <param name="regex">正则表达式</param>
/// <param name="input">文本</param>
/// <returns></returns>
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlInt32 RegexMatchsCount(string regex, string input)
{
return Regex.Matches(input, regex, RegexOptions.IgnoreCase).Count;
}
/// <summary>
/// 正则替换
/// </summary>
/// <param name="regex">正则表达式</param>
/// <param name="input">文本</param>
/// <param name="replace">要替换的目标</param>
/// <returns></returns>
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlString RegexReplace(string regex, string input, string replace)
{
return string.IsNullOrEmpty(input) ? "" : Regex.Replace(input, regex, replace, RegexOptions.IgnoreCase);
} /// <summary>
/// 正则校验
/// </summary>
/// <param name="regex">正则表达式</param>
/// <param name="input">文本</param>
/// <returns></returns>
[Microsoft.SqlServer.Server.SqlFunction]
public static SqlBoolean RegexIsMatch(string regex, string input)
{
return !string.IsNullOrEmpty(input) && Regex.IsMatch(input, regex, RegexOptions.IgnoreCase);
}

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

   alter  ASSEMBLY SQLfunctionAssembly
FROM 'D:\SQLClr.dll' --改为自己C#写的dll路径填写
WITH PERMISSION_SET = UNSAFE; --正则匹配
CREATE FUNCTION[dbo].[RegexMatch] (
@regex NVARCHAR(max),
@input NVARCHAR(max)
)
RETURNS NVARCHAR(max)
WITH EXECUTE AS CALLER
AS
EXTERNAL NAME [SQLfunctionAssembly].[SQLClr.SQLfunction].[RegexMatch] --[SQL程序集名].[命名空间.类名].[方法名] --正则匹配次数
CREATE FUNCTION[dbo].[RegexMatchsCount] (
@regex NVARCHAR(max),
@input NVARCHAR(max)
)
RETURNS int
WITH EXECUTE AS CALLER
AS
EXTERNAL NAME [SQLfunctionAssembly].[SQLClr.SQLfunction].[RegexMatchsCount] --[SQL程序集名].[命名空间.类名].[方法名] --正则替换
CREATE FUNCTION[dbo].[RegexReplace] (
@regex NVARCHAR(max),
@input NVARCHAR(max),
@replace NVARCHAR(max)
)
RETURNS NVARCHAR(max)
WITH EXECUTE AS CALLER
AS
EXTERNAL NAME [SQLfunctionAssembly].[SQLClr.SQLfunction].[RegexReplace] --[SQL程序集名].[命名空间.类名].[方法名] --正则校验
CREATE FUNCTION[dbo].[RegexIsMatch] (
@regex NVARCHAR(max),
@input NVARCHAR(max)
)
RETURNS bit
WITH EXECUTE AS CALLER
AS
EXTERNAL NAME [SQLfunctionAssembly].[SQLClr.SQLfunction].[RegexIsMatch] --[SQL程序集名].[命名空间.类名].[方法名]

四.正则函数应用例子

应用场景1:

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

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

应用场景2:

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

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

应用场景3:

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

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

六.综合实例

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

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

CREATE     FUNCTION [dbo].[IsMatchPpeflowOrderno] (@regex VARCHAR(MAX),@isTechno bit,@pdctno varchar(50))
RETURNS BIT
AS
BEGIN
DECLARE @reStr varchar(5000)
IF (@isTechno = 1)
BEGIN
SELECT @reStr = FP_EMSDB_PUB.dbo.JoinString(TechNo,',',GlobalOrder)
FROM FP_EMS_DB.dbo.V_PPEFlow
WHERE FlowLevel = 2 AND pdctno = @pdctno
GROUP BY pdctno
END
ELSE
BEGIN
SELECT @reStr = FP_EMSDB_PUB.dbo.JoinString(techname,',',GlobalOrder)
FROM FP_EMS_DB.dbo.V_PPEFlow
WHERE FlowLevel = 2 AND pdctno = @pdctno
GROUP BY pdctno
END
SET @reStr = ISNULL(@reStr,'')
RETURN dbo.RegexIsMatch(@regex,@reStr)
END

2.实际函数调用

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

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

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. JavaScript--小白入门篇2

    一.布尔值和关系运算符.逻辑运算符 1.1 布尔值   我们上篇文章说了,学习了两种变量的类型数值型.字符串型.   实际上,还有很多变量的类型.我们今天再学习一种,叫做“布尔类型”. 数值型里面的值 ...

  2. 2n皇后 - 回溯

    题目地址:http://www.51cpc.com/web/problem.php?id=1172 Summarize: 1. 递归回溯: 2. 先扫完一种皇后,再扫描另一种: 3. 循环输入: 4. ...

  3. Moving Tables POJ - 1083 (思维)

    题目大意 在一层楼上推桌子,每个空间一次只能推1种桌子,且消耗十分钟.可以同时推多个桌子,但是他们所占的空间不能是相交的如图 解法 真的很考验思维能力,首先考虑到这个走廊是有两排的,我瞬间想到了宿舍楼 ...

  4. BZOJ 4385 洛谷3594 POI2015 WIL-Wilcze doły

    [题解] 手残写错调了好久QAQ...... 洛谷的数据似乎比较水.. n个正整数!!这很重要 这道题是个类似two pointer的思想,外加一个单调队列维护当前区间内长度为d的子序列中元素之和的最 ...

  5. Oracle 关于几个随机函数sys_guid、dbms_random.random、dbms_random.value(取随机的结果集)

    sys_guid():SYS_GUID (),是Oracle 8i 后提供的函数.SYS_GUID产生并返回一个全球唯一的标识符(原始值)由16个字节组成.更适合多个数据库数据集成时使用(--源自百度 ...

  6. [BZOJ2594] [Wc2006]水管局长数据加强版(LCT + kruskal + 离线)

    传送门 WC这个题真是丧心病狂啊,就是想学习一下怎么处理边权,给我来了这么一个破题! ORZ hzwer 临摹黄学长代码233 但还是复杂的一匹 理一下思路吧 题目大意:给定一个无向图,多次删除图中的 ...

  7. Junit4使用总结

    常用注解 @Before:初始化方法,在任何一个测试方法执行之前,必须执行的代码. @After:释放资源,在任何一个测试方法执行之后,需要进行的收尾工作.   @Test:测试方法,表明这是一个测试 ...

  8. 【python】字符遍历

    Python为我们提供了很多便捷的方式去遍历一个字符串中的字符.比如,将一个字符串转换为一个字符数组(列表): theList = list(theString) 同时,我们可以方便的通过for语句进 ...

  9. ios block 内存管理时使用注意

    XMGStudent *stu = [[XMGStudent alloc] init]; __weak XMGStudent *weakStu = stu; stu.block = ^{ NSLog( ...

  10. Robot Framework 使用技巧 快捷键

        ctrl+alt+space 自动带出相关关键字,以及相关用法,里边有对应参数的说明. Ctrl+鼠标悬浮 直接显示关键字的相关用法 F5 关键字说明 (方法名函数名)             ...