如何使用XQuery将xml插入另一个xml中的节点?

时间:2009-12-11 08:12:52

标签: sql sql-server sql-server-2005 xquery

我在SQL server 2005的存储过程中有两个xml变量@res,@ student。

@res contains

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

@student包含:

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

我需要使用XQuery将@res的xml插入@student变量中的节点结果

如何实现?

请帮忙。

3 个答案:

答案 0 :(得分:33)

在SQL Server 2008中,它非常简单:

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

这给了我输出:

<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>

不幸的是,仅在SQL Server 2008中引入了在插入语句中调用.modify()并使用sql:variable的功能 - 在SQL Server 2005中不起作用。

我没有看到你如何在SQL Server 2005中做到这一点,除了回到丑陋的字符串解析和替换:

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

马克

答案 1 :(得分:7)

这将在SQL 2005中运行,并且主要是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

如果需要,可以在此时将@student变量设置为@final。节点的“test”名称就是我选择使用的名称。您可以使用任何名称,只要它不会出现在您的XML中

您基本上只是将两个XML字符串放在一起,以便它们可以同时用于xquery。

答案 2 :(得分:0)

你也可以尝试回到关系数据而不是回到xml;类似的东西:

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

返回:

<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>

不完全是你的例子,但是关闭。