Я пытаюсь запросить таблицу со столбцом, который представляет собой XML-данные с функциями запроса и значения. При использовании регулярных строковых литералов все в порядке, но если я поместил это в хранимую процедуру и попытаюсь использовать переменные, это не сработает.Хранимый параметр процедуры с XML-запросом в MSSQL дает «аргумент должен быть строковым литералом»
Я полагаю, что я не использую правильный тип данных, но после некоторых поисков я не могу понять, какой тип данных хочет функция запроса.
Пример: таблица содержит
| Id | xmldata |
| 1 | <data><node>value</node></data> |
сейчас, используя запрос на выборку
select id
from table
where xmldata.query('/data/node').value('.', 'VARCHAR(50)') = 'value'
получает мне данные, которые я хочу. Но, если я использую это в хранимой процедуре и использовать параметр @xpath varchar(100)
и передать методу запроса, как xmldata.query(@xpath)
я получаю ошибку
The argument 1 of the xml data type method "query" must be a string literal.
Я думаю, VARCHAR (100) не является правильным, но то, что тип данных может Я использую это, чтобы сделать MSSQL счастливым?
Обновление: Хорошо, так. По-видимому, вы не можете передать параметр методу запроса «точно так же», но можно использовать переменную sql: в сочетании с локальным именем, чтобы отработать ее часть. Так, например, это будет работать
declare @xpath VarChar(100)
set @xpath='node'
select objectData.query('/data/*[local-name() = sql:variable("@xpath")]')
.value('.', 'varchar(100)') as xmldata
from table
и значение выбрано в колонке xmldata. Но (!) Это требует, чтобы корневой узел был первым значением в функции запроса. Ниже будет не работы
declare @xpath VarChar(100)
set @xpath='/data/node'
select objectData.query('*[local-name() = sql:variable("@xpath")]')
.value('.', 'varchar(100)') as xmldata
from table
уведомление, как путь запроса «перешел» к переменной. Я продолжу свои расследования.
Я не знаю, как заменить все выражение XPath переменной (кроме динамического SQL). Вы можете сравнить имя узла с переменной, используя 'local-name()', как вы. Если вам неважно, что такое имя корневого узла, вы можете использовать '// * [local-name() = sql: variable (" @ xpath ")]', чтобы выполнить глубокий поиск для всех узлов, который соответствует '@xpath 'независимо от того, где в XML они расположены. –
@MikaelEriksson: О, ладно .. Я не думал, что двойной '//' работал, но спасибо за подсказку. Думаю, я буду использовать либо это, либо просто не использовать параметры. – Patrick