2016-11-28 25 views
1

Xml存儲在varchar列中。通過select語句獲取xml節點作爲逗號分隔列表

其中一個節點就像

<PreviousItem> 
<string>501</string> 
<string>502</string> 
<string>505</string> 
</PreviousItem> 

我需要得到這個節點,在此XML和表中的其他項目一起元素comma delimited list (having issue with this part only)

SELECT 
    nId, cDescription, 
    ,CAST(cSettings AS XML).value('data(/clsSettings/PreviousItem)[1]','nvarchar(max)') AS PreviousItem 
    ,CAST(cSettings AS XML).value('data(/clsSettings/RegistrationType)[1]','nvarchar(50)') AS RegistrationType 
FROM tblX 

以上是給我的PreviousItem爲501502505

我曾嘗試以下,但我在CAST(cSettings AS XML)

(SELECT  
      STUFF((SELECT ',' + Prods.Prod.value('text()[1]','varchar(max)') 
        FROM CAST(cSettings AS XML).nodes('/clsSettings/PreviousItem') AS Prods (Prod) 
        FOR XML PATH('') 
      ), 1, 1, '') 
     ) prods 
+0

是否有對XML存儲在VARCHAR理由嗎?作爲一般規則,建議您爲作業使用正確的[數據類型](https://msdn.microsoft.com/en-gb/library/hh403385.aspx?f=255&MSPPError=-2147217396)。這有幾個好處,包括:輸入無效數據更加困難,並且更容易處理(例如,每次都不需要投射列)。 –

+0

[將多行連接成單個文本字符串?]可能的重複(http://stackoverflow.com/questions/194852/concatenate-many-rows-into-a-single-text-string) –

+0

我沒有對數據庫的任何控制,我都這樣,所以不知道爲什麼。 –

回答

1

及彼Incorrect syntax near the keyword 'AS'的一種方法:

-- Sample Data 
DECLARE @tblX TABLE (cID int identity, cSettings xml); 
INSERT @tblX (cSettings) 
VALUES 
('<PreviousItem> 
<string>501</string> 
<string>502</string> 
<string>505</string> 
</PreviousItem>'), 
('<PreviousItem> 
<string>4433</string> 
<string>5577</string> 
</PreviousItem>'); 

-- Solution 
SELECT 
    cID, 
    PreviousItem = STUFF 
    (
    (
     SELECT ',' + x.value('(text())[1]', 'varchar(500)') 
     FROM @tblX t 
     CROSS APPLY cSettings.nodes('/PreviousItem/string') x(x) 
     WHERE t.cID = tx.cId 
     FOR XML PATH('') 
    ),1,1,'' 
) 
FROM @tblX tx; 

根據您的樣本數據,你必須生活在你的XML,你需要一個RegistrationType得到...這是我的第一個解決方案的調整版本。

-- Updated Sample Data with RegistrationType 
DECLARE @tblX TABLE (cID int identity, cSettings xml); 
INSERT @tblX (cSettings) 
VALUES 
('<PreviousItem> 
<string>501</string> 
<string>502</string> 
<string>505</string> 
</PreviousItem> 
<RegistrationType>Type A</RegistrationType> 
'), 
('<PreviousItem> 
<string>4433</string> 
<string>5577</string> 
</PreviousItem> 
<RegistrationType>Type B</RegistrationType> 
'); 

-- Solution which includes RegistrationType 
SELECT 
    cID, 
    PreviousItem = STUFF 
    (
    (
     SELECT ',' + x.value('(text())[1]', 'varchar(500)') 
     FROM @tblX t 
     CROSS APPLY cSettings.nodes('/PreviousItem/string') x(x) 
     WHERE t.cID = tx.cId 
     FOR XML PATH('') 
    ),1,1,'' 
),  
    RegistrationType = STUFF 
    (
    (
     SELECT ',' + x.value('(text())[1]', 'varchar(500)') 
     FROM @tblX t 
     CROSS APPLY cSettings.nodes('RegistrationType') x(x) 
     WHERE t.cID = tx.cId 
     FOR XML PATH('') 
    ),1,1,'' 
) 
FROM @tblX tx; 

如需更準確的解決方案,請包括一些DDL和可消耗的樣品數據,我可以相應地修改我的解決方案。

更新:因爲你的XML數據存儲爲文本,你將需要調整我原來的解決方案,像這樣:

-- Updated Sample Data with RegistrationType 
DECLARE @tblX TABLE (cID int identity, cSettings varchar(max)); 
INSERT @tblX (cSettings) 
VALUES 
('<PreviousItem> 
<string>501</string> 
<string>502</string> 
<string>505</string> 
</PreviousItem> 
<RegistrationType>Type A</RegistrationType> 
'), 
('<PreviousItem> 
<string>4433</string> 
<string>5577</string> 
</PreviousItem> 
<RegistrationType>Type B</RegistrationType> 
'); 

-- Solution which includes RegistrationType 
SELECT 
    cID, 
    PreviousItem = STUFF 
    (
    (
     SELECT ',' + x.value('(text())[1]', 'varchar(500)') 
     FROM @tblX t 
     CROSS APPLY (VALUES (CAST(cSettings AS xml))) xx(xx) 
     CROSS APPLY xx.xx.nodes('/PreviousItem/string') x(x) 
     WHERE t.cID = tx.cId 
     FOR XML PATH('') 
    ),1,1,'' 
), 
    RegistrationType = STUFF 
    (
    (
     SELECT ',' + x.value('(text())[1]', 'varchar(500)') 
     FROM @tblX t 
     CROSS APPLY (VALUES (CAST(cSettings AS xml))) xx(xx) 
     CROSS APPLY xx.xx.nodes('RegistrationType') x(x) 
     WHERE t.cID = tx.cId 
     FOR XML PATH('') 
    ),1,1,'' 
) 
FROM @tblX tx; 
+0

感謝您的回覆!我的xml駐留在varchar字段內而不是xml。你的例子是使用.node,它只適用於xml類型。 –

+0

我更新了我的答案,以處理存儲爲varchar的數據。 –

+0

謝謝,正是我需要的! –

0

因爲你在處理文字和不支持XML,你可以處理這個更有效地利用一些基本的T-SQL和PatExclude8K像這樣:

-- Updated Sample Data with RegistrationType 
DECLARE @tblX TABLE (cID int identity, cSettings varchar(max)); 
INSERT @tblX (cSettings) 
VALUES 
('<PreviousItem> 
<string>501</string> 
<string>502</string> 
<string>505</string> 
</PreviousItem> 
<RegistrationType>Type A</RegistrationType> 
'), 
('<PreviousItem> 
<string>4433</string> 
<string>5577</string> 
</PreviousItem> 
<RegistrationType>Type B</RegistrationType> 
'); 

-- Solution using PatExclude8K 
SELECT 
    cID, 
    PreviousItem  = SUBSTRING(NewString,1, LEN(NewString)-1), 
    RegistrationType = SUBSTRING 
    (
    cSettings, 
    CHARINDEX('<RegistrationType>', cSettings)+18, 
    CHARINDEX('</RegistrationType>', cSettings) - 
     (CHARINDEX('<RegistrationType>', cSettings)+18) 
) 
FROM @tblX o 
CROSS APPLY dbo.PatExclude8K(REPLACE(cSettings,'</string>',','), '[^0-9,]'); 
相關問題