SQL Server - 从XML文件查询数据

时间:2015-08-18 17:54:01

标签: sql sql-server xml

我是XML新手。我已经弄清楚如何从XML文件中查询和返回值(例如下面的例子)。但是,我遇到的问题是它只捕获'SerialNo'标记的第一个节点,因为标记具有相同的节点名称“SerialNo”重复。在XML文件中,它有4个SKU#TT234343的序列号,但它只给我第一个Serial11111。我完全陷入困境,不知道如何列出所有这些序列#。

我想询问SKU#TT234343的查询结果,如果可能,请列出所有4个序列号。

请帮忙。谢谢!

XML文件如下所示:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<ROOT>
  <ShipNotice version="1" >
    <InvoiceDate>01/01/2015</InvoiceDate>
    <InvoiceNumber>6868686</InvoiceNumber>
    <ShipDate>02/02/2015</ShipDate>
    <ShipTime>2306</ShipTime>
    <PONumber>P444444</PONumber>
    <PODate>03/03/2015</PODate>
    <ShipCode>XXX</ShipCode>
    <ShipDescription>FedEx Economy</ShipDescription>
    <ShipTo>
      <AddressName>ShipABC</AddressName>
      <AddressContact>Name1</AddressContact>
      <AddressLine1>2222 Street Name</AddressLine1>
      <AddressLine2> </AddressLine2>
      <City>AUSTIN</City>
      <State>TX</State>
      <ZipCode>78111</ZipCode>
    </ShipTo>
    <BillTo>
      <AddressName>BillABC</AddressName>
      <AddressContact>Name1</AddressContact>
      <AddressLine1>1234 Street Name</AddressLine1>
      <AddressLine2>-SUITE 111</AddressLine2>
      <City>Los Angeles</City>
      <State>CA</State>
      <ZipCode>95136</ZipCode>
    </BillTo>
    <TotalWeight>324</TotalWeight>
    <EmptyCartonWGT>0</EmptyCartonWGT>
    <NumberOfCarton>1</NumberOfCarton>
    <DirectShipFlag>D</DirectShipFlag>
    <ShipFromWarehouse>88</ShipFromWarehouse>
    <ShipFromZip>94538</ShipFromZip>
    <ShipTrackNo>33333333</ShipTrackNo>
    <EndUserPONumber>55555555</EndUserPONumber>
    <CustomerSONumber/>
    <Package sequence="1" >
      <TrackNumber>666666666</TrackNumber>
      <PackageWeight>324</PackageWeight>
      <Item sequence="1" >
        <SOLineNo>1</SOLineNo>
        <MfgPN>XYZ1111111</MfgPN>
        <SKU>TT234343</SKU>
        <ShipQuantity>4</ShipQuantity>
        <CustPOLineNo>1</CustPOLineNo>
        <CustSOLineNo/>
        <Description>Server1234</Description>
        <CustPN/>
        <UPC/>
        <UnitPrice>1000</UnitPrice>
        <EndUserPOLineNo>0</EndUserPOLineNo>
        <SerialNo>Serial11111</SerialNo>
        <SerialNo>Serial22222</SerialNo>
        <SerialNo>Serial33333</SerialNo>
        <SerialNo>Serial44444</SerialNo>
      </Item>
      <Item sequence="2" >
        <SOLineNo>2</SOLineNo>
        <MfgPN>XYZ222222</MfgPN>
        <SKU>TT8848788</SKU>
        <ShipQuantity>4</ShipQuantity>
        <CustPOLineNo>2</CustPOLineNo>
        <CustSOLineNo/>
        <Description>GGG localization</Description>
        <CustPN/>
        <UPC/>
        <UnitPrice>0.00</UnitPrice>
        <EndUserPOLineNo>0</EndUserPOLineNo>
        <SerialNo/>
      </Item>
    </Package>
  </ShipNotice>
</ROOT>

SQL查询:

DECLARE @XML AS XML, @hDoc AS INT, @SQL NVARCHAR (MAX)
EXEC sp_xml_preparedocument @hDoc OUTPUT, @xmlData

SELECT 
InvoiceNumber, PONumber, PODate
, AddressName
, MfgPN, SerialNo
--, AddressContact, AddressLine1, AddressLine2, City, State, ZipCode
FROM OPENXML(@hDoc, '/ROOT/ShipNotice/Package/Item')
WITH 
(
    --- #################  Level 1 #################
    InvoiceNumber [varchar](50) '../../InvoiceNumber',
    PONumber [varchar](100) '../../PONumber',
    PODate [varchar](100) '../../PODate',

    --- #################  Level 2 #################
    AddressName [varchar](100) '../../ShipTo/AddressName',


    --- #################  Level 3 #################
    MfgPN [varchar](100) 'MfgPN',
    SerialNo [varchar](100) 'SerialNo'

)

1 个答案:

答案 0 :(得分:1)

您可以尝试使用较新的技术XQuery而不是OPENXML()。使用XQuery,您可以使用nodes()方法在与输出中的行对应的元素上粉碎XML,并使用value()提取元素值:

SELECT
    shipnotice.value('InvoiceNumber[1]','varchar(20)') InvoiceNumber
    , shipnotice.value('PONumber[1]','varchar(20)') PONumber
    , shipnotice.value('PODate[1]','varchar(20)') PODate
    , shipnotice.value('(ShipTo/AddressName)[1]','varchar(100)') AddressName
    , item.value('MfgPN[1]','varchar(100)') MfgPN
    , serialno.value('.','varchar(100)') SerialNo
FROM @XML.nodes('/ROOT/ShipNotice') as t(shipnotice)
    OUTER APPLY shipnotice.nodes('Package/Item') as t2(item)
    OUTER APPLY item.nodes('SerialNo') as t3(serialno)

<强> Sqlfiddle Demo

输出

| InvoiceNumber | PONumber |     PODate | AddressName |      MfgPN |    SerialNo |
|---------------|----------|------------|-------------|------------|-------------|
|       6868686 |  P444444 | 03/03/2015 |     ShipABC | XYZ1111111 | Serial11111 |
|       6868686 |  P444444 | 03/03/2015 |     ShipABC | XYZ1111111 | Serial22222 |
|       6868686 |  P444444 | 03/03/2015 |     ShipABC | XYZ1111111 | Serial33333 |
|       6868686 |  P444444 | 03/03/2015 |     ShipABC | XYZ1111111 | Serial44444 |
|       6868686 |  P444444 | 03/03/2015 |     ShipABC |  XYZ222222 |             |