好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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

正则表达式非常好,但在数据库中就是没有,但可以通过程序集方式扩展 先编写一个dll,标量函数很好写,表值函数麻烦一点 下面是C#代码 using System; using System.Data; using System.Data.SqlClient; using System.Data.SqlTypes; using Microsoft.SqlServ

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

先编写一个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  )
        {            
              //  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  ' , '  (?  '  

结果为

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

查看更多关于用程序集编写clr表值函数:把正则表达式引入数据库中的详细内容...

  阅读:35次