2012-03-02 65 views
9

我正在尝试编写以下SQL。无法将CTE结果分配给varchar变量?

declare @s varchar(max) = (
    with c as (select ...) 
    select a, b, c, d, .... 
    from ... join c on .... join c on .... join c on .... 
    order by ... 
    for xml raw('...'), elements 
); 

但是,它的语法不正确(下面显示了错误信息)。我必须将其转换为子查询吗?我试图避免在多个地方扩展CTE。

关键字'with'附近的语法不正确。如果此语句是公用表表达式,xmlnamespaces子句或变更跟踪上下文子句,则前面的语句必须以分号结尾。

更新:
for xmlorder by使得select @s = ...

回答

3

好吧,我想通了。它不能在一个声明和初始化语句中完成。

declare @s varchar(max); 

with c as (select 1 a union all select 2 union all select 3) 
, x(s) as (select a from c order by a desc for xml raw('tr'), elements) 
select @s = s from x 
+2

看起来很熟悉...... – 2012-03-02 22:13:01

+2

@Abe - _“原创性的秘诀就是忘记来源”__1给你的答案。 – 2013-11-25 14:43:56

7

我认为这只是您要分配价值的方式。尝试使用下面的方法来代替:

declare @s varchar(max); 
with temp as 
(
    select .... 
    from ... join c on .... join c on .... join c on .... 
    for xml raw('...'), elements 
) 
select @s = value from temp 
select @s 

随着错误消息状态,你真正的问题是,你的CTE前声明不与;使用CTE时,这是一个要求终止。

我用select 'test' as value定义了CTE而不是您的查询,并按预期工作。

+0

的'为xml'可能使得可行不? – ca9163d9 2012-03-02 21:54:58

+0

我不确定。目前我无法测试它。我会建议尝试我上面提供的方法。您得到的错误似乎与使用'for xml'没有关系...... – 2012-03-02 22:00:59

+0

“如果CTE用于作为批处理一部分的语句中,则在它之前的语句必须后跟分号“。 (...),温度(值)为(...)'时,需要将temp(as ... for xml ...)''temp'改为' – HABO 2012-03-02 22:10:52

10

您需要将@s的声明与作业分开。

像这样的东西将适用于你。

declare @T table 
(
    ID int, 
    Col1 int 
) 

insert into @T values(1, 10),(2, 20) 

declare @s varchar(max) 

;with C as 
(
    select * 
    from @T 
) 
select @s = 
    (
    select * 
    from C as C1 
     inner join C as C2 
     on C1.ID = C2.ID 
    for xml raw, elements 
) 

select @s 

结果:

<row> 
    <ID>1</ID> 
    <Col1>10</Col1> 
    <ID>1</ID> 
    <Col1>10</Col1> 
</row> 
<row> 
    <ID>2</ID> 
    <Col1>20</Col1> 
    <ID>2</ID> 
    <Col1>20</Col1> 
</row>