在不同的DBMS中提取XML数据的最佳方法?
我在写一个基于PHP的Web应用程序,它使用PDO连接到多个数据库后端。目前它们是MySQL 5.1+,SQLite 3.6+和PostgreSQL 8/9。其他系统稍后可能会添加,因为他们理解我的SQL查询的程度还不错,或者查询可以通过我的抽象层进行转换。在不同的DBMS中提取XML数据的最佳方法?
现在我想以XML格式将日志数据存储在数据库中,因为这些日志事件的结构高度依赖于事件的类型。大多数情况下,大多数列为空时,我不想为任何可能的日志信息添加单独的列。
但是我怎样才能从数据库中取回数据呢?我需要一种一致的方式在SELECT查询中从XML文档中提取数据。我知道MySQL的ExtractValue()函数,我也可以通过PDO向SQLite添加一个UDF(用户定义的函数)。但是我还没有发现任何与PostgreSQL类似的东西。然后我不知道哪种方式最适合在所有DBMS中获得XML支持以用于相同的SQL查询。有没有人有解决方案或最佳做法?
更新:这里有这样的日志记录的例子:
Num | Time | EventId | UserId | Data
1 | 2011-02-... | 1 | 42 | <data><messageid>123</messageid></data>
2 | 2011-02-... | 2 | 43 | <data><messageid>123</messageid></data>
3 | 2011-02-... | 23 | 7 | <data><oldname>006</oldname><newname>007</newname></data>
凡EVENTID描述了发生的事情,比如锁定或解锁的消息,或重命名用户的事件。我可能想要查询/ data/messageid(以及设置该XML值的适当的EventIds)来查找所有关于特定消息的事件,这些消息是我想绘制的管理历史记录。
它不像整个网页那样大的XML文档,只是一个很好的结构化方式来保留所有那些没有专用表格列的值。而且它是可扩展的,所以如果我想象一个新的EventId编号,我可以用这个事件存储任何数据块。决不会将XML值的条件作为我查询的唯一条件。首先应该按照其他标准缩小(大部分)行,如时间跨度或EventId列表。
如果你努力争取数据库独立性,那么在你的数据库中存储XML会给你的抽象层带来相当大的负担,因为每个DBMS都会以不同的方式处理它。这并不是说它不能完成,但是你将不得不在许多支持的数据库中研究XML功能(或缺少它)。 (我认为SQLite根本不具备任何XML功能......)
如果您绝对必须使用XML,XQuery几乎是查询原始XML的理想方法,但它不受关系数据库支持。 SQL/XML是查询XML的标准之一,但尚未广泛实施。
否则,在表中存在大量空值并没有什么坏处。假设您的应用程序代码将不得不检查空值,无论它们来自数据库表还是来自不存在的XML元素...
我会远离DB提供的XML功能,并将任何XML存储为BLOB。这可能意味着你必须复制一些数据;基本上你想查询的任何东西。如果你想让它全部可查询,那么使用原生XML数据库会更好。
XML扩展的原因往往只是眼光,即使服务器解析XML,它仍然需要通过线路发送它;再次被解码或解析。因此,最好将它作为字节序列进行流式处理,并在客户端处理解析。唯一的例外是如果你想使用基于XML的访问方法(xpath或xquery查找);但这就是原生XML数据库比关系数据库更适合的地方(“猪的口红”)。最后,一个更常见的双重设置是将数据库与搜索索引系统(如Lucene,Elastic Search)结合起来,而不是将XML和关系数据库组合起来;这为您提供了强大的自由文本搜索以及存储。搜索索引然后在数据库中的数据被修改时递增更新。
等等,什么?你能否只提取一次数据,并将其与原始XML一起保存在数据库中?将XML和数据库结合起来......疯狂的谎言就是这样。 (或者我误解了这个问题 - 你能详细解释一下吗?) – Piskvor 2011-02-10 21:05:25
查看我的更新以获得我在表中使用XML数据的意向。 XML文档是为数据库中的各种值的结构化存储而构建的,它不是来自外部的,而是应该按原样存储。 – ygoe 2011-02-11 18:48:35