簡介
PHP 支持簡單的 Web 應用程序開發和部署環境。這是它得到普遍應用的原因之一。DB2 9的原生 XML 功能進一步簡化了開發過程。這種簡化體現在以下方面:
- 應用程序代碼較少,復雜性降低
- 較簡單的關系模式
- 更好地管理因為更改業務需要而發生的模式演化
在本文中,我們將在該基礎上進行構建並說明使用
DB2 原生 XML 功能簡化應用程序代碼和關系模式的有效性。還將講述業務需求更改對數據的影響(模式演化)以及對應用程序代碼和關系模式的影響。
為了說明我們的推理,將通過一個模擬在線商店的使用情景來進行說明,該商店向注冊客戶出售古董銀器。
我們將在該情景中說明的一些要點包括:
設置 PHP 環境的容易程度將 DB2 原生 XML 功能與 PHP 應用程序(包括用 PHP 和 XQuery 編寫的 Web 服務)集成的容易程度使用 XQuery、存儲過程和視圖將業務邏輯和數據轉換放到數據庫中。在該情景中使用的
DB2 XML 功能將包含以下方面:
按分列結構在列中存儲 XML 文檔使用 XQuery 進行搜索和發布在 DB2 存儲過程和視圖中支持 XML使用 XML 索引提高性能
為突出使用 DB2 原生 XML 支持對 PHP 應用程序代碼和關系模式設計的影響,該情景將創建一個並行環境,該環境使用不包含任何 XML 功能的數據庫(例如,MySQL)。我們將研究這兩個環境在應用程序代碼、數據庫查詢和關系模式方面的差異。還將說明選擇特定代碼、模式或查詢以及備選方案(如果可能)的理由。
情景
該情景模擬向注冊客戶出售古董銀器的在線商店。因為該情景的一個目的是說明不同的數據庫環境以及它們對應用程序代碼的影響,所以我們將對兩個應用程序進行同時說明,一個應用程序使用 DB2 原生 XML,另一個應用程序使用類似 MySQL 的開放源碼 RDMS,具有有限的 XML 功能或沒有任何 XML 功能。
因此,訪問 Web 站點的客戶將看到一個包含兩個垂直面板的頁面。每個面板都將顯示同一應用程序的一個版本,提供相同的用戶體驗,但在後端使用不同的數據庫:
具有原生 XML 支持的 DB2其他 RDBMS(在本例中為不使用任何 XML 功能的 DB2)
為顯示應用程序代碼的差異,每個面板進一步分為兩個水平框架,上面的框架顯示在線商店,下面部分顯示代碼段。當用戶進行任何操作(如單擊某一種類或產品圖像)時,上面部分都會生成一個新頁面。下面部分顯示創建此頁面所需的代碼。
圖 1. 示例應用程序面板
這將說明,雖然在任何一個應用程序中用戶的體驗沒有變化,但代碼復雜性發生了很大變化。這種對比將突出用 PHP 編寫的普通 SMB 應用程序使用 DB2 原生 XML 功能的好處。
注意:我們對此情景的假設是業務數據已經是 XML 格式的,盡管數據庫可能沒有任何 XML 功能。這將產生可用於數據庫的使用 XML 功能的 PHP 應用程序代碼(如簡單 DOM)。具有有限 XML 功能或無 XML 功能的數據庫將 XML 數據存儲為 CLOB/BLOB 數據類型,或分割到關系字段中。
在 Web 站點中浏覽時的功能和用戶體驗
Web 站點將為用戶提供索引,列出商店中所有可用銀器的種類和品牌。用戶單擊某一種類或品牌時,將顯示該種類或品牌的貨品列表。選擇列表中的任何貨品都會在頁面中顯示該貨品的詳細信息。用戶可以將這些貨品添加到購物車中。一旦用戶提交了訂單,將會創建采購訂單並根據此采購訂單向用戶提供發票。用戶可以隨時檢查購物車中的貨品。用戶還能夠得到他們過去已訂購的所有貨品的報告。
應用程序體系結構
圖 2 顯示了示例應用程序的基本體系結構。
圖 2. 應用程序體系結構
關系和 XML 模式
XML 文檔和模式
原生 XML 存儲不需要 XML 列與特定 XML 模式關聯。需要對插入到數據庫中的 XML 文檔進行的任何驗證都在插入語句中使用 SQL/XML 函數顯式地進行。附錄中包含 XML 文檔示例。
每個產品的圖像 URL 需要存儲在單獨的圖像表中:
$images = array();
foreach($dom->description->images->image as $image) {
switch((string) $image[type']) {
case thumbnail':$prodImgThumb = (string) $image;
$prodImgAlias = (string) $image[alias'];
if(!$prodImgAlias) $prodImgAlias = NULL;
$stmt = db2_prepare($conn, "INSERT INTO sqlimages (Pid, Type, Alias, Location) VALUES (?, ?, ?, ?)");
db2_execute($stmt, array($prodID, thumbnail', $prodImgAlias, $prodImgThumb));
case full':
$prodImgFull = (string) $image;
$prodImgAlias = (string) $image[alias'];
if(!$prodImgAlias) $prodImgAlias = NULL;
$stmt = db2_prepare($conn, "INSERT INTO sqlimages (Pid, Type, Alias, Location) VALUES (?, ?, ?, ?)");
db2_execute($stmt, array($prodID, full', $prodImgAlias, $prodImgFull));
}
}
當前實現 ibm_db2 驅動程序不能適當地將 NULL 變量作為參數來處理,以便執行函數;因此我們使用一個非強制性解決方案:
if(!$prodBrand) $prodBrand = " ";
if(!$prodCategory) $prodCategory = " ";
if(!$prodImgFull) $prodImgFull = " ";
現在保存產品表中的產品信息:
$stmt = db2_prepare($conn, "INSERT INTO sqlproduct (Pid, Name, Details, Brand,
Category, Price, Weight, Size, Description) VALUES
(?, ?, ?, ?, ?, ?, ?, ?, ?)");
db2_execute($stmt, array($prodID, $prodName,
$prodDetails, $prodBrand, $prodCategory,
$prodPrice, $prodWeight, $prodSize, $fileContents));
創建主頁
主頁包含在線商店中所有可用產品的種類和品牌的索引。索引的右邊區域顯示所有貨品的列表。
圖 5. 主頁
創建種類和品牌的索引列表
索引通過查詢數據庫中所有產品的惟一種類和品牌的列表而創建。啟動應用程序時將創建此列表。
DB2 Viper
- 首先創建 DB2 視圖,以使用 XQuery 列出種類,XQuery 在所有產品中循環並返回所有惟一種類:
CREATE VIEW CategorIEs(Category) AS SELECT DISTINCT(XMLCAST(
XMLQUERY(for $i in $t/product/description/category return $i'
PASSING BY REF T.DESCRIPTION AS "t" RETURNING SEQUENCE)
AS VARCHAR(128))) FROM
XMLproduct AS t
- 現在從應用程序調用該視圖:
$stmt = db2_exec($conn, "SELECT * FROM CategorIEs");
while(list($cat) = db2_fetch_array($stmt)) {
echo "$cat
"; }
非 XML RDBMS
從產品表創建種類的惟一列表:
$stmt = db2_exec($conn, "SELECT DISTINCT(category) FROM SQLPRODUCT");
while(list($cat) = db2_fetch_array($stmt)) {
echo "$cat
";}
這兩種情況中的應用程序代碼相似。創建 XML 數據視圖使我們可以輕松地查詢視圖,從而有助於從應用程序代碼理解產品 XML 的結構。需要更改視圖中的 XQuery 以查找品牌元素,同樣 SQL 調用也需要查看 Brand 列。
模式演化對索引列表的影響
根據客戶反饋,我們需要允許用戶浏覽站點,以查找鍍銀的貨品或由純銀制造的貨品。我們看一下向索引中添加子種類對以下各項的影響:XML 模式、關系模式、查詢和 PHP 應用程序代碼。
對 XML 模式和文檔實例的影響
向產品 XML 模式中的種類元素添加新屬性(catx)。產品的所有新 XML 文檔現在都用純銀或鍍銀適當地填充了此屬性:
Miscellaneous
對關系模式的影響
- DB2 Viper
這將不需要對關系模式進行任何更改,因為 XML 文檔存儲在單個列中。
- 非 XML RDBMS
在基本關系數據庫中,將需要更改產品表的模式,添加名為 catx 的另一列。這可能涉及刪除並重新插入所有產品文檔。
對查詢的影響