2012-11-27 64 views
0

可能重複:
T-SQL: Opposite to string concatenation - how to split string into multiple records
Splitting variable length delimited string across multiple rows (SQL)SQL - SUBSTRING和CHARINDEX

我有一個包含這樣的列數據的數據庫表:

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,但我不認爲這樣的元素在每個單元數量的方式(通過分隔逗號)未知。

回答

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 with Demo

結果:

| 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 
0
SELECT REPLACE(field_name, ',', ' ') from table 

編輯:沒關係這個答案,因爲你改變了你的問題。

+0

我改變了問題的格式,以使其更清晰。對於那個很抱歉。 – w0051977

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