SQL 拆分字符串

/*
    问题描述:分隔字符串,大都用临时表或表变量,有时候要在存储过程里用到,又在循环里采用此种方式就会成为性能的颈瓶,
    现在采用 charindex 函数解决这个问题。
*/

    
-- 
if object_id(N'DivStr'is not null
    
begin
        
drop table DivStr;
    
end
-- 创建测试表
create table DivStr
(
    id 
int not null identity(1,1)    ,
    Iname 
nvarchar(200),
    PNo 
nvarchar(500)
)
-- 填充测试数据,现在为 700 行,假设每个数据行不同的情况
declare @a int
select @a = 0    
while @a < 100        -- 可以修改之后再运行
    begin
        
insert into DivStr
        
select 'a','a|aa|aaa' + cast(@a as varcharunion all
        
select 'b','|b|bb|bbb' + cast(@a as varcharunion all
        
select 'c','c|cc|ccc|' + cast(@a as varcharunion all
        
select 'd','|d|dd|ddd|' + cast(@a as varcharunion all
        
select 'e','e||ee|eee' + cast(@a as varcharunion all
        
select 'f','f||ff|fff|' + cast(@a as varcharunion all
        
select 'g','|g|g||g||' + cast(@a as varchar)
        
select @a = @a + 1;
    
end

-- select * from DivStr
--
 select count(*) from DivStr

declare @i int                        -- 控制循环变量
declare @c int                        -- 循环次数
declare @p int                        -- 查找字符串位置
declare @str nvarchar(500)            -- 动态执行字符串
declare @pnostr nvarchar(500)        -- 每行取的数据串
declare @pnostrtemp nvarchar(500)    -- 拆分字符串时临时变量
declare @pno nvarchar(100)            -- 拆分之后的单个字符串

select @i = 0,@p = 0                -- 初值
    
select @c = count(*from DivStr    -- 循环次数值

-- print @c

while @i < @c
    
begin
        
declare @ii int                -- 控制内层循环
        declare @cc int                -- 内层循环次数
        select @ii = 0,@str = 'select @pnostr = PNo from DivStr 
                        where id =' + str(@i)

        
-- print @str    
        exec sp_executesql @str,N'@pnostr nvarchar(500) output',@pnostr output        -- 取每行数据
        select @pnostr = '''' + replace(@pnostr,'|',''','''+ ''''                    -- 转换 | -> ',' 
        select @pnostr = replace(@pnostr,''''',','')                                -- 过滤 '',         注: 最前面有'|'
        select @pnostr = replace(@pnostr,',''''','')                                -- 过滤 ,''         注: 最后面有'|'
        select @pnostr = replace(@pnostr,'''''','')                                    -- 过滤 ''         注: 连续||的情况
        select  @i = @i + 1,@cc = len(@pnostr- len(replace(@pnostr,',','')) + 1    
        
-- print @cc
        -- print @pnostr
        select @pnostrtemp = @pnostr
        
while @ii < @cc
            
begin
                
select @ii = @ii + 1,@p = charindex(',',@pnostrtemp,@p)                -- 第一个,起始位置
                -- print @p
                if @p = 0
                    
begin
                        
select @pno = @pnostrtemp                                    -- 如果位置为 0,则说明为最后一个字符串
                    end                    
                
else
                    
begin
                        
select @pno = left(@pnostrtemp,@p - 1)                        -- 否则取第一个','号前的字符串
                    end
                
-- print @pno
                select @pnostrtemp = right(@pnostrtemp,len(@pnostrtemp- @p)        -- 取第一个','之后的字符串
                -- print @pnostrtemp                
            end        
    
end
posted on 2007-11-18 19:30  sunbird69  阅读(895)  评论(0)    收藏  举报