В SQL Server я могу вставить несколько узлов в XML из таблицы? - PullRequest
2 голосов
/ 29 сентября 2008

Я хочу сгенерировать XML в хранимой процедуре на основе данных в таблице.

Следующая вставка позволяет мне добавить много узлов, но они должны быть жестко запрограммированы или использовать переменные (sql: variable):

SET @MyXml.modify('
      insert
         <myNode>
            {sql:variable("@MyVariable")}
         </myNode>
      into (/root[1]) ') 

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

Но есть ли способ, которым я могу сделать это, просто комбинируя с оператором select и избегая цикла?

Редактировать Я использовал SELECT FOR XML, чтобы делать подобные вещи раньше, но мне всегда трудно читать при работе с иерархией данных из нескольких таблиц. Я надеялся, что будет что-то, использующее modify, где сгенерированный XML будет более явным и более управляемым.

Ответы [ 3 ]

7 голосов
/ 29 сентября 2008

Вы пробовали вложение ДЛЯ ПУТИ XML Скалярные функции? С помощью техники вложенности вы можете разбить ваш SQL на очень управляемые / читаемые элементарные части

Отказ от ответственности: следующее, хотя и адаптированное из рабочего примера, само по себе буквально не проверено

Некоторые справочные ссылки для широкой аудитории

Простейший пример вложенного узла самого низкого уровня

Рассмотрим следующий вызов

DECLARE  @NestedInput_SpecificDogNameId int
SET @NestedInput_SpecificDogNameId = 99
SELECT [dbo].[udfGetLowestLevelNestedNode_SpecificDogName] 
(@NestedInput_SpecificDogNameId)

Допустим, если udfGetLowestLevelNestedNode_SpecificDogName был записан без предложения FOR XML PATH, а для @NestedInput_SpecificDogName = 99 он возвращает одну запись набора строк:

@SpecificDogNameId  DogName
99                  Astro

Но с предложением FOR XML PATH,

CREATE FUNCTION dbo.udfGetLowestLevelNestedNode_SpecificDogName
(
@NestedInput_SpecificDogNameId
)
    RETURNS XML
    AS
    BEGIN

        -- Declare the return variable here
        DECLARE @ResultVar XML

        -- Add the T-SQL statements to compute the return value here
        SET @ResultVar =
            (
            SELECT 
                  @SpecificDogNameId as "@SpecificDogNameId",
                  t.DogName 
            FROM tblDogs t
            FOR XML PATH('Dog')
            )

        -- Return the result of the function
        RETURN @ResultVar

END

пользовательская функция создает следующий XML-код (знаки @ приводят к тому, что поле SpecificDogNameId возвращается в качестве атрибута)

<Dog SpecificDogNameId=99>Astro</Dog>

Вложение пользовательских функций типа XML

Пользовательские функции, такие как вышеупомянутый udfGetLowestLevelNestedNode_SpecificDogName, могут быть вложенными, чтобы обеспечить мощный метод для создания сложного XML.

Например, функция

CREATE FUNCTION [dbo].[udfGetDogCollectionNode]()
    RETURNS XML
    AS
    BEGIN

        -- Declare the return variable here
        DECLARE @ResultVar XML

        -- Add the T-SQL statements to compute the return value here
        SET @ResultVar =
            (
                SELECT  
                [dbo].[udfGetLowestLevelNestedNode_SpecificDogName]
                        (t.SpecificDogNameId)
                FROM tblDogs t

                FOR XML PATH('DogCollection') ELEMENTS
            )
        -- Return the result of the function
        RETURN @ResultVar

END

когда вызывается как

SELECT [dbo].[udfGetDogCollectionNode]()

может создать сложный узел XML (с учетом соответствующих базовых данных)

<DogCollection>
    <Dog SpecificDogNameId="88">Dino</Dog>
    <Dog SpecificDogNameId="99">Astro</Dog>
</DogCollection>

С этого момента вы можете продолжать работать вверх во вложенном дереве, чтобы построить настолько сложную структуру XML, сколько пожелаете

CREATE FUNCTION [dbo].[udfGetAnimalCollectionNode]()
RETURNS XML
AS
BEGIN

DECLARE @ResultVar XML

SET @ResultVar =
(
SELECT 
dbo.udfGetDogCollectionNode(),
dbo.udfGetCatCollectionNode()
FOR XML PATH('AnimalCollection'), ELEMENTS XSINIL
)

RETURN @ResultVar

END

когда вызывается как

SELECT [dbo].[udfGetAnimalCollectionNode]()

udf может создать более сложный узел XML (с учетом соответствующих базовых данных)

<AnimalCollection>
  <DogCollection>
    <Dog SpecificDogNameId="88">Dino</Dog>
    <Dog SpecificDogNameId="99">Astro</Dog>
  </DogCollection>
  <CatCollection>
    <Cat SpecificCatNameId="11">Sylvester</Cat>
    <Cat SpecificCatNameId="22">Tom</Cat>
    <Cat SpecificCatNameId="33">Felix</Cat>
  </CatCollection>
</AnimalCollection>
1 голос
/ 15 марта 2010

Используйте sql: column вместо sql: variable. Вы можете найти подробную информацию здесь: http://msdn.microsoft.com/en-us/library/ms191214.aspx

1 голос
/ 29 сентября 2008

Можете ли вы рассказать немного больше о том, что именно вы планируете делать? Это просто генерирование данных XML на основе содержимого таблицы или добавить некоторые данные из таблицы в существующую структуру XML?

Существует большая серия статей на тему XML в SQLServer, написанная Джейкобом Себастьяном. Она начинается с основ генерации XML из данных таблицы

...