如何将OrderContact结构XML数据转换为指定列SQL Server数据表
基于SQL Server原生XQuery实现XML转目标结构数据表
核心逻辑是利用SQL Server内置的XML类型解析能力,先把嵌套在层级节点里的所有联系方式逐行拆解为结构化数据,再通过条件聚合把不同类型的联系方式映射为独立列,最终生成要求的宽表结构。
实现要点
- 兼容原始XML中存在的不规范标签写法(第一个ContactNumber节点提前自闭合
<ContactNumberValue />的问题,无需修改原XML即可正常取值) - 特殊类型的联系方式(Switchboard)需要同时匹配
ContactNumberTypeCoded为Other、ContactNumberTypeCodedOther为Switchboard两个判断条件,避免取值错误 - 因为每个联系类型只会对应一条有效记录,使用
MAX()做聚合即可实现单行透视,不需要依赖PIVOT语法,兼容性更好
可直接运行的实现代码
DECLARE @SourceXml XML = N' <OrderContact> <Contact> <ContactName>Harj Dhamrait</ContactName> <ContactDescription>13</ContactDescription> <ListOfContactNumber> <ContactNumber> <ContactNumberValue />454854 5532281</ContactNumberValue> <ContactNumberTypeCoded>TelephoneNumber</ContactNumberTypeCoded> </ContactNumber> <ContactNumber> <ContactNumberValue>0987262 532281</ContactNumberValue> <ContactNumberTypeCoded>Other</ContactNumberTypeCoded> <ContactNumberTypeCodedOther>Switchboard</ContactNumberTypeCodedOther> </ContactNumber> <ContactNumber> <ContactNumberValue>abc@gmail.com</ContactNumberValue> <ContactNumberTypeCoded>EmailAddress</ContactNumberTypeCoded> </ContactNumber> <ContactNumber> <ContactNumberValue>01322 296 252</ContactNumberValue> <ContactNumberTypeCoded>FaxNumber</ContactNumberTypeCoded> </ContactNumber> </ListOfContactNumber> </Contact> </OrderContact> ' SELECT MAX(CASE WHEN ContactType = 'TelephoneNumber' THEN ContactValue END) AS TelephoneNumber, MAX(CASE WHEN ContactType = 'Other' AND ContactSubType = 'Switchboard' THEN ContactValue END) AS Switchboard, MAX(CASE WHEN ContactType = 'EmailAddress' THEN ContactValue END) AS EmailAddress, MAX(CASE WHEN ContactType = 'FaxNumber' THEN ContactValue END) AS FaxNumber FROM ( -- 从XML中逐行拆解所有联系方式节点 SELECT ContactNode.value('(ContactNumberTypeCoded)[1]', 'VARCHAR(50)') AS ContactType, ContactNode.value('(ContactNumberTypeCodedOther)[1]', 'VARCHAR(50)') AS ContactSubType, LTRIM(RTRIM(ContactNode.value('(ContactNumberValue/text())[1]', 'VARCHAR(100)'))) AS ContactValue FROM @SourceXml.nodes('/OrderContact/Contact/ListOfContactNumber/ContactNumber') AS XmlSplit(ContactNode) ) AS RawContactData
输出结果
执行上述代码将得到与要求完全一致的单行列结构:
| TelephoneNumber | Switchboard | EmailAddress | FaxNumber |
|---|---|---|---|
| 454854 5532281 | 0987262 532281 | abc@gmail.com | 01322 296 252 |
内容的提问来源于stack exchange,提问作者Chandan
相关产品推荐
相关产品推荐

