2014-11-05 4 views
2

У меня есть таблица базы данных в SQL Server 2014 с только столбцом ID (int) и столбец xmldata типа XML.SQL Server 2014 - XQuery - получить разделенный запятой Список

xmldata Этот столбец содержит, например:

<book> 
    <title>a nice Novel</title> 
    <author>Maria</author> 
    <author>Peter</author> 
</book> 

Как и ожидалось, у меня есть несколько книг, поэтому несколько строк с xmldata.

Теперь я хочу выполнить запрос для всех книг, где Питер является автором. Я пробовал это в некоторых тестировщиках xPath2.0 и пришел к выводу, что:

/book/author/concat(text(), if(position() != last())then ',' else '') 

работы.

Если вы пытаетесь перенести этот успех в SQL Server 2014 Express, это выглядит так, что правильно сбежавшего синтаксис и т.п .:

SELECT id 
FROM books 
WHERE 'Peter' IN (xmldata.query('/book/author/concat(text(), if(position() != last())then '','' else '''')')) 

SQL Server, однако, кажется, не поддерживает конструкцию, как /concat(...) из-за :

Синтаксис XQuery '/ function()' не поддерживается.

Я в растерянности, то тем не менее, почему /text() будет работать в:

SELECT id, xmldata.query('/book/author/text()') 
FROM books 

, который он делает.

Мои ограничения:

  • Я обязан использовать SQL Server
  • Я обязан XPath или что-то другое, что может быть «впрыскивается» как утверждение выше (если структура XML или изменения в базе данных, выше XPath может быть изменен в изоляции и логика приложения выше, что создает положение о Where не будут затронуты) SEE EDIT

есть ли способ сделать это приста к?

С уважением,

BillDoor

EDIT:

Моя вторая ограничение сводится к следующему:

Применение конструкции ИНЕКЕ по

expression <operator> value(s) 

выражение хранится в базе данных и отображается в xmlTag, например .:

| tokenname| querystring 
    | "author" | "xmldata.query(/book/author/text())" 

значения представлены запрашивающим пользователем.так что если пользователь запрашивает у автора «Питера» с оператором «РАВНО» приложение конструирует:

xmaldata.query(/book/author/text()) = "Peter" 

, как где п.

Если заказчик теперь решил, что автор должен быть вложен в элемент <authors>, я могу просто изменить выражение в базе данных построения, и вся машина будет работать без каких-либо изменений кода, просто управляемая.

Так я нужен способ, чтобы добиться того, что

<xPath> <operator> "Peter" 

или любой другой комбинации этих трех изолированных компонентов (смотри выше: "Peter" IN <xPath>...) получает меня все книги Петерса, даже если Есть несколько несортированный авторы.

Это не хватило бы ни (его не синтаксис SQLServer, но вы получите идею):

WHERE xmldata.exist('/dossier/client[text() = "$1"]', "Peter") = 1; 

, потому что оператор еще вложенный в выражении, я не мог просить <> "Peter".

Я знаю, что это странно, пожалуйста, не ставит под сомнение концепции в целом - это есть история:/

EDIT: дальнейшее уточнение:

Фильтр-правила вступают в приложение в структура XML в основном:

  • Оператор: "EQ"
  • поле: "имя"
  • значение "Питер"

вычисляет:

  • выражение = lookupExpressionForField("name") -> "table2.xmldata.value ('книга/автор/название [1]', 'VARCHAR')"
  • оператор = lookUpOperatorMapping("EQ") - -> "="
  • значение = FormatValues("Peter") -> "Питер" (если несколько значений передаются FormatValues ​​cosntructs с запятыми список)

приложение затем строит: - constructClause(String expression,String operator,String value)

"table2.xmldata.value ('книга/автор/название [1]', 'VARCHAR')" + "=" + "Питер"

затем конструирует Выберите заявление с результатом как предложение WHERE.

он не строит его таким образом, неизолированный, нефильтрованный для инъекций и т. Д., Но это основная идея.

я могу влиять как вход Transalted, то есть я могу реализовать методы:

  • lookupExpressionForField(String field)
  • lookUpOperatorMapping(String operator)
  • Formatvalues(List<String> values) | Formatvalues(String value)
  • constructClause(String expression,String operator,String value)

однако я выбираю сделать, я могу изменить типы параметров, я могу свободно реализовывать их. Чем меньше, тем лучше. Таким образом, простое создание разделенного запятыми списка с xPath было бы оптимальным (например, если бы я мог где-то просто отметить «enable/function() - синтаксис в xPath» в sqlserver и/concat (if ...) будет работать)

+0

'/ текст()' не функция, даже если она синтаксически выглядит как одна. – choroba

ответ

2

Как о чем-то вроде этого:

SET NOCOUNT ON; 

DECLARE @Books TABLE (ID INT NOT NULL IDENTITY(1, 1) PRIMARY KEY, BookInfo XML); 

INSERT INTO @Books (BookInfo) 
VALUES (N'<book> 
    <title>a nice Novel</title> 
    <author>Maria</author> 
    <author>Peter</author> 
</book>'); 

INSERT INTO @Books (BookInfo) 
VALUES (N'<book> 
    <title>another one</title> 
    <author>Bob</author> 
</book>'); 

SELECT * 
FROM @Books bk 
WHERE bk.BookInfo.exist('/book/author[text() = "Peter"]') = 1; 

Это возвращает только первую запись «книга». Оттуда вы можете извлечь любую часть поля XML, используя функцию «значение».

Функция «существует» возвращает логическое/BIT. Это будет проверяться через все «авторские» узлы в «книге», поэтому нет необходимости вступать в список, разделенный запятыми, только для использования в списке IN, который не будет работать в любом случае ;-).

Для получения дополнительной информации о «ценности» и «существует» функцию, а также другие функции для использования с данными XML, см:

xml Data Type Methods

+0

спасибо за решение, я добавил объяснение моего второго ограничения - так как теперь это кажется мне слишком расплывчатым. ^^. То, что вы предлагаете, потребует значительных изменений, поскольку значение является частью выражения и не имеет оператора (см. Мое редактирование). Если у вас есть какие-то дальнейшие идеи относительно этого, я прошу вас помочь, но ваш ответ - это то, что нужно учитывать наименее, спасибо еще раз! – billdoor

+0

@ billdoor: ну, я посмотрел обновления на вопрос, и они требуют больше информации. Каковы возможные значения ''? Строка для поиска (в настоящее время «Питер») также динамическая? Похоже, вы ищете динамическое предложение WHERE. –

+0

Оператором может быть любая строка («=», «IN», «LIKE», что-нибудь действительно), «Питер» - это значение, о котором идет речь, так что динамично, да – billdoor

Смежные вопросы