擴充SQL的靈活性——靜態T_SQL和動態SQL,sqlt_sql
其實我覺得這個部落格寫在基於web的應用程式開發是最好的,因為目前我們很少在用戶端實現排序和過濾功能,而且很多開發採用的都是輕量級的兩層模型,所以缺少專門處理資料緩衝和過濾業務,有些人會說,我們可以建立預存程序或者嵌套複雜的控制流程程塊?但是我想說,這些方案只能解決一部分問題,但是它們帶來的問題遠遠比我想解決的問題要多得多。
問題
出現這個問題是在我們機房合作通過商務邏輯層來拼接字串來最佳化D層代碼的時候,但是出現這樣一個問題:我這裡寫好了update一張表的所有欄位,但是事實上傳入的實體值一般僅僅是其中的幾個欄位,這就需要擴充我們SQL的靈活性。
解決過程
在合作中我是負責D層的,但是如何解決這個問題我還是無從下手。後來通過查詢很久的資料和論壇的提問,大體瞭解是關於靜態SQL和動態SQL的方向。
1. 靜態T_SQL解決方案:
update card set cardName=isnull(@cardName,cardName),date=isnull(@date,date),Time=isnull(@Time,time),status=isnull(@status,status) where cardID=@cardID
由上面這段代碼可以看到只是需要加上一個isnull()判斷。當然方法不只是一個,比如通過控制流程的判斷,但是控制流程判斷還是存在很多潛在問題,也可以用case運算式,我覺得這種方法是在最佳化控制流程來達到如果cardname為空白時候,這個欄位就保持原來資料,不進行改變。
上面的語句問題:可讀性差。
可以通過case運算式來最佳化:
update card set cardName=case when @cardName is null then cardName else @cardName end,date=case when @date is null then date else @date end,Time=case when @Time is null then Time else @Time end,status=case when @status is null then status else @status endwhere cardID=@cardID
這樣子的使用CASE運算式替代SQL Server中的動態SQL語句。
2. 動態SQL解決方案
原理:拼接的SQL語句,在預存程序中。
注意:
所以說一般不建議使用動態SQL。
exec sp_executesql N'update card set cardName=isnull(@cardName,cardName),date=isnull(@date,date),Time=isnull(@Time,Time),status=isnull(@status,status) where cardID=@cardID',N'@cardName varchar(100),@date date,@Time time,@status varchar(30),@cardID int','test',null,null,null,'001'
然後exec(sql)就可以了。
感悟
關於動態SQL知識一是我理解的不多,所以我也不大敢輕易的解讀,以後在我學習的過程中我再把我的理解寫出來;二是這對我來說是個新知識,需要時間消化和吸收,需要更多的和別人討論才能決定是否運用動態SQL。
另外,通過這次出現的問題讓我重新對sql sever有了理解,我曾經以為我學了視圖,觸發器,就已經差不多了,但是即使是小小的sql語句都有這麼大學問,不過我覺得滿有意思的,就是因為豐富,我每天對曾經學過的知識才會有全新的感受。我覺得sql sever不會學完,永遠都在學習中,知識也是,永遠都在學習中。