使用SQLServer查询XML数据

使用SQLServer查询XML数据,sql,sql-server,tsql,xpath,xquery,Sql,Sql Server,Tsql,Xpath,Xquery,我有一些xml文件需要解析并转换为关系数据。数据将存储在SQL Server中。我从不同的来源获得文件,其中一个文件给我带来了麻烦,因为采购订单号的段重复了。我遇到的问题是,它创建了一个重复的记录或行。下面是xml的外观 <?xml version="1.0" encoding="UTF-8"?> <pt:PTShipmentNotification xmlns:cmn="urn:tracelink:mapper:sl:commontypes" xmlns:pt="u

我有一些xml文件需要解析并转换为关系数据。数据将存储在SQL Server中。我从不同的来源获得文件,其中一个文件给我带来了麻烦,因为采购订单号的段重复了。我遇到的问题是,它创建了一个重复的记录或行。下面是xml的外观

<?xml version="1.0" encoding="UTF-8"?>
<pt:PTShipmentNotification  xmlns:cmn="urn:tracelink:mapper:sl:commontypes"     xmlns:pt="urn:tracelink:mapper:sl:product_track">
<pt:MessageBody>
<pt:ShipmentTransaction>
<cmn:ShipmentIdentifiers>
<cmn:ShipmentId type="ShipmentNumber">22584</cmn:ShipmentId>
<cmn:ShipmentId type="BillOfLading">2584226516</cmn:ShipmentId>
</cmn:ShipmentIdentifiers>
</pt:ShipmentTransaction>
<pt:ShipmentItemDetails>
<cmn:LineItemNumber>1</cmn:LineItemNumber>
<cmn:LotNumber>FT0109</cmn:LotNumber>
<cmn:OrderNDC type="NDC542">49884066009</cmn:OrderNDC>
<cmn:ExpirationDate>2018-09-30</cmn:ExpirationDate>
<cmn:SalesQuantity quantityUnitOfMeasure="EA">12</cmn:SalesQuantity>
<pt:ReferenceDocuments>
<cmn:BusinessDocument type="PurchaseOrder">024136</cmn:BusinessDocument>
<cmn:DocumentDate>2016-02-03</cmn:DocumentDate>
</pt:ReferenceDocuments>
<pt:ReferenceDocuments>
<cmn:BusinessDocument type="PurchaseOrder">024136</cmn:BusinessDocument>
<cmn:DocumentDate>2016-02-03</cmn:DocumentDate>
</pt:ReferenceDocuments>
</pt:ShipmentItemDetails>
<pt:ShipmentItemDetails>
<cmn:LineItemNumber>2</cmn:LineItemNumber>
<cmn:LotNumber>FN0043</cmn:LotNumber>
<cmn:OrderNDC type="NDC542">49884082710</cmn:OrderNDC>
<cmn:ExpirationDate>2019-01-31</cmn:ExpirationDate>
<cmn:SalesQuantity quantityUnitOfMeasure="EA">36</cmn:SalesQuantity>
<pt:ReferenceDocuments>
<cmn:BusinessDocument type="PurchaseOrder">024136</cmn:BusinessDocument>
<cmn:DocumentDate>2016-02-03</cmn:DocumentDate>
</pt:ReferenceDocuments>
<pt:ReferenceDocuments>
<cmn:BusinessDocument type="Invoice">024136</cmn:BusinessDocument>
<cmn:DocumentDate>2016-02-03</cmn:DocumentDate>
</pt:ReferenceDocuments>
</pt:ShipmentItemDetails>
</pt:MessageBody>
</pt:PTShipmentNotification>

参考上面的xml,如果第二次出现的采购订单号被称为其他名称,例如发票号(通常是这样),那么就没有问题。每行项目编号只能获得一条记录或一行。我试图让发件人修复文件,但我也有兴趣能够修改代码来处理这个问题。因此,对于上面xml中的行项目1,我得到了两条记录。对于行项目2,我只得到一条记录。是否有人对修改查询以更正问题有任何建议

尝试只交叉应用于一行,而不是尝试在where中进行筛选

CROSS APPLY @XmlFile.nodes('pt:PTShipmentNotification/pt:MessageBody/pt:ShipmentItemDetails/pt:ReferenceDocuments[@type=''PurchaseOrder''][1]')  x1(n)
删除PurchaseOrder上的where筛选器

DECLARE @XmlFile XML

SELECT @XmlFile = BulkColumn
FROM  OPENROWSET(BULK 'C:\Files\in\badxml.xml', SINGLE_BLOB) x

;WITH XMLNAMESPACES (
    'urn:tracelink:mapper:sl:commontypes' AS cmn,
    'urn:tracelink:mapper:sl:product_track' AS pt 
)



select 

    T.data.value('@type', 'varchar(20)') AS ShipType,
    T.data.value('.', 'varchar(35)') AS ShipNum,
    n.value('../cmn:LineItemNumber[1]','VARCHAR(30)') AS LineItem,
    n.value('../cmn:OrderNDC[1]/@type', 'varchar(20)' ) AS OrderNDC,


    n.value('../cmn:OrderNDC[1]','VARCHAR(30)') AS NDC,
    n.value('../cmn:LotNumber[1]','VARCHAR(30)') AS Lot,
    n.value('../cmn:SalesQuantity[1]/@quantityUnitOfMeasure','VARCHAR(30)') AS UOM,
    n.value('../cmn:SalesQuantity[1]','VARCHAR(30)') AS QTY,
    n.value('cmn:BusinessDocument[0]','VARCHAR(50)') AS PO,


    GETDATE() ProcessedDt,
    0 ProcessedFlag,
    @XmlFile

from
    @XmlFile.nodes('pt:PTShipmentNotification/pt:MessageBody/pt:ShipmentTransaction/cmn:ShipmentIdentifiers/cmn:ShipmentId') T(data)
CROSS APPLY @XmlFile.nodes('pt:PTShipmentNotification/pt:MessageBody/pt:ShipmentItemDetails/pt:ReferenceDocuments[@type=''PurchaseOrder''][1]')  x1(n)

WHERE 
    T.data.value('@type', 'varchar(20)') = 'ShipmentNumber' 

尝试只交叉应用于一行,而不是尝试在where中进行筛选

CROSS APPLY @XmlFile.nodes('pt:PTShipmentNotification/pt:MessageBody/pt:ShipmentItemDetails/pt:ReferenceDocuments[@type=''PurchaseOrder''][1]')  x1(n)
删除PurchaseOrder上的where筛选器

DECLARE @XmlFile XML

SELECT @XmlFile = BulkColumn
FROM  OPENROWSET(BULK 'C:\Files\in\badxml.xml', SINGLE_BLOB) x

;WITH XMLNAMESPACES (
    'urn:tracelink:mapper:sl:commontypes' AS cmn,
    'urn:tracelink:mapper:sl:product_track' AS pt 
)



select 

    T.data.value('@type', 'varchar(20)') AS ShipType,
    T.data.value('.', 'varchar(35)') AS ShipNum,
    n.value('../cmn:LineItemNumber[1]','VARCHAR(30)') AS LineItem,
    n.value('../cmn:OrderNDC[1]/@type', 'varchar(20)' ) AS OrderNDC,


    n.value('../cmn:OrderNDC[1]','VARCHAR(30)') AS NDC,
    n.value('../cmn:LotNumber[1]','VARCHAR(30)') AS Lot,
    n.value('../cmn:SalesQuantity[1]/@quantityUnitOfMeasure','VARCHAR(30)') AS UOM,
    n.value('../cmn:SalesQuantity[1]','VARCHAR(30)') AS QTY,
    n.value('cmn:BusinessDocument[0]','VARCHAR(50)') AS PO,


    GETDATE() ProcessedDt,
    0 ProcessedFlag,
    @XmlFile

from
    @XmlFile.nodes('pt:PTShipmentNotification/pt:MessageBody/pt:ShipmentTransaction/cmn:ShipmentIdentifiers/cmn:ShipmentId') T(data)
CROSS APPLY @XmlFile.nodes('pt:PTShipmentNotification/pt:MessageBody/pt:ShipmentItemDetails/pt:ReferenceDocuments[@type=''PurchaseOrder''][1]')  x1(n)

WHERE 
    T.data.value('@type', 'varchar(20)') = 'ShipmentNumber' 

谢谢你的回答很有帮助!如前所述,您的交叉申请没有返回任何记录,但我做了一个更改,它似乎正在工作。下面是我现在使用的:交叉应用@XmlFile.nodes('pt:PTShipmentNotification/pt:MessageBody/pt:ShipmentItemDetails/pt:ReferenceDocuments[cmn:BusinessDocument[1]/@type='PurchaseOrder'][1]')x1(n)谢谢你的回答非常有用!如前所述,您的交叉申请没有返回任何记录,但我做了一个更改,它似乎正在工作。下面是我现在使用的:交叉应用@XmlFile.nodes('pt:PTShipmentNotification/pt:MessageBody/pt:ShipmentItemDetails/pt:ReferenceDocuments[cmn:BusinessDocument[1]/@type='PurchaseOrder'][1]')x1(n)