按XML结构定义的顺序插入XML节点

时间:2014-04-11 08:15:37

标签: sql-server xml tsql sql-server-2012 nodes

我有一个带有后续列的表变量:

[ID] TINYINT
[XML] XML

XML结构如下:

 <conditions>

    <condition type='expresion'>
        ...
    </condition>
    <condition type='operand'>
        ...
    </condition>
    <condition type='expresion'>
        ...
    </condition>
    <condition type='operand'>
        ...
    </condition>
    <condition type='expresion'>
        ...
    </condition>

</conditions>

我需要提取上面的信息并使用以下结构填充表格:

[ID]
[ConditionID]
[ConditionXML]

其中ConditionID为数字列,ConditonXML将从原始XML中提取。

对我来说非常重要的是生成ConditionID值以表示原始XML结构中的顺序。

have read可以使用ROW_NUMBER这样做:

SELECT [ID]
        ,ROW_NUMBER() OVER (PARTITION BY [ID] ORDER BY T.c) AS T
        ,T.c.query('.')
FROM @Test
CROSS APPLY [CondtionsXML].nodes('conditions/condition') T(c)
ORDER BY [ID], T

但在official documentation中说:

  

无法保证查询返回的行使用   每次执行时,ROW_NUMBER()的排序方式都完全相同   除非满足以下条件:

     
      
  1. 分区列的值是唯一的。
  2.   
  3. ORDER BY列的值是唯一的。
  4.   
  5. 分区列和ORDER BY列的值的组合   是独一无二的。
  6.   

由于我的operand节点可能相同,我担心我可能会遇到一些问题。此外,如果我删除PARTITON BY子句,则会出错。

我可以使用的其他术语是创建一个带有INDENTITY列的separete故事,并将值插入其中:

DECLARE @TEST1 TABLE
(
     [ID] SMALLINT IDENTITY(1,1)
    ,[ParentID] TINYINT
    ,[XML] XML
)

INSERT INTO @TEST1 ([ParentID], [XML])
SELECT [ID]
      ,T.c.query('.')
FROM @Test
CROSS APPLY [CondtionsXML].nodes('conditions/condition') T(c)

有人可以说这是否是按照XML结构中表示的顺序在表中插入XML个节点的方式。

2 个答案:

答案 0 :(得分:3)

我认为文档错了,我无法向您展示其他一些支持我的文档。

这是我认为应该的。我强调了改变。

  

无法保证查询返回的行使用   对于每次执行,ROW_NUMBER()将编号完全相同   除非 中的一个满足以下条件:

<强> 1。分区列的值是唯一的。

如果此条件为真,那么row_number()将为所有行返回1。它总会这样做,没有什么可以改变这种行为,所以这个条件单独保证每次执行的结果都是一样的。

<强> 2。 ORDER BY列的值是唯一的。

如果order by中的值是唯一的,并且您没有partition by子句,则row_number()返回的每个值在结果集中都是唯一的,并且它将始终返回完全相同的值每次执行查询。

第3。分区列和ORDER BY列的值组合是唯一的。

这种情况下你有一个partition by子句和一个order by子句。 row_number()从每个分区的一个开始,如果order by子句中使用的值在分区中是唯一的,则每次执行的编号都是相同的。

答案 1 :(得分:-2)

您可以使用(select 1)构造。它表示按原样对结果集进行排序。

select [ID]
    , row_number() over (partition by [ID] order by (select 1) ) as T
    , T.c.query('.')
from @Test
cross apply [XML].nodes ('/conditions[1]/condition')T(c)