正则表达式非常好,但在数据库中就是没有,但可以通过程序集方式扩展 先编写一个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 calleras 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 callerasexternal name [regulerexp].[regulerexp].[matches]
别的一样
运行
exec dbo.macths '1,2,4,12,24,41','(?'
结果为
其他标量函数很简单,自己百度,类似