English 中文(简体)
How to insert xml into a node in another xml using XQuery?
原标题:

I have two xml variable say @res, @student in a stored proc in SQL server 2005.

@res contains

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

@student contains:

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

I need to insert the xml of @res into the node Result in @student variable using XQuery.

How to implement that?

Please help.

问题回答

In SQL Server 2008, it s pretty easy:

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

That gives me the output:

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

Unfortunately, the ability to call .modify() and use a sql:variable in the insert statement was introduced with SQL Server 2008 only - doesn t work in SQL Server 2005.

I don t see how you could do this in SQL Server 2005, other than resorting back to ugly string parsing and replacement:

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

Marc

This will work in SQL 2005 and is mostly an xquery solution:

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

You can set your @student variable to @final at that point if you need to do that. The name of "test" for the node was just what I chose to use. You can use any name as long as it will not already appear in your XML.

You basically just throw the two XML strings together so that they are both available to xquery at once.

You may also try to go back to relational data and than back to xml; something like:

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

Returns:

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

Not exactly your example, but close.





相关问题
SQL SubQuery getting particular column

I noticed that there were some threads with similar questions, and I did look through them but did not really get a convincing answer. Here s my question: The subquery below returns a Table with 3 ...

难以执行 REGEXP_SUBSTR

I m 查询Oracle 10g。 我有两张表格(样本数据见下文)。 i m 试图提取一些领域

SQL Query Shortcuts

What are some cool SQL shorthands that you know of? For example, something I learned today is you can specify to group by an index: SELECT col1, col2 FROM table GROUP BY 2 This will group by col2

PHP array callback functions for cleaning output

I have an array of output from a database. I am wondering what the cleanest way to filter the values is example array Array ( [0] => Array ( [title] => title 1 ...

OracleParameter and DBNull.Value

we have a table in an Oracle Database which contains a column with the type Char(3 Byte). Now we use a parameterized sql to select some rows with a DBNull.Value and it doesn t work: OracleCommand ...

Running numbers in SQL

I have a SQL-statement like this: SELECT name FROM users WHERE deleted = 0; How can i create a result set with a running number in the first row? So the result would look like this: 1 Name_1 2 ...

How to get SQL queries for each user where env is production

I’m developing an application dedicated to generate statistical reports, I would like that user after saving their stat report they save sql queries too. To do that I wrote the following module: ...

热门标签