2011-07-19 91 views
4

我想創建一個連接硬編碼字符串和使用FOR XML PATH創建的字符串的值。FOR XML PATH和字符串連接

SUBSTRING(
(SELECT (', ' + [value]) 
FROM [values] 
FOR XML PATH('') 
), 3, 1000) + 
' text in between my values ' + 
SUBSTRING(
(SELECT (', ' + [otherValue]) 
FROM [otherValues] 
FOR XML PATH('') 
), 3, 1000) 

所以,我希望是這樣的:Value1, Value2, Value3 text in between my values OtherValue1, OtherValue2, OtherValue3,而是我得到一個空字符串。

如果我拿出子字符串(包括其中的查詢),我得到的值之間的罰款,如果我只是自己添加一個子字符串塊,我得到列表字符串回來。所以我不能解決爲什麼連接子字符串和FOR XML PATH查詢導致它返回一個空字符串....幫助!

+0

不知道空白字符串,但如果您針對[[Values] **或**'[otherValues]'的查詢返回0行,您將得到'NULL'。你可以嘗試將'substring'嵌入'coalesce'中。 –

回答

2

您不需要使用XML功能來創建您想要的東西列表。它確實不是爲了這樣做而構建的:它是爲生成XML而構建的。 :)

試試這個。我用這種方法有很多:

DECLARE @myList nvarchar(MAX) 

SELECT 
    @myList = COALESCE(@myList + ', ', '') + MyColumn 
    FROM MyTable; 

對於未來的讀者,請注意使用ORDER BY使用這種技術並不能保證該值最終會在輸出有序;見here

+0

感謝您的指針。恐怕SQL是以這種方式即時生成的,我不能在其中使用任何變量,這就是爲什麼我使用了FOR XML PATH。 –

+0

@John:一般來說,即使使用即席查詢,也可以使用變量。你可以編輯問題來顯示你運行查詢的上下文嗎? –

3

我覺得你原來的嘗試幾乎是在那裏。我始終使用相同的FOR XML方法來完成這種類型的任務。下面的解決方案解決您的具體例子,可以很容易地適用於其他用途:

DECLARE @delimiter NVARCHAR(10) 
SET @delimiter = ', ' 

declare @values TABLE (
    [value] NVARCHAR(25) 
) 

declare @otherValues TABLE (
    [otherValue] NVARCHAR(25) 
) 

INSERT INTO @values VALUES ('Value1') 
INSERT INTO @values VALUES ('Value2') 
INSERT INTO @values VALUES ('Value3') 

INSERT INTO @otherValues VALUES ('OtherValue1') 
INSERT INTO @otherValues VALUES ('OtherValue2') 
INSERT INTO @otherValues VALUES ('OtherValue3') 

SELECT 
    STUFF(
     (
      SELECT 
       @delimiter + CAST([value] AS NVARCHAR(500)) + '' AS [text()] 
      FROM 
       @values 
      FOR 
       XML PATH('') 
     ), 
     1, 
     LEN(REVERSE(@delimiter)), -- Reverse the delimiter string in case it has trailing spaces; LEN() won't count those 
     '' 
    ) + 
    ' text in between my values ' + 
    STUFF(
     (
      SELECT 
       @delimiter + CAST([otherValue] AS NVARCHAR(500)) + '' AS [text()] 
      FROM 
       @otherValues 
      FOR 
       XML PATH('') 
     ), 
     1, 
     LEN(REVERSE(@delimiter)), -- Reverse the delimiter string in case it has trailing spaces; LEN() won't count those 
     '' 
    ) 
+0

正是我需要的,謝謝! – Lukas

1

我猜你有一個空字符串,因爲SUBSTRING 我不知道爲什麼你使用SUBSTRING 得到一個結果,如「值1,值2,值3我的值之間的文本OtherValue1,OtherValue2,OtherValue3「 試試這個。

SELECT 
-- ISNULL(here in case [values] is empty table 
    ISNULL(STUFF((
     SELECT ', ' + [value] 
-- should be ', ' + NULLIF(value,'') or ', ' + ISNULL(value,'') depends on what you need 
-- there is no column name for ', ' + [value], so AS [text()] is not need here 
     FROM [values] 
     FOR XML PATH(''),TYPE 
    ).value('text()[1]','nvarchar(max)'), 1, 2, ''), '') + 
-- you can replace PATH(''),TYPE).value('text()[1]','nvarchar(max)') 
-- with PATH('')) it will be faster but if the values contain & > < etc. chars, 
-- they will result in &amp &gt; &lt; 
    ' text in between my values ' + 
    ISNULL(STUFF((
     SELECT ', ' + [otherValue] 
     FROM [otherValues] WHERE [otherValues]<>'' 
     FOR XML PATH(''),TYPE 
    ).value('text()[1]','nvarchar(max)'), 1, 2, ''), '')