2009-12-11 18 views
6

Tengo dos variable XML decir @res, @student en un procedimiento almacenado en SQL Server 2005.¿Cómo insertar xml en un nodo en otro xml usando XQuery?

@res contiene

<Subject>English</Subject> 
<Marks>67</Marks> 
<Subject>Science</Subject> 
<Marks>75</Marks> 

@student contiene:

<Student> 
    <Name>XYZ</Name> 
    <Roll>15</Roll> 
    <Result /> 
    <Attendance>50</Attendance> 
</Student> 

Necesito inserte el xml de @res en el nodo Resultado en la variable @student usando XQuery.

¿Cómo implementar eso?

Por favor ayuda.

+0

Se agregó una solución de análisis de cadenas "hacky" que debería funcionar para SQL Server 2005 también, no es bonita, pero debería funcionar. –

Respuesta

31

En SQL Server 2008, que es bastante fácil:

DECLARE @res XML = '<Subject>English</Subject> 
<Marks>67</Marks> 
<Subject>Science</Subject> 
<Marks>75</Marks>' 


DECLARE @student XML = '<Student> 
    <Name>XYZ</Name> 
    <Roll>15</Roll> 
    <Result /> 
    <Attendance>50</Attendance> 
</Student>' 


SET @student.modify('insert sql:variable("@res") as first into (/Student/Result)[1]') 

SELECT @student 

Eso me da la salida:

<Student> 
    <Name>XYZ</Name> 
    <Roll>15</Roll> 
    <Result> 
    <Subject>English</Subject> 
    <Marks>67</Marks> 
    <Subject>Science</Subject> 
    <Marks>75</Marks> 
    </Result> 
    <Attendance>50</Attendance> 
</Student> 

Por desgracia, se introdujo la posibilidad de llamar .modify() y utilizar un sql:variable en la instrucción de inserción con SQL Server 2008 solamente - no funciona en SQL Server 2005.

No veo cómo se puede hacer esto en SQL Server 2005, o Ther de recurrir de nuevo a análisis de cadenas fea y sustitución:

SET @student = 
    CAST(REPLACE(CAST(@student AS VARCHAR(MAX)), 
       '<Result/>', 
       '<Result>' + CAST(@res AS VARCHAR(MAX)) + '</Result>') AS XML) 

Marc

0

También puede tratar de volver a los datos relacionales y de nuevo a XML; algo así como:

DECLARE @res xml = 
'<result> 
    <StudentID>1</StudentID> 
    <Subject>English</Subject> 
    <Marks>67</Marks> 
</result> 
<result> 
    <StudentID>1</StudentID> 
    <Subject>Science</Subject> 
    <Marks>75</Marks> 
</result>' 

DECLARE @student xml = 
'<Student> 
    <StudentID>1</StudentID> 
    <Name>XYZ</Name> 
    <Roll>15</Roll> 
    <Attendance>50</Attendance> 
</Student>' 

; 
WITH cte_1 
     AS (SELECT t.c.value('StudentID[1]', 'int') AS [StudentID] 
        ,t.c.value('Subject[1]', 'varchar(50)') AS [Subject] 
        ,t.c.value('Marks[1]', 'int') AS [Marks] 
      FROM @res.nodes('/result') AS t (c) 
      ), 
     cte_2 
     AS (SELECT t.c.value('StudentID[1]', 'int') AS [StudentID] 
        ,t.c.value('Name[1]', 'varchar(50)') AS [Name] 
        ,t.c.value('Roll[1]', 'int') AS [Roll] 
        ,t.c.value('Attendance[1]', 'int') AS [Attendance] 
      FROM @student.nodes('/Student') AS t (c) 
      ) 
    SELECT student.StudentID 
     ,student.[Name] 
     ,student.Roll 
     ,student.Attendance 
     ,(SELECT result.[Subject] 
        ,result.Marks 
      FROM cte_1 AS result 
      WHERE student.StudentID = result.StudentID 
      FOR 
      XML AUTO 
       ,TYPE 
       ,ELEMENTS 
     ) 
    FROM cte_2 AS student 
FOR  XML AUTO 
      ,ELEMENTS 

devoluciones:

<student> 
    <StudentID>1</StudentID> 
    <Name>XYZ</Name> 
    <Roll>15</Roll> 
    <Attendance>50</Attendance> 
    <result> 
    <Subject>English</Subject> 
    <Marks>67</Marks> 
    </result> 
    <result> 
    <Subject>Science</Subject> 
    <Marks>75</Marks> 
    </result> 
</student> 

No exactamente tu ejemplo, pero cerca.

7

Esto funcionará en SQL 2005 y es sobre todo una solución xquery:

DECLARE @res xml 

SET @res = 
'<Subject>English</Subject> 
<Marks>67</Marks> 
<Subject>Science</Subject> 
<Marks>75</Marks>' 

DECLARE @student xml 
SET @student = 
'<Student> 
    <Name>XYZ</Name> 
    <Roll>15</Roll> 
    <Result /> 
    <Attendance>50</Attendance> 
</Student>' 

DECLARE @final XML 

SET @final = CAST(CAST(@student AS VARCHAR(MAX)) + '<test>' + CAST(@res AS VARCHAR(MAX)) + '</test>' AS XML) 

SET @final.modify('insert /test/* into (/Student/Result)[1]') 
SET @final.modify('delete /test') 

SELECT @final 

Puede establecer la variable de @student a @final en ese momento si es necesario hacerlo. El nombre de "prueba" para el nodo fue justo lo que elegí usar. Puede usar cualquier nombre , siempre que no aparezca en su XML.

Básicamente tira las dos cadenas XML juntas para que ambas estén disponibles para xquery a la vez.

Cuestiones relacionadas