【问题标题】:How do I select data from a XML column on SQL Server?如何从 SQL Server 上的 XML 列中选择数据?
【发布时间】:2019-10-01 13:07:54
【问题描述】:

如何在 SQL Server Management Studio 中从 SQL Server 表的 XML 列中选择数据?

我想得到这个结果:

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>

我有最后一个问题(我希望);)

如何从 product-lineitems 返回数据。我的意思是:数量,数量单位

我正在尝试这样:但它返回重复的行:(

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)

'看起来你的帖子主要是代码;请添加更多详细信息' '看起来你的帖子主要是代码;请添加更多详细信息' '看起来你的帖子主要是代码;请添加更多详细信息'

【问题讨论】:

  • 总是最好包含期望的结果?它会消除假设,例如您是在寻找列还是行?
  • "如何在 sql server management studio 上从 xml 文件中选择数据?" SSMS 只是一个用于对 SQL Server 实例执行操作的应用程序(通常使用 SQL) .您不使用 SSMS 来读取您使用 SQL Server 执行此操作的文件(我假设为行)。 SSMS 本身没有要连接的 SQL Server 实例,无法从 XML 文件中“选择”数据。在这种情况下,您需要编写一个使用 XQUERY 的 SQL 语句。
  • 我正在寻找行
  • “我正在寻找行” 但是 order-date 显然是 datecreated-byvarchar。同一列中不能有不同的数据类型。你能告诉我们(在你的问题中)你期望你的最终结果集是什么样的吗?你自己的尝试也会很有帮助。
  • 不,order-date 和 created-by 用于区分列。抱歉,我没听懂您的上一篇文章...我的英文是...:/所以我在看专栏

标签: sql sql-server xml xml-parsing


【解决方案1】:

你可以这样试试:

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(),因为“orders”听起来像复数。您的样品仅包含一份订单,但可能还有更多...

更新:您的附加“注释”

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()。这将返回一个派生集,每个 &lt;note&gt; 有一行。

【讨论】:

  • 它正在工作,但我在我的主帖' 中添加了一些 xml 数据,现在我只从 notes->note 获得第一个数据。但我想从列中获取所有数据。
  • 得到他们每个人
  • @ThomasTl 查看我的更新。并且请下次:与其改变原来的问题,不如开始一个新的问题。这将有助于未来的研究人员找到接近问题的接近答案,并避免所谓的变色龙问题...
  • 哇,你是最棒的 ;) 非常抱歉多次编辑我的主帖 :( 你说得对 - 我的第一篇文章应该是开头。
  • @ThomasTl 没关系,SO-police 有时对新手有点苛刻 :-) 编辑 OP 以添加细节或清除内容是可以的,但您不应该更改问题本身(在这种情况下:问题的结构)......快乐编码! (哈!我刚刚检查过你根本不是新来者 :-))
【解决方案2】:

你可以使用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

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-11
  • 1970-01-01
  • 1970-01-01
  • 2021-09-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多