如何从SQL中的xml节点中提取数据

时间:2016-11-09 13:04:44

标签: sql xml xpath sql-server-2008-r2 xquery

下面是我的xml,它记录在数据库表中。

<root>
  <pagelocation>
    <nodeid>3178</nodeid>
      <webpart id="editabletextdescriptio2;b5518b76-9fe6-47d2-8d8b-4ab169d3a127">
            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse non nisl lacus. Donec in rutrum lorem, consectetur semper nunc. 
        </webpart>
    </pagelocation>
    <pagelocation>
        <NodeId>3180</NodeId>
            <webpart id="editabletexttitle;a36d4858-5d61-49b6-a860-221ad0b72310">
                    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse non nisl lacus. Donec in rutrum lorem, consectetur semper nunc. 
            </webpart>
            <webpart id="editabletextdescriptio1;f4873da3-bf3b-43d3-9dc6-cdabfa8c7b6d">
                    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse non nisl lacus. Donec in rutrum lorem, consectetur semper nunc. 
            </webpart>
            <webpart id="editabletextdescriptio2;b5518b76-9fe6-47d2-8d8b-4ab169d3a127">
                        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse non nisl lacus. Donec in rutrum lorem, consectetur semper nunc. 
            </webpart>
      </pagelocation>
</root>

我只需要获取属于的信息 <webpart id="editabletextdescriptio1;f4873da3-bf3b-43d3-9dc6-cdabfa8c7b6d">如何在SQL中编写类似这样的查询

3 个答案:

答案 0 :(得分:1)

如果我说得对(你的#34;只有#34;不清楚),这是一个例子:

DECLARE @xml XML = '
<root>
  <pagelocation>
    <nodeid>3178</nodeid>
      <webpart id="editabletextdescriptio2;b5518b76-9fe6-47d2-8d8b-4ab169d3a127">
            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse non nisl lacus. Donec in rutrum lorem, consectetur semper nunc. 
        </webpart>
    </pagelocation>
    <pagelocation>
        <nodeid>3180</nodeid>
            <webpart id="editabletexttitle;a36d4858-5d61-49b6-a860-221ad0b72310">
                    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse non nisl lacus. Donec in rutrum lorem, consectetur semper nunc. 
            </webpart>
            <webpart id="editabletextdescriptio1;f4873da3-bf3b-43d3-9dc6-cdabfa8c7b6d">
                    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse non nisl lacus. Donec in rutrum lorem, consectetur semper nunc. 
            </webpart>
            <webpart id="editabletextdescriptio2;b5518b76-9fe6-47d2-8d8b-4ab169d3a127">
                        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse non nisl lacus. Donec in rutrum lorem, consectetur semper nunc. 
            </webpart>
      </pagelocation>
</root>'

SELECT n.c.value('@id', 'nvarchar(max)') FROM 
@xml.nodes('/root/pagelocation/webpart') AS n(c)

输出:

editabletextdescriptio2;b5518b76-9fe6-47d2-8d8b-4ab169d3a127
editabletexttitle;a36d4858-5d61-49b6-a860-221ad0b72310
editabletextdescriptio1;f4873da3-bf3b-43d3-9dc6-cdabfa8c7b6d
editabletextdescriptio2;b5518b76-9fe6-47d2-8d8b-4ab169d3a127

答案 1 :(得分:1)

这使用XPath表达式查找具有特定ID的节点。这使用SQL Server中的nodes()函数CROSS APPLY将其应用于表中的XML,并使用value()函数进行选择。

如果你不清楚这是如何工作的:研究SQL Server中的XPath表达式,XPath / XQuery功能以及CROSS APPLY

DECLARE @t TABLE(x XML);
INSERT INTO @t(x)VALUES('<root>
  <pagelocation>
    <nodeid>3178</nodeid>
      <webpart id="editabletextdescriptio2;b5518b76-9fe6-47d2-8d8b-4ab169d3a127">
            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse non nisl lacus. Donec in rutrum lorem, consectetur semper nunc. 
        </webpart>
    </pagelocation>
    <pagelocation>
        <NodeId>3180</NodeId>
            <webpart id="editabletexttitle;a36d4858-5d61-49b6-a860-221ad0b72310">
                    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse non nisl lacus. Donec in rutrum lorem, consectetur semper nunc. 
            </webpart>
            <webpart id="editabletextdescriptio1;f4873da3-bf3b-43d3-9dc6-cdabfa8c7b6d">
                    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse non nisl lacus. Donec in rutrum lorem, consectetur semper nunc. 
            </webpart>
            <webpart id="editabletextdescriptio2;b5518b76-9fe6-47d2-8d8b-4ab169d3a127">
                        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse non nisl lacus. Donec in rutrum lorem, consectetur semper nunc. 
            </webpart>
      </pagelocation>
</root>');

SELECT
    n.v.value('.','NVARCHAR(256)')
FROM
    @t AS t
    CROSS APPLY t.x.nodes('//webpart[@id="editabletextdescriptio1;f4873da3-bf3b-43d3-9dc6-cdabfa8c7b6d"]') AS n(v);

答案 2 :(得分:1)

我理解如下:

  • 此XML(以及许多其他XML)位于多行的表格列中
  • 这些XML中的每一个都有或多或少<webpart>个节点
  • 在一个XML中,@id是唯一的
  • 您想阅读 中的 文本元素

以下代码将在声明的表中插入三行,模拟三种不同的情况。

webpart

- 您要搜索的ID可以定义为参数

DECLARE @tbl TABLE(ID INT IDENTITY,Descritpion VARCHAR(100),XmlColumn XML);
INSERT INTO @tbl VALUES
('Contains the Id'
,N'<root>
    <pagelocation>
        <NodeId>3180</NodeId>
            <webpart id="editabletextdescriptio1;f4873da3-bf3b-43d3-9dc6-cdabfa8c7b6d">
                    Some Content 
            </webpart>
      </pagelocation>
</root>')
,('Does not contain the Id'
,N'<root>
  <pagelocation>
    <nodeid>3178</nodeid>
      <webpart id="editabletextdescriptio2;b5518b76-9fe6-47d2-8d8b-4ab169d3a127">
            Other Content 
        </webpart>
    </pagelocation>
</root>')
,('Multiple IDs, one of them fitting'
,N'<root>
  <pagelocation>
    <nodeid>3178</nodeid>
      <webpart id="editabletextdescriptio2;b5518b76-9fe6-47d2-8d8b-4ab169d3a127">
            id is not correct
        </webpart>
    </pagelocation>
    <pagelocation>
        <NodeId>3180</NodeId>
            <webpart id="editabletexttitle;a36d4858-5d61-49b6-a860-221ad0b72310">
                    Same here 
            </webpart>
            <webpart id="editabletextdescriptio1;f4873da3-bf3b-43d3-9dc6-cdabfa8c7b6d">
                    Yeah! that is is 
            </webpart>
            <webpart id="editabletextdescriptio2;b5518b76-9fe6-47d2-8d8b-4ab169d3a127">
                    One more 
            </webpart>
      </pagelocation>
</root>')

- 此命令首先使用DECLARE @SearchFor NVARCHAR(100)=N'editabletextdescriptio1;f4873da3-bf3b-43d3-9dc6-cdabfa8c7b6d'; 来获取正确的节点,而不是.query()来获取文本内容

.value

- 此命令直接使用SELECT * ,XmlColumn.query('//webpart[@id=sql:variable("@SearchFor")]').value('.','nvarchar(max)') AS Content FROM @tbl; 中的XQuery(更快,第一次出现时停止)

.value()

可以使用SELECT * ,XmlColumn.value('(//webpart[@id=sql:variable("@SearchFor")])[1]','nvarchar(max)') AS Content FROM @tbl (和其他答案一样),但是 - 如果你a)不要指望多行,或者b)想要从一个位置读取不同的值,那就是善意的开销...