資料庫表單的多層分類搜尋 - 資料庫連結與遞迴篇

遞迴篇

  這個需求是在大鳥需要的拍賣網站會用到,其實一般搜尋引擎也常常會用類似這種「搜尋此分類下所有項目」的功能。


  不過這篇不是講如何搜尋,而是要抓出分類之下的所有次分類,有了所有的分類之後,再下搜尋語法就沒什麼困難了。

我們先來定義一個簡單的分類結構範例:

女性用品 ->保養品 ->臉部
->身體
--------------------------------------------------------------------------------
->背包 ->水餃包
->側揹包
->方包

  資料庫規畫上,每個分類只要記住自己屬於誰之下(也就是上一層的分類) 就可以了。

範例:


資料庫:CATA
欄位1 :NAME (分類名稱)
欄位2 ARENT (上層分類名稱)

  再來我們的目的主要是列出某個分類之下所有的分類清單,像是我要抓出「背包」之下的所有分類,只要執行 getSubs("背包"),即可回傳 "水餃包","側揹包","方包"

(以下語法範例為 php + adodb 遞迴)

function getSubs($n)

{
global $conn, $subs;
sql = "SELECT NAME FROM CATA WHERE PARENT=".$n ;
$rs = &$conn->Execute($sql);
$subs.= $n.", ";
while ($rs && !$rs->EOF)
{
$nextname = $rs->fields["NAME"];
getSubs($i); //開始遞迴:
$rs->MoveNext();
}
}


這樣就完成這個功能了。

  使用遞迴雖然很方便,但要注意遞迴的原罪,在層數太多時,系統 Loading 會加重,而且在伺服器記憶體不夠的狀況下,非常容易產生 Stack Overflow ,造成整台伺服器突然就當在那邊了。

  如果需要的層數很多、伺服器記憶體又小的話,在下一篇我將介紹另一種方法來達到同樣的功能,而且一點都不複雜喔!

 
資料庫連結篇
 
  上一次我介紹了多層目錄的遞迴演算法,其實這已經是基礎中的基礎了。但是在不得已的硬體限制下,或許有另一種寫作簡單方式,讓我現在來告訴大家。


  當伺服器主機記憶體不足時,通常會把硬碟當記憶體用,但是這樣是極端耗費系統資源的,別忘了伺服器還有可能當 Web Server、Email Server 使用,在多使用者重覆達行遞迴程式時,那可是不容小看的負擔。

於是,我們就利用資料庫的空間來換取記憶體空間。怎麼說呢?其實很簡單,只要在資料庫加一個欄位,記錄自己所有的上層目錄即可。同樣以上次的範例,我再來解說一次:

女性用品 ->保養品 ->臉部

->身體
--------------------------------------------------------------------------------
->背包 ->水餃包
->側揹包
->方包
資料庫:CATA
欄位1 :NAME (分類名稱)
欄位2 ARENT (上層分類名稱)
欄位3 ARENT_LINK (所有上層分類名稱)

  PARENT_LINK 記載的就是自己所有的上層目錄,以「方包」為例,方包的PARENT_LINK 就是:
"女性用品,背包"

  當每個分類的 PARENT_LINK 都建好之後,我要找「背包」之下所有的分類名稱時,只要下一段 SQL Command:

SELECT NAME FROM CATA WHERE PARENT_LINK LIKE '%背包%'

這樣是不是簡單很多,相信連初學者都看的懂。^_^

  使用這個方法雖然方便,但同時也有一個缺點。就是 PARENT_LINK 的維護相當不容易,當所有分類有任何變動時,必須同時去更新每一個分類的 PARENT_LINK,才能確保這個分類的連結是正確的,這樣程式寫起來或許比遞迴還要多。

  當然使用遞迴或這個方法各有優缺,就看您自己的需求而定囉!

參考資料:
http://www.neo.com.tw/archives/105
http://www.neo.com.tw/archives/109

留言

這個網誌中的熱門文章

用PHP寄MAIL的方法

ImageMagick應用大全(一)

php安裝openssl的方法