分享方式:


value() 方法(xml 資料類型)

適用於:SQL Server Azure SQL 資料庫 Azure SQL 受控執行個體

對 XML 執行 XQuery,並傳回 SQL 類型的值。 此方法會傳回純量值。

通常您會使用此方法,從儲存在 xml 類型資料行、參數或變數中的 XML 執行個體擷取值。 如此一來,您可以指定 SELECT 結合或比較 XML 資料與非 XML 資料行中資料的查詢。

語法

value ( XQuery , SQLType )

引數

XQuery

XQuery 表達式是字串常值,可擷取 XML 實例內的數據。 XQuery 最多只能傳回一個值。 否則,就會傳回錯誤。

SQLType

要傳回的慣用 SQL 類型,字串常值。 此方法的傳回類型符合 SQLType 參數。 SQLType 可以是使用者定義的 SQL 資料類型。

注意

SQLType 不能是下列其中一種數據類型:xml、imagetext、ntextsql_variant或 Common Language Runtime (CLR) 使用者定義型別。

方法會 value() 隱含使用 Transact-SQL CONVERT 運算符。 value() 會嘗試將 XQuery 運算式的結果、串行化的字串表示,從 XML 架構定義 (XSD) 類型轉換為 Transact-SQL 轉換所指定的對應 SQL 類型。 如需 類型轉換規則 CONVERT的詳細資訊,請參閱 CAST 和 CONVERT

基於效能考慮,您可以搭配 使用 exist()sql:column() 而不是 value() 在述詞中使用 方法,以與關係型值進行比較。 本文稍後會顯示此 exist() 範例。

範例

本文 Transact-SQL 程式碼範例使用 AdventureWorks2022AdventureWorksDW2022 範例資料庫,從 Microsoft SQL Server Samples 和 Community Projects (Microsoft SQL Server 範例和社群專案)首頁即可下載。

A. 針對 XML 類型變數使用 value() 方法

在下列範例中,XML 實例會儲存在 xml 類型的變數中。 value() 方法會從 XML 擷取 ProductID 屬性值, 該值接著會指派給 int 變數。

DECLARE @myDoc XML;
DECLARE @ProdID INT;

SET @myDoc = '<Root>
<ProductDescription ProductID="1" ProductName="Road Bike">
<Features>
  <Warranty>1 year parts and labor</Warranty>
  <Maintenance>3 year parts and labor extended maintenance is available</Maintenance>
</Features>
</ProductDescription>
</Root>';

SET @ProdID = @myDoc.value('(/Root/ProductDescription/@ProductID)[1]', 'int');
SELECT @ProdID;

因此,傳回 的值 1

雖然 XML 實例中只有一個 ProductID 屬性,但靜態輸入規則會要求您明確指定路徑表達式會傳回單一屬性。 因此,會將 [1] 新增至路徑表達式的結尾。 如需靜態類型的詳細資訊,請參閱 XQuery 與靜態類型

B. 使用 value() 方法從 XML 類型資料行擷取整數值

下列查詢是針對 AdventureWorks2022 資料庫中的 xml 類型資料行 (CatalogDescription) 所指定。 此查詢會從儲存在資料行中的每一個 XML 執行個體擷取 ProductModelID 屬性值。

SELECT CatalogDescription.value(
    'declare namespace PD="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
       (/PD:ProductDescription/@ProductModelID)[1]', 'int') AS Result
FROM Production.ProductModel
WHERE CatalogDescription IS NOT NULL
ORDER BY Result DESC;

上一個查詢的附註:

  • namespace 關鍵字是用來定義命名空間前置詞。

  • 根據靜態類型需求,會在 [1] 方法的路徑運算式結尾加入 value(),以明確指出路徑運算式會傳回單一值。

結果集如下所示。

35
34
28
25
23
19

C. 使用 value() 方法從 XML 類型資料行擷取字串值

下列查詢會針對資料庫中的 xml 類型資料列 (CatalogDescriptionAdventureWorks2022 指定。 此查詢會從儲存在資料行中的每一個 XML 執行個體擷取 ProductModelName 屬性值。

SELECT CatalogDescription.value(
    'declare namespace PD="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
       (/PD:ProductDescription/@ProductModelName)[1]', 'varchar(50)') AS Result
FROM Production.ProductModel
WHERE CatalogDescription IS NOT NULL
ORDER BY Result DESC;

上一個查詢的附註:

  • namespace 關鍵字是用來定義命名空間前置詞。

  • 根據靜態類型需求,會在 [1] 方法的路徑運算式結尾加入 value(),以明確指出路徑運算式會傳回單一值。

結果集如下所示。

Touring-2000
Touring-1000
Road-450
Road-150
Mountain-500
Mountain 100

D. 使用 value() 和 exist() 方法來從 XML 類型數據行擷取值

下列範例顯示如何使用 xml 資料類型的 value() 方法和 exist() 方法。 value() 方法是用於擷取 XML 中的 ProductModelID 屬性值。 exist() 子句中的 WHERE 方法則是用於篩選資料表中的資料列。

此查詢會從將保固資訊 (<Warranty> 元素) 作為功能之一的 XML 執行個體中,擷取產品型號識別碼。 WHERE 子句中的條件會使用 exist() 方法,只擷取滿足此條件的資料列。

SELECT CatalogDescription.value(
    'declare namespace PD="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
           (/PD:ProductDescription/@ProductModelID)[1]', 'int') AS Result
FROM Production.ProductModel
WHERE CatalogDescription.exist(
    'declare namespace PD="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
     declare namespace wm="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelWarrAndMain";

     /PD:ProductDescription/PD:Features/wm:Warranty') = 1;

上一個查詢的附註:

  • CatalogDescription 資料行是具類型的 XML 資料行。 這表示它有相關聯的結構描述集合。 在 Modules 和 Prologs - XQuery Prolog 中,命名空間宣告是用來定義稍後在查詢主體中使用的前置詞。

  • exist()如果方法傳1回 (true),表示 XML 實例包含<Warranty>子專案做為其中一項功能。

  • value() 子句中的 SELECT 方法就會擷取 ProductModelID 屬性值做為整數。

部分結果如下:

19
23
...

E. 使用 exist() 方法,而不是 value() 方法

基於效能的考量,不要在述詞中使用 value() 方法來與關聯式值做比較,而是使用 exist() 搭配 sql:column() 進行比較。 例如:

CREATE TABLE T (c1 INT, c2 VARCHAR(10), c3 XML);
GO

SELECT c1, c2, c3
FROM T
WHERE c3.value('(/root/@a)[1]', 'integer') = c1;
GO

此程式代碼可以重寫,如下所示:

SELECT c1, c2, c3
FROM T
WHERE c3.exist('/root[@a=sql:column("c1")]') = 1;
GO