字符串分解

--各种字符串分拆处理函数.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)[email protected],‘‘)
    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,@[email protected],ID)-ID)
    FROM @t
    WHERE ID<=LEN(@s+‘a‘) 
        AND CHARINDEX(@split,@[email protected],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,@[email protected],ID)-ID) as varchar(100))
    FROM tb_splitSTR
    WHERE ID<=LEN(@s+‘a‘) 
        AND CHARINDEX(@split,@[email protected],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,@[email protected],ID)-ID))
        FROM @t
        WHERE ID<=LEN(@s+‘a‘) 
            AND CHARINDEX(@split,@[email protected],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,@[email protected]))
            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 行受影响) 
*/

时间: 2024-10-07 23:45:09

字符串分解的相关文章

java字符串分解 StringTokenizer用法(比split()方法效率高)

Java中substring方法可以分解字符串,返回的是原字符串的一个子字符串.如果要讲一个字符串分解为一个一个的单词或者标记,StringTokenizer可以帮你. int countTokens():返回nextToken方法被调用的次数.boolean hasMoreTokens():返回是否还有分隔符.boolean hasMoreElements():返回是否还有分隔符.String nextToken():返回从当前位置到下一个分隔符的字符串.Object nextElement(

java字符串分解 StringTokenizer用法

Java中substring方法可以分解字符串,返回的是原字符串的一个子字符串.如果要讲一个字符串分解为一个一个的单词或者标记,StringTokenizer可以帮你. 先看个例子: 1 public static void main(String[] args) { 2 StringTokenizer st = new StringTokenizer("www.ooobj.com", ".b"); 3 while(st.hasMoreElements()){ 4

【51CTO/BBS】请教: SQL里有没有字符串分解、组合的函数??

[51CTO/BBS]请教: SQL里有没有字符串分解.组合的函数?? 原帖地址:http://bbs.51cto.com/thread-1133863-1.html 问题描述: VB 中有两个非常好用的字符串处理函数: Split(字符串,分隔符)作用:将[字符串]以[分隔符]作为边界,分解成数组. 返回:一个字符串数组. Join(字符数组,分隔符)作用:将[字符数组]中的元素,以[分隔符]作为边界,连接成一个字符串.返回:一个字符串. 请教老师们,SQL里是否有类似的函数? 解决方案: 如

ORACLE编程的套路——字符串分解

作者按,字符串分解在ORACLE编程中可用于词.字的解析,继而可实现单词搜索的合并,为基础代码. 代码如下,作者保留所有权. create or replace function FUN_STRING_SPLIT ( v_string IN VARCHAR2, v_sep IN VARCHAR2) return fs.stringList IS /***************************************************************************

SQL-一道特殊的字符串分解题目

本题不是一道直接的字符串拆解, 应用场景如下,表中有一个字段,是表示事件受影响的国家集合,使用逗号进行分隔,不幸的是,居然发现有些国家本身就带有逗号,这样在规范化的时候,如何准确地找到这些国家呢? 以下的代码是有一定限制的.但基本上够用. 下面的代码使用到了分析函数lag和lead还有cte,sqlserver2012及其以后的版本都支持,oracle好像10g以上就支持了. 主要思路: 字符串的分解,可以使用数字辅助表,然后cross join刷副本,然后根本分隔符出现的位置然后切豁字符串拆解

Leetcode:Word Break 字符串分解为单词

Word Break Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words. For example, given s = "leetcode", dict = ["leet", "code"]. Return t

萌新笔记——C++里将string类字符串(utf-8编码)分解成单个字(可中英混输)

最近在建词典,使用Trie字典树,需要把字符串分解成单个字.由于传入的字符串中可能包含中文或者英文,它们的字节数并不相同.一开始天真地认为中文就是两个字节,于是很happy地直接判断当前位置的字符的ASCII码是否处于0~127之间,如果是就提取一个字符,否则提取两个.在测试分字效果的时候,这种方法出了问题.比如我传一个"abcde一二三四五"进去,abcde可以正常分解成 a b c d e,而后面的"一二三四五"则成了乱码. 于是我开启了谷歌之旅,搜索"

PHP 统计中文字符串的长度

中文网站一般会选择两种编码:gbk/gb2312或是utf-8. gbk编码下每个中文字符所占字节为2,例: $zhStr = ‘您好,中国!’; echo strlen($zhStr); // 输出:12 UTF-8编码下每个中文字符占3个字节. $zhStr = ‘您好,中国!’; echo strlen($zhStr); // 输出:18 那么如何计算这组中文字符串的长度呢?有人可能会说gbk下获取中文字符串长度除以2,utf-8编码下除以3不就行了吗?但是您要考虑字符串并不老实,99%的

Java将一段逗号分割的字符串转换成一个数组

String 类:String 类代表字符串.Java 程序中的所有字符串字面值都作为此类的实例实现.字符串是常量,它们的值在创建之后不能更改.字符串缓冲区支持可变的字符串.因为 String 对象是不可变的,所以 可以共享.String 类包括的方法可用于检查序列的单个字符.比较字符串.搜索字符串.提取子字符串.创建字符串副本并将所有字符全部转换为大写或小写.Java 语言提供对字符串串联符号("+")以及将其他 对象转换为字符串的特殊支持.字符串串联是通过 StringBuilde