SQL Server使用OPENXML扁平化XML时嵌套行值重复问题
问题根因
Direct字段的XPath映射路径写错了。你写的../Direct逻辑是:从当前遍历到的<Direct>节点回退到父节点<HID>,再取父节点下第一个<Direct>子节点的文本,所以不管遍历到哪一行,返回的永远是第一个Direct节点的内容,自然会重复。
修正方案
要取当前行对应<Direct>节点自身的文本,XPath直接写.就行,.代表当前上下文节点。
修正后的完整代码:
declare @idoc int, @XML XML = '<HID Name="LEESA5" CodeName="YBAS" Sequences="12,30"> <Direct Sequence="12">PUNED/BODAS/OSINA/IGDEB/LEESA</Direct> <Direct Sequence="30">RUGMU/IGDEB/LEESA</Direct> </HID>' EXEC sp_xml_preparedocument @idoc OUTPUT, @XML select * from OPENXML(@idoc,'/HID/Direct') with ( Name varchar(10) '../@Name', CodeName varchar(10) '../@CodeName', Sequences varchar(10) '../@Sequences', Sequence varchar(10) '@Sequence', Direct varchar(100) '.' -- 替换原有错误路径'../Direct',直接取当前节点文本 ) EXEC sp_xml_removedocument @idoc
注:原XPath写
/HID/*虽然当前场景能用,但显式指定/HID/Direct可读性更好,后续HID节点新增其他子节点时不会查出多余行。
运行后输出完全符合预期:
| Name | CodeName | Sequences | Sequence | Direct |
|---|---|---|---|---|
| LEESA5 | YBAS | 12,30 | 12 | PUNED/BODAS/OSINA/IGDEB/LEESA |
| LEESA5 | YBAS | 12,30 | 30 | RUGMU/IGDEB/LEESA |
额外优化建议
SQL Server 2005及以上版本优先用原生XML方法(nodes()+value())解析,不需要手动管理XML文档句柄,没有内存泄漏风险,写法更清晰,示例如下:
declare @XML XML = '<HID Name="LEESA5" CodeName="YBAS" Sequences="12,30"> <Direct Sequence="12">PUNED/BODAS/OSINA/IGDEB/LEESA</Direct> <Direct Sequence="30">RUGMU/IGDEB/LEESA</Direct> </HID>' SELECT HID.value('@Name','varchar(10)') Name, HID.value('@CodeName','varchar(10)') CodeName, HID.value('@Sequences','varchar(10)') Sequences, Direct.value('@Sequence','varchar(10)') Sequence, Direct.value('text()[1]','varchar(100)') Direct FROM @XML.nodes('/HID') H(HID) CROSS APPLY H.HID.nodes('Direct') D(Direct)
内容的提问来源于stack exchange,提问作者B Ward
相关产品推荐
相关产品推荐

