使用SQL / TSQL,如何在WHILE子句中使用STUFF?

时间:2014-11-25 19:06:53

标签: sql sql-server tsql

我有一个字符串,例如:

@String = 'filename.jpg##!!!##file description##|||##filename2.jpg##!!!##file description'

然后是一个循环,我将暂时解释:

WHILE LEN(@String) > 0
    BEGIN
        set @filestring = LEFT(@String, CHARINDEX('##|||##', @String+'##|||##') -1)
        set @filename = LEFT(@filestring, CHARINDEX('##!!!##', @filestring+'##!!!##') -1)
        set @filedesc = RIGHT(@filestring, CHARINDEX('##!!!##', REVERSE(@filestring)) -1)

        UPDATE Table SET Description = @filedesc
        WHERE Filename = @filename

        set @String = STUFF(@String, 7, charindex('##|||##', @String+'##|||##'), '')

    END

这个循环工作正常,直到它结束。

示例:

通过1:

WHILE LEN(@String) > 0
    BEGIN
        set @filestring = LEFT(@String, CHARINDEX('##|||##', @String+'##|||##') -1)
        -- 'filename.jpg##!!!##file description'
        set @filename = LEFT(@filestring, CHARINDEX('##!!!##', @filestring+'##!!!##') -1)
        -- 'filename.jpg'
        set @filedesc = RIGHT(@filestring, CHARINDEX('##!!!##', REVERSE(@filestring)) -1)
        -- 'file description'
        UPDATE Table SET Description = @filedesc
        WHERE Filename = @filename

        set @String = STUFF(@String, 7, charindex('##|||##', @String+'##|||##'), '')
        -- 'filename2.jpg##!!!##file description'   
    END

通过2

WHILE LEN(@String) > 0
    BEGIN
        set @filestring = LEFT(@String, CHARINDEX('##|||##', @String+'##|||##') -1)
        -- 'filename2.jpg##!!!##file description'
        set @filename = LEFT(@filestring, CHARINDEX('##!!!##', @filestring+'##!!!##') -1)
        -- 'filename2.jpg'
        set @filedesc = RIGHT(@filestring, CHARINDEX('##!!!##', REVERSE(@filestring)) -1)
        -- 'file description'
        UPDATE Table SET Description = @filedesc
        WHERE Filename = @filename

        set @String = STUFF(@String, 7, charindex('##|||##', @String+'##|||##'), '')
        -- 'filen'  <------ problem
    END

这种方法在过去对我有用,没有任何问题,但仅限于使用单个字符作为分隔符。

因此,最后一组@String应该使它成为一个空字符串,但它抓住了一些文件名字符。

感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

在最后一个循环中RIGHT(@filestring, CHARINDEX('##!!!##', REVERSE(@filestring)) 评估为RIGHT(@filestring,-1),这是RIGHT的无效长度 如果你想留下循环,可以使用以下方法来避免这种情况:

WHILE CHARINDEX('##!!!##',@String) > 0

而不是

WHILE LEN(@String) > 0

答案 1 :(得分:0)

以下是使用Aaron文章(http://sqlperformance.com/2012/07/t-sql-queries/split-strings)中引用的原始Moden分割器执行此操作的示例。这是直接链接。 http://www.sqlservercentral.com/articles/Tally+Table/72993/

declare @String varchar(500) = 'filename.jpg##!!!##file 1 description##|||##filename2.jpg##!!!##file 2 description'

if OBJECT_ID('tempdb..#Something') is not null
    drop table #Something

create table #Something
(
    MyFileName varchar(50),
    FileDescription varchar(50)
)

insert #Something (MyFileName, FileDescription)
select 'filename.jpg', '' union all
select 'filename2.jpg', ''

select * from #Something

set @String = REPLACE(REPLACE(@String, '##!!!##', '^'), '##|||##', '|')
select @String;

with MyUpdateValues as
(
    select
        MAX(case when x.ItemNumber = 1 then x.Item end) as MyFileName
        , MAX(case when x.ItemNumber = 2 then x.Item end) as FileDescription
    from dbo.DelimitedSplit8K(@String, '|') files
    cross apply dbo.DelimitedSplit8K(files.Item, '^') x
    group by files.ItemNumber
)

update s
set FileDescription = u.FileDescription
from #Something s
join MyUpdateValues u on u.MyFileName = s.MyFileName

select * from #Something