使用CONCAT_NULL_YIELDS_NULL选项的XML .value()方法问题

时间:2013-11-06 00:57:12

标签: sql-server tsql

我正在尝试将行转换为逗号分隔的字符串。这是我的表和数据

drop table test
create table test (a int, b int, c varchar(30), d varchar(30))
insert into test values(1,1,'<1>','<d>')
insert into test values(1,1,'<2>','<d>')
insert into test values(1,2,'<3>','<d>')
insert into test values(1,2,'<4>','<d>')
insert into test values(1,3,'<5>','<d>')
insert into test values(1,3,'<6>','<d>')

我期待

的结果
, <1> - <d>, <2> - <d>, <3> - <d>, <4> - <d>, <5> - <d>, <6> - <d>

如果我使用

select 
(SELECT ',' + ' ' +ltrim(rtrim(tc.c)) +' - '+ ltrim(rtrim(tc.d))
   FROM  test tc
    FOR XML PATH(''),type)

查询给出以下结果

, &lt;1&gt; - &lt;d&gt;, &lt;2&gt; - &lt;d&gt;, &lt;3&gt; - &lt;d&gt;, &lt;4&gt; - &lt;d&gt;, &lt;5&gt; - &lt;d&gt;, &lt;6&gt; - &lt;d&gt;

因此我添加了.value方法如下

select 
(SELECT ',' + ' ' +ltrim(rtrim(tc.c)) +' - '+ ltrim(rtrim(tc.d))
   FROM  test tc
    FOR XML PATH(''),type).value('(./text())[1]','varchar(max)')

这个产生正确的结果。这是我真正的问题: 它仅在我设置CONCAT_NULL_YIELDS_NULL时有效。 如果我设置CONCAT_NULL_YIELDS_NULL关闭Sql Server抱怨

"Msg 1934, Level 16, State 1, Line 1
SELECT failed because the following SET options have incorrect settings: 'CONCAT_NULL_YIELDS_NULL'. Verify that SET options are correct for use with indexed views and/or indexes on computed columns and/or filtered indexes and/or query notifications and/or XML data type methods and/or spatial index operations."

但我不想设置CONCAT_NULL_YIELDS_NULL,因为它会与我的其他查询冲突。 谁能告诉我这个问题的解决方案是什么?

提前致谢。

P.S。 我在SO

中看到了这一点
SELECT @XYList = @XYList + CONVERT(varchar, X) + ',' + CONVERT(varchar, Y) + ','
FROM POINTS

我的要求是构建一个视图。因此我不能使用变量的解决方案。

我的最终结果是这样的。

a   b   products
1   1    <1> - <d>, <2> - <d>
1   2    <3> - <d>, <4> - <d>
1   3    <5> - <d>, <6> - <d>
当CONCAT_NULL_YIELDS_NULL设置为on时,查询产生

SELECT  tp.a, tp.b ,
        STUFF((SELECT ',' + ' ' +ltrim(rtrim(tc.c)) +' - '+ ltrim(rtrim(tc.d))
                 FROM  test tc
                WHERE tp.a = tc.a
                  AND tp.b = tc.b
                  FOR XML PATH(''), type).value('(./text())[1]','varchar(max)'), 1, 1, '' ) products
 FROM test tp
GROUP BY tp.a, tp.b

1 个答案:

答案 0 :(得分:1)

根据BOL,XML类型值方法需要设置concat_null_yields_null。如果我想将concat_null_yields_null设置为off我无法使用

FOR XML PATH(''), type).value('(./text())[1]','varchar(max)')

所以我转向一个不太合理的解决方案作为创可贴。我使用replace函数来替换5个基本的XML预定义实体。查询看起来像这样。

SELECT  tp.a, tp.b ,
        replace(replace(replace(replace(replace(
        STUFF((SELECT ',' + ' ' +ltrim(rtrim(tc.c)) +' - '+ ltrim(rtrim(tc.d))
                 FROM  test tc
                WHERE tp.a = tc.a
                  AND tp.b = tc.b
                  FOR XML PATH('')), 1, 1, '' )
                ,'&quot;','"'),'&amp;','&'),'&apos;',''''),'&lt;','<'),'&gt;','>') auto_products
 FROM test tp
GROUP BY tp.a, tp.b

以上解决了我目前的恐慌。任何更好的解决方案仍然是受欢迎的。