爲何阿里禁止使用存儲過程?

送你們如下java學習資料,文末有領取方式




之因此有這個題目,我既不是故意吸引眼球,也不想在本文對存儲過程進行教科書般論述。最近項目中遇到的存儲過程問題,讓我想起了去年在武漢出差時一位同事的發問:java

我以爲存儲過程挺好用的,爲何你不建議用?

當時我好似胸有萬言,但終究沒用一個實在的例子回答同事,只是從結論上大侃一通,代碼相對於SQL,複用、擴展、通用性都要更強。想必同事並不信服。web

如今想來,我最近正碰到的問題,算是一個能夠回答同事的例子吧。數據庫

最近項目中有個新需求,須要校驗一個用戶是否有Job,Certification,Disclosure這三個業務數據。服務器

翻看了代碼發現,系統的用戶我的頁面的C#代碼調用了三個存儲過程,去抓取用戶的Job,Certification,Disclosure數據。
個人新需求,天然須要複用這三個存儲過程,不然:網絡

若每一處都寫一次抓取數據的業務邏輯代碼,若業務邏輯發生變化,難以追查和維護全部讀取Job,Certification,Disclosure的SQL。

若是我在C#代碼中調用這已有的三個存儲過程,事情本該很是快就能結束。我也是這麼作的。性能

但code reviewer認爲,個人需求中,並不須要Job,Certification,Disclosure這三個業務對象的數據。我只是須要給定用戶\_是否\_有Job,Certification,Disclosure而已。因此我應將是否有無Job,Certification,Disclosure的判斷邏輯寫在數據庫,最終經過網絡從數據庫傳到web服務器的僅是true或false,節省網絡流量,這樣最好不過了。學習

也對。除開網絡性能,從接口設計的角度講,接口的傳入和返回值,都應是你自己須要的數據,不該帶有大量不須要或者須要caller去預處理的數據。從接口語義表達就可知調用的目的,這樣代碼可讀性也會有大大提升。ui

那就動手改。但沒想到的是問題來了。spa

爲了講述問題,我簡化代碼,假設系統現有的存儲過程以下:設計

`CREATE PROCEDURE [dbo].[GetJobs]`
`(`
 `@PersonId int,`
 `@OrganizaitionId int`
 `)`
`AS`
`BEGIN`
 `SELECT JobId,JobName,JobType FROM Job WHERE PersonId = @PersonId AND OrganizaitionId = @OrganizaitionId`
`END`

我在新的存儲過程當中調用它,我須要得到該person的jobs的數量,即GetJobs返回結果集的count。

爲了實現這一目的,首先想到的是使用臨時表,將返回結果集存入臨時表,再對其進行count(*)的計數操做:

`CREATE PROCEDURE [dbo].[MyProc]`
`(`
 `@PersonId int,`
 `@OrganizaitionId int,`
 `)`
`AS`
`BEGIN`
 `CREATE TABLE #Temp(`
 `PersonId int,`
 `OrganizaitionId int`
 `)`
 `INSERT INTO #Temp EXEC dbo.GetJobs`
 `@PersonId = @PersonId,`
 `@ParentOrgId = @ParentOrgId`
 `SELECT COUNT(*) FROM #Temp`
`END`

這種辦法簡單有效,但它存在嚴重的維護問題。將來若是被調用的存儲過程的返回結果集字段有變更,那麼MyProc中的臨時表結構也須要隨之變化。這是使人難以接受的。

那麼將MyProc中的INSERT INTO換爲SELECT INTO呢?很遺憾,答案是不行。SQL自己並不支持這種用法。

給現有存儲過程GetJobsoutput參數?本例中由於GetJobs已被其餘多處代碼或SQL scripts調用,因此對現有現有存儲過程進行改動會有不小風險。

我搜遍網絡,一位MS MVP的大神的文章幾乎總結了全部存儲過程之間傳遞數據的方法: How to Share Data between Stored Procedures。他在文章中也迫不得已地說道

Keep in mind that compared to languages such as C# and Java, Transact-SQL is poorly equipped for code reuse, why solutions in T‑SQL to reuse code are clumsier.

最終我沒能找到一種滿意的辦法,無奈之下我在新寫的存儲過程當中將查詢Jobs的語句寫一了次。

存儲過程在不少場景時有其優點,好比性能。但對於業務邏輯的通用方法,很是不推薦將其寫在存儲過程當中,代碼複用、擴展與客戶端語言比,相差甚遠。也許終究能實現,但代價與風險比客戶端語言要高,得不償失。

天知道還有沒有機會和那位前同事再討論這一話題呢。

圖片

相關文章
相關標籤/搜索