2025年9月25日: PostgreSQL 18 釋出!
支援版本: 當前 (18) / 17 / 16 / 15 / 14 / 13
開發版本: devel
不受支援的版本: 12 / 11 / 10

D.3. XML 限制和 SQL/XML 合規性 #

ISO/IEC 9075-14 (SQL/XML) 中與 XML 相關的規範在 SQL:2006 中引入了重大修訂。PostgreSQL 對 XML 資料型別及相關函式的實現很大程度上遵循 2003 年的早期版本,並借鑑了一些後續版本的內容。特別是

  • 雖然當前標準提供了一系列 XML 資料型別來儲存“文件”或“內容”(包括未型別或 XML Schema 型別的變體),以及一個 XML(SEQUENCE) 型別來儲存任意 XML 內容片段,但 PostgreSQL 只提供了一個 xml 型別,它可以儲存“文件”或“內容”。標準中的“序列”型別在該型別中沒有等效項。

  • PostgreSQL 提供了兩個在 SQL:2006 中引入的函式,但它們使用 XPath 1.0 語言,而不是標準為它們指定的 XML 查詢語言。

  • PostgreSQL 不支援 RETURNING CONTENTRETURNING SEQUENCE 子句。在規範中定義了這些子句的函式,其行為將隱式返回內容。

本節將介紹您可能遇到的一些由此產生的差異。

D.3.1. 查詢僅限於 XPath 1.0 #

PostgreSQL 特有的函式 xpath()xpath_exists() 使用 XPath 語言查詢 XML 文件。PostgreSQL 還提供了標準函式 XMLEXISTSXMLTABLE 的僅限 XPath 的變體,這些函式官方使用 XQuery 語言。對於所有這些函式,PostgreSQL 都依賴於 libxml2 庫,該庫僅提供 XPath 1.0。

XQuery 語言與 XPath 2.0 及更高版本之間存在緊密的聯絡:在兩個版本中語法正確且執行成功的任何表示式都會產生相同的結果(對於包含數字字元引用或預定義實體引用的表示式,XQuery 會將其替換為相應的字元,而 XPath 會保留它們,這是一個小的例外)。但這些語言與 XPath 1.0 之間沒有這種聯絡;XPath 1.0 是一個較早的語言,在許多方面都存在差異。

需要注意兩類限制:標準 SQL 中定義的函式從 XQuery 限制為 XPath,以及標準和 PostgreSQL 特有的函式都將 XPath 限制為 1.0 版本。

D.3.1.1. XQuery 限制為 XPath #

XQuery 超出 XPath 功能的特性包括:

  • XQuery 表示式除了 XPath 的所有可能值之外,還可以構造和返回新的 XML 節點。XPath 可以建立和返回原子型別(數字、字串等)的值,但只能返回輸入到表示式中的文件中已存在的 XML 節點。

  • XQuery 具有用於迭代、排序和分組的控制結構。

  • XQuery 允許宣告和使用區域性函式。

較新的 XPath 版本開始提供與這些功能重疊的能力(例如函式式 for-eachsort、匿名函式以及用於從字串建立節點的 parse-xml),但這些功能在 XPath 3.0 之前不可用。

D.3.1.2. XPath 限制為 1.0 #

對於熟悉 XQuery 和 XPath 2.0 或更高版本的開發者來說,XPath 1.0 會帶來一些需要應對的差異:

  • XQuery/XPath 表示式的基本型別 sequence(可以包含 XML 節點、原子值或兩者兼有)在 XPath 1.0 中不存在。1.0 表示式只能產生一個節點集(包含零個或多個 XML 節點),或者一個原子值。

  • 與可以包含任意所需項且順序任意的 XQuery/XPath 序列不同,XPath 1.0 節點集沒有保證的順序,並且像任何集合一樣,不允許同一項多次出現。

    注意

    libxml2 庫似乎總是將節點集以其在輸入文件中出現的相對順序返回給 PostgreSQL。其文件並未承諾此行為,並且 XPath 1.0 表示式也無法控制它。

  • XQuery/XPath 提供了 XML Schema 中定義的所有型別以及許多針對這些型別的運算子和函式,而 XPath 1.0 僅具有節點集和三個原子型別:booleandoublestring

  • XPath 1.0 沒有條件運算子。XQuery/XPath 表示式如 if ( hat ) then hat/@size else "no hat" 在 XPath 1.0 中沒有等效項。

  • XPath 1.0 沒有字串的順序比較運算子。 "cat" < "dog""cat" > "dog" 都為 false,因為它們是對兩個 NaN 的數值比較。相比之下,=!= 會像字串一樣比較字串。

  • XPath 1.0 模糊了 XQuery/XPath 定義的“值比較”和“一般比較”之間的區別。 sale/@hatsize = 7sale/@customer = "alice" 都是存在量化的比較,如果存在任何 sale 具有給定的屬性值,則為 true。但 sale/@taxable = false() 是對整個節點集的“有效布林值”進行值比較。只有當不存在任何 sale 具有 taxable 屬性時,它才為 true。

  • 在 XQuery/XPath 資料模型中,“文件節點”可以具有文件形式(即,只有一個頂級元素,外部只有註釋和處理指令)或內容形式(這些約束已放寬)。在 XPath 1.0 中,其等效項“根節點”只能是文件形式。這也是為什麼傳遞給任何 PostgreSQL 基於 XPath 的函式作為上下文項的 xml 值必須是文件形式的原因之一。

這裡強調的差異並非全部。在 XQuery 和 XPath 2.0 及更高版本中,存在一個 XPath 1.0 相容模式,W3C 的 函式庫更改在該模式下應用的語言更改 列表更全面地(但仍不詳盡)地說明了這些差異。相容模式不能使後期語言與 XPath 1.0 完全等同。

D.3.1.3. SQL 與 XML 資料型別和值之間的對映 #

在 SQL:2006 及更高版本中,標準 SQL 資料型別與 XML Schema 型別之間的雙向轉換都得到了精確的指定。但是,這些規則是使用 XQuery/XPath 的型別和語義來表達的,並且與 XPath 1.0 的不同資料模型沒有直接應用。

PostgreSQL 將 SQL 資料值對映到 XML(如 xmlelement)或將 XML 對映到 SQL(如 xmltable 的輸出列)時,除了少數特殊處理的情況外,PostgreSQL 僅假設 XML 資料型別的 XPath 1.0 字串形式將作為 SQL 資料型別的文字輸入形式有效,反之亦然。此規則的優點在於簡單性,同時為許多資料型別產生與標準中指定的對映類似的結果。

如果需要與其他系統進行互操作,對於某些資料型別,可能需要顯式使用資料型別格式化函式(例如 第 9.8 節 中的函式)來生成標準對映。

D.3.2. 實現的附帶限制 #

本節涉及的限制並非 libxml2 庫固有的,而是適用於 PostgreSQL 當前實現的限制。

D.3.2.1. 只支援 BY VALUE 傳遞機制 #

SQL 標準定義了兩個“傳遞機制”,它們適用於將 XML 引數從 SQL 傳遞到 XML 函式或接收結果:BY REF,在這種機制下,特定的 XML 值保留其節點身份;以及 BY VALUE,在這種機制下,傳遞 XML 的內容,但節點身份不保留。可以在引數列表之前指定一個機制,作為所有引數的預設機制,或在任何引數之後指定,以覆蓋預設值。

為了說明區別,如果在 SQL:2006 環境中,x 是一個 XML 值,那麼以下兩個查詢將分別產生 true 和 false:

SELECT XMLQUERY('$a is $b' PASSING BY REF x AS a, x AS b NULL ON EMPTY);
SELECT XMLQUERY('$a is $b' PASSING BY VALUE x AS a, x AS b NULL ON EMPTY);

PostgreSQL 會接受 XMLEXISTSXMLTABLE 構造中的 BY VALUEBY REF,但會忽略它們。xml 資料型別儲存的是字串序列化表示,因此沒有需要保留的節點身份,傳遞總是有效地 BY VALUE

D.3.2.2. 無法將命名引數傳遞給查詢 #

基於 XPath 的函式支援傳遞一個引數作為 XPath 表示式的上下文項,但不支援傳遞額外的命名引數供表示式使用。

D.3.2.3. 沒有 XML(SEQUENCE) 型別 #

PostgreSQLxml 資料型別只能儲存 DOCUMENTCONTENT 形式的值。XQuery/XPath 表示式的上下文項必須是單個 XML 節點或原子值,但 XPath 1.0 進一步將其限制為僅限 XML 節點,並且沒有允許 CONTENT 的節點型別。結果是,一個格式正確的 DOCUMENTPostgreSQL 可以作為 XPath 上下文項提供的唯一形式的 XML 值。

提交更正

如果您在文件中發現任何不正確、與您的實際使用經驗不符或需要進一步澄清的內容,請使用 此表單 報告文件問題。