簡體   English   中英

如何從SQL中的xml節點中提取數據

[英]How to extract data from xml node in SQL

下面是我的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中編寫類似這樣的查詢

如果我找對你(你的“唯一”不清楚),這是一個例子:

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

這使用XPath表達式查找具有特定ID的節點。 這使用SQL Server中的nodes()函數, CROSS APPLY將其應用於表中的XML,並使用value()函數進行選擇。

如果您不清楚它是如何工作的:研究XPath表達式,SQL Server中的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);

我理解如下:

  • 這個XML(和許多其他XML)存在於許多行的表列中
  • 這些XML中的每一個都有或多或少的<webpart>節點
  • 在一個XML中,@ @id是唯一的
  • 你想讀這給的文本webpart元素

以下代碼將在聲明的表中插入三行,模擬三種不同的情況。

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>')

- 您要搜索的ID可以定義為參數

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;

- 這個命令直接在.value()使用XQuery (更快,在第一次出現時停止)

SELECT *
      ,XmlColumn.value('(//webpart[@id=sql:variable("@SearchFor")])[1]','nvarchar(max)') AS Content
FROM @tbl

可以使用CROSS APPLY .nodes() (就像在其他答案中一樣),但是 - 如果你a)不要指望多行,或者b)想要從一個位置讀取不同的值,它就是一種開銷...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM