在SQL中将xmlnamespaces默认为变量

时间:2015-07-30 05:19:14

标签: sql sql-server xml

我有一个XML,我在SQL中处理它以将数据传递到SQL Server表。

XML如下所示

<SearchProgramsResponse xmlns="http://api.abc.com/2011-03-01/">
    <page>1</page>
    <items>50</items>
    <total>3129</total>
    <programItems>
        <programItem id="7779">
            <name>Coolblue NL</name>
            <adrank>5.4</adrank>
            <categories>
                <category id="34">Shopping &amp; Mail Order Shops</category>
                <category id="43">Other</category>
        </programItem>
    </programItems>
</SearchProgramsResponse>

现在我使用以下查询来获得结果

;with xmlnamespaces(default 'http://api.abc.com/2011-03-01/')
select
    t1.c.value('@id', 'int') as id,
    t1.c.value('(name/text())[1]', 'nvarchar(200)') as name,
    t1.c.value('(adrank/text())[1]', 'decimal(29,2)') as adrank
from 
    @xmldata.nodes('SearchProgramsResponse/programItems/programItem') as t1(c)

但这里的xmlnamespaces default值是硬编码的。我怎样才能使它成为传递的变量。

我尝试过动态SQL但收到错误 这是我正在尝试的

DECLARE @xmldata XML 
SET @xmldata = N'<SearchProgramsResponse xmlns="http://api.abc.com/2011-03-01/">
    <page>1</page>
    <items>50</items>
    <total>3129</total>
    <programItems>
    <programItem id="7779">
    <name>Coolblue NL</name>
    <adrank>5.4</adrank>
    <categories>
    <category id="34">Shopping &amp; Mail Order Shops</category>
    <category id="43">Other</category>
    </programItem>
    </programItems>
    </SearchProgramsResponse>';


DECLARE @d NVARCHAR(200)='http://api.abc.com/2011-03-01/'
DECLARE @ns NVARCHAR(max);

SET @ns = '
;with xmlnamespaces(default ' + @d +' )
select
    t1.c.value(''@id'', ''int'') as id,
    t1.c.value(''(name/text())[1]'', ''nvarchar(200)'') as name,
    t1.c.value(''(adrank/text())[1]'', ''decimal(29,2)'') as adrank
from @xmldata.nodes(''SearchProgramsResponse/programItems/programItem'') as t1(c)';

exec sp_executesql @ns;

现在抛出错误

  

必须声明标量变量&#34; @ xmldata&#34;

因为它是变量而我正在执行动态SQL。

但如果我尝试更换它

SET @ns = REPLACE(@ns, '@xmldata', @xmldata);

EXEC sp_executesql @ns;

这将再次抛出错误,因为可以用整个XML替换表。

如果没有动态SQL,还有其他方法可以实现吗?

如果不能,我怎样才能获得动态SQL的结果?

由于

3 个答案:

答案 0 :(得分:2)

如果查询中不需要命名空间,则可以使用通配符作为命名空间,并避免动态查询。

select
    t1.c.value('@id', 'int') as id,
    t1.c.value('(*:name/text())[1]', 'nvarchar(200)') as name,
    t1.c.value('(*:adrank/text())[1]', 'decimal(29,2)') as adrank
from 
    @xmldata.nodes('*:SearchProgramsResponse/*:programItems/*:programItem') as t1(c);

答案 1 :(得分:1)

您需要将附加参数传递给sp_executesql,该参数指定本地参数名称和该参数的值:

.....
.....
exec sp_executesql @ns, N'@xmldata XML', @xmldata=@xmldata;

<强> Sqlfiddle Demo

答案 2 :(得分:0)

试试这个..

declare @t nvarchar (max)

set @t='DECLARE @xmldata XML '+'
SET @xmldata = ''<SearchProgramsResponse xmlns="http://api.abc.com/2011-03-01/">
<page>1</page>
<items>50</items>
<total>3129</total>
<programItems>
    <programItem id="7779">
        <name>Coolblue NL</name>
        <adrank>5.4</adrank>
        <categories>
            <category id="34">Shopping &amp; Mail Order Shops</category>
            <category id="43">Other</category>
        </categories>
</programItem>
</programItems>
</SearchProgramsResponse>'''

--


DECLARE @d NVARCHAR(200)='http://api.abc.com/2011-03-01/'
DECLARE @ns NVARCHAR(max);
DECLARE @ns2 NVARCHAR(max);
SET @ns = '
;with xmlnamespaces(default ''' + @d +''') 
select
     t1.c.value(''(@id)'', ''int'') as id,
   t1.c.value(''(name/text())[1]'', ''nvarchar(200)'') as name,
   t1.c.value(''(adrank/text())[1]'', ''decimal(29,2)'') as adrank
   from @xmldata.nodes(''//SearchProgramsResponse/programItems/programItem'') as t1(c)
';

set @ns2=@t+@ns

print @ns2
exec(@ns2)