posts - 431,  comments - 344,  trackbacks - 0
          四,根據條件有選擇的UPDATE。

          例,有如下更新條件
          1. 工資5000以上的職員,工資減少10%
          2. 工資在2000到4600之間的職員,工資增加15%
          很容易考慮的是選擇執行兩次UPDATE語句,如下所示
          --條件1
          UPDATE Personnel
          SET salary = salary * 0.9
          WHERE salary >= 5000;
          --條件2
          UPDATE Personnel
          SET salary = salary * 1.15
          WHERE salary >= 2000 AND salary < 4600;
          

          但是事情沒有想象得那么簡單,假設有個人工資5000塊。首先,按照條件1,工資減少10%,變成工資4500。接下來運行第二個SQL時候,因為這個人的工資是4500在2000到4600的范圍之內, 需增加15%,最后這個人的工資結果是5175,不但沒有減少,反而增加了。如果要是反過來執行,那么工資4600的人相反會變成減少工資。暫且不管這個規章是多么荒誕,如果想要一個SQL 語句實現這個功能的話,我們需要用到Case函數。代碼如下:
          UPDATE Personnel
          SET salary = CASE WHEN salary >= 5000
                       THEN salary * 0.9
          WHEN salary >= 2000 AND salary < 4600
          THEN salary * 1.15
          ELSE salary END;
          

          這里要注意一點,最后一行的ELSE salary是必需的,要是沒有這行,不符合這兩個條件的人的工資將會被寫成NUll,那可就大事不妙了。在Case函數中Else部分的默認值是NULL,這點是需要注意的地方。
          這種方法還可以在很多地方使用,比如說變更主鍵這種累活。
          一般情況下,要想把兩條數據的Primary key,a和b交換,需要經過臨時存儲,拷貝,讀回數據的三個過程,要是使用Case函數的話,一切都變得簡單多了。
          p_key col_1 col_2
          a 1 張三
          b 2 李四
          c 3 王五


          假設有如上數據,需要把主鍵ab相互交換。用Case函數來實現的話,代碼如下
          UPDATE SomeTable
          SET p_key = CASE WHEN p_key = 'a'
          THEN 'b'
          WHEN p_key = 'b'
          THEN 'a'
          ELSE p_key END
          WHERE p_key IN ('a', 'b');
          

          同樣的也可以交換兩個Unique key。需要注意的是,如果有需要交換主鍵的情況發生,多半是當初對這個表的設計進行得不夠到位,建議檢查表的設計是否妥當。

          五,兩個表數據是否一致的檢查。

          Case函數不同于DECODE函數。在Case函數中,可以使用BETWEEN,LIKE,IS NULL,IN,EXISTS等等。比如說使用IN,EXISTS,可以進行子查詢,從而 實現更多的功能。
          下面具個例子來說明,有兩個表,tbl_A,tbl_B,兩個表中都有keyCol列。現在我們對兩個表進行比較,tbl_A中的keyCol列的數據如果在tbl_B的keyCol列的數據中可以找到, 返回結果'Matched',如果沒有找到,返回結果'Unmatched'。
          要實現下面這個功能,可以使用下面兩條語句
          --使用IN的時候
          SELECT keyCol,
          CASE WHEN keyCol IN ( SELECT keyCol FROM tbl_B )
          THEN 'Matched'
          ELSE 'Unmatched' END Label
          FROM tbl_A;
          --使用EXISTS的時候
          SELECT keyCol,
          CASE WHEN EXISTS ( SELECT * FROM tbl_B
          WHERE tbl_A.keyCol = tbl_B.keyCol )
          THEN 'Matched'
          ELSE 'Unmatched' END Label
          FROM tbl_A;
          

          使用IN和EXISTS的結果是相同的。也可以使用NOT IN和NOT EXISTS,但是這個時候要注意NULL的情況。

          六,在Case函數中使用合計函數

          假設有下面一個表
          學號(std_id) 課程ID(class_id) 課程名(class_name) 主修flag(main_class_flg)
          100 1 經濟學 Y
          100 2 歷史學 N
          200 2 歷史學 N
          200 3 考古學 Y
          200 4 計算機 N
          300 4 計算機 N
          400 5 化學 N
          500 6 數學 N

          有的學生選擇了同時修幾門課程(100,200)也有的學生只選擇了一門課程(300,400,500)。選修多門課程的學生,要選擇一門課程作為主修,主修flag里面寫入 Y。只選擇一門課程的學生,主修flag為N(實際上要是寫入Y的話,就沒有下面的麻煩事了,為了舉例子,還請多多包含)。
          現在我們要按照下面兩個條件對這個表進行查詢
          1. 只選修一門課程的人,返回那門課程的ID
          2. 選修多門課程的人,返回所選的主課程ID

          簡單的想法就是,執行兩條不同的SQL語句進行查詢。
          條件1
          --條件1:只選擇了一門課程的學生
          SELECT std_id, MAX(class_id) AS main_class
          FROM Studentclass
          GROUP BY std_id
          HAVING COUNT(*) = 1;
          

          執行結果1
          STD_ID   MAIN_class
          ------   ----------
          300      4
          400      5
          500      6
          

          條件2
          --條件2:選擇多門課程的學生
          SELECT std_id, class_id AS main_class
          FROM Studentclass
          WHERE main_class_flg = 'Y' ;
          

          執行結果2
          STD_ID  MAIN_class
          ------  ----------
          100     1
          200     3
          

          如果使用Case函數,我們只要一條SQL語句就可以解決問題,具體如下所示
          SELECT  std_id,
          CASE WHEN COUNT(*) = 1  --只選擇一門課程的學生的情況
          THEN MAX(class_id)
          ELSE MAX(CASE WHEN main_class_flg = 'Y'
          THEN class_id
          ELSE NULL END
          )
          END AS main_class
          FROM Studentclass
          GROUP BY std_id;
          

          運行結果
          STD_ID   MAIN_class
          ------   ----------
          100      1
          200      3
          300      4
          400      5
          500      6
          

          通過在Case函數中嵌套Case函數,在合計函數中使用Case函數等方法,我們可以輕松的解決這個問題。使用Case函數給我們帶來了更大的自由度。
          最后提醒一下使用Case函數的新手注意不要犯下面的錯誤
          CASE col_1
          WHEN 1        THEN 'Right'
          WHEN NULL  THEN 'Wrong'
          END
          

          在這個語句中When Null這一行總是返回unknown,所以永遠不會出現Wrong的情況。因為這句可以替換成WHEN col_1 = NULL,這是一個錯誤的用法,這個時候我們應該選擇用WHEN col_1 IS NULL。
          posted on 2008-09-24 11:29 周銳 閱讀(425) 評論(0)  編輯  收藏 所屬分類: MySQLOracleSQL Server
          主站蜘蛛池模板: 中山市| 北宁市| 项城市| 泽库县| 黄龙县| 芦山县| 岢岚县| 贵州省| 宜兴市| 舒城县| 湘潭县| 阳谷县| 旺苍县| 重庆市| 星座| 屏东县| 体育| 华亭县| 泾阳县| 文登市| 明光市| 阿克| 长武县| 靖安县| 伊宁县| 云南省| 保德县| 城口县| 克什克腾旗| 中山市| 赞皇县| 九江市| 浪卡子县| 宜兴市| 永修县| 竹溪县| 永平县| 榆中县| 卓尼县| 合作市| 屏东县|