XML 支持
过时内容 - XML 支持规划
SQL 数据库中的 XML 支持可以包含很多不同的意思,但通常指以下三种之一
- XML 数据类型和支持函数
- XML 导出格式
- 将 XML 文档映射到 SQL 数据库
前两部分的大多数接口由 ISO/IEC 9075-14(“与 XML 相关的规范” - SQL/XML)编制。自 2006-06-12 起,我们现在可使用 ISO/IEC 9075-14:2006。(这实际上可能不是“SQL:2006”,因为它是在那时发布的唯一 SQL 部分。)IBM DB/2、Microsoft SQL Server、OpenLink Virtuoso、Oracle 和其他一些系统已实施了这些接口,因此遵循该路径有一定的道理。您可以在 http://www.sqlx.org/ 上找到更多有关此标准的信息,尽管已经过时了。
请注意,2006 标准是对 2003 版本(SQL/XML 的第一个版本)的相当大的提升,因此,为了保持我们的理智,最好首先瞄准 2003 版本。
XML 数据类型和支持函数
XML 数据类型可能是“XML 支持”中最有意思的一项。以下是一些有关其工作原理和状态报告的详细信息。
XML 数据类型
实际操作中的 XML 数据类型毫不奇怪地看起来是这样的
CREATE TABLE test ( ..., data xml, ... );
与任何数据类型一样,它具有输入检查和支持功能,使其变得有用。
严格来说,xml类型不接受字符串文本作为输入。将文本字符串转换为 XML 数据并返回的方法是
XMLPARSE ( DOCUMENT|CONTENT value ) --> xml XMLSERIALIZE ( DOCUMENT|CONTENT xmlvalue AS varchar ) --> varchar
这些用作 PostgreSQL 输入/输出函数,周围具有某些语法包装器以支持标准语法。
一个xmldatum 可包含两种类型的值:文档或片段。文档包含报头、根元素和使 XML 文档成型的所有其他内容。片段仅看起来像 XML 语法,但并非(不一定)一个完整的文档。这就是某些语法部分引用DOCUMENT和CONTENT(与片段相同,命名不一致)。
XML 支持函数
SQL 为以下函数式表达式指定了xml数据类型
- XMLCOMMENT
- XMLCONCAT
- XMLELEMENT
- XMLFOREST
- XMLPI
- XMLROOT
- XMLAGG
- IS DOCUMENT, IS NOT DOCUMENT
实际上,这些是经过美化的字符串连接函数,但它们执行所有正确的转义和嵌套,并添加了一些便利功能,用于将 SQL 数据处理成 XML 数据。以下是一些示例
XMLROOT ( XMLELEMENT ( NAME gazonk, XMLATTRIBUTES ( ’val’ AS name, 1 + 1 AS num ), XMLELEMENT ( NAME qux, ’foo’ ) ), VERSION ’1.0’, STANDALONE YES )
这生成以下 XML 文档
<?xml version=’1.0’ standalone=’yes’ ?> <gazonk name=’val’ num=’2’> <qux>foo</qux> </gazonk>
这展示了 SQL 表达式如何像 XML 元素一样嵌套。
这是一个 XML “林”的示例
SELECT xmlforest ( "FirstName" as "FName", "LastName" as "LName", ’string’ as "str", "Title", "Region" ) FROM "Demo"."demo"."Employees";
如果有部分 employees 表中的数据,可能会导致
<FName>Nancy</FName> <LName>Davolio</LName> <str>string</str> <Title>Sales Representative</Title> <Region>WA</Region> ... <FName>Anne</FName> <LName>Dodsworth</LName> <str>string</str> <Title>Sales Representative</Title>
每个这些员工记录都是一个 SQL datum。
由于XMLFOREST的结果是一个xmldatum,你可以将它与XMLELEMENT和其他表达式一起嵌套,以进一步修饰结果。
这是一个使用聚合函数的示例XMLAGG:
SELECT xmlelement (’Emp’, xmlattributes (’Sales Representative’ as "Title"), xmlagg (xmlelement (’Name’, "FirstName", ’ ’, "LastName"))) FROM "Demo"."demo"."Employees" WHERE "Title" = ’Sales Representative’;
这可能会导致
<Emp Title="Sales Representative"> <Name>Nancy Davolio</Name> <Name>Janet Leverling</Name> <Name>Margaret Peacock</Name> <Name>Michael Suyama</Name> <Name>Robert King</Name> <Name>Anne Dodsworth</Name> </Emp>
这里,结果是一个 SQL datum。
SQL/XML 2006
SQL/XML 2006 添加了更多
- 有一个具体 XML 数据类型,不仅允许文档与片段,还允许文档验证
- XML
- XML(DOCUMENT)
- XML(CONTENT)
- XML(SEQUENCE)
- XML(DOCUMENT(ANY))
- XML(DOCUMENT(UNTYPED))
- XML(DOCUMENT(XMLSCHEMA ’http://...’))
- 添加了一些支持函数/表达式
- XMLDOCUMENT
- XMLTEXT
- XMLVALIDATE
- IS CONTENT
- IS VALID
- 在所有意想不到的语法元素中都添加了更多与 XML 相关的选项。这不太好看。
- 添加了 XQuery 支持。
状态
帕维尔·斯蒂胡勒提供的一份支持 SQL/XML 2003 函数的补丁包已可用一段时间。此补丁包不包括 XML 数据类型;它操作存储在文本字段中的 XML 数据。
Nikolay Samokhvalov 的 2006 年 Google 夏日编程代码项目,由 Peter Eisentraut 指导,旨在提供对 SQL/XML 2003 的完整支持。此工作整合并改进了 Pavel Stehule 的补丁。夏日编程代码已结束,一个相当完整的实现已经产生。我们希望尽早将其集成到 8.3 中。
实现问题
如提案中所述,实现使用了著名的 libxml,它获得了 LGPL 授权,因此不会给 PostgreSQL 造成问题。已在某一时刻遇到的某些实现问题(现在可能已经得到解决)是
- 编码处理很奇怪。XML 文档携带有它们自己的编码信息。如果您(比如说)拥有一份自认为是以 UTF-8 编码的文档,并且在 PostgreSQL 客户端/服务器连接(该连接将客户端侧的 UTF-8 转换为服务器上其他内容)中发送该文档,服务器中的 XML 解析器将抱怨。其他组合中也存在类似的情况。目前尚不清楚如何解决此问题。
- libxml 中的内存管理需要仔细处理。libxml 提供了更换挂钩malloc()和free(),这很好,但它似乎想怎样就怎样调用 free 挂钩,如果以其他方式 PostgreSQL 内存管理器已经释放了内存,这可不妙。此问题在错误恢复期间尤为严重。这个问题肯定可以解决,但需要进行验证。
- 此功能在多大程度上应该是强制性的还是可选的?某些构建时选项没问题,但无法轻松使用 ifdef 忽略特殊语法支持。我们需要针对这些情况提供一些可靠的恢复能力。
未来项目
一旦xml类型可用,contrib/xml/中的功能应调整为这些新功能。
很多人提交了夏日编程代码申请,准备实现 CTree 索引。关于这一点的信息不多,但如果您在 Google Scholar 上查看,会发现它是一种适用于 XML 数据的新型索引类型(并不稀奇)。在 XML 类型真正存在之前提出为此工作可能为时过早,但一旦完成,CTree 支持可能是一个有趣的项目。
SQL/XML 2006 要求完全集成 XQuery。Sleepycat 有一个 XQuery 库,我们可以使用该库。(我上次查看时,构建库很麻烦,部署也并不广泛。不过,Sleepycat 的人非常乐意满足 PostgreSQL 的兴趣。不过,那是在他们被收购之前。)但是,重复使用 PostgreSQL 现有的查询计划和执行设施,并将 XQuery 视为 SQL 的并行备选方案似乎更有意义。这是其他一些供应商处理此问题的方法。但是,对于 PostgreSQL 来说,这将是一个大的不敢说范式的转变。
XML 导出格式
每个人都可以创建自己的关系数据 XML 导出格式,并且许多人过去都曾在 PostgreSQL 邮件列表中提出了自己的发明。为了确定一种格式,SQL 标准包含对其进行规范说明。
具体而言,针对以下内容提供规范说明:
- 将 SQL 架构映射到 XML 模式
- 将数据库内容映射到 XML 文档(遵循上述 XML 模式文档)
XML 导出格式可能对以下内容有用:
- 使用 XSLT 进行后处理
- 轻松、自动地将 SQL 数据转换为 XHTML 或 DocBook。
- pg_dump
- 作为通用备份格式?
- psql
- 替换或增强现有的 HTML 支持?
转义
SQL 指定的 XML 导出格式胜过临时定义格式之处在于其完善的转义机制,如下所示
SQL <标识符> | 完全转义的 XML 名称 | 部分转义的 XML 名称 |
---|---|---|
员工 | EMPLOYEE | EMPLOYEE |
"雇员" | 员工 | 员工 |
"入职日期" | hire_x0020_date | hire_x0020_date |
"补偿计划" | comp_x005F_plan | comp_x005F_plan |
"部门:编号" | dept_x003A_id | dept:id |
xmlcol | _xFFFF_xmlcol | xmlcol |
根据实际情况,使用两种不同的转义形式。
模式映射
例如,以下是表定义在 XML 模式中的方式。
CREATE TABLE test (a int PRIMARY KEY, b varchar(200));
<xsd:complexType name="RowType.catalog.schema.test"> <xsd:sequence> <xsd:element name="a" type="INTEGER"></xsd:element> <xsd:element name="b" type="VARCHAR_200_200" minOccurs="0"></xsd:element> </xsd:sequence> </xsd:complexType> <xsd:complexType name="TableType.catalog.schema.test"> <xsd:sequence> <xsd:element name="row" type="RowType.catalog.schema.test" minOccurs="0" maxOccurs="unbounded" /> </xsd:sequence> </xsd:complexType>
数据映射
以下是导出只有一个表的通用数据库的方式
<catalogname> <schemaname> <tablename> <row> <colname1>value</colname1> <colname2 xsi:nil=’true’/> ... </row> ... </tablename> ... </schemaname> ... </catalogname>
元素名称实际上将被相关对象的实际名称替换(因此需要转义)。以上示例中唯一的元素名称文字是行,因为行没有名称。
对于 NULL 处理有多种选择。以上示例使用特殊属性对其进行处理。另一种选择是省略元素。
状态
Peter Eisentraut 为 XML 导出和导入提供了可用原型。导出几乎只是提取目录信息并将其打印出来的勤奋工作。在这个原型中,导入实际上是一个表函数。总的来说,首先拥有 XML 数据类型很有好处,然后才能进一步进行,这样以后不必更改界面。
一个问题是将它放在哪里。
- pg_dump?
- 这将符合“导出”主题,但它可能会限制该功能的灵活性。
- psql?
- 许多之前的建议将工作放在 psql 中,但这似乎不太妥当。
- 用户定义函数?
- 这听起来不错,并且可以很好地与 XML 数据类型支持集成。但我们可能需要一个“流”变体来导出大型表。
将 XML 文档映射到 SQL 数据库
将 XML 文档映射到 SQL 数据库包括解析 XML 文档的层次结构,并使用各自的数据创建相应的互连 SQL 表。SQL 未对此进行规范说明,但数据库理论家肯定已经弄清楚了这一点。
但实际上,这不是特定于 PostgreSQL 的问题,所以解决它并不是真正我们的工作。例如,Perl 模块 DBIx-XML-DataLoader 实现了该功能。