2011-07-19 16 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'となります。あなたは、 '合体 'に'部分文字列 'を埋め込むことができます。 –

答えて

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

私はあなたが私はあなたが「値1のような結果を得るためにSUBSTRING を使用する理由わからないSUBSTRING ので、空の文字列を得たと思います、私の値の間のValue2、Value3のテキスト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, ''), '')