使用 FOR XML 子句的規則
FOR XML 子句可以使用在最上層的查詢與子查詢中。最上層的 FOR XML 子句只能用在 SELECT 陳述式中。在子查詢中,FOR XML 可以在 INSERT、UPDATE 與 DELETE 陳述式中使用。它也可用在指派陳述式中。例如:
DECLARE @x xml
SET @x = (SELECT *
FROM Sales.Customer
FOR XML AUTO, TYPE)
SELECT @x
請注意,TYPE 指示詞會傳回 xml 類型的查詢結果。若未加入 TYPE 指示詞,就會以 nvarchar(max) 傳回 FOR XML 查詢結果。接著,此結果會轉換為 xml 並指派到 xml 類型的變數。
FOR XML 子句有下列幾項限制:
對於任何使用 COMPUTE BY 或 FOR BROWSE 子句的選取作業,FOR XML 皆無效。例如,以下查詢將會產生錯誤:
SELECT TOP 5 SalesOrderID, UnitPrice FROM Sales.SalesOrderDetail ORDER BY SalesOrderID COMPUTE SUM(UnitPrice) BY SalesOrderID FOR XML AUTO
不含 TYPE 指示詞的最上層 FOR XML 無法與資料指標一起使用。
當包含 FOR XML 子句的 SELECT 陳述式在查詢中指定四個部份的名稱時,若在本機電腦上執行查詢則伺服器名稱並不會隨著 XML 文件的結果傳回。但如果是在網路伺服器上執行查詢,則伺服器名稱是以四個部份的名稱而傳回。
例如,請考量以下的查詢:SELECT TOP 1 LastName FROM ServerName.AdventureWorks.Person.Contact FOR XML AUTO
若
ServerName
是本機伺服器,查詢將會傳回下列結果:<AdventureWorks.Person.Contact LastName="Achong" />
若
ServerName
是網路伺服器,查詢將會傳回下列結果:<ServerName.AdventureWorks.Person.Contact LastName="Achong" />
您可以指定下列別名來避免這種模稜兩可的情況:
SELECT TOP 1 LastName FROM ServerName.AdventureWorks.Person.Contact x FOR XML AUTO
此查詢傳回的內容如下:
<x LastName="Achong"/>
此外,若 SQL Server 名稱中含有對 XML 名稱而言無效的字元 (如空格),則會在轉譯為 XML 名稱時,將其無效字元轉譯為逸出的數值實體編碼。
XML 名稱中只允許兩種非字母字元:冒號 (:) 和底線 (_)。這是因為冒號已保留給命名空間,而底線已被選為逸出字元。以下是適用於編碼的逸出規則:
根據 XML 1.0 規格,任何不屬於有效 XML 名稱字元的 UCS-2 字元,都會逸出為 _xHHHH_。HHHH 代表最高階位元優先順序之字元的四位數十六進位 UCS-2 碼。例如,資料表名稱 Order Details 就編碼為 Order_x0020_Details。
不符合 UCS-2 範圍 (UCS-4 新增的,範圍介於 U+00010000 與 U+0010FFFF 之間) 的字元都會編碼為 _xHHHHHHHH_。在 SQL Server 2000 回溯相容性模式中,HHHHHHHH 代表字元的八位數十六進位 UCS-4 編碼。在其他情況下,字元會編碼為 _xHHHHHH_,以符合 SQL-2003 標準。
除非下一個字元是 x,否則底線字元不需要逸出,例如資料表名稱 Order_Details 就未編碼。
識別碼的冒號也不會逸出,因此命名空間元素及屬性名稱才能夠由 FOR XML 查詢產生。例如,下列查詢所產生的命名空間屬性在名稱中就有冒號:
SELECT 'namespace-urn' as 'xmlns:namespace', 1 as 'namespace:a' FOR XML RAW
此查詢產生以下結果:
<row xmlns:namespace="namespace-urn" namespace:a="1"/>
請注意,建議使用 WITH XMLNAMESPACES 來加入 XML 命名空間。
在 SELECT 查詢中,將任何資料行轉換為二進位大型物件 (BLOB),會使其成為遺失關聯資料表名稱與資料行名稱的暫存實體。而這會使得 AUTO 模式查詢產生錯誤,因為查詢不知道要將此值放入 XML 階層中的哪個位置。例如:
CREATE TABLE MyTable (Col1 int PRIMARY KEY, Col2 binary) INSERT INTO MyTable VALUES (1, 0x7)
由於轉換為二進位大型物件 (BLOB),因此查詢產生錯誤:
SELECT Col1, CAST(Col2 as image) as Col2 FROM MyTable FOR XML AUTO
解決方法是將 BINARY BASE64 選項加入 FOR XML 子句中。若將轉換移除,則查詢會產生預期中的結果:
SELECT Col1, Col2 FROM MyTable FOR XML AUTO
以下是結果:
<MyTable Col1="1" Col2="dbobject/MyTable[@Col1='1']/@Col2" />
在 SQL Server 2000 中,FOR XML 輸出可包含無效的 XML 字元。例如,十六進位值 7 可做為格式字元使用,但在其他情況下通常無法在輸出中當作文字檢視。目前,SQL Server 2005 已可在未使用 TYPE 指示詞的 FOR XML 查詢傳回這類字元時,將這些字元實體化。
雖然不論這些字元是否已實體化,XML 1.0 相容剖析器都會引發剖析錯誤,但實體化格式與 XML 1.1 之間的相容性已有所提升。實體化格式與未來的 XML 標準版本之間也將具有較好的相容性。此外,它還可簡化偵錯作業,因為已可看見無效字元的字碼指標。
對於 XML 工具的使用者,則不需使用任何解決方案,因為無論如何 XML 剖析器都會在資料流中出現無效字元時失敗。若您使用非 XML 工具,則此項變更需要您更新程式設計邏輯,使其搜尋這些做為實體化值的字元。在 SQL Server 2005 中,目前已可透過不同的方式在 FOR XML 查詢中實體化下列空白字元,而在往返過程中加以保留:
- 在元素內容與屬性中:hex(0D) (歸位字元)
- 在屬性內容中:hex(09) (索引標籤)、hex(0A) (換行字元)
若您的應用程式原本設計為處理 SQL Server 2000 輸出 (其中會將這些字元正規化),則會受到影響。SQL Server 2005 輸出現在將會保留這些字元,剖析器不會再加以正規化。