db2case语句_DB2 常用的SQL语句
1、組合語句執行
BEGINATOMIC
表達式1分號空格/回車
表達式2分號空格/回車
END
2、應該限制訪問權限的表(應該撤銷這些表PUBLIC SELECT訪問權)
SYSCAT.DBAUTH
SYSCAT.TABAUTH
SYSCAT.PACKAGEAUTH
SYSCAT.INDEXAUTH
SYSCAT.COLAUTH
SYSCAT.PASSTHRUAUTH
SYSCAT.SCHEMAAUTH
比較有用的目錄表
SYSCAT.COLUMNS:包含每一行對應于表或視圖中定義的列
SYSCAT.INDEXCOLUSE:包含每一行包含的所有列
SYSCAT.INDEXES:包含每一行對應于表或視圖中定義的每個索引
SYSCAT.TABLES:所創建每個表,視圖,別名對應其中一行
SYSCAT.VIEWS:所創建每個視圖對應其中一行或幾行
通過索引保持數據唯一性:CREATE UNIQUE INDEX INDEXNAME ON TABLE (COLUMN)
消除重復行:SELECT DISTINCT COLUMN FROM TABLE
3、DB2關于時間的一些函數
得到當前時間的年份、月份、天、小時等等:
YEAR (current timestamp)
MONTH (current timestamp)
DAY (current timestamp)
HOUR (current timestamp)
MINUTE (current timestamp)
SECOND (current timestamp)
MICROSECOND (current timestamp)
分別得到當時的日期和時間
DATE (current timestamp)
TIME (current timestamp)
關于時間的一些計算:
current date + 1 YEAR
current date + 3 YEARS + 2 MONTHS + 15 DAYS
current time + 5 HOURS - 3 MINUTES + 10 SECONDS
計算兩個日期之間有多少天:
days (current date) - days (date(’1999-10-22′))
得到去除毫秒的當前時間:
CURRENT TIMESTAMP - MICROSECOND (current timestamp) MICROSECONDS
將時間轉換成字符串:
char(current date)
char(current time)
char(current date + 12 hours)
將字符串轉換成時間:
TIMESTAMP (’2002-10-20-12.00.00.000000′)
TIMESTAMP (’2002-10-20 12:00:00′)
DATE (’2002-10-20′)
DATE (’10/20/2002′)
TIME (’12:00:00′)
TIME (’12.00.00′)
注意:在DB2的命令編輯器中可以輸入SQL語句和DB2中的內部命令。要想顯示當前時間的話,不能直接輸入current time,這個只能在SQL語言中引用,要想顯示有下面方式:
1)VALUES(current time)
2)SELECT?CURRENT TIME FROM SYSIBM.SYSDUMMY1
這個與SQL SERVER2000中不一樣,在SQL SERVER2000中可以輸入Getdate()得到時間,既可以顯示,也可以在語句SQL中用。
4、所有返回前N條數據的表達式
在SQL SERVER2000中使用TOP N格式
比如:SELECT TOP 10 CARDNO FROM CARD
在DB2中使用fetch first N rows only格式
比如:SELECT CARDNO FROM SEALCARD fetch first 10 rows only
5、函數使用
查看系統函數:SELECT * FROM?SYSibm.sysfunctions;
比如:ABS(-89)可以作為值輸入到SQL中,但是要想在命令編輯器中顯示函數的結果的話可以用下列方式:
1)SELECT ABS(-89) FROM SYSIBM.SYSDUMMY1;
2)VALUES ABS(-89);
6、存儲過程
在進行DB2存儲過程開發時,我們可以利用很多DB2自帶的工具,例如開發中心,控制中心等。但有時使用腳本能帶給開發人員更大的靈活性和更高的工作效率。
在開始開發一個新的或修改一個已存在的存儲過程時,我們通常會進行下面一些準備工作:
1.查看該存儲過程會用到的表的表結構、字段類型、相關索引和示例數據。
2.查看相關的存儲過程或用戶自定義函數(UDF)的定義。
3.查找無效的存儲過程并生成綁定語句。
4.如某個表發生了改變,查看依賴于該表的所有視圖、存儲過程和用戶自定義函數(UDF)
雖然上述信息都可以通過DB2提供的開發工具和管理工具獲得,但是通過腳本可以更快速的獲得所需信息,并且可以重復執行。
使用腳本完成上述任務的關鍵是理解和使用DB2的系統表。我們先簡單回顧一下有關的DB2的系統表和視圖:
1.syscat.routines:存儲所有的存儲過程和用戶自定義函數(UDF)信息。其中routinename字段為存儲過程或用戶自定義函數(UDF)的名稱,routinetype字段表示該記錄表示的是存儲過程(P)還是用戶自定義函數(F),lib_id字段為存儲過程編譯后生成的包序列號,origin字段表示該存儲過程或用戶自定義函數的出處(Q表示是由SQL組成的,E表示用戶定義的且是外部的),valid字段表示該存儲過程或用戶自定義函數是否有效,如果origin字段不是Q的話,該域為空。
2.syscat.packages:存儲所有被綁定的程序包。其中pkgname表示包名稱,valid字段表示該包是否合法。
3.syscat.packagedep:存儲關于程序包的依賴關系。其中pkgname字段表示程序包名,btype字段表示被依賴對象的類型,bname字段表示被依賴對象的名稱。
4.syscat.routinedep:存儲關于程序(routine)的依賴關系。其中routinename字段表示程序名,btype字段表示被依賴對象的類型,bname字段表示被依賴對象的名稱。
5.syscat.viewdep:存儲了關于視圖的依賴關系。其中viewname字段表示視圖名,btype字段表示被依賴對象的類型,bname字段表示被依賴對象的名稱。
回顧并了解了上述系統表和視圖,我們就可以很容易的創建腳本以完成前面提到的開發存儲過程所要做的準備工作。
1.查看該表結構、字段類型、相關索引和示例數據
雖然我們可以查詢sysibm.systables表獲得表結構,但有一種更簡便的方法來獲取表結構,即使用db2look工具。該工具可以生成創建該表和相關的索引的DDL。如我們要獲取指定數據庫中指定表的結構和前20條數據作為參考,可編寫腳本viewtbl.cmd如下,傳入參數分別為數據庫名和表名。
@echo ------------------ DDL of table %2 and related index(ex)?------------------
@db2look -d %1 -t %2 -e
@echo?------------------ fisrt 20 rows in table %2 ------------------
@db2 select * from %2 fetch first 20 rows only
2.查看已存在的存儲過程和用戶自定義函數(UDF)的定義,將結果存入文件并自動打開結果文件。
可以從syscat.routines表中做簡單查詢實現腳本viewrtn.cmd。
@db2 SELECT text?FROM SYSCAT.ROUTINES WHERE ROUTINENAME=upper('%1') > %1.sql
@start %1.sql
3.查看所有無效的存儲過程并生成綁定語句
刪除存儲過程引用的表會引起該存儲過程無效。無效存儲過程可以采用查詢syscat.routines和syscat.packages的方法獲得:
SELECT
RTRIM(r.routineschema) || '.' || RTRIM(r.routinename) AS spname?,
RTRIM(r.routineschema) || '.' || 'P'||SUBSTR(CHAR(r.lib_id+10000000),2) AS pkgname
FROM
SYSCAT.routines r
WHERE
r.routinetype = 'P'
AND (
(r.origin = 'Q' AND r.valid != 'Y')
OR EXISTS (
SELECT 1 FROM syscat.packages
WHERE pkgschema = r.routineschema
AND pkgname = 'P'||SUBSTR(CHAR(r.lib_id+10000000),2)
AND valid !='Y'
)
)
ORDER BY spname
注意要同時查詢syscat.routines和syscat.packages表,因為在程序包無效時syscat.routines中的valid值仍可能為Y。
如果要自動生成重新綁定語句,只需將上述SQL改寫并存成invalidSP.cmd:
@echo off
db2 "SELECT '@db2 rebind package '|| RTRIM(r.routineschema) || '.' || 'P'||SUBSTR(CHAR(r.lib_id+10000000),2)||' resolve any' FROM SYSCAT.routines r WHERE r.routinetype = 'P' AND ((r.origin = 'Q' AND r.valid != 'Y') OR EXISTS (SELECT 1 FROM syscat.packages WHERE pkgschema = r.routineschema AND pkgname = 'P'||SUBSTR(CHAR(r.lib_id+10000000),2) AND valid !='Y') )" >rebindsp.bat
4.查看某個表所依賴的視圖、存儲過程和用戶自定義函數(UDF)
使用上述系統視圖,我們很容易編寫出腳本:
@echo off
echo --- dependent SPs ---
db2 "select proc.procschema, proc.procname from syscat.routines r, syscat.procedures proc, syscat.packagedep pdep where pdep.bname=upper('%2') and pdep.bschema=upper('%1') and r.specificname=proc.specificname AND pdep.pkgname = 'P'||SUBSTR(CHAR(r.lib_id+10000000),2)"
echo --- dependent UDF ---
db2 select routineschema, routinename from syscat.routinedep where bschema = upper('%1')?and bname = upper('%2') and btype ='T'?order by bname
echo --- dependent view ---
db2 select viewschema, viewname from syscat.viewdep where bschema = upper('%1')?and bname = upper('%2') and btype ='T' order by bname
行業借鑒經驗:提高DB2存儲過程性能和健壯性的3個最佳實踐
最佳實踐1:在創建存儲過程語句中提供必要的參數
創建存儲過程語句(CREATE PROCEDURE)可以包含很多參數,雖然從語法角度講它們不是必須的,但是在創建存儲過程時提供這些參數可以提高執行效率。下面是一些常用的參數:
l容許SQL(allowed-SQL)
容許SQL(allowed-SQL)子句的值指定了存儲過程是否會使用SQL語句,如果使用,其類型如何。它的可能值如下所示:
NO SQL:表示存儲過程不能夠執行任何SQL語句。
CONTAINS SQL:表示存儲過程可以執行SQL語句,但不會讀取SQL數據,也不會修改SQL數據。
READS SQL DATA:表示在存儲過程中包含不會修改SQL數據的SQL語句。也就是說該儲存過程只從數據庫中讀取數據。
MODIFIES SQL DATA:表示存儲過程可以執行任何SQL語句。即可以對數據庫中的數據進行增加、刪除和修改。
如果沒有明確聲明allowed-SQL,其默認值是MODIFIES SQL DATA。不同類型的存儲過程執行的效率是不同的,其中NO SQL效率最好,MODIFIES SQL DATA最差。如果存儲過程只是讀取數據,但是因為沒有聲明allowed-SQL類型,它會被當作對數據進行修改的存儲過程來執行,這顯然會降低程序的執行效率。因此創建存儲過程時,應當明確聲明其allowed-SQL類型。
l返回結果集個數(DYNAMIC RESULT SETS n)
存儲過程能夠返回0個或者多個結果集。為了從存儲過程中返回結果集,需要執行如下步驟:
在CREATE PROCEDURE語句的DYNAMIC RESULT SETS子句中聲明存儲過程將要返回的結果集的數量。如果這里聲明的返回結果集的數量小于存儲過程中實際返回的結果集數量,在執行該存儲過程的時候,DB2會返回一個警告。
使用WITH RETURN子句,在存儲過程體中聲明游標。
為結果集打開游標。當存儲過程返回的時候,保持游標打開。
在創建存儲過程時指定返回結果集的個數可以幫助程序員驗證存儲過程是否返回了所期待數量的結果集,提高了程序的完整性。
最佳實踐2:對輸入參數進行必要的的檢查和預處理
無論使用哪種編程語言,對輸入參數的判斷都是必須的。正確的參數驗證是保證程序良好運行的前提。同樣的,在DB2存儲過程中對輸入參數的驗證和處理也是很重要的。正確的驗證和預處理操作包括:
如果輸入參數錯誤,存儲過程應返回一個明確的值告訴客戶應用,然后客戶應用可以根據返回的值進行處理,或者向存儲過程提交新的參數,或者去調用其他的程序。
根據業務邏輯,對輸入參數作一定的預處理,如大小寫的轉換,NULL與空字符串或0的轉換等。
在DB2儲存過程開發中,如需要遇到對空(NULL)進行初始化,我們可以使用COALESCE函數。該函數返回第一個非NULL的參數。例如,COALESCE(piName,''),如果變量piName為NULL,那么函數會返回'',否則就會返回piName本身的值。因此,可以用下面的代碼檢查piName是否非NULL并且非空字符串:
SETpoGenStatus=0;
SETpiName=RTRIM(COALESCE(piName,''));
IF(piName='')
THEN
SETpoGenStatus=34100;
RETURNpoGenStatus;
ENDIF;
同理,使用COALESCE可以對任何類型的輸入參數進行初始化或驗證。下面是對參數初始化規則的一個總結:
1.輸入參數為字符類型,且允許為NULL的,如希望缺省值為空字符串,可以使用COALESCE(inputParameter, '')把NULL轉換成空字符串;
2.輸入類型為整型,且允許為NULL的,如希望缺省值為0,可以使用COALESCE(inputParameter,0),把NULL轉換成0;
3.輸入參數為字符類型,且不允許是NULL或空字符串的,可以使用RTRIM(COALESCE(inputParameter, ''))把NULL轉換成空字符串,然后驗證函數返回值是否為空字符串;
4.輸入類型為整型,且不允許是NULL的,不需要使用COALESCE函數,直接使用IS NULL進行驗證。
最佳實踐3:異常(condition)處理
在存儲過程執行的過程中,經常因為數據或者其他問題產生異常(condition)。根據業務邏輯,存儲過程應該對異常進行相應處理或直接返回給調用者。此處暫且將condition譯為異常以方便理解。實際上有些異常(condition)并非是由于錯誤引起的。
當存儲過程中的語句返回的SQLSTATE值超過00000的時候,就表明在存儲過程中產生了一個異常(condition),它表示出現了錯誤、數據沒有找到或者出現了警告。為了處理存儲過程中出現的異常,我們必須在存儲過程體中聲明異常處理器(condition handler),它可以決定存儲過程怎樣響應一個或者多個系統定義的異常或者自定義異常。
異常處理器類型(handler-type)有以下幾種:
lCONTINUE:在處理器操作完成之后,會繼續執行產生這個異常語句之后的下一條語句。
lEXIT:在處理器操作完成之后,存儲過程會終止,并將控制返回給調用者。
lUNDO:在處理器操作執行之前,DB2會回滾存儲過程中執行過的SQL操作。在處理器操作完成之后,存儲過程會終止,并將控制返回給調用者。
異常處理器可以處理基于特定SQLSTATE值的自定義異常,或者處理系統預定義異常。系統預定義的3種異常如下所示:
lNOT FOUND:標識導致SQLCODE值為+100或者SQLSATE值為02000的異常。這個異常通常在SELECT沒有返回行的時候出現。
lSQLEXCEPTIOIN:標識導致SQLCODE值為負的異常。
lSQLWARNING:標識導致警告異常或者導致正100以上的SQLCODE值的異常。
如果產生了NOT FOUND或者SQLWARNING異常,并且沒有為這個異常定義異常處理器,系統就會忽略這個異常,并且將控制流轉向下一個語句。如果產生了SQLEXCEPTION異常,并且沒有為這個異常定義異常處理器,那么存儲過程就會失敗,系統會將控制流返回調用者。因此如果開發人員想改變這種異常處理流程,必須自定義異常處理器。例如,希望在出現SQLWARNING異常時也終止存儲過程,并將名為stmt的變量設為“ABORTED”,可以定義下面語句定義異常處理器:
DECLAREEXITHANDLERFORSQLEXCEPTION, SQLWARNING
SETstmt='ABORTED';
如果預定義異常集仍不能滿足需求,可以為特定的SQLSTATE值聲明自定義異常,然后再為這個異常定制異常聲明處理器。為特定的SQLSTATE值聲明自定義異常的語法如下:
DECLARE condition-name CONDITION FOR SQLSATE‘mysqlstate’
定義了異常和異常處理器后,在存儲過程執行的任何都使用SIGNAL condition-name語句觸發這種自定義類型的異常。
異常處理器可以由單獨的存儲過程語句定義,也可以使用復合語句定義。注意在執行復合語句的時候,SQLSATE和SQLCODE的值會被改變,如果需要保留異常前的SQLSATE和SQLCODE值,就需要在復合語句中的第一個語句把SQLSATE和SQLCODE賦予本地變量或參數。下面是一個例子:
DECLARECONTINUEHANDLERFORSQLEXCEPTION, SQLWARNING,NOTFOUND
BEGINNOTATOMIC
-- Capture SQLCODE & SQLSTATE?to local variables
SELECTSQLCODE, SQLSTATE
INTOhSqlcode, hSqlstate
FROMSYSIBM.SYSDUMMY1;
-- your handler statements below
……
END;
應用難點技巧:使用Case讓你的SQL語句有條件的執行
我們在編寫SQL語句時,常常遇到希望SQL能夠按條件執行的情況。這里的條件不是指Where子句中的條件,而是指讓DB2根據條件執行SQL的語句塊。大多數情況下我們可以使用case來實現。
例如,我們希望從員工表中查出員工的工資情況,如果小于20000,則標志為low,20000到50000間為middle,否則為high。一般大家會想到先取出工資數據然后在Java代碼中做判斷,但我們也可以在SQL中完成上述操作。如下例:
select empno, sex, salary,
case
when salary < 20000 then 'low'
when salary >=20000 and salary <50000 then 'middle'
else 'high'
end as salaryclass
from employee
類似的,如果想在SQL語句中把性別翻譯成文字,也可以用case實現,注意這兩條SQL語句使用了不同的case表達式寫法:
select empno,
case sex
when 'M' then 'male'
when 'F' then 'female'
else 'invalid'
end,
salary
from employee
Case不但能夠在Select子句中使用,在From子句和Where子句中同樣可以使用。下面是在Where子句中使用的一個例子:
select empno, sex, age
from employee
where
case sex
when 'M' then 55
when 'F' then 50
end > age
在From子句中使用的例子極為少見,下面是一個極端的例子。在合同表ctrct_list、客戶表customer和訂單表quote中都有合同號字段,但訂單表中的合同號可能為空。要求查詢出訂單表訂單id和合同號,如訂單表中合同號為空的話,查出客戶表中相應的合同號。
select distinct
q.quote_id,
case rtrim(coalesce(q.ctrct_num, ''))
when '' then rtrim(coalesce(c.ctrct_num, ''))
else rtrim(coalesce(q.ctrct_num, ''))
end ctrct_num
from
(quote q
left outer join customer c
on?q.sold_to_cust_num = c.cust_num)
inner join ctrct_list cl
on?cl.cust_num = q.sold_to_cust_num
and cl.ctrct_num = (
case rtrim(coalesce(q.ctrct_num, ''))
when '' then c.ctrct_num
else q.ctrct_num
end
)
有時讓SQL語句有條件的執行也可以不使用case。下面是一個例子:
select *
from EMPLOYEE
WHERE
((job='MANAGER') AND vMgrFlag=1)
or
((job='DESIGNER' or job='ANALYST') AND vTechFlag =1)
or
((job='CLERK' or job='OPERATOR') AND vOfficeFlag=1)
此SQL可以要求根據標志位的不同選擇出不同類型的雇員。各個標志位在執行SQL前應提前設置好。這種方法可以在某些情況下將動態SQL改寫為靜態SQL,因此在編寫存儲過程時非常實用。但要指出的是,DB2的查詢優化器不可能將這種SQL也優化得非常高效,因此在數據量比較大時可能會帶來性能問題。開發人員需要在編寫完成后使用實際數據測試,必要的話進行性能優化。
總結
以上是生活随笔為你收集整理的db2case语句_DB2 常用的SQL语句的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 斗罗大陆魂师对决千仞雪怎么加点?
- 下一篇: python和anaconda的区别_a