SQL Server打开XML选择值

时间:2018-03-28 00:04:31

标签: sql sql-server xml openxml

我正在尝试使用openxml api从订单xml中选择一些值。每当我执行这个命令时,我都会看到Null结果。我在select - with下写的语句可能是错误的。任何建议如何才能得到正确的值。

DECLARE @XML AS XML, @hDoc AS INT, @SQL NVARCHAR (MAX)

SELECT @XML = N'<order>
  <order-date>2017-07-24T20:48:57.000Z</order-date>
  <invoice-no>00000001</invoice-no>
  <customer>
    <customer-name>abc abcd</customer-name>
    <customer-email>avbc@gmail.com</customer-email>
  </customer>
  <current-order-no>00000001</current-order-no>
  <payments>
    <payment>
      <credit-card>
        <card-type>VISA</card-type>
        <card-number>XXXX-XXXX-XXXX-1111</card-number>
        <card-holder>abc</card-holder>
        <expiration-month>1</expiration-month>
        <expiration-year>2021</expiration-year>
      </credit-card>
      <amount>325.48</amount>
    </payment>
  </payments>
</order>';


EXEC sp_xml_preparedocument @hDoc OUTPUT, @XML


SELECT *
FROM OPENXML(@hDoc, '/order/customer',2)
WITH 
(
customerName [varchar](50) '@customer-name',
customerEmail [varchar](100) '@customer-email'
)


SELECT cardType, cardNumber, cardHolder
FROM OPENXML(@hDoc, '/order/payments/payment/credit-card',2)
WITH 
(
cardType [varchar](50) '@card-type',
cardNumber [varchar](100) '@card-number',
cardHolder [varchar](100) '@card-holder'
)

EXEC sp_xml_removedocument @hDoc
GO

1 个答案:

答案 0 :(得分:2)

您引用这些字段就好像它们是属性(带有@标志),但它们实际上是元素。尝试删除@符号。 e.g。

EXEC sp_xml_preparedocument @hDoc OUTPUT, @XML

select hDoc = @hDoc
SELECT *
FROM OPENXML(@hDoc, '/order/customer', 2)
WITH 
(
customerName [varchar](50) 'customer-name',
customerEmail [varchar](100) 'customer-email'
)


SELECT cardType, cardNumber, cardHolder
FROM OPENXML(@hDoc, '/order/payments/payment/credit-card',2)
WITH 
(
cardType [varchar](50) 'card-type',
cardNumber [varchar](100) 'card-number',
cardHolder [varchar](100) 'card-holder'
)

EXEC sp_xml_removedocument @hDoc
GO

此外,这只是个人偏好,但除非您的XML文档非常大,否则您可能会考虑使用@ xml.nodes()。它不必首先将完整文档加载到内存中,也不会冒着意外卸载文档句柄的风险。您可以等效地编写第一个查询:

SELECT 
    t.c.value('customer-name[1]', 'varchar(50)'),
    t.c.value('customer-email[1]', 'varchar(50)')
FROM @xml.nodes('/order/customer') t(c)