Используя XQuery SQL Server 2005, выберите все узлы с определенным значением атрибута или с отсутствующим атрибутом.

StackOverflow https://stackoverflow.com/questions/90023

  •  01-07-2019
  •  | 
  •  

Вопрос

Обновлять:приведя гораздо более подробный пример.

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

SELECT x.query('.') FROM @xml.nodes('/Books/*[not(@ID) or @ID = 5]') x1(x)

Оригинальный вопрос с лучшим примером:

Используя реализацию XQuery в SQL Server 2005, мне нужно выбрать все узлы в XML-документе, каждый только один раз, сохраняя их исходную структуру, но только в том случае, если в них отсутствует определенный атрибут или этот атрибут имеет определенное значение (передаваемое параметром).Запрос также должен работать со всем XML-документом (ось «потомок-или-сам»), а не выбирать на заранее определенной глубине.

Другими словами, каждый отдельный узел появится в результирующем документе только в том случае, если он и все его предки не имеют атрибута или имеют атрибут с одним конкретным значением.

Например:

Если бы это был XML:

    DECLARE @Xml XML
    SET @Xml =
    N'
<Library>
  <Novels>
    <Novel category="1">Novel1</Novel>
    <Novel category="2">Novel2</Novel>
    <Novel>Novel3</Novel>
    <Novel category="4">Novel4</Novel>
  </Novels>
  <Encyclopedias>
    <Encyclopedia>
      <Volume>A-F</Volume>
      <Volume category="2">G-L</Volume>
      <Volume category="3">M-S</Volume>
      <Volume category="4">T-Z</Volume>
    </Encyclopedia>
  </Encyclopedias>
  <Dictionaries category="1">
    <Dictionary>Webster</Dictionary>
    <Dictionary>Oxford</Dictionary>
  </Dictionaries>
</Library>
    '

Параметр 1 для категории приведет к следующему:

<Library>
  <Novels>
    <Novel category="1">Novel1</Novel>
    <Novel>Novel3</Novel>
  </Novels>
  <Encyclopedias>
    <Encyclopedia>
      <Volume>A-F</Volume>
    </Encyclopedia>
  </Encyclopedias>
  <Dictionaries category="1">
    <Dictionary>Webster</Dictionary>
    <Dictionary>Oxford</Dictionary>
  </Dictionaries>
</Library>

Параметр 2 для категории приведет к следующему:

<Library>
  <Novels>
    <Novel category="2">Novel2</Novel>
    <Novel>Novel3</Novel>
  </Novels>
  <Encyclopedias>
    <Encyclopedia>
      <Volume>A-F</Volume>
      <Volume category="2">G-L</Volume>
    </Encyclopedia>
  </Encyclopedias>
</Library>

Я знаю, что XSLT идеально подходит для этой работы, но это не вариант.Мы должны выполнить это полностью в SQL Server 2005.Любые реализации, не использующие XQuery, также подходят, если их можно выполнить полностью на T-SQL.

Это было полезно?

Решение

Из вашего примера мне неясно, чего вы на самом деле пытаетесь достичь.Хотите ли вы вернуть новый XML со всеми удаленными узлами, кроме тех, которые соответствуют условию?Если да, то это похоже на работу по преобразованию XSLT, которое, я не думаю, встроено в MSSQL 2005 (можно добавить как UDF: http://www.topxml.com/rbnews/SQLXML/re-23872_Performing-XSLT-Transforms-on-XML-Data-Stored-in-SQL-Server-2005.aspx).

Если вам просто нужно вернуть список узлов, вы можете использовать это выражение:

//Book[not(@ID) or @ID = 5]

но у меня такое впечатление, что это не то, что вам нужно.Было бы полезно, если бы вы могли привести более ясный пример.

Редактировать:Этот пример действительно более ясен.Лучшее, что я смог найти, это:

SET @Xml.modify('delete(//*[@category!=1])')
SELECT @Xml

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

Однако изменить имеет некоторые ограничения - кажется, вы не можете использовать его в операторе выбора, он должен изменять данные на месте.Если вам нужно вернуть такие данные с помощью выбора, вы можете использовать временную таблицу, в которую можно скопировать исходные данные, а затем обновить эту таблицу.Что-то вроде этого:

INSERT INTO #temp VALUES(@Xml)
UPDATE #temp SET data.modify('delete(//*[@category!=2])')

Надеюсь, это поможет.

Другие советы

Вопрос не совсем ясен, но это то, что вы ищете?

DECLARE @Xml AS XML
        SET @Xml =
        N'
        <Books>
                <Book ID="1">Book1</Book>
                <Book ID="2">Book2</Book>
                <Book ID="3">Book3</Book>
                <Book>Book4</Book>
                <Book ID="5">Book5</Book>
                <Book ID="6">Book6</Book>
                <Book>Book7</Book>
                <Book ID="8">Book8</Book>
        </Books>
        '
DECLARE @BookID AS INT
SET @BookID = 5
DECLARE @Result AS XML

SET @result = (SELECT @xml.query('//Book[not(@ID) or @ID = sql:variable("@BookID")]'))
SELECT @result
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top