Разбейте XML-файлы с использованием SQL Server на отдельные строки - PullRequest
3 голосов
/ 10 января 2012

Вот что я делаю.Я вставляю файл XML в столбец XML вместе с другими столбцами, такими как отметки даты и т. Д. Для ведения журнала (они не имеют отношения к этому запросу)

Файл выглядит примерно так:

<topLevelItem>
  <secondLevelItem>
    <secondLevelItemDetail>
    </secondLevelItemDetail>
    <secondLevelItemAnotherDetail>
    </secondLevelItemAnotherDetail>
  </secondLevelItem>
  <secondLevelItem>
    <secondLevelItemDetail>
    </secondLevelItemDetail>
    <secondLevelItemAnotherDetail>
    </secondLevelItemAnotherDetail>
  </secondLevelItem>
  <secondLevelItem>
    <secondLevelItemDetail>
    </secondLevelItemDetail>
    <secondLevelItemAnotherDetail>
    </secondLevelItemAnotherDetail>
  </secondLevelItem>
<topLevelItem>

Моя цель - иметь возможность запросить поле XML и получить набор результатов с каждым <secondLevelItem> в отдельной строке в форме XML.Например:

Строка 1:

  <secondLevelItem>
    <secondLevelItemDetail>
    </secondLevelItemDetail>
    <secondLevelItemAnotherDetail>
    </secondLevelItemAnotherDetail>
  </secondLevelItem>

Строка 2:

  <secondLevelItem>
    <secondLevelItemDetail>
    </secondLevelItemDetail>
    <secondLevelItemAnotherDetail>
    </secondLevelItemAnotherDetail>
  </secondLevelItem>

Строка 3:

  <secondLevelItem>
    <secondLevelItemDetail>
    </secondLevelItemDetail>
    <secondLevelItemAnotherDetail>
    </secondLevelItemAnotherDetail>
  </secondLevelItem>

Это должно бытьсделано с использованием Microsoft SQL Server и без использования CLI.Мне нужно иметь возможность объявить, с какого XML-узла я хочу начать разбивку, поскольку в некоторых файлах есть дополнительные XML-элементы, которые мне не нужны.Так что-то типа WHERE node = secondLevelItem.

Ответы [ 3 ]

2 голосов
/ 10 января 2012

В SQL Server 2005 и новее в SQL Server имеется отличная поддержка XQuery.

При таком подходе будет использоваться метод .nodes() и .query():

SELECT 
    Col.query('.')
FROM 
dbo.YourTable
CROSS APPLY
    YourXmlColumn.nodes('/topLevelItem/secondLevelItem') AS Tbl(Col)
WHERE
    (some condition)

Функция .nodes() создает «временную встроенную» псевдотаблица Tbl с одним столбцом Col, который содержит одну запись XML для каждого узла в столбце XML, которая соответствует заданному XPath (в данном случае: каждый <secondLevelItem> внутри<topLevelItem> будет сопоставлено).

Поскольку вам нужен полный XML для каждого из этих элементов XML, просто используйте .query('.'), чтобы вернуть этот полный элемент XML.

1 голос
/ 10 января 2012

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

DECLARE @XML xml
SET @XML = '<topLevelItem>
  <secondLevelItem>
    <secondLevelItemDetail>One</secondLevelItemDetail>
    <secondLevelItemAnotherDetail>One One</secondLevelItemAnotherDetail>
  </secondLevelItem>
  <secondLevelItem>
    <secondLevelItemDetail>Two</secondLevelItemDetail>
    <secondLevelItemAnotherDetail>Two Two</secondLevelItemAnotherDetail>
  </secondLevelItem>
  <secondLevelItem>
    <secondLevelItemDetail>Three</secondLevelItemDetail>
    <secondLevelItemAnotherDetail>Three Three</secondLevelItemAnotherDetail>
  </secondLevelItem>
</topLevelItem>'


SELECT 
    Tbl.Col.query('.')
FROM 
    @XML.nodes('/topLevelItem/secondLevelItem') AS Tbl(Col)
1 голос
/ 10 января 2012

Используйте node () , чтобы уничтожить ваш XML, и используйте local-name () и sql: variable () , чтобы найти нужный вам узел, получитьXML с query () .

declare @NodeName varchar(100) = 'secondLevelItem'

select T.N.query('.')
from YourTable
  cross apply XMLCol.nodes('//*[local-name()=sql:variable("@NodeName")]') as T(N)
...