0

可能重复:
T-SQL:与字符串连接相反 - 如何将字符串拆分为多个记录将
可变长度分隔的字符串拆分为多行(SQL)

我有一个包含如下列数据的数据库表:

Data (field name)
1111,44,666,77
22,55,76,54
32,31,56

我意识到这是一个非常糟糕的设计,因为它没有标准化(我没有设计它 - 我继承了它)。是否有一个查询会返回这样的数据:

1111
44
666
77
22
55
76
54
32
31
56

我习惯使用 CHARINDEX 和 SUBSTRING,但我想不出这样做的方法,因为每个单元格中的元素数量(由逗号分隔)是未知的。

4

5 回答 5

2

我创建了一个名为 [dbo].[stack] 的表,并用您提供的数据填充它,这个脚本产生了您需要的数据。可能有一种更有效的方法可以做到这一点,但这完全符合您的要求。

    BEGIN
        DECLARE @tmp TABLE (data VARCHAR(20))
        DECLARE @tmp2 TABLE (data VARCHAR(20))

        --Insert all fields from your table
        INSERT INTO @tmp (data)
        SELECT [data]           
        FROM   [dbo].[stack] -- your table name here

        --Loop through all the records in temp table
        WHILE EXISTS (SELECT 1
                                    FROM   @tmp)            
            BEGIN 
                DECLARE @data VARCHAR(100) --Variable to chop up 
                DECLARE @data1 VARCHAR(100) -- Untouched variable to delete from tmp table
                SET @data =  (SELECT TOP 1 [data]
                                            FROM   @tmp)
                SET @data1 =  (SELECT TOP 1 [data]
                                             FROM   @tmp)

                --Loop through variable to get individual value 
                WHILE PATINDEX('%,%',@data) > 0     
                    BEGIN
                        INSERT INTO @tmp2
                        SELECT SUBSTRING(@data,1,PATINDEX('%,%',@data)-1);
                        SET @data = SUBSTRING(@data,PATINDEX('%,%',@data)+1,LEN(@data))
                        IF PATINDEX('%,%',@data) = 0
                            INSERT INTO @tmp2
                            SELECT @data            
                    END

                DELETE FROM @tmp 
                WHERE [data] = @data1

            END     

        SELECT * FROM @tmp2     
    END
于 2012-11-27T21:47:32.570 回答
2

您可以使用 CTE 拆分数据:

;with cte (DataItem, Data) as
(
  select cast(left(Data, charindex(',',Data+',')-1) as varchar(50)) DataItem,
         stuff(Data, 1, charindex(',',Data+','), '') Data
  from yourtable
  union all
  select cast(left(Data, charindex(',',Data+',')-1) as varchar(50)) DataItem,
    stuff(Data, 1, charindex(',',Data+','), '') Data
  from cte
  where Data > ''
) 
select DataItem
from cte

请参阅带有演示的 SQL Fiddle

结果:

| DATAITEM |
------------
|     1111 |
|       22 |
|       32 |
|       31 |
|       56 |
|       55 |
|       76 |
|       54 |
|       44 |
|      666 |
|       77 |

或者您可以创建一个拆分功能:

create FUNCTION [dbo].[Split](@String varchar(MAX), @Delimiter char(1))       
returns @temptable TABLE (items varchar(MAX))       
as       
begin      
    declare @idx int       
    declare @slice varchar(8000)       

    select @idx = 1       
        if len(@String)<1 or @String is null  return       

    while @idx!= 0       
    begin       
        set @idx = charindex(@Delimiter,@String)       
        if @idx!=0       
            set @slice = left(@String,@idx - 1)       
        else       
            set @slice = @String       

        if(len(@slice)>0)  
            insert into @temptable(Items) values(@slice)       

        set @String = right(@String,len(@String) - @idx)       
        if len(@String) = 0 break       
    end   
return 
end;

您可以在查询时使用它,这将产生相同的结果:

select s.items declaration
from yourtable t1
outer apply dbo.split(t1.data, ',') s
于 2012-11-27T21:58:47.340 回答
0
SELECT REPLACE(field_name, ',', ' ') from table

编辑:当你改变你的问题时,不要介意这个答案。

于 2012-11-27T17:38:02.453 回答
0

不谈论性能,您可以将数据连接到单个列中,然后将其拆分。

连接数据:http ://sqlfiddle.com/#!6/487a4/3

拆分它:T-SQL:与字符串连接相反 - 如何将字符串拆分为多条记录

于 2012-11-27T19:50:32.043 回答
0

看看在类似问题中引用的这篇文章:

http://www.codeproject.com/Articles/7938/SQL-User-Defined-Function-to-Parse-a-Delimited-Str

如果您创建他们在那篇文章中拥有的函数,您可以使用以下方法调用它:

select * from dbo.fn_ParseText2Table('100|120|130.56|Yes|Cobalt Blue','|')

于 2012-11-27T21:36:14.760 回答