查询 XML 内的 SQL 具有命名空间的服务器

Querying XML within SQL Server with namespace

我正在尝试查询发送给我的一些 XML 数据。我遵循了各种示例,但甚至无法解决根目录下的任何元素。我不确定我错过了什么。我试过简单地将 xml 拉到 /KitchenSupply/StoreInfo 下面,但什么也没有。命名空间是我无法 return 任何东西的罪魁祸首吗?

declare @myxmlinv as xml = 
'<?xml version="1.0" encoding="utf-8"?>
<KitchenSupply xmlns="http://www.starstandards.org/STAR" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="KitchenSupply.xsd">
  <StoreInfo>
    <RCPT>
      <SubTaskCode>ZZZ</SubTaskCode>
      <SubComponentCode>BS1</SubComponentCode>
      <StoreNumber>2241</StoreNumber>
      <USRegionNumber>SE</USRegionNumber>
    </RCPT>
    <SentDateTime>02/04/2015</SentDateTime>
    <IntId>ABC1234587</IntId>
    <Destinations>
      <DestinationFormatType>KS_XML_v3</DestinationFormatType>
    </Destinations>
  </StoreInfo>
  <KitchenOrder>
    <KsRecord SalesTransactionPayType="CC" SalesTransactionType="Closed">
      <ReceiptAmt RcptTotalAmt="0.00" CustRcptTotalAmt="25.22" CCPostDate="01/07/2015" InvoiceDate="01/05/2015" CustName="JOHN SMITH" CustNo="13998" RcptNo="78476221" />
      <KsCosts>
        <SaleAmts UnitCost="15.00" TxblAmt="15.00" PayType="Cust" />
        <SalesInfo JobStatus="F" JobNo="1" ItemCode="HT093" ItemDesc="Hand Towel">
          <EmpInfo EmpRate="16.00" EmpCommPct="1.2" EmpName="DOUG ROGERS" EmpNo="998331" />
        </SalesInfo>
      </KsCosts>
    </KsRecord>
    <CustomerRecord>
      <ContactInfo LastName="SMITH" FreqFlag="Y">
        <Address Zip="90210" State="CA" City="BEV" Addr1="123 MAIN ST" Type="Business" />
        <Email MailTo="FAKE@USA.COM" />
        <Phone Num="1235551212" Type="H" />
        <Phone Num="1235551213" Type="B" />
      </ContactInfo>
    </CustomerRecord>
  </KitchenOrder>
  <KitchenOrder>
    <KsRecord SalesTransactionPayType="CC" SalesTransactionType="Closed">
      <ReceiptAmt RcptTotalAmt="0.00" CustRcptTotalAmt="5.71" CCPostDate="01/08/2015" InvoiceDate="01/07/2015" CustName="SARAH BALDWIN" CustNo="14421" RcptNo="78476242" />
      <KsCosts>
        <SaleAmts UnitCost="2.00" TxblAmt="2.00" PayType="Cust" />
        <SalesInfo JobStatus="F" JobNo="1" ItemCode="HS044" ItemDesc="Hand Soap">
          <EmpInfo EmpRate="16.00" EmpCommPct="1.2" EmpName="DOUG ROGERS" EmpNo="998331" />
        </SalesInfo>
      </KsCosts>
    </KsRecord>
    <CustomerRecord>
      <ContactInfo LastName="BALDWIN" FreqFlag="N">
        <Address Zip="90210" State="CA" City="BEV" Addr1="123 VINE ST" Type="Home" />
        <Email MailTo="FAKESARAH@USA.COM" />
        <Phone Num="1235555512" Type="H" />
        <Phone Num="1235556613" Type="M" />
      </ContactInfo>
    </CustomerRecord>
  </KitchenOrder>
</KitchenSupply>';


declare @myxmlinv_table as table (
 row_id tinyint,
 inv_xml xml   
);

insert into @myxmlinv_table(row_id,inv_xml) values('1',@myxmlinv);

显示 XML 文档并提取 IntId 列:(不起作用)

select i.row_id, i.inv_xml, i.inv_xml.value('(/KitchenSupply/StoreInfo/IntId)[1]','varchar(255)') as data_description
from @myxmlinv_table i

尝试使用 XMLNAMESPACES 在 StoreInfo 级别显示 XML 文档:(也不起作用)

WITH XMLNAMESPACES ('http://www.starstandards.org/STAR' as ks)
SELECT 
   XmlCol.query('/ks:KitchenSupply/StoreInfo')
FROM T;

理想情况下,我想使用节点将所有数据提取和输入以分离 table 以供查询。

KitchenOrders 都在一个 table 中,CustomerRecord 在另一个中,等等

有什么想法吗?

你需要使用这样的东西:

-- define the XML namespace as the "default" so you don't have to 
-- prefix each and every XPath element with the XML namespace prefix
WITH XMLNAMESPACES( DEFAULT 'http://www.starstandards.org/STAR')
SELECT
    -- reach into the <KsRecord> subnode under <KitchenOrder>
    ReceiptNo = XC.value('(KsRecord/ReceiptAmt/@RcptNo)[1]', 'int'),
    CustName = XC.value('(KsRecord/ReceiptAmt/@CustName)[1]', 'varchar(25)'),
    -- reach into the <CustomerRecord> subnode under <KitchenOrder>     
    CustomerLastName = xc.value('(CustomerRecord/ContactInfo/@LastName)[1]', 'varchar(50)'),
    CustomerEmail = xc.value('(CustomerRecord/ContactInfo/Email/@MailTo)[1]', 'varchar(50)')
FROM
    -- get a "virtual" table of XML fragments, one for each <KitchenOrder> node
    @myxmlinv.nodes('/KitchenSupply/KitchenOrder') AS XT(XC)

是的,这是命名空间。要让 SQL 服务器忽略命名空间,您可以使用 local-name:

SELECT *
FROM @myxmlinv_table
WHERE inv_xml.exist('//*[local-name()="KitchenSupply"]') = 1