Как преобразовать XML в не-XML текст, используя XQuery в SQL Server 2005/2008? - PullRequest
1 голос
/ 11 марта 2012

Следующий код вернет 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)

Ответы [ 3 ]

2 голосов
/ 11 марта 2012

Используйте .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)
1 голос
/ 11 марта 2012

Решение:

--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
0 голосов
/ 12 марта 2012

Просто нужно обернуть все во внешний тег XML.

...