SQL語言的CASE語句備忘

做者:熔  巖
日期:2007-04-11
聲明:原創做品,未經受權,謝絕轉載!
 
SQL語言的CASE語句備忘
 
概述:
SQL語句中的CASE語句與高級語言中的switch語句,是標準SQL的語法,適用與一個條件判斷有多種值的狀況下分別執行不一樣的操做。靈活應用CASE語句可使SQL語句變得簡潔易讀,下面在DB2環境下經過一個簡單的查詢來展現SQL CASE語句的強大功能。
 
環境:
Windows XP Professional
DB2 V9.1
 
問題:
有一個行業代碼表,建表SQL和數據以下,要求查出代碼別名、代碼名、行業名、代碼長度。代碼別名爲數字序號與大寫英文字母的序號的映射值,好比代碼 '01'的別名就是'A','02'的別名就是'B',依次類推。
 
建表SQL和初始化數據SQL
-------------------------------------
drop table DM_HYML;
create table DM_HYML
(
  HYML_DM CHAR(2) not null,
  HYML_MC VARCHAR(100) not null,
  XYBZ    CHAR(1) not null
);
alter table DM_HYML
  add primary key (HYML_DM);
comment on table DM_HYML is
    '行業門類代碼表';
comment on column DM_HYML.HYML_DM is
    '行業門類代碼';
comment on column DM_HYML.HYML_MC is
    '行業門類名稱';
comment on column DM_HYML.XYBZ is
    '選用標誌';
 
delete from DM_HYML;
insert into DM_HYML (HYML_DM, HYML_MC, XYBZ)
values ('01', '農、林、牧、漁業', 'Y');
insert into DM_HYML (HYML_DM, HYML_MC, XYBZ)
values ('03', '製造業', 'Y');
insert into DM_HYML (HYML_DM, HYML_MC, XYBZ)
values ('02', '採礦業', 'Y');
insert into DM_HYML (HYML_DM, HYML_MC, XYBZ)
values ('04', '電力、燃氣及水的生產和供應業', 'Y');
insert into DM_HYML (HYML_DM, HYML_MC, XYBZ)
values ('05', '建築業', 'Y');
insert into DM_HYML (HYML_DM, HYML_MC, XYBZ)
values ('06', '交通運輸、倉儲和郵政業', 'Y');
insert into DM_HYML (HYML_DM, HYML_MC, XYBZ)
values ('07', '信息傳輸、計算機服務和軟件業', 'Y');
insert into DM_HYML (HYML_DM, HYML_MC, XYBZ)
values ('08', '批發和零售業', 'Y');
insert into DM_HYML (HYML_DM, HYML_MC, XYBZ)
values ('09', '住宿和餐飲業', 'Y');
insert into DM_HYML (HYML_DM, HYML_MC, XYBZ)
values ('10', '金融業', 'Y');
insert into DM_HYML (HYML_DM, HYML_MC, XYBZ)
values ('11', '房地產業', 'Y');
insert into DM_HYML (HYML_DM, HYML_MC, XYBZ)
values ('12', '租賃和商務服務業', 'Y');
insert into DM_HYML (HYML_DM, HYML_MC, XYBZ)
values ('13', '科學研究、技術服務和地質勘查業', 'Y');
insert into DM_HYML (HYML_DM, HYML_MC, XYBZ)
values ('14', '水利、環境和公共設施管理業', 'Y');
insert into DM_HYML (HYML_DM, HYML_MC, XYBZ)
values ('15', '居民服務和其餘服務業', 'Y');
insert into DM_HYML (HYML_DM, HYML_MC, XYBZ)
values ('16', '教育', 'Y');
insert into DM_HYML (HYML_DM, HYML_MC, XYBZ)
values ('17', '衛生、社會保障和社會福利業', 'Y');
insert into DM_HYML (HYML_DM, HYML_MC, XYBZ)
values ('18', '文化、體育和娛樂業', 'Y');
insert into DM_HYML (HYML_DM, HYML_MC, XYBZ)
values ('19', '公共管理和社會組織', 'Y');
insert into DM_HYML (HYML_DM, HYML_MC, XYBZ)
values ('20', '國際組織', 'Y');
commit;
 
實現:
 
select (case t.hyml_dm
         when '01' then 'A'
         when '02' then 'B'
         when '03' then 'C'
         when '04' then 'D'
         when '05' then 'E'
         when '06' then 'F'
         when '07' then 'G'
         when '08' then 'H'
         when '09' then 'I'
         when '10' then 'J'
         when '11' then 'K'
         when '12' then 'L'
         when '13' then 'M'
         when '14' then 'N'
         when '15' then 'O'
         when '16' then 'P'
         when '17' then 'Q'
         when '18' then 'R'
         when '19' then 'S'
         when '20' then 'T'
         when '21' then 'U'
         when '22' then 'V'
         when '23' then 'W'
         when '24' then 'X'
         when '25' then 'Y'
         when '26' then 'Z'
       end) as hydmbm,
       t.hyml_dm,
       t.hyml_mc,
       length(t.hyml_dm) as sublenth,
       '00' as zb
  from dm_hyml t
 
  將此sql代碼保存爲C:\test.sql文件,在DOS下進入DB2安裝目錄的bin目錄下,連接數據庫並執行(命令)此SQL,並重定向輸出查詢結果和信息到C:\test.txt。
 
C:\IBM\SQLLIB\BIN>db2  -tvf C:\test.sql > C:\test.txt
 
執行結果:
打開C:\test.txt文件查看結果:
 
select (case t.hyml_dm when '01' then 'A' when '02' then 'B' when '03' then 'C' when '04' then 'D' when '05' then 'E' when '06' then 'F' when '07' then 'G' when '08' then 'H' when '09' then 'I' when '10' then 'J' when '11' then 'K' when '12' then 'L' when '13' then 'M' when '14' then 'N' when '15' then 'O' when '16' then 'P' when '17' then 'Q' when '18' then 'R' when '19' then 'S' when '20' then 'T' when '21' then 'U' when '22' then 'V' when '23' then 'W' when '24' then 'X' when '25' then 'Y' when '26' then 'Z' end) as hydmbm, t.hyml_dm, t.hyml_mc, length(t.hyml_dm) as sublenth, '00' as zb from dm_hyml t
 
HYDMBM HYML_DM HYML_MC                                                                                                                                                                                                  SUBLENTH    ZB
------ ------- ---------------------------------- ----- --
A      01      農、林、牧、漁業                       2 00
C      03      製造業                                 2 00
B      02      採礦業                                 2 00
D      04      電力、燃氣及水的生產和供應業           2 00
E      05      建築業                                 2 00
F      06      交通運輸、倉儲和郵政業                 2 00
G      07      信息傳輸、計算機服務和軟件業           2 00
H      08      批發和零售業                           2 00
I      09      住宿和餐飲業                           2 00
J      10      金融業                                 2 00
K      11      房地產業                               2 00
L      12      租賃和商務服務業                       2 00
M      13      科學研究、技術服務和地質勘查業         2 00
N      14      水利、環境和公共設施管理業             2 00
O      15      居民服務和其餘服務業                   2 00
P      16      教育                                   2 00
Q      17      衛生、社會保障和社會福利業             2 00
R      18      文化、體育和娛樂業                     2 00
S      19      公共管理和社會組織                     2 00
T      20      國際組織                               2 00
 
  20 條記錄已選擇。
 
呵呵,CASE語句方便吧。
 
注意:DB2命令行下執行sql語句只能是一行,若是要執行多行,能夠將sql保存爲文件執行,執行的方法是:
 
一、執行SQL語句
db2  -tvf [filename].sql
二、執行存儲過程
db2 -td@ -vf [filename].sql
 
固然這些命令的選項根據須要有所不一樣,能夠直接從命令行查看這些選項:db2 ? OPTIONS
 選項    描述                                      缺省設置
 ------  ----------------------------------------  ---------------
   -a    顯示 SQLCA                                OFF
   -c    自動落實                                  ON
   -d    檢索並顯示 XML 聲明                       OFF
   -e    顯示 SQLCODE/SQLSTATE                     OFF
   -f    讀取輸入文件                              OFF
   -i    顯示 XML 數據並帶有縮進                   OFF
   -l    將命令記錄到歷史記錄文件中                OFF
   -n    除去換行字符                              OFF
   -o    顯示輸出                                  ON
   -p    顯示 db2 交互式提示符                     ON
   -q    保留空格和換行符                          OFF
   -r    將輸出報告保存到文件                      OFF
   -s    在命令出錯時中止執行                      OFF
   -t    設置語句終止字符                          OFF
   -v    回傳當前命令                              OFF
   -w    顯示 FETCH/SELECT 警告消息                ON
   -x    不打印列標題                              OFF
   -z    將全部輸出保存到輸出文件                  OFF
 
注意:
 使用 DB2OPTIONS 環境變量定製選項缺省值。
 緊跟選項字母后的減號(-)使該選項關閉。
 若將減號(-)更改成加號(+),則選項
 文件輸入方式)。
 
 
CASE和IF的區別:
在高級語言中,CASE的能夠用IF來替代,可是在SQL中不行。
CASE是SQL標準定義的,IF是數據庫系統的擴展。
CASE能夠用於SQL語句和SQL存儲過程、觸發器,IF只能用於存儲過程和觸發器。
在SQL過程和觸發器中,用IF替代CASE代價都至關的高,至關的麻煩,難以實現。
 
CASE語句應用對比:
下面作兩組查詢,每組用兩種方法來實現,一種是用case,一種是不用case,誰快誰獲勝,測試環境依然DB2 V9.一、windows server 2003。
 
第一組:查詢dj_zt表狀態爲'07'或'11'、qylx_dm = '03'的全部記錄數。
A:用CASE語句
select count(case a.zt when '07' then a.bs end)+
    count(case a.zt when '11' then a.bs end)
  from dj_zt a
 where a.qylx_dm = '03'
----------------
11829
 
B:不用CASE語句
select count(*)
  from dj_zt a
 where a.qylx_dm = '03'
   and a.zt in ('07', '11')
----------------
11829
 
結果:A、B兩組耗費的代價同樣的,相比B的寫法簡潔,平局。

第二組:分別查詢dj_zt表狀態爲'07'和'11'且qylx_dm = '03'的全部記錄數。
A:用CASE語句
select count(case a.zt when '07' then a.bs end),
    count(case a.zt when '11' then a.bs end)
  from dj_zt a
 where a.qylx_dm = '03
----------------
4565 7264
 
B:不用CASE語句(寫了兩條語句,掃描表兩遍,效率明顯低下)
select count(*)
  from dj_zt a
 where a.qylx_dm = '03'
   and a.zt='07'
----------------
4565 
 
select count(*)
  from dj_zt a
 where a.qylx_dm = '03'
   and a.zt='11'
----------------
7264 
 
結果:B組代價明顯高出A組不少,而且麻煩,A勝!
 
CASE語句的兩種格式:
1、上面是case單條件表達式的用法,屬於一種很是經常使用的特殊狀況。語法格式爲:
case <單值表達式>
       when <表達式值> then <SQL語句或者返回值>
       when <表達式值> then <SQL語句或者返回值>
       ...
       when <表達式值> then <SQL語句或者返回值>
       end
 
有個很典型的用法(測試DB2 SQL腳本環境見附件):
SELECT
(CASE X.XZ
        WHEN '01' THEN '內資'
        WHEN '02' THEN '外資'
        WHEN '03' THEN '私營'
        WHEN '04' THEN '個體'
        ELSE '變態性質'
 END
) AS XZ_MC
FROM ODS.dm_rpt_qyhf X
GROUP BY XZ;
 
注意:這語句用在查詢中,WHEN字句後面千萬不要加逗號或者引號。不然就錯了。
 
另外,這種語法經常使用於控制存儲過程的SQL流程或者用於一個條件多種分支(值)的狀況下執行不一樣的操做或返回(也叫獲取)不一樣的值。當用於存儲過程當中的時候,實際上已經不是基本SQL的CASE語句了,是存儲過程當中CASE語句,用來控制流程:
 
好比:用於存儲過程當中的case語句
case var1
    when '01' then values 'A' into var2;
    when '02' then values 'B' into var2;
    when '03' then values 'C' into var2;
    when '04' then values 'D' into var2;
    when '05' then values 'E' into var2;
    when '06' then values 'F' into var2;
    when '07' then values 'G' into var2;
    when '08' then values 'H' into var2;
    when '09' then values 'I' into var2;
    when '10' then values 'J' into var2;
    when '11' then values 'K' into var2;
    when '12' then values 'L' into var2;
    when '13' then values 'M' into var2;
    when '14' then values 'N' into var2;
    when '15' then values 'O' into var2;
    when '16' then values 'P' into var2;
    when '17' then values 'Q' into var2;
    when '18' then values 'R' into var2;
end case;
 
 
好比:用於單值條件表達式多分支查詢中
select count(case a.zt when '07' then a.bs end),
    count(case a.zt when '11' then a.bs end)
  from dj_zt a
 where a.qylx_dm = '03
 
 
 
2、下面是case語句更爲通用的用法:
case when <關係條件表達式> then <SQL語句或者返回值> end
 
例如:
select count(case when a.zt='07' then a.bs end),
    count(case when a.zt='11' then a.bs end)
  from dj_zt a
 where a.qylx_dm = '03
 
上面的sql實際上能夠改寫爲:
select count(case a.zt when '07' then a.bs end),
    count(case a.zt when '11' then a.bs end)
  from dj_zt a
 where a.qylx_dm = '03
 
二者在效率上沒有差異的。
 
 
總結:經過上面兩組實例能夠看出,靈活應用CASE語句可讓SQL變得簡潔高效,能夠明顯減小遍歷要查詢表的次數,從而大大提升了執行效率。並且,CASE的使用通常不會引發性能(相比沒有用CASE的語句)低下。
 
                                                   ----------<end>---------
相關文章
相關標籤/搜索