在SQL中解析xml:如何循环子节点?

时间:2014-12-18 09:05:08

标签: sql sql-server xml tsql

我正在为最新的Service Pack开发SQL Server 2012 Express和开发人员版的存储过程。

我想解析XML并将其数据插入表中。

这是我的XML

<Parent ParentId="1" ParentCodeId="ASDAS121" ParentLevelId="1">
    <Child ParentId="1" ChildCode="GF342" ChildLevel="0" Position="1"/>
    <Child ParentId="1" ChildCode="G1A42" ChildLevel="0" Position="2"/>
    <Child ParentId="1" ChildCode="GFS42" ChildLevel="0" Position="3"/>
    <Child ParentId="1" ChildCode="GF242" ChildLevel="0" Position="4"/>
                        <!-- N childs more -->
    <Child ParentId="1" ChildCode="DF342" ChildLevel="0" Position="N"/>
</Parent>

这是我的存储过程代码:

CREATE PROCEDURE [dbo].[InsertXML]
    @xmlString NVARCHAR(MAX)
AS
BEGIN
    DECLARE @xml xml

    set nocount on

    -- Convert string data into XML.
    SET @xml = @XmlString

    DECLARE @hDoc int

    --Prepare input values as an XML document
    exec sp_xml_preparedocument @hDoc OUTPUT, @xmlData

    INSERT INTO [dbo].[AGGREGATIONS]
        SELECT ID_AGGREGATION, CODE, CODE_LEVEL
          FROM OPENXML(@hdoc, '/Parent', 1) WITH (ID_AGGREGATION bigint '@ParentId', CODE nvarchar(20) '@ParentCodeId', CODE_LEVEL tinyint '@ParentLevelId')

-- I don't know how to continue

    INSERT INTO [dbo].[AGGREGATION_CHILDS]
        SELECT ID_AGGREGATION, CODE, CODE_LEVEL
          FROM OPENXML(@hdoc, '/Parent/Child', 1) WITH (ID_AGGREGATION bigint 'ParentId', CODE nvarchar(20) '@ChildCodeId', CODE_LEVEL tinyint '@ChildLevelId', POSITION int  '@Position')

我如何循环所有孩子?我不知道会有多少孩子。

2 个答案:

答案 0 :(得分:1)

查看此链接transforming xml并尝试此操作:

SQL Fiddle

MS SQL Server 2012架构设置

查询1

DECLARE @xml AS XML

SET @xml =
'<Parent ParentId="1" ParentCodeId="ASDAS121" ParentLevelId="1">
    <Child ParentId="1" ChildCode="GF342" ChildLevel="0" Position="1"/>
    <Child ParentId="1" ChildCode="G1A42" ChildLevel="0" Position="2"/>
    <Child ParentId="1" ChildCode="GFS42" ChildLevel="0" Position="3"/>
    <Child ParentId="1" ChildCode="GF242" ChildLevel="0" Position="4"/>
    <Child ParentId="1" ChildCode="DF342" ChildLevel="0" Position="N"/>
</Parent>'


SELECT T.c.value('@ParentId', 'int') as ParentId,
       T.c.value('@ChildCode', 'char(5)') As ChildCode,
       T.c.value('@ChildLevel', 'int') As ChildLevel,
       T.c.value('@Position', 'char(1)') As Position
FROM   @xml.nodes('/Parent/Child') T(c)

<强> Results

| PARENTID | CHILDCODE | CHILDLEVEL | POSITION |
|----------|-----------|------------|----------|
|        1 |     GF342 |          0 |        1 |
|        1 |     G1A42 |          0 |        2 |
|        1 |     GFS42 |          0 |        3 |
|        1 |     GF242 |          0 |        4 |
|        1 |     DF342 |          0 |        N |

答案 1 :(得分:0)

使用CURSOR

DECLARE @ParentId   INT
       ,@ChildCode  VARCHAR(10)
       ,@ChildLevel INT
       ,@Position   VARCHAR(10);

DECLARE C CURSOR FOR
SELECT X_ParentId   AS ParentId
      ,X_ChildCode  AS ChildCode
      ,X_ChildLevel AS ChildLevel
      ,X_Position   AS Position
FROM OPENXML (@hdoc, '/Parent/Child', 1)
WITH (X_ParentId   INT         '@ParentId'
     ,X_ChildCode  VARCHAR(10) '@ChildCode'
     ,X_ChildLevel INT         '@ChildLevel'
     ,X_Position   VARCHAR(10) '@Position');

OPEN C;
FETCH NEXT FROM C INTO @ParentId, @ChildCode, @ChildLevel, @Position;

WHILE @@FETCH_STATUS = 0
BEGIN
    -- Place your INSERT here
    SELECT @ParentId, @ChildCode, @ChildLevel, @Position;

    FETCH NEXT FROM C INTO @ParentId, @ChildCode, @ChildLevel, @Position;
END

CLOSE C;
DEALLOCATE C;

或者只是:

-- Place your INSERT here
SELECT X_ParentId   AS ParentId
      ,X_ChildCode  AS ChildCode
      ,X_ChildLevel AS ChildLevel
      ,X_Position   AS Position
FROM OPENXML (@hdoc, '/Parent/Child', 1)
WITH (X_ParentId   INT         '@ParentId'
     ,X_ChildCode  VARCHAR(10) '@ChildCode'
     ,X_ChildLevel INT         '@ChildLevel'
     ,X_Position   VARCHAR(10) '@Position');