• 用程序集编写clr表值函数:把正则表达式引入数据库中


    正则表达式非常好,但在数据库中就是没有,但可以通过程序集方式扩展

    先编写一个dll,标量函数很好写,表值函数麻烦一点

    下面是C#代码

    using System;
    using System.Data;
    using System.Data.SqlClient;
    using System.Data.SqlTypes;
    using Microsoft.SqlServer.Server;
    using System.Text.RegularExpressions;
    using System.Collections;
    public partial class RegExpFunctions
    {

        [SqlFunction(
          DataAccess = DataAccessKind.Read,
          FillRowMethodName = "MatchsFun_FillRow",
          TableDefinition = "pos int,match NVARCHAR(500)")]
        public static IEnumerable MatchsFun(string input, string patten)
        {
          MatchCollection mc;
          Regex r = new Regex(patten);
          mc = r.Matches(input);
          return mc;
        }

    
    

        public static void MatchsFun_FillRow(object mc,out int pos,out SqlString sqlmatch)
        {
          Match it = (Match)mc;
          pos = it.Index;
          sqlmatch = it.Value;
        }

    };

    程序集名称是RegulerExp2

    代码中有几点解释一下:

    (1)表值函数必须是IEnumerable,简单讲是必须有这个接口的类,MatchCollection就具有这个接口;

    (2)必须提供一个回调函数,在函数属性FillRowMethodName = "MatchsFun_FillRow"中指明,这个函数负责填充数据,

        public static void MatchsFun_FillRow(object mc,out int pos,out SqlString sqlmatch)
        {
          Match it = (Match)mc;
          pos = it.Index;
          sqlmatch = it.Value;
        }

    这里的object mc是什么呢?

    我们可以想象一下遍历

    foreach (Match it in mc)
    {  
    }

    这里的object mc就是foreach里的Match it。

    然后数据库把out int pos,out SqlString sqlmatch这两个量取出去放进表里。

    下一步是添加程序集

    第一步是把数据库的clr打开,不细说,自己网上查

    第二步添加程序集

    第三步,写一个数据库表值函数包装

    create FUNCTION [dbo].[MatchList](@input [nvarchar](1000), @patten [nvarchar](1000))
    RETURNS  TABLE (
        pos int,[match] [nvarchar](500) NULL
    ) WITH EXECUTE AS CALLER
    AS 
    EXTERNAL NAME [RegulerExp2].[RegExpFunctions].[MatchsFun]

    可以了。

    前面写了一个小示例,大家好像没兴趣,写一个实用点的例子吧。数据库中没有split函数,用正则表达式就很容易了

    select match from dbo.MatchList('1,2,4,12,24,41','(?<=,|^).*?(?=,|$)')

    结果为

    如果以一个存储过程方式

    C#代码为

    [Microsoft.SqlServer.Server.SqlProcedure]
        public static void Matches(string input, string patten)
        {
            //像构造Table一样来构造SqlDataRecord,其中SqlMetaData类似DataColumn
            SqlDataRecord dataRecord = new SqlDataRecord(new SqlMetaData[] {                
                    new SqlMetaData("ID", SqlDbType.Int),
                    new SqlMetaData("index", SqlDbType.Int),
                    new SqlMetaData("match", SqlDbType.NVarChar,100)
                        });
            //开始填充
            SqlContext.Pipe.SendResultsStart(dataRecord);
    
            MatchCollection mc;
            Regex r = new Regex(patten);
            mc = r.Matches(input);
            for (int i = 0; i < mc.Count; i++)
            {            
                //SqlDataRecord.SetString类似DataRow的功能,像Table中填充值
                dataRecord.SetInt32(0, i);
                dataRecord.SetInt32(1, mc[i].Index);
                dataRecord.SetString(2,  mc[i].Value);
                //通过SendResultsRow把数据填充到Table,相关于Table.Rows.Add(DataRow);
                SqlContext.Pipe.SendResultsRow(dataRecord);
            }
    
            
            //填充结束,返回结果集
            SqlContext.Pipe.SendResultsEnd();
        }

    数据库端写一个存储过程包装

    CREATE PROCEDURE [dbo].[Macths]
        @input [nvarchar](1000),
        @patten [nvarchar](1000)
    WITH EXECUTE AS CALLER
    AS
    EXTERNAL NAME [RegulerExp].[RegulerExp].[Matches]

    别的一样

    运行

    exec dbo.Macths '1,2,4,12,24,41','(?<=,|^).*?(?=,|$)'

    结果为

    其他标量函数很简单,自己百度,类似

  • 相关阅读:
    mongodb添加延时节点
    AFNetworking 遇到错误 Code=-1016 "Request failed: unacceptable content-type: text/plain"
    使用cocoa捕获dock栏中的“退出”事件,解决qt开发的应用程序退出异常的问题
    【Grails 代理Proxy设置】部署Grails遇到Error Resolve error obtaining dependencies:错误,及解决方法
    【转】MongoDB 3.0 正式版本即将发布,强力推荐
    求数组的一个最大子数组
    MergeSort 归并排序(java)
    java查询几个菜单下的所有下级菜单
    InsertionSort 直接插入排序(java)
    sublime3配置java开发环境
  • 原文地址:https://www.cnblogs.com/eyye/p/3808545.html
Copyright © 2020-2023  润新知