Разделите XML, чтобы отправить его в хранимую процедуру на SQL сервере - PullRequest
0 голосов
/ 18 февраля 2020

У меня есть вопрос о разделении входного параметра XML и отправке его в другую хранимую процедуру (SQL Сервер).

У меня есть главная хранимая процедура, которая имеет на входе XML ( см. ниже). Я хотел бы, чтобы эта хранимая процедура разделяла XML по RDHistorique. Затем отправьте каждый RDHistorique на дочернюю хранимую процедуру.

<ArrayOfRDHistorique>
  <RDHistorique>
    <Id>1955</Id>
    <sect_code>08</sect_code> 
    <arch_islast>0</arch_islast>  
    <ListeEtapes>
        <EtapeWorkflowArchive>
            <Statut>00</Statut>
            <Nom>John DOE</Nom>
            <Date>2009-12-31</Date>
            <Commentaire />
            <Id>1955</Id>
        </EtapeWorkflowArchive>
        <EtapeWorkflowArchive>
            <Statut>02</Statut>
            <Nom>John DOE</Nom>
            <Date>2009-12-31</Date>
            <Commentaire />
            <Id>1955</Id>
        </EtapeWorkflowArchive>
        <EtapeWorkflowArchive>
            <Statut>03</Statut>
            <Nom>John DOE</Nom>
            <Date>2010-06-23</Date>
            <Commentaire>Silly comment</Commentaire>
            <Id>1955</Id>
        </EtapeWorkflowArchive>
        <EtapeWorkflowArchive>
            <Statut>04</Statut>
            <Nom>John DOE</Nom>
            <Date>2010-06-23</Date>
            <Commentaire>Silly comment</Commentaire>
            <Id>1955</Id>
        </EtapeWorkflowArchive>
        <EtapeWorkflowArchive>
            <Statut>05</Statut>
            <Nom>John DOE</Nom>
            <Date>2010-06-23</Date>
            <Commentaire />
            <Id>1955</Id>
        </EtapeWorkflowArchive>
    </ListeEtapes>
  </RDHistorique>
    <RDHistorique>
    <Id>1999</Id>
    <sect_code>08</sect_code> 
    <arch_islast>0</arch_islast> 
    <ListeEtapes>
        <EtapeWorkflowArchive>
            <Statut>00</Statut>
            <Nom>John DOE</Nom>
            <Date>2010-12-31</Date>
            <Commentaire />
            <Id>1999</Id>
        </EtapeWorkflowArchive>
        <EtapeWorkflowArchive>
            <Statut>02</Statut>
            <Nom>John DOE</Nom>
            <Date>2010-12-31</Date>
            <Commentaire />
            <Id>1999</Id>
        </EtapeWorkflowArchive>
        <EtapeWorkflowArchive>
            <Statut>03</Statut>
            <Nom>NULL</Nom>
            <Date>2011-06-29</Date>
            <Id>1999</Id>
        </EtapeWorkflowArchive>
        <EtapeWorkflowArchive>
            <Statut>06</Statut>
            <Nom>NULL</Nom>
            <Commentaire>Silly comment</Commentaire>
            <Id>1999</Id>
        </EtapeWorkflowArchive>
        <EtapeWorkflowArchive>
            <Statut>11</Statut>
            <Nom>NULL</Nom>
            <Commentaire>NULL</Commentaire>
            <Id>1999</Id>
        </EtapeWorkflowArchive>
    </ListeEtapes>
  </RDHistorique>
</ArrayOfRDHistorique>

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

SELECT 
    b.value('(./Statut/text())[1]','Varchar(50)') as Statut,
    b.value('(./Nom/text())[1]','Varchar(50)') as Nom,
    b.value('(./Commentaire/text())[1]','Varchar(50)') as Commentaire


FROM @xml.nodes('/ArrayOfRDHistorique/RDHistorique/ListeEtapes/*') as a(b) 

Мой вопрос: могу ли я вызвать хранимую процедуру для каждого узла в файле XML?

1 Ответ

1 голос
/ 18 февраля 2020

Если вам действительно нужен итеративный подход (процедура уже написана, вы выполняете несколько NON- SQL заданий), CURSOR - это опция:

CREATE PROCEDURE ProcessStatut(@statut varchar(50), @nom varchar(50),@commentaire varchar(50)) AS
BEGIN
    SELECT @statut Statut, @nom Nom, @commentaire Commentaire, 'Hello world!' Hello
END

Тогда:

DECLARE @statut varchar(50), @nom varchar(50),@commentaire varchar(50);
DECLARE c CURSOR FOR
SELECT 
    b.value('(./Statut/text())[1]','Varchar(50)') as Statut,
    b.value('(./Nom/text())[1]','Varchar(50)') as Nom,
    b.value('(./Commentaire/text())[1]','Varchar(50)') as Commentaire
FROM @xml.nodes('/ArrayOfRDHistorique/RDHistorique/ListeEtapes/*') as a(b)

OPEN c
FETCH NEXT FROM c INTO @statut, @nom, @commentaire
WHILE @@FETCH_STATUS = 0  
BEGIN
    EXEC ProcessStatut @statut, @nom, @commentaire
    FETCH NEXT FROM c INTO @statut, @nom, @commentaire
END
CLOSE c
DEALLOCATE c

Каждая строка будет обрабатываться отдельно.


Редактировать 1: Если вам нужно передать таблицу, вы можете объявить тип TABLE:

CREATE TYPE StatutList AS TABLE (
    Statut varchar(50),
    Nom varchar(50),
    Commentaire varchar(50)
)
GO
CREATE PROCEDURE ProcessStatutList(@statutList StatutList READONLY) AS
BEGIN
    SELECT *, 'I was here!' Hello FROM @statutList
END
GO

И затем , используйте это, чтобы передать все предметы сразу:

DECLARE @statutList StatutList;
INSERT @statutList
SELECT 
    b.value('(./Statut/text())[1]','Varchar(50)') as Statut,
    b.value('(./Nom/text())[1]','Varchar(50)') as Nom,
    b.value('(./Commentaire/text())[1]','Varchar(50)') as Commentaire
FROM @xml.nodes('/ArrayOfRDHistorique/RDHistorique/ListeEtapes/*') as a(b)

EXEC ProcessStatutList @statutList;
...