Как выбрать данные из столбца XML на SQL Server? - PullRequest
0 голосов
/ 01 октября 2019

Как выбрать данные из столбца XML в таблице SQL Server в SQL Server Management Studio?

Я хотел бы получить такой результат:

orderDdate  createdBby  orderNo currency    taxation    inv customer    mail
2019-09-05  storefront  000001  USD gross   0099999 Jonh Smith  JonhSmith@gmail.com

<orders xmlns="www address">
<order>
    <order-date>2019-09-05</order-date>
    <created-by>storefront</created-by>
    <original-order-no>000001</original-order-no>
    <currency>USD</currency>
    <taxation>gross</taxation>
    <invoice-no>0099999</invoice-no>
    <customer>
        <customer-name>Jonh Smith</customer-name>
        <customer-email>JonhSmith@gmail.com</customer-email>
    </customer>
    <notes>
        <note>
            <created-by>system</created-by>
            <creation-date>2019-09-06T07:05:03.000Z</creation-date>
            <subject>Fulfilment Status</subject>
            <text>The order fulfilment status was changed from '01' to '02'.</text>
        </note>
        <note>
            <created-by>system</created-by>
            <creation-date>2019-09-06T07:05:03.000Z</creation-date>
            <subject>Fulfilment Status</subject>
            <text>The order fulfilment status was changed from '02' to '03'.</text>
        </note>
        <note>
            <created-by>system</created-by>
            <creation-date>2019-09-06T07:05:03.000Z</creation-date>
            <subject>Fulfilment Status</subject>
            <text>The order fulfilment status was changed from '03' to '03'.</text>
        </note>
    </notes>

<product-lineitems>
    <product-lineitem>
        <product-id>0001</product-id>
        <quantity unit="BOX">1.0</quantity>
        <tax-rate>0.23</tax-rate>
    </product-lineitem>
    <product-lineitem>
        <product-id>0002</product-id>
        <quantity unit="PCS">1.0</quantity>
        <tax-rate>0.23</tax-rate>
    </product-lineitem>
</product-lineitems>
</order>

У меня есть последняя проблема (я надеюсь);)

Как вернуть данные из товарных позиций. Я имею в виду: Количество, Количество-единица

Я пытаюсь так: Но это возвращает дубликаты строк: (*

WITH XMLNAMESPACES(DEFAULT N'www address')
SELECT 
    o.value(N'(current-order-no/text())[1]',N'varchar(10)') AS OrderNo
    ,n.value(N'(quantity/text())[1]',N'varchar(10)') AS Qty
    ,u.value(N'@unit',N'varchar(10)') AS Unit
FROM 
    dbSupply.dbo.MyXmlTable t
CROSS APPLY 
    t.XMLData.nodes(N'/orders/order') A(o)
OUTER APPLY 
    A.o.nodes(N'product-lineitems/product-lineitem') B(n)
OUTER APPLY 
    A.o.nodes(N'product-lineitems/product-lineitem/quantity') C(u)

'Похоже, ваше сообщение в основном код; пожалуйста, добавьте некоторые подробности«Похоже, что ваше сообщение в основном состоит из кода; пожалуйста, добавьте некоторые подробности» «Похоже, что ваше сообщение в основном состоит из кода; пожалуйста, добавьте некоторые подробности»

Ответы [ 2 ]

1 голос
/ 01 октября 2019

Вы можете попробовать это так:

DECLARE @mockupTable TABLE(ID INT IDENTITY, YourXml XML);
INSERT INTO @mockupTable VALUES
(N'<orders xmlns="www address">
    <order order-no="000001">
        <order-date>2019-09-05</order-date>
        <created-by>storefront</created-by>
        <original-order-no>000001</original-order-no>
        <currency>USD</currency>
        <taxation>gross</taxation>
        <invoice-no>0099999</invoice-no>
        <customer>
            <customer-name>Jonh Smith</customer-name>
            <customer-email>JonhSmith@gmail.com</customer-email>
        </customer>
    </order>
</orders>');

WITH XMLNAMESPACES(DEFAULT N'www address')
SELECT o.value(N'@order-no',N'varchar(10)') AS OrderNo
      ,o.value(N'(order-date/text())[1]',N'date') AS OrderDate
      ,o.value(N'(created-by/text())[1]',N'varchar(100)') AS CreatedBy
      ,o.value(N'(original-order-no/text())[1]',N'varchar(10)') AS OriginalOrderNo
      ,o.value(N'(currency/text())[1]',N'varchar(10)') AS Currency
      ,o.value(N'(taxation/text())[1]',N'varchar(10)') AS Taxation
      ,o.value(N'(invoice-no/text())[1]',N'varchar(10)') AS InvoiceNo
      ,o.value(N'(customer/customer-name/text())[1]',N'varchar(100)') AS CustomerName
      ,o.value(N'(customer/customer-email/text())[1]',N'varchar(100)') AS CustomerEMail
FROM @mockupTable t
CROSS APPLY t.YourXml.nodes(N'/orders/order') A(o);

Помните о необходимости правильно объявлять пространство имен (по умолчанию). Я использовал .nodes(), потому что «заказы» звучат как множественное число. Ваш образец включает только один заказ, но может быть больше ...

ОБНОВЛЕНИЕ: Ваши дополнительные "примечания"

В любом случае отношения 1:n (многие узлы связаны с одним узлом-участником), вам нужно .nodes(), чтобы получить каждый фрагмент в виде отдельной строки:

WITH XMLNAMESPACES(DEFAULT N'www address')
SELECT o.value(N'@order-no',N'varchar(10)') AS OrderNo
      ,o.value(N'(order-date/text())[1]',N'date') AS OrderDate
      ,o.value(N'(created-by/text())[1]',N'varchar(100)') AS CreatedBy
      ,o.value(N'(original-order-no/text())[1]',N'varchar(10)') AS OriginalOrderNo
      ,o.value(N'(currency/text())[1]',N'varchar(10)') AS Currency
      ,o.value(N'(taxation/text())[1]',N'varchar(10)') AS Taxation
      ,o.value(N'(invoice-no/text())[1]',N'varchar(10)') AS InvoiceNo
      ,o.value(N'(customer/customer-name/text())[1]',N'varchar(100)') AS CustomerName
      ,o.value(N'(customer/customer-email/text())[1]',N'varchar(100)') AS CustomerEMail
      ,n.value(N'(created-by/text())[1]',N'nvarchar(100)') AS Note_CreatedBy
      ,n.value(N'(creation-date/text())[1]',N'datetime') AS Note_CreatedBy
      ,n.value(N'(subject/text())[1]',N'nvarchar(100)') AS Note_CreatedBy
      ,n.value(N'(text/text())[1]',N'nvarchar(1000)') AS Note_CreatedBy
FROM @mockupTable t
CROSS APPLY t.YourXml.nodes(N'/orders/order') A(o)
OUTER APPLY A.o.nodes(N'notes/note') B(n);

Последняя строка выберет текущий ордер и передаст его в .nodes(). Это вернет производный набор с одной строкой на <note>.

0 голосов
/ 01 октября 2019

Вы можете использовать OPENROWSET

CREATE DATABASE MyXmlDataBase
GO

USE MyXmlDataBase
GO

CREATE TABLE MyXmlTable
(
Id INT IDENTITY PRIMARY KEY,
Name NVARCHAR(50),
XMLData XML
)

INSERT INTO MyXmlTable(Name, XMLData)
SELECT CONVERT(XML, BulkColumn) AS BulkColumn, GETDATE() 
FROM OPENROWSET(BULK 'D:\MyXmlFileOnDisk.xml', SINGLE_BLOB) AS x;

SELECT * FROM MyXmlTable
...