大大毛 的筆記

            DDM's Note

          哪怕沒有辦法一定有說法,
          就算沒有鴿子一定有烏鴉,
          固執(zhí)無罪 夢想有價,
          讓他們驚訝.

          posts - 14, comments - 23, trackbacks - 0, articles - 58
             :: 首頁 ::  :: 聯(lián)系 ::  :: 管理

          MsSQL中合并條件語句的方法

          Posted on 2006-08-15 17:06 大大毛 閱讀(1367) 評論(1)  編輯  收藏 所屬分類: SQL


          ???起因:
          ??????在工作中經常都會用到根據一個參數(shù)的值來做不同的 Where 條件的情況,例如:
          ??????1.在提供給用戶的查詢界面上提供了多個篩選條件,如果用戶選了就使用條件,如果不選就放棄該條件;
          ??????2.存儲過程的預留擴充功能,如 當前要求返回條件為真的記錄,為了擴充,讓存儲過程根據參數(shù)可以返回條件為 真/假/全部 的記錄等。
          ??????在這些情況下,通常有3種實現(xiàn)方法:
          ?????????a.在外部(相對于數(shù)據庫)拼裝查詢語句,我稱它為外部動態(tài)SQL,嘻嘻;
          ?????????b.在內部(同上)拼裝查詢語句,我稱它為內部動態(tài)SQL;
          ?????????c.在存儲過程中使用大量的 IF 開關,搭配 ctrl+C,ctrl+V,edit操作,寫上N條的SQL語句。

          ???問題的分析
          ??????a 方法,該方法最多見,因為這是非常easy的辦法,而且適用面最廣,干啥事都直接來個SQL語句發(fā)往連接對象即可。當然這種方法在實現(xiàn)時也是N多的 IF,同時這種方法也會遺留下隱患,稍不留神就會成為 SQL注入 的犧牲品。
          ??????b 方法,只是在存儲過程實現(xiàn)了 a 方法,在減少隱患的同時,縮小了適用面,比如低版本的 mysql 就不支持存儲過程。
          ??????c 方法,是 b 方法的變種,雖然代碼量非常的大,但是結構上很清晰,執(zhí)行速度快。

          ???解決方法:
          ??????在工作中找到的一個方法,適用于一定的問題域,可以將N多的SQL合并。
          ??????為了能夠清楚的說明,舉個例子先。
          ??????例(特定值的條件查詢):
          ????????????現(xiàn)在提供一個查詢界面給管理員,讓他能夠對 log表 的查詢條件進行定制。
          ????????????查詢條件有:
          ???????????????1.組ID,對應字段gID
          ???????????????2.用戶ID,對應字段uID
          ???????????????3.記錄類型,對應字段logType
          ????????????條件的判斷為:
          ???????????????如果用戶選擇了條件,那么就在Where中進行篩選,否則就忽略該條件,例如用戶如果選擇了 gID=1,那么就只選擇組ID=1的用戶Log,否則就返回全部的用戶。通常是用上IF,這樣:

          string ?sql? = ? " select?*?from?log? " ;
          string ?where? = ? ""
          ;

          if (gID? != ? null
          )?{
          ??where?
          = ?where? + ? " ?gID= " ? + ?gID? + ? " ?and? "
          ;
          }
          //
          更多的IF
          // where字串還要處理一下

          sql? += ?where;

          ??????現(xiàn)在使用MS SQL 的存儲過程可以這樣實現(xiàn):

          定值條件查詢

          ??????仔細分析一下上面的存儲過程不難看出問題所在,實際上就是用了Ms SQL的 isNull系統(tǒng)函數(shù),它在判斷特征值或列為空時,就用第2參數(shù)所示的值或列去取代,否則就取原值,就拿 gID = isNull ( @gID , gID ) 語句來說吧,
          ??????@gID?為一個非空值時,如?@gID = 1,那么表達式成為 where gID = 1
          ??????@gID的值為空 =null 時?,那么該表達式實現(xiàn)上就成了 where gID = gID,多了這個不用擔心會增加負荷,數(shù)據庫還是有點智能會忽略掉這個條件的,嘻。
          ??????上面的代碼是一個比較簡單的例子,可以在存儲過程的代碼區(qū)增加對輸入參數(shù)的過濾,如 if?not exists(select 1 from log where gID = @gID) set @gID=null 等。
          ??????這樣一來,既可以利用存儲過程帶來的好處,又利用了 isNull 帶來的實惠,一舉N得啊。

          ???后記:
          ??????這個解決方案是存在有局限性的,并不是什么地方都能適用,但是它也不失為一個解決問題的方法。
          ??????--是人總要有點自己的想法,呵呵。


          評論

          # re: MsSQL中合并條件語句的方法  回復  更多評論   

          2007-11-29 13:38 by 1229363
          不是俺向得到的東西。

          你的方法俺用了N年了,根本不是什么高深的東西……

          i am ddm

          主站蜘蛛池模板: 德钦县| 北碚区| 东丽区| 新建县| 海伦市| 西安市| 阿尔山市| 汾阳市| 吴川市| 秦安县| 涡阳县| 衡阳县| 仁怀市| 西盟| 若羌县| 凤阳县| 鞍山市| 普洱| 合山市| 乐至县| 海盐县| 和林格尔县| 新郑市| 电白县| 镇赉县| 盈江县| 钟祥市| 大港区| 兴宁市| 陵水| 苍山县| 论坛| 定安县| 华亭县| 姜堰市| 永德县| 南开区| 香港| 沭阳县| 枝江市| 鸡泽县|