选择 打开 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0
历史版本PostgreSQL 9.2 已于 2017 年 11 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本

8.13. XML类型 #

xml 数据类型可用于存储 XML 数据。与把 XML 数据存储在 text 字段中相比,它的优势在于会检查输入值的良构性,并且提供了可执行类型安全操作的支持函数;见 第 9.14 节。使用该数据类型要求构建时使用 configure --with-libxml

xml 类型既可以存储 XML 标准所定义的良构文档,也可以存储内容片段,后者由 XML 标准中的产生式 XMLDecl? content 定义。粗略地说,这意味着内容片段可以拥有多个顶层元素或字符节点。表达式 xmlvalue IS DOCUMENT 可用来判定某个特定的 xml 值是完整文档还是仅仅一个内容片段。

8.13.1. 创建XML值

要从字符数据生成 xml 类型的值,可以使用函数 xmlparse

XMLPARSE ( { DOCUMENT | CONTENT } value)

示例:

XMLPARSE (DOCUMENT '<?xml version="1.0"?><book><title>Manual</title><chapter>...</chapter></book>')
XMLPARSE (CONTENT 'abc<foo>bar</foo><bar>foo</bar>')

按照 SQL 标准,这是把字符串转换为 XML 值的 唯一方法;但 PostgreSQL 特有的下列语法:

xml '<foo>bar</foo>'
'<foo>bar</foo>'::xml

也可以使用。

即使输入值指定了文档类型声明(DTD),xml 类型也不会 根据 DTD 来验证输入值。 目前也没有内置支持可依据其他 XML 模式语言(如 XML Schema) 来执行验证。

反向操作,也就是从 xml 生成字符串值,则使用函数 xmlserialize

XMLSERIALIZE ( { DOCUMENT | CONTENT } value AS type )

type 可以是 charactercharacter varyingtext(或它们的别名)。同样,根据 SQL 标准,这是在 xml 与字符类型之间进行转换的唯一方式,但 PostgreSQL 也允许你直接进行类型转换。

当字符串值在不经过 XMLPARSEXMLSERIALIZE 的情况下与 xml 类型互相转换时, 选择 DOCUMENT 还是 CONTENT 由会话配置参数 XML 选项 决定,可以使用 标准命令设置:

SET XML OPTION { DOCUMENT | CONTENT };

或使用更接近 PostgreSQL 风格的语法

SET xmloption TO { DOCUMENT | CONTENT };

默认值是 CONTENT,因此允许所有形式的 XML 数据。

注意

在使用默认的 XML 选项设置时,如果字符串中包含文档类型声明, 则不能直接把它转换为 xml 类型,因为 XML 内容片段的定义 不接受文档类型声明。如果需要这样做,可以使用 XMLPARSE, 或者更改 XML 选项。

8.13.2. 编码处理

在客户端、服务器以及其间传输的 XML 数据上处理多种字符编码时, 必须格外小心。使用文本模式向服务器发送查询并把查询结果返回给 客户端时(这是通常使用的模式),PostgreSQL 会将客户端与 服务器之间传输的所有字符数据转换为目标端的字符编码,参见 第 22.3 节。这也包括表示 XML 值的字符串,如上例 所示。这通常意味着,由于字符数据在客户端和服务器之间传输时可能被 转换为其他编码,XML 数据中包含的编码声明可能会失效,因为内嵌的 编码声明本身并不会被修改。为处理这种情况,表示 xml 类型输入值的字符串中所包含的编码声明会被 忽略,其内容被假定为当前服务器编码。因此, 为了正确处理,客户端发出的 XML 数据字符串必须采用当前客户端编码。 客户端负责在将文档发送给服务器之前把它们转换为当前客户端编码, 或适当调整客户端编码。输出时,xml 类型值不会带有 编码声明,而客户端应假定所有数据都采用当前客户端编码。

若使用二进制模式把查询参数传给服务器并把查询结果返回客户端, 则不会执行字符集转换,因此情况有所不同。在这种情况下,XML 数据中的 编码声明会被识别;如果缺少编码声明,则该数据会被假定为 UTF-8 (由于 XML 标准的要求,请注意 PostgreSQL 不支持 UTF-16)。 输出时,除非客户端编码是 UTF-8(此时编码声明会被省略),否则 数据会带有一个指明客户端编码的编码声明。

不言而喻,在 PostgreSQL 中处理 XML 数据时,如果 XML 数据编码、客户端编码和服务器编码三者相同, 不仅更高效,也更不容易出错。由于 XML 数据在内部以 UTF-8 处理, 如果服务器编码也是 UTF-8,则处理效率最高。

小心

当服务器编码不是 UTF-8 时,某些与 XML 相关的函数在非 ASCII 数据上可能完全无法工作。尤其是 xpath(),这是一个已知问题。

8.13.3. 访问XML值

xml 数据类型有些特殊,因为它不提供任何比较操作符。 这是因为对 XML 数据并不存在良定义且通用的比较算法。其结果是, 你无法通过把某个 xml 列与搜索值比较来检索行。 因此,XML 值通常应伴随一个独立的键字段,例如 ID。另一种比较 XML 值的办法,是先把它们转换成字符串;但请注意,字符串比较对 XML 的比较需求通常帮助不大。

由于 xml 数据类型没有可用的比较操作符,因此无法直接 在这种类型的列上创建索引。如果需要在 XML 中快速搜索,可行方案包括: 将表达式转换为字符串类型后为其建立索引,或者为某个 XPath 表达式 建立索引。当然,实际查询也必须相应调整为使用该被索引的表达式。

PostgreSQL 的文本检索功能也可用于加速 XML 数据的全文检索。不过,目前 PostgreSQL 发行版中仍缺少所需的 预处理支持。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。