大家都知道在C#把一个字符串以指定的字符分成一个数组,实用split方法很容易办到,但是在t-sql 中却。。。。 在我的项目中,有如下应用:批量读取一批数据,然后处理每行的数据,处理完后,把处理成功的id和处理失败的id返回给数据库,这就涉及到一个批量更新的一个问题,你是把id一个一个写成批处理更新回数据库还是每个id就打开一次数据库,更新呢?其实,只要t-sql支持数组就能够做到。好了,我们现在就让t-sql支持数组!

大家都说我的描述很不好,这次我干脆直接用代码+注释来表示了。
using System;
using System.Collections;
using System.Text;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

namespace StringSplit
{
    
public class Stringhelp
    
{
        
//这个特性定义了一个sql表值函数,此函数返回的表的定义为:String nvarchar(200)
        
//并且指定了填充这个表的行的方法是FillRow 方法
        
//注意这个方法返回的一定是一个IEnumerable类型的,并且为公开,静态,这个方法的入参就是sql函数的入参
        [SqlFunction(TableDefinition = " String nvarchar(200)", FillRowMethodName = "FillRow")]
        
public static IEnumerable GetStrings(string x,char y)
        
{
            
//返回一个string 数组,这个数组符合IEnumerable接口,当然你也可以返回hashtable等类型。
            return x.Split(y);
        }

        
//填充返回表的行的方法,这个方法有一定的规定:
        
//一定是空返回的void类型,并且入参的第一个必须为object,其后面的参数都必须为out类型
        
//参数的类型,个数和顺序由返回表的列结构决定!(在TableDefinition = " String nvarchar(200)"中定义的表结构)
        public static void FillRow(object row,out string splitedstring)
        
{
            
//这个object 其实就是GetStrings(string x,char y)函数返回的迭代,这样你直接赋值给那个列就可以了。
             splitedstring = (String)row;
        }

    }

}



这样,编译此类库,实用如下sql 语句将dll创建到数据库中:
create assembly ArrayAssembly
from 'd:\stringSplit.dll'
WITH permission_set = Safe;
注意更改dll的对应地址。
然后如果是第一次做clr集成应用,需要把clr功能开启,使用如下语句开启:
EXEC sp_configure 'clr enabled', '1';
GO
RECONFIGURE;
GO

然后开启了的朋友可以创建这个表值函数了,使用如下语句:
create function splitstring(@x nvarchar (200),@y nchar(1))
RETURNS TABLE(StringElement nvarchar(200))
AS EXTERNAL NAME ArrayAssembly.[StringSplit.Stringhelp].GetStrings;
GO
这个语句要注意命名规则,规则我在以前的文章中讲过了。
然后可以测试这个表值函数了。

select * from splitstring('xiangxiang,zangjifei',',')

返回结果:

这样,就可以很容易的使用了。
比如:
select * from dbo.T_test as t where t.id in  (select * from splitstring('12,23',','))