2010-06-17 50 views
1

我有一個相當簡單的要求 - 我有一個表,其中包含以下(相關)結構。SQL Server 2008每行分割字符串變量令牌數

with cte as(
select 1 id,'AA,AB,AC,AD' names union all 
select 2,'BA,BB' union all 
select 3,'CA,CB,CC,CD,CE' union all 
select 4,'DA,DB,DC' 
) 

我想創建一個select語句,將每個「名稱」列拆分爲多行。

例如第一行應該產生

1,'AA' 
1,'AB' 
1,'AC' 
1,'AD' 

我們能做到這一點只使用SQL。這在Oracle中很容易實現。

+0

它通常是不透明的查詢,但逗號是分開的d列表確實使情況複雜化。理想情況下,您應該更正數據模型,以便在單個列值中不包含用逗號分隔的值。 – 2010-06-17 20:44:43

回答

2

您可以沒有任何自定義的功能做在一個查詢,如果你利用XML:

WITH cte AS(/*your data*/ 
    SELECT 1 id,'AA,AB,AC,AD' names UNION ALL 
    SELECT 2,'BA,BB' UNION ALL 
    SELECT 3,'CA,CB,CC,CD,CE' UNION ALL 
    SELECT 4,'DA,DB,DC' 
) 
, xmlData AS (/*make into xml*/ 
    SELECT id, cast('<root><x>'+replace(names,',','</x><x>')+'</x></root>' as xml) AS theXML 
    FROM cte 
) 
SELECT id, x.value('.','varchar(100)') /*split up*/ 
FROM xmlData 
CROSS APPLY xmlData.theXML.nodes('//x') AS func(x) 
+0

請注意,如果您的名稱超過100個字符,則轉換爲varchar時必須具有更大的長度。除了2008年,這也將在SQL Server 2005上運行。 – Zugwalt 2010-06-17 20:59:25

1

您可以創建一個返回表的分割函數,然後從該表中選擇。

/*************************************************************************** 
** 
** Function: split 
** In: @ipRowData - The delimited list of items to split. 
** In: @ipSplitOn - The delimiter which separates the items in @rowData. 
** Returns: A table object containing the split items. The table object 
** will have an ID and Data column, where ID is the number of the item 
** in the original list and Data is the value of the item. 
** 
** Description: 
** Splits a delimited set of items and returns them 
** as a table object. 
***************************************************************************/ 
CREATE FUNCTION [dbo].[split] 
(
    @ipRowData NVARCHAR(4000), 
    @ipSplitOn NVARCHAR(5) 
) 
RETURNS @rtnValue table 
(
    ID INT identity(1,1), 
    Data NVARCHAR(100) 
) 
AS 
BEGIN 
    DECLARE 
     @cnt INT 
     Set @cnt = 1 

    WHILE (Charindex(@ipSplitOn,@ipRowData)>0) 
    BEGIN 
     INSERT INTO @rtnValue 
       (data) 
        SELECT Data = ltrim(rtrim(Substring(@ipRowData,1,Charindex(@ipSplitOn,@ipRowData)-1))) 
     SET @ipRowData = Substring(@ipRowData,Charindex(@ipSplitOn,@ipRowData)+1,len(@ipRowData)) 
     SET @cnt = @cnt + 1 
    END 

    INSERT INTO @rtnValue (data) 
    SELECT DATA = ltrim(rtrim(@ipRowData)) 

    RETURN 
END 

GO 

用法示例:

select 1,data from [dbo].split('AA,AB,AC,AD', ','); 

輸出:

(No column name) data 
1     AA 
1     AB 
1     AC 
1     AD