最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網 會員登陸 & 注冊

[sql雜談]我們是否還一定應該使用存儲過程

2019-10-28 22:22 作者:游戲理想國  | 我要投稿



SQL是一種語言,用來聲明在數據庫上想要執(zhí)行的操作(查詢,更新或管理等)。數據庫引擎得到的均是文本,就像C#源代碼要由編譯器處理一樣,SQL源碼也要必須通過某種方式的編譯,以便生成一系列的底層數據庫操作,這個輸出就叫著執(zhí)行計劃。從概念角度考慮,生成執(zhí)行計劃的過程可以看做是程序編譯的過程。


所謂的存儲過程要比普通SQL有性能提升體現(xiàn)在對執(zhí)行計劃的重用上。換句話說,第一執(zhí)行存儲過程時,數據庫將生成執(zhí)行計劃。然后執(zhí)行代碼。下一次執(zhí)行的時候即可重用前面已經生成的執(zhí)行計劃,因此效率上會有提高。所有的SQL命令都需要執(zhí)行計劃。


這個(錯誤的)會議聲明,數據庫僅會重用存儲過程的執(zhí)行計劃。不過在SQL Server和Oracle數據庫(我們對其它產品也并不十分的了解)中,重要執(zhí)行計劃將會應用到任何SQL語句上。下面是SQL Server2005在線文檔中的一段引用。


在SQL Server2005執(zhí)行任何 SQL語句時,關系引擎首先查看緩存,判斷其中是否有當前SQL的執(zhí)行計劃。SQL Server2005將重用任何可行的執(zhí)行計劃,以便減小重新編譯SQL語句對性能上的影響。若沒有找到現(xiàn)有的執(zhí)行計劃,SQL Server2005才會為當前查詢生成新的執(zhí)行計劃。


因此,當前強調存儲過程要比簡單的SQL代碼更高效的爭論就沒有任何意義了。從性能角度考慮,所有達到數據庫的SQL代碼都會被同等對待,編譯之后,二者性能沒有任何差別,這就是結論。


傳言2:存儲過程可以用來阻擋SQL注入攻擊


這個傳言和前面有關性能的傳言有些相似。存儲過程當然可以降低SQL注入發(fā)生的可能性,因為存儲過程使用強類型參數。因此對于攻擊者來說,很難在需要數字的地方傳入字符串,反之亦然。


參數化查詢也提供了同樣的功能,例如,ADO.NET就對創(chuàng)建參數化查詢提供了很好的支持,且ADO.NET被廣泛應用于.NET平臺上的很多數據庫中,包括Entity Frameword,NHibernate和其它O/RM中。使用參數構造的SQL語句也可以和存儲過程一樣阻擋SQL注入攻擊。

這里我們必須假設,讀者都很了解存儲過程,存儲過程就是關系型數據庫中定義的一個子集。隨后,連接到該數據庫的并提供了必要認識的用戶即可以執(zhí)行這個存儲過程。


我們認為,這里的子程序一詞是理解存儲過程的知用范圍和好處的關鍵,且這里我們所說的存儲過程的適用范圍和好處都是其目前的狀態(tài)。我們承認,10年前人們會對存儲過程有不同的看法,且總體來說更加傾向于使用。不過 ,軟件領域中的10年是一段相當長的時間,相當于遠古和現(xiàn)代。


維基百科上對于子程序的定義是一個大型程序中的一部分代碼,用來執(zhí)行專門的任務并從某種程序上與其它代碼獨立。在數據庫編程中,子程序則表示將幾個SQL語句組合起來,組成單一的一個復雜語句,即存儲過程。這樣調用者即可用統(tǒng)一的

接口

與數據庫交互,易于保證安全,測試,優(yōu)化和維護,其運行速度也會有所提升。


上述描述闡明了存儲過程的優(yōu)勢和劣勢。在不同的上下文中,前面提到的每個特征都可能成為優(yōu)勢或者劣勢,這取決于你所創(chuàng)建的應用程序的需求和約束,以及邏輯的最終復雜性和處理復雜性的方式。同樣,開發(fā)方式的不同也會對于存儲過程成為優(yōu)勢或劣勢產生影響。


客戶的說,存儲過程并不是萬惡之源。不過對于那些使用現(xiàn)代觀點,模式,工具和技術實現(xiàn)的帶有一般復雜性的應用程序來說,存儲過程被認為是一種過時的技術。我們的觀點是存儲過程并不是絕對不能使用,而是應該在必要也確定有所幫助時才使用。


在過去的10~15年中,編寫系統(tǒng)的趨勢是分層并依賴于真正的設計模式,不過仍有一個地方被很多人忽視。人們仍舊經常將業(yè)務邏輯放在存儲過程中實現(xiàn),讓兩個完全不同的層的功能混在一起。你會很容易地不小心將某段業(yè)務邏輯放在存儲過程中,這樣做真的合理嗎?以后的幾章就列舉一些長久以來一直聽到的編寫復雜存儲過程的理由,其中有些理由在10年前可能更加合理一些,不過今天事情已經發(fā)生了很多變化。因此,我們在以后幾章中介紹一些常見的有關儲過程的傳言并進行分析,當然,其中會根據現(xiàn)在和以前的技術作出對比分析。

傳言3:存儲過程要比 SQL代碼更加安全


在執(zhí)行任何SQL語句之前,數據庫引擎都會嘗試匹配調用者提供的論證信息和所請求資源的訪問權限。根據匹配結果,引擎決定是否執(zhí)行該SQL代碼。


這樣看來,從安全角度存儲過程顯然要比普通的SQL代碼更有優(yōu)勢。為什么會這樣呢?因為存儲過程可看做是數據庫中的一個實體,可以由數據庫管理員DBA顯式給其安全需求,即借助數據庫的安全基礎設施來保護存儲過程,因為存儲過程本來就是屬于數據庫資源的一部分。


而普通的SQL語句就是個字符串,將動態(tài)地發(fā)送給數據庫執(zhí)行,因此數據庫引擎不能將其當成內部資源,也無法把權限關聯(lián)在它上面。權限僅能應用在SQL將使用的數據表或視圖上,這顯然屬于另一個層次的安全。因此,操作整體上的安全性要交給調用者負責保證。


大多數人應該對上面的分析沒有疑義,關鍵是通過上面的分析可以產生兩個相反的結論,且這取決于人們的態(tài)度,技能和看待問題的角度。


若你更熟悉數據庫,那么通常會停在這里并得出結論:存儲過程是設計數據訪問層中必不可少的。


不過問問自己這3個問題:存儲過程中將要執(zhí)行哪些類型的操作?這些操作都要帶有什么樣的簽名?在大型系統(tǒng)中你實際需要多少個存儲過程?


在我們看來,若你覺得存儲過程中必不可少的,那么也會不自覺地在存儲過程中實現(xiàn)(至少一部分)業(yè)務邏輯,但這一點是我們提倡應該竭力避免的。稍后將繼續(xù)討論這個問題,這里我們先來完成對安全性的討論。


安全性是個橫切的關注點,應該在從表現(xiàn)層到數據庫的各層中都有處理。今天,基于角色的安全是最靈活且有效的做法。在基于角色的安全模型中,我們對安全性有著雙重的保證,第一重是中間層中使用基于角色的安全,第二重是數據庫引擎中的聲明安全。且這一點和使用動態(tài)SQL代碼或存儲過程并不相關。


若使用存儲過程來實現(xiàn)系統(tǒng)的安全性需求,則會不自覺地將數據庫開發(fā)人員和其它開發(fā)人員分離開來。而前面曾提到過,安全性應該是個團隊的工作。因些我們就回到了那些傾向于使用存儲過程的說法中———“若想保證安全的話,就要使用存儲過程”。不過實際上,若你真的想要保證安全,則必須放棄將存儲過程作為必不可少的功能的想法。之所以這樣說,并不是因為存儲過程有什么不好,而是因為若將存儲過程作為整個系統(tǒng)的核心,那么必定會讓人作出不好的設計決定———從安全角度考慮。你仍然可以使用存儲過程,不過不要再說是出于安全性考慮,也不要用存儲過程來實現(xiàn)邏輯。那存儲過程還有什么用呢?一般也僅用在處理數據表訪問上。


傳言4:存儲過程可以讓SQL代碼更加穩(wěn)定且不易改變




軟件領域中有很多讓人孜孜不倦追求的理想目標,其中一個就是使編程可以不受到數據庫模型的變化影響。若某個數據庫表發(fā)生了變化,會不會影響到其相關的代碼嗎?這是一個常見的疑慮。不過正確的答案仍然不是使用存儲過程。


若將SQL命令放在數據訪問層中(就像我們在手工數據訪問層中的實現(xiàn)一樣),就會在代碼和物料數據模型之間建立依賴。若數據模型有所變化,就需要更新代碼。不過我們可以說,此類依賴僅僅存在于數據映射器類中,且SQL語句也是作為私有成員聲明的。因此雖然存在依賴,不過范圍非常小。若數據表發(fā)生了變化,必須更新數據映射類。不過這也就是所有需要的修改,僅限于數據訪問層內部。


使用存儲過程是不是真的能讓代碼與數據模型的變化完全獨立呢?若數據模型發(fā)生了變化,那么要實現(xiàn)兩種更新:修改SQL代碼和修改調用者代碼。其實,我們并沒有看到在數據映射器類中調用存儲過程和普通SQL語句有什么區(qū)別。


在我們看來,存儲過程可以讓數據訪問代碼更加穩(wěn)定的說法僅僅是個傳言,這個傳言是以前的那種系統(tǒng)設計方式的自然產物,即數據庫開發(fā)人員和其他開發(fā)人員基本沒有溝通交流。


若你真想完全不依賴于物理數據模型,那么應該選擇領域驅動設計,并將數據庫設計成一個簡單的持久化層。數據訪問代碼將由O/R映射層負責以參數化查詢(甚至是以存儲過程)的方式動態(tài)生成。


[sql雜談]我們是否還一定應該使用存儲過程的評論 (共 條)

分享到微博請遵守國家法律
迭部县| 拉萨市| 安溪县| 巩义市| 闻喜县| 长白| 广饶县| 逊克县| 碌曲县| 舒兰市| 宜宾市| 巴青县| 金塔县| 伽师县| 兴隆县| 公主岭市| 琼海市| 台东市| 满城县| 新巴尔虎右旗| 南汇区| 黄梅县| 竹山县| 宁陵县| 靖西县| 定安县| 丰顺县| 海南省| 喜德县| 许昌县| 灵璧县| 博爱县| 东丰县| 观塘区| 黄平县| 上栗县| 嘉善县| 阿尔山市| 治多县| 安义县| 肇源县|