2011-02-10 65 views
1

我在寫一個基於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列表。

+1

等等,什麼?你能否只提取一次數據,並將其與原始XML一起保存在數據庫中?將XML和數據庫結合起來......瘋狂的謊言就是這樣。 (或者我誤解了這個問題 - 你能詳細解釋一下嗎?) – Piskvor 2011-02-10 21:05:25

+0

查看我的更新以獲得我在表中使用XML數據的意向。 XML文檔是爲數據庫中的各種值的結構化存儲而構建的,它不是來自外部的,而是應該按原樣存儲。 – ygoe 2011-02-11 18:48:35

回答

1

如果你努力爭取數據庫獨立性,那麼在你的數據庫中存儲XML會給你的抽象層帶來相當大的負擔,因爲每個DBMS都會以不同的方式處理它。這並不是說它不能完成,但是你將不得不在許多支持的數據庫中研究XML功能(或缺少它)。 (我認爲SQLite根本不具備任何XML功能......)

如果您絕對必須使用XML,XQuery幾乎是查詢原始XML的理想方法,但它不受關係數據庫支持。 SQL/XML是查詢XML的標準之一,但尚未廣泛實施。

否則,在表中存在大量空值並沒有什麼壞處。假設您的應用程序代碼將不得不檢查空值,無論它們來自數據庫表還是來自不存在的XML元素...

1

我會遠離DB提供的XML功能,並將任何XML存儲爲BLOB。這可能意味着你必須複製一些數據;基本上你想查詢的任何東西。如果你想讓它全部可查詢,那麼使用原生XML數據庫會更好。

XML擴展的原因往往只是眼光,即使服務器解析XML,它仍然需要通過線路發送它;再次被解碼或解析。因此,最好將它作爲字節序列進行流式處理,並在客戶端處理解析。唯一的例外是如果你想使用基於XML的訪問方法(xpath或xquery查找);但這就是原生XML數據庫比關係數據庫更適合的地方(「豬的口紅」)。最後,一個更常見的雙重設置是將數據庫與搜索索引系統(如Lucene,Elastic Search)結合起來,而不是將XML和關係數據庫組合起來;這爲您提供了強大的自由文本搜索以及存儲。搜索索引然後在數據庫中的數據被修改時遞增更新。

相關問題