【问题标题】:How to convert xml to non-xml text using XQuery in SQL Server 2005/2008?如何在 SQL Server 2005/2008 中使用 XQuery 将 xml 转换为非 xml 文本?
【发布时间】:2012-03-28 02:03:26
【问题描述】:

以下代码将返回select $f/field/text() from table1

declare @x xml = '<meta><field>Column1</field></meta>';
select @x.query('
for $f in /meta
return
    "select $f/field/text() from table1"
')

我尝试将返回部分更改为"select"+$f/field"select" $f/field,但这些无法解析。


更新:
@x 将从带有for xml raw,elements 的表中生成。使用 xml/xquery 的目的是避免样板字符串连接。似乎 XQuery 无法将 xml 转换为文本?


更新问题:
下面是我要写的代码。

declare @meta table (field sysname primary key, validate varchar(8000));
insert into @meta values ('Col1', '< 100'), ('Col2', '> Col1');

declare @x xml = (select * from @meta for xml path('meta'));
select @x;

-- The following code cannot be parsed. It will be nice to replace /meta/field/text() with shorter variable too
select @x.query('
    "select 1" 
        {"," /meta/field/text() "= case when" /meta/field/text() /meta/validate/text() "then" /meta/field/text()}
    "from table1"
    "where 1=1 " 
        { "or (" /meta/field/text() /meta/validate/text() ")" }
')

而生成的结果应该是,

select 1
    , Col1 = case when Col1 < 100 then Col1 end
    , Col2 = case when Col2 > Col1 then Col2 end
from table1
where 1=1
        or (Col1 < 100)
        or (Col2 > Col1)

【问题讨论】:

    标签: sql-server xml sql-server-2008 sql-server-2005 xquery


    【解决方案1】:

    使用 .value 而不是 .query 从 XML 获取值。

    declare @x xml = '<meta><field>Column1</field></meta>';
    
    select 'select '+quotename(@x.value('(/meta/field)[1]', 'sysname'))+' from table1'
    

    结果:

    select [Column1] from table1
    

    更新:

    这是一种直接使用元表构建查询的方法。

    select 'select '+
           stuff((select ', '+field+' = case when '+field+' '+validate+' then '+field+' end'
                  from @meta 
                  for xml path(''), type).value('.', 'nvarchar(max)'), 1, 2, '')+
           ' from table1 where '+
           stuff((select ' or ('+field+' '+validate+')'
                  from @meta 
                  for xml path(''), type).value('.', 'nvarchar(max)'), 1, 4, '')
    

    结果:

    select Col1 = case when Col1 < 100 then Col1 end,
           Col2 = case when Col2 > Col1 then Col2 end 
    from table1 
    where (Col1 < 100) or 
          (Col2 > Col1)
    

    【讨论】:

    • 谢谢。 @x 将从带有for xml raw,elements 的表中生成。使用 xml/xquery 的目的是避免样板字符串连接。似乎 XQuery 无法将 xml 转换为文本?
    • @NickW - XQuery 非常强大。如果您可以用更多您正在尝试做的事情来更新您的问题,我可能会有一些对您有所帮助的想法。从 XML 中获取一些文本通常没有问题,但通过阅读您的问题,我无法理解您遇到的问题。
    • @NickW - 使用您正在使用的表格更新您的问题、一些示例数据和预期输出,也许还有一些限制,例如“请不要使用游标或循环”:)
    • @NickW - 使用元表而不是 XML 的版本更新了答案。如果您出于某种原因确实需要使用 XML,请告诉我。
    • 我一直在使用字符串连接,并希望为这类任务找到一种更优雅的方法。维护代码更加困难,额外的填充/修剪使其代码看起来更混乱。不幸的是,在 T-Sql 中执行 xslt 并不容易。
    【解决方案2】:

    解决办法:

    --drop table #tmp
    declare @x xml = '<meta><field>Column1</field> <field>Column2</field></meta>';
    declare @field  varchar(max) 
    CREATE TABLE #tmp (field varchar(max) )
    
    set @field = ( select cast(@x.query('for $f in /meta/field
    return  concat("insert into #tmp(field)  select ", $f, " from table1;")
    ') as varchar(max)))
    
     EXEC (@field);
    
     select field from #tmp
    
     drop table #tmp
    

    【讨论】:

    • $f 将被 包围。
    【解决方案3】:

    只需将所有内容包装在外部 xml 标记中即可。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-20
      相关资源
      最近更新 更多