上千行的 SQL 代碼常見,且永不過期!html
經歷了大大小小的 MIS 系統,小到幾人用的協做系統,幾十人用的 OA 系統,到上千人用的 MES/ERP 系統,再到百萬人用的電商系統,存儲過程的影子在半個世紀(20世紀70年代末開始)以來從未淡出它的戰場。咱們幾個 SQL 老玩家常常自吹, SQL 是半衰期最長的編程語言。玩會它不用擔憂失業。git
如何去閱讀和拆解一個上千行的 SQL 存儲過程,有四大步驟 :理解代碼,分拆代碼,改寫代碼和保存代碼。拆過無數的代碼,從上千行縮減到 2 成,也組裝過無數的代碼,從上百行塞成了上千行,業務所需。見過最長的 SQL 代碼超 5000 行,已簡無所簡,那就實事求是了。人有分分合合,有生命力的代碼也同樣。程序員
但裝和拆並非一個逆反的過程!github
就像咱們能讀懂村上春樹的小說《且聽風吟》、《刺殺騎士團長》同樣,但咱們沒法寫出來或者說沒法寫的那麼好。固然那畢竟是村上賴覺得生的技能,老人家寫了30多年的小說,咱們可能一部都沒完整的寫完過,無法兒比。既然如此,在咱們賴覺得生的SQL陣營,這門吃飯的技能必定是要好好磨練的。編程
下面的領悟來自我實戰中真實的想法,趟過無數次的坑,用教訓總結出來的幾條自認爲極有用的經驗。設計模式
理解業務性能優化
快速實現併發
重構與測試編程語言
版本控制工具
覆盤記錄
一、理解業務:
你確定不會去寫沒有業務邏輯的代碼。充分理解業務邏輯對你有兩個好處:一是寫出可執行的而且可擴展的代碼;二是主動了解業務將有利於職業生涯升級。
第一個好處不言而喻,寫代碼寫出頸椎病的程序員,確定意識到代碼的擴展性,能夠節省去醫院的時間,能夠霸屏更屢次王者。
舉例說說什麼是代碼的擴展性?
好比產品的價格。電商時代,產品的價格擁有明顯的擴展屬性。也就是說,今天是這個價,明天又是另外一個價。電商時代給雙11,雙12附上了商業促銷標籤,對產品價格提出了高要求。此時,你去設定一個商品價格,你會怎麼設計?是在原來的價格基礎上直接更新,仍是另起一列,承載新價格?這類價格設計,會直接影響對電商促銷活動的成果分析。
若是咱們直接更新價格,就會失去與歷史銷售對比的便捷,若是不隨單記錄單價,更是丟失了與歷史的對比。從設計角度,這很失敗,失去了靈活性,擴展性。這樣的設計,每次更換價格,都須要大量更新產品價格表和銷售歷史表,對已有的商業活動形成干擾。更好的辦法是,增長價格的有效使用日期。好比在這段時間內這個價格生效,在促銷階段又是另外一個價格。並採用視圖(view)的方式去提供產品數據,而不是直接從原表直接讀取數據,失去中間業務的緩衝。
對這類業務的理解,kimball 最有說服力,他的《Dimensional modeling》(《維度建模》)總結了幾十個行業的通用設計模型,堪稱數據模型界的設計模式。
第二個好處可不是人人都能意識到了。雖然 SQL 是擁有最長職業生涯的編程語言,好比與其一塊兒出現的 VFP 大概 90 後聞所未聞,但顯然沒人一生願意鼓搗 CRUD 。玩吃雞的同窗把你的 iPhone X 放下,家裏有礦沒說你。理解業務使你成爲整個應用生態中不可缺乏的一環。信息化的目的不是寫代碼,最終落腳點仍是利潤。我以爲二爺(邱嶽)確定能贊同我這話。
話說到這份上,你們能夠明白,咱們寫SQL就是在通曉一個行業的數據流,資金流,作好大盤的監控。那麼還有誰比咱們更瞭解一個企業的真實經營狀況呢,沒有,徹底沒有。前提是,你要作對,要通曉。當你還只是把本身定位成一個碼工,那真是大材小用。追逐SQL的技巧能夠,但最終仍是商業會支持你走的更遠。你永遠不可能20歲,30歲,總有一天你會被但願擁有開拓事業的本領,擁有能夠指導後生的經驗。到那時,技術經驗就很泛泛了。甚至有可能技能上徹底不如年輕人。惟一能給你樹立權威的,還在於你在其餘方向上可以走的多遠。
二、快速實現:
不少朋友(包括我)有時候碰到需求,苦思冥想,要的是一口氣把 SQL 從頭至尾完整的,暢快淋漓的寫出來。「Wow」 和漂亮的回車,就是憋着這口氣的期待。
但現實無數次打了個人臉!
越是有這種想法,越是憋得時間很長才寫那麼一點。總以爲這裏很差,那裏不行,這裏的變量名稱寫得不夠爽朗,那邊的 Pivot 寫得不夠優化。結果每每是一個上午就在那裏糾結,什麼都沒完成。
你是否是也有相似的經歷?不孤獨
村上春樹、海明威、博爾赫斯,歷來寫小說都是第一遍爽快的寫下去了,一旦寫得卡殼了怎麼辦,束之高閣,明兒繼續。我這裏想說的策略,你們均可以猜獲得了。先把業務實現了再說,命名規則,變量申明,事務控制以及性能優化,通通先放起來。寫好 CRUD 交上第一稿,存檔,Over!
做家們要是等靈感來了再動筆寫,咱們哪能看到那麼多有趣的故事。一樣,咱們寫代碼哪能等到全盤都考慮好了再動手呢。想到一個數據流,用到哪些表,直接就能夠寫了。 等着等着就慌了,寫着寫着思路就來了。
好比實現下面的CRUD,你會花多少時間?
若是一開始,盯着這圖你開始考慮日誌怎麼記,檢查用戶是否單點登陸,用戶是否用促銷券,訂單怎麼撤回,要不要控制併發,那麼無疑是給本身加了不少戲,不少無形的壓力使得你本身沒法動手作,越想越宏大,越以爲本身作不來。在你迷茫同時,若是有個會議,有個熱鬧的新聞,一開小差,再想回到你的宏偉藍圖上來,就難了。
怎麼辦?抓大放小
此時,你要作的第一件事,就是快速去實現這麼幾個關鍵點的CRUD代碼。好比購物車的增刪改查,用戶登陸,填寫訂單信息,還有結單。等到這一系列操做都完成,你對整個業務流,數據流都熟悉了,第二遍再去增長附加的功能。
三、重構與測試:
終於,在初版本時,你增長好了附加功能。實現了絕大多數的業務功能。
那這個時候,是否是能夠交稿,checkin你的代碼了呢?並非!
若是此時你就認爲高枕無憂,那會死的很慘。你會成爲別人口中的「豬同樣的隊友,坑貨……」
《巴黎評論》中,村上春樹提到他的小說常常修改 4 - 5 遍才交稿,並且編輯還須要修改。咱們一遍過的 SQL 就免檢了?這個時候才考驗你 SQL 真實功底和編碼素質。
再檢查命名規則,變量申明,事務控制以及性能優化。你會發現還有不少事情要作。
好比本來有不少次的嵌套
我知道不少朋友會這麼寫 :
SELECT * FROM ( SELECT * FROM (SELECT * FROM BASE ) T1 )T2
若是繼續聽任你的項目裏存在這樣的代碼,那項目很快就失控了。
至少,第一遍走讀代碼,咱們須要完成格式上的美化:
SELECT * FROM
( SELECT *
FROM (
SELECT * FROM BASE
) T1
)T2
這樣即便代碼不夠優雅,別人在閱讀這塊代碼時,也不至於罵娘。
第二遍動手重構的時候,能夠考慮減小嵌套,或加上 CTE 封裝嵌套:
; WITH BASE_TABLE AS ( SELECT * FROM BASE )
SELECT * FROM BASE_TABLE
再好比,unpivot 以後的聚合:
一開始咱們能把 unpivot 寫出來就很好了,而後嵌套一層作聚合,以下:
SELECT Convert(Date,OrderDate) as OrderDate
, Sum(Amount) AS Amount
FROM (
SELECT
OrderDate,
Unp.Amount AS Amount
FROM FctOrderAmounts
UNPIVOT( Amount for Type in(Shipment,UnitCost) ) Unp
) RSL
GROUP BY Convert(Date,OrderDate)
這麼一看特別清晰,可是信息量大,結構複雜,加上中間可能有其餘字段或者Join,變得複雜,那咱們至少還需再一次簡化:
SELECT
OrderDate,
Sum(Unp.Amount) AS Amount
FROM FctOrderAmounts
UNPIVOT( Amount for Type in(Shipment,UnitCost) ) Unp
Group by Unp.Amount
再比如,有不少的關鍵步驟,其實咱們能夠拆分開來,直到一個存儲過程完成一個功能,這樣既完成代碼簡化,還能夠提供複用的接口,還可使得組裏的小夥伴協同做戰。一舉三得,這樣的事情才值得花時間。
最後,將全部的測試分支跑完測試,提交!
四、版本控制:
若是你的團隊沒有 git, SVN, TFS 這些 Source Code Version Control, 趕忙上一個。沒有自動化部署工具,本身想辦法整一個。都 2020 年了,別偷懶吧。
爲何必定要版本控制呢?這,應該在剛入門編程的時候就知道。
比如你以爲愈加討厭如今的本身,或是太胖,或是太文弱,或是太沒文化,好想要一臺時光穿梭機,回到15,16歲,從新再來。你會告訴本身多吃蔬菜和水果,堅持天天鍛鍊,堅持天天看書寫字讀報。
雖然咱們不能實現穿越,但代碼能夠。使用上述提到的軟件,就能夠幫助咱們回退到想要從新開始的那個版本,修正代碼。
五、覆盤記錄
作好上面4步,對公司項目是有個交代了。但作這一步,纔是對本身有交代。
就比如剛纔重構的時候,提到 CTE, UNPIVOT , 代碼簡化的策略,可能由於一時靈感或責任心爆棚,反正你當時想到了,但你不及時記錄下來,可能好久事後就忘記你曾作過這麼神奇的操做。
因此,等你費盡心思寫完很長的代碼,必定要經過覆盤記錄下來,放到你的 blog, github, 等你之後碰到相似狀況,卻想不出來如何解,你能夠隨時拿出來用上。
寫好SQL代碼,素質固然遠不止這些!
分享一個最近作的腦圖,掌握了這些才能夠說 SQL 編碼入門了
摸着你的良心,看看這個圖,有則改良,無則加勉
以上腦圖是我閱讀了《SQL Programming Style》後,加上平時編碼總結而成。
上面都是我的實戰所學,所悟。鑑於本人技術水平和經驗,還有表達能力有限,不免有些地方寫得晦澀,有些地方深刻不夠,但願你們可以給予反饋,感謝!
來自 「開源世界 」 ,連接:http://ym.baisou.ltd/post/659.html,如需轉載,請註明出處,不然將追究法律責任。