天天看點

《MongoDB管理與開發精要》——3.4節遊标和存儲過程

3.4 遊标和存儲過程

遊标是系統為使用者開設的一個資料緩沖區,用來存放sql語句的執行結果。在資料庫中,遊标是一個十分重要的概念,遊标提供了一種對從表中檢索出的資料進行操作的靈活手段。

存儲過程是一組為了完成特定功能的操作語句集,它可以經編譯後存儲在資料庫中。存儲過程是資料庫中的一個重要對象,使用者通過指定存儲過程的名字并給出參數(如果該存儲過程帶有參數)來執行它。

3.4.1 遊标

每個遊标區都有一個名字,使用者可以用sql語句逐一從遊标中擷取記錄,并賦給主變量,交由主語言進一步處理。遊标實際上是一種能從包括多條資料記錄的結果集中每次提取一條記錄的機制。

跟大多數資料庫産品一樣,mongodb也是用遊标來循環處理每一條結果資料,具體文法如下面的代碼所示:

在本例中,首先聲明了一個遊标c,代表t3表的所有記錄,通過c.hasnext方法判斷是否還有資料,然後将找到的資料通過c.next方法取出來,最後通過printjson方法将結果輸出。

mongodb還有另一種foreach方式來處理遊标,如下面的代碼所示:

這兩種處理方式實作的結果是一樣的,都是要傳回t3表的所有資料,隻是文法上略有不同。

3.4.2 存儲過程

mongodb為很多問題提供了一系列的解決方案,面對其他資料庫的特性,它仍然毫不示弱,表現得非比尋常。mongodb同樣支援存儲過程。

存儲過程可由應用程式通過一個調用來執行,而且允許使用者聲明變量 。同時,存儲過程可以接收和輸出參數、傳回執行存儲過程的狀态值,也可以嵌套調用。關于存儲過程你需要知道的第一件事就是它是用javascript來寫的。也許這會讓你很奇怪,為什麼用javascript來寫,但實際上它會讓你非常滿意。

mongodb存儲過程存儲在db.system.js表中,想象一個簡單的sql自定義函數如下面的代碼所示:

本例中聲明了一個存儲過程addnumbers,實作的功能是加法計算,它接收2個參數,都代表被加數,最後傳回一個相加後的結果。

将這個sql自定義函數轉換為mongodb的存儲過程,隻需要調用db.system.js.save指令即可,它接收2個參數,參數_id代表存儲過程的名字,參數value代表存儲過程的定義,如下面的代碼所示:

存儲過程可以被檢視、修改和删除,用find來檢視是否這個存儲過程已經被建立,如下面的代碼所示:

在本例中通過執行“db.system.js.find”指令獲得了系統中存儲的存儲過程清單,下面來實際調用這個存儲過程,如下面的代碼所示:

通過執行“db.eval”指令調用加法計算的接口,這樣的操作方法太簡單了,也許這就是mongodb的魅力所在。

db.eval()是一個比較奇怪的東西,可以将存儲過程的邏輯直接放在db.eval()的參數裡直接調用,而無需事先聲明存儲過程的邏輯,如下面的代碼所示:

從上面代碼可以看出,mongodb的存儲過程可以友善地完成算術運算,但其他資料庫産品在存儲過程中可以處理資料庫内部的一些事情。例如,取出某張表的資料量等操作,這些mongodb能做到嗎?答案是肯定的,mongodb可以通過在存儲過程的定義裡寫上表級别來實作,如下面的代碼所示:

2

本例中通過定義一個存儲過程“get_count”來統計c1表的記錄條數。可以看到,存儲過程可以很輕松地操作表。

綜上所述,存儲過程有如下優點:

存儲過程用流控制語句編寫,有很強的靈活性,可以完成複雜的判斷和運算。

通過存儲過程可以使相關的動作同時發生,進而維護資料庫的完整性。

降低網絡的通信量。

當企業規則發生變化時,隻在伺服器中改變存儲過程即可,無需修改任何應用程式。企業規則的特點是要經常變化,如果把展現企業規則的運算程式放入應用程式中,當企業規則發生變化時,就需要修改應用程式,工作量非常大(修改、發行和安裝應用程式)。如果把展現企業規則的運算放入存儲過程中,當企業規則發生變化時,隻要修改存儲過程就可以了,應用程式無需任何變化。