2016-09-08 1 views
0
set @xml = ' 
<body> 
    <Record> 
     <A>a</A> 
     <B>b</B> 
     <C>c</C> 
    </Record> 
    <Record> 
     <A>d</A> 
     <B>e</B> 
     <C>f</C> 
    </Record> 
    <Record> 
     <A>g</A> 
     <B>h</B> 
     <C>i</C> 
    </Record> 
</body> 
' 

я пытаюсь использовать этот синтаксис, но не работаетс помощью переменной в XPath для XQuery (значение)

я хотел бы использовать переменную с XPath в XQuery (значение)

SET @xmlQuery = '/Record[2]/A' 

set @nodevalue = (@xml.value('(//*[local-name()=sql:variable("@xmlQuery")])/text())[1]', 'nvarchar(50)')) 

что не так?

+0

... это что-то вроде бастардировки Microsoft XQuery, а не реального/законного языка, определенного стандартом? (Если вы задаете вопросы, зависящие от конкретной реализации поставщика, пожалуйста, отметьте соответствующим образом). –

+0

... Я имею в виду, что переменные XQuery имеют такие имена, как '$ foo', а не' @ foo', а синтаксис для определения переменной использует 'declare', а не' set' и 'nvarchar' - недействительные данные типа там. То есть - это совсем не похоже на XQuery. –

+0

в действительности значение @xmlQuery происходит из таблицы. Короче говоря, я бы получил значение, используя переменную, если возможно, вместо использования литеральной строки, я знаю, что ее можно было бы достичь с помощью динамического sql, но я не знаю, как назначить значение, исходящее из exec sp_executesql. см. http://stackoverflow.com/questions/39399317/save-result-of-exec-sp-excutequery-using-xpath – zanza67

ответ

0

В SQL Server XML отсутствует возможность динамического пути. Ваши варианты

Split путь на отдельные компоненты, такие как:

declare @xml xml; 

declare @Node1 sysname = N'Record', @Node2 sysname = N'A', @Node1Number int = 2; 

set @xml = '<body> 
    <Record> 
     <A>a</A> 
     <B>b</B> 
     <C>c</C> 
    </Record> 
    <Record> 
     <A>d</A> 
     <B>e</B> 
     <C>f</C> 
    </Record> 
    <Record> 
     <A>g</A> 
     <B>h</B> 
     <C>i</C> 
    </Record> 
</body>'; 

select @xml.value('(/body/ 
*[local-name() = sql:variable("@Node1") and position() = sql:variable("@Node1Number")]/ 
*[local-name() = sql:variable("@Node2")]/ 
text())[1]', 'nvarchar(50)'); 

Однако, если ваш путь идет в целом строку, и вы не хотите, чтобы написать парсер, единственным вариантом является динамический SQL:

declare @Path nvarchar(max) = N'/body/Record[2]/A', @Sql nvarchar(max); 

set @Sql = N'select t.c.value(''./text()[1]'', ''nvarchar(50)'') from @xml.nodes(' 
+ quotename(@Path, '''') 
+ ') t(c);' 

exec sys.sp_executesql @Sql, N'@xml xml', @xml = @xml; 

Лично я не люблю никого из них и рекомендовал бы переосмыслить всю задачу. Скорее всего, есть лучшее решение, чем динамический запрос XML на стороне базы данных.

+0

спасибо Роджер, я зелёная фасоль в sql, поэтому не могли бы вы предложить лучшее решение, пожалуйста? – zanza67

+0

@ zanza67, я имею в виду, что лучшее решение должно лежать вне SQL (скорее всего). Однако существует ли такое решение, зависит от деталей вашей задачи. –