SQL各种字符串分拆处理函数

字符串分解


--各种字符串分拆处理函数.sql 
--


--各种字符串分函数

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[f_splitSTR]') and xtype in (N'FN', N'IF', N'TF'))
drop function [dbo].[f_splitSTR]
GO

--3.2.1 循环截取法
CREATE FUNCTION f_splitSTR(
@s   varchar(8000),   --待分拆的字符串
@split varchar(10)     --数据分隔符
)RETURNS @re TABLE(col varchar(100))
AS
BEGIN
    DECLARE @splitlen int
    SET @splitlen=LEN(@split+'a')-2
    WHILE CHARINDEX(@split,@s)>0
    BEGIN
        INSERT @re VALUES(LEFT(@s,CHARINDEX(@split,@s)-1))
        SET @s=STUFF(@s,1,CHARINDEX(@split,@s)+@splitlen,'')
    END
    INSERT @re VALUES(@s)
    RETURN
END
GO


/*==============================================*/

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[f_splitSTR]') and xtype in (N'FN', N'IF', N'TF'))
drop function [dbo].[f_splitSTR]
GO

--3.2.3.1 使用临时性分拆辅助表法
CREATE FUNCTION f_splitSTR(
@s   varchar(8000),  --待分拆的字符串
@split varchar(10)     --数据分隔符
)RETURNS @re TABLE(col varchar(100))
AS
BEGIN
    --创建分拆处理的辅助表(用户定义函数中只能操作表变量)
    DECLARE @t TABLE(ID int IDENTITY,b bit)
    INSERT @t(b) SELECT TOP 8000 0 FROM syscolumns a,syscolumns b

    INSERT @re SELECT SUBSTRING(@s,ID,CHARINDEX(@split,@s+@split,ID)-ID)
    FROM @t
    WHERE ID<=LEN(@s+'a') 
        AND CHARINDEX(@split,@split+@s,ID)=ID
    RETURN
END
GO

/*==============================================*/

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[f_splitSTR]') and xtype in (N'FN', N'IF', N'TF'))
drop function [dbo].[f_splitSTR]
GO

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[tb_splitSTR]') and objectproperty(id,N'IsUserTable')=1)
drop table [dbo].[tb_splitSTR]
GO

--3.2.3.2 使用永久性分拆辅助表法
--字符串分拆辅助表
SELECT TOP 8000 ID=IDENTITY(int,1,1) INTO dbo.tb_splitSTR
FROM syscolumns a,syscolumns b
GO

--字符串分拆处理函数
CREATE FUNCTION f_splitSTR(
@s     varchar(8000),  --待分拆的字符串
@split  varchar(10)     --数据分隔符
)RETURNS TABLE
AS
RETURN(
    SELECT col=CAST(SUBSTRING(@s,ID,CHARINDEX(@split,@s+@split,ID)-ID) as varchar(100))
    FROM tb_splitSTR
    WHERE ID<=LEN(@s+'a') 
        AND CHARINDEX(@split,@split+@s,ID)=ID)
GO


/*==============================================*/

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[f_splitSTR]') and xtype in (N'FN', N'IF', N'TF'))
drop function [dbo].[f_splitSTR]
GO

--3.2.5 将数据项按数字与非数字再次拆份
CREATE FUNCTION f_splitSTR(
@s   varchar(8000),    --待分拆的字符串
@split varchar(10)     --数据分隔符
)RETURNS @re TABLE(No varchar(100),Value varchar(20))
AS
BEGIN
    --创建分拆处理的辅助表(用户定义函数中只能操作表变量)
    DECLARE @t TABLE(ID int IDENTITY,b bit)
    INSERT @t(b) SELECT TOP 8000 0 FROM syscolumns a,syscolumns b

    INSERT @re 
    SELECT    No=REVERSE(STUFF(col,1,PATINDEX('%[^-^.^0-9]%',col+'a')-1,'')),
        Value=REVERSE(LEFT(col,PATINDEX('%[^-^.^0-9]%',col+'a')-1))
    FROM(
        SELECT col=REVERSE(SUBSTRING(@s,ID,CHARINDEX(@split,@s+@split,ID)-ID))
        FROM @t
        WHERE ID<=LEN(@s+'a') 
            AND CHARINDEX(@split,@split+@s,ID)=ID)a
    RETURN
END
GO


/*==============================================*/

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[f_splitSTR]') and xtype in (N'FN', N'IF', N'TF'))
drop function [dbo].[f_splitSTR]
GO

--3.2.6 分拆短信数据
CREATE FUNCTION f_splitSTR(@s varchar(8000))
RETURNS @re TABLE(split varchar(10),value varchar(100))
AS
BEGIN
    DECLARE @splits TABLE(split varchar(10),splitlen as LEN(split))
    INSERT @splits(split)
    SELECT 'AC' UNION ALL
    SELECT 'BC' UNION ALL
    SELECT 'CC' UNION ALL
    SELECT 'DC'    
    DECLARE @pos1 int,@pos2 int,@split varchar(10),@splitlen int
    SELECT TOP 1 
        @pos1=1,@split=split,@splitlen=splitlen
    FROM @splits
    WHERE @s LIKE split+'%'
    WHILE @pos1>0
    BEGIN
        SELECT TOP 1
            @pos2=CHARINDEX(split,@s,@splitlen+1)
        FROM @splits
        WHERE CHARINDEX(split,@s,@splitlen+1)>0
        ORDER BY CHARINDEX(split,@s,@splitlen+1)
        IF @@ROWCOUNT=0
        BEGIN
            INSERT @re VALUES(@split,STUFF(@s,1,@splitlen,''))
            RETURN
        END
        ELSE
        BEGIN
            INSERT @re VALUES(@split,SUBSTRING(@s,@splitlen+1,@pos2-@splitlen-1))
            SELECT TOP 1 
                @pos1=1,@split=split,@splitlen=splitlen,@s=STUFF(@s,1,@pos2-1,'')
            FROM @splits
            WHERE STUFF(@s,1,@pos2-1,'') LIKE split+'%'
        END
    END
    RETURN
END
GO

/*
标题:分解字符串并查询相关数据
作者:爱新觉罗.毓华(十八年风雨,守得冰山雪莲花开) 
时间:2008-03-18
地点:广东深圳
说明:通过使用函数等方法分解字符串查询相关数据。

问题:通过分解一个带某种符号分隔的字符串在数据库中查找相关数据。
例如 @str = '1,2,3',查询下表得到记录1,4,5,6
ID TypeID
1  1,2,3,4,5,6,7,8,9,10,11,12
2  2,3 
3  3,7,8,9 
4  2,6 
5  4,5
6  6,7 
*/
-----------------------------
create table tb (ID int , TypeID varchar(30)) 
insert into tb values(1 , '1,2,3,4,5,6,7,8,9,10,11,12') 
insert into tb values(2 , '2,3') 
insert into tb values(3 , '3,7,8,9') 
insert into tb values(4 , '2,6') 
insert into tb values(5 , '4,5')
insert into tb values(6 , '6,7')
go
-----------------------------
--如果仅仅是一个,如@str = '1'.
declare @str as varchar(30)
set @str = '1'
select * from tb where charindex(',' + @str + ',' , ',' + TypeID + ',') > 0
select * from tb where ',' + TypeID + ',' like '%,' + @str + ',%'
/*
ID          TypeID                         
----------- ------------------------------ 
1           1,2,3,4,5,6,7,8,9,10,11,12
(所影响的行数为 1 行)
*/

-----------------------------
--如果包含两个,如@str = '1,2'.
declare @str as varchar(30)
set @str = '1,2'
select * from tb where charindex(',' + left(@str , charindex(',' , @str) - 1) + ',' , ',' + typeid + ',') > 0 or 
  charindex(',' + substring(@str , charindex(',' , @str) + 1 , len(@str)) + ',' , ',' + typeid + ',') > 0
select * from tb where ',' + typeid + ',' like '%,' + left(@str , charindex(',' , @str) - 1) + ',%' or 
  ',' + typeid + ',' like '%,' + substring(@str , charindex(',' , @str) + 1 , len(@str)) + ',%'
/*
ID          TypeID                         
----------- ------------------------------ 
1           1,2,3,4,5,6,7,8,9,10,11,12
2           2,3
4           2,6
(所影响的行数为 3 行)
*/

-------------------------------------------
--如果包含三个或四个,用PARSENAME函数来处理.
declare @str as varchar(30)
set @str = '1,2,3,4'
select * from tb where 
  charindex(',' + parsename(replace(@str , ',' , '.') , 4) + ',' , ',' + typeid + ',') > 0 or
  charindex(',' + parsename(replace(@str , ',' , '.') , 3) + ',' , ',' + typeid + ',') > 0 or
  charindex(',' + parsename(replace(@str , ',' , '.') , 2) + ',' , ',' + typeid + ',') > 0 or
  charindex(',' + parsename(replace(@str , ',' , '.') , 1) + ',' , ',' + typeid + ',') > 0 
select * from tb where 
  ',' + typeid + ',' like '%,' + parsename(replace(@str , ',' , '.') , 4) + ',%' or
  ',' + typeid + ',' like '%,' + parsename(replace(@str , ',' , '.') , 3) + ',%' or
  ',' + typeid + ',' like '%,' + parsename(replace(@str , ',' , '.') , 2) + ',%' or
  ',' + typeid + ',' like '%,' + parsename(replace(@str , ',' , '.') , 1) + ',%'
/*
ID          TypeID                         
----------- ------------------------------ 
1           1,2,3,4,5,6,7,8,9,10,11,12
2           2,3
3           3,7,8,9
4           2,6
5           4,5
(所影响的行数为 5 行)
*/

---------------------------------------
--如果超过四个,则只能使用函数或动态SQL来分解并查询数据。
/*
名称:fn_split函数.
功能:实现字符串分隔功能的函数
*/
create function dbo.fn_split(@inputstr varchar(8000), @seprator varchar(10))
returns @temp table (a varchar(200))
as 
begin
  declare @i int
  set @inputstr = rtrim(ltrim(@inputstr))
  set @i = charindex(@seprator , @inputstr)
  while @i >= 1
  begin
    insert @temp values(left(@inputstr , @i - 1))
    set @inputstr = substring(@inputstr , @i + 1 , len(@inputstr) - @i)
    set @i = charindex(@seprator , @inputstr)
  end
  if @inputstr <> '/'
  insert @temp values(@inputstr)
  return 
end
go

--调用
declare @str as varchar(30)
set @str = '1,2,3,4,5'

select distinct m.* from tb m,
(select * from dbo.fn_split(@str,',')) n
where charindex(',' + n.a + ',' , ',' + m.typeid + ',') > 0

drop table tb
drop function dbo.fn_split 

/*
ID          TypeID                         
----------- ------------------------------ 
1           1,2,3,4,5,6,7,8,9,10,11,12
2           2,3
3           3,7,8,9
4           2,6
5           4,5
(所影响的行数为 5 行)
*/

------------------------------------------
--使用动态SQL的语句。
declare @str varchar(200)
declare @sql as varchar(1000)
set @str = '1,2,3,4,5'
set @sql = 'select ''' + replace(@str , ',' , ''' as id union all select ''')
set @sql = @sql + ''''
set @sql = 'select distinct a.* from tb a , (' + @sql + ') b where charindex(' + ''','' + b.id + ' + ''',''' + ' , ' + ''','' + a.typeid + ' + ''',''' + ') > 0 '
exec (@sql)
/*
ID          TypeID                         
----------- ------------------------------ 
1           1,2,3,4,5,6,7,8,9,10,11,12
2           2,3
3           3,7,8,9
4           2,6
5           4,5
(所影响的行数为 5 行)
*/

 ---分拆列值 

--原著:邹建 
--改编:爱新觉罗.毓华(十八年风雨,守得冰山雪莲花开)  2007-12-16  广东深圳 

--有表tb, 如下: 
id          value 
----------- --------
1          aa,bb 
2          aaa,bbb,ccc 
欲按id,分拆value列, 分拆后结果如下: 
id          value 
----------- -------- 
1          aa 
1          bb 
2          aaa 
2          bbb 
2          ccc 

1. 旧的解决方法(sql server 2000) 
SELECT TOP 8000 id = IDENTITY(int, 1, 1) INTO # FROM syscolumns a, syscolumns b 

SELECT A.id, SUBSTRING(A.[values], B.id, CHARINDEX(',', A.[values] + ',', B.id) - B.id) 
FROM tb A, # B 
WHERE SUBSTRING(',' + A.[values], B.id, 1) = ',' 

DROP TABLE # 

2. 新的解决方法(sql server 2005) 

create table tb(id int,value varchar(30)) 
insert into tb values(1,'aa,bb') 
insert into tb values(2,'aaa,bbb,ccc') 
go 
SELECT A.id, B.value 
FROM( 
    SELECT id, [value] = CONVERT(xml,' <root> <v>' + REPLACE([value], ',', ' </v> <v>') + ' </v> </root>') FROM tb 
)A 
OUTER APPLY( 
    SELECT value = N.v.value('.', 'varchar(100)') FROM A.[value].nodes('/root/v') N(v) 
)B 

DROP TABLE tb 

/* 
id          value 
----------- ------------------------------ 
1          aa 
1          bb 
2          aaa 
2          bbb 
2          ccc 

(5 行受影响) 
*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQL Server中,可以使用不同的方法来拆分字符串。以下是一些常用的方法: 1. 使用SUBSTRING和CHARINDEX函数:这种方法适用于字符串中的分隔符是固定的。您可以使用CHARINDEX函数找到分隔符的位置,并使用SUBSTRING函数将字符串拆分为子字符串。重复此步骤,直到将整个字符串拆分为所需的部分。 例如,假设您有一个以逗号分隔的字符串'apple,banana,orange',您可以使用以下查询将其拆分为三个部分: ```sql DECLARE @str VARCHAR(100) = 'apple,banana,orange' SELECT SUBSTRING(@str, 1, CHARINDEX(',', @str) - 1) AS Part1, SUBSTRING(@str, CHARINDEX(',', @str) + 1, LEN(@str) - CHARINDEX(',', @str) - LEN(REPLACE(@str, ',', ''))) AS Part2, SUBSTRING(@str, CHARINDEX(',', @str, CHARINDEX(',', @str) + 1) + 1, LEN(@str) - CHARINDEX(',', @str, CHARINDEX(',', @str) + 1) - LEN(REPLACE(@str, ',', ''))) AS Part3 ``` 2. 使用STRING_SPLIT函数(仅适用于SQL Server 2016及更高版本):从SQL Server 2016开始,引入了STRING_SPLIT函数,它可以直接将字符串拆分为多个行。您可以使用此函数将字符串拆分为表格,并使用SELECT语句检索每个部分。 例如,使用STRING_SPLIT函数拆分字符串'apple,banana,orange': ```sql SELECT value AS Part FROM STRING_SPLIT('apple,banana,orange', ',') ``` 3. 使用XML和XQuery:这种方法将字符串转换为XML,并使用XQuery从XML中检索所需的部分。 例如,使用XML和XQuery拆分字符串'apple,banana,orange': ```sql DECLARE @xml XML SET @xml = '<root><part>' + REPLACE('apple,banana,orange', ',', '</part><part>') + '</part></root>' SELECT t.c.value('.', 'VARCHAR(100)') AS Part FROM @xml.nodes('/root/part') t(c) ``` 这些是一些常见的字符串拆分方法,您可以根据您的需求选择适合的方法。请注意,每种方法都有其自己的优缺点,请根据您的场景进行选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值