2011-07-19 70 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, ''), '')