DB2 時間函數小結


  1. 這篇比較簡單明瞭
  2. --獲取當前日期:  
  3.  
  4. select current date from sysibm.sysdummy1;   
  5. values current date;  
  6.  
  7. --獲取當前日期   
  8. select current time from sysibm.sysdummy1;   
  9. values current time;   
  10. --獲取當前時間戳   
  11. select current timestamp from sysibm.sysdummy1;   
  12. values current timestamp;   
  13.  
  14. --要使當前時間或當前時間戳記調整到 GMT/CUT,則把當前的時間或時間戳記減去當前時區寄存器:  
  15.  
  16. values current time -current timezone;   
  17. values current timestamp -current timezone;   
  18.  
  19. --獲取當前年份  
  20.  
  21. values year(current timestamp);  
  22.  
  23. --獲取當前月   
  24. values month(current timestamp);  
  25.  
  26. --獲取當前日   
  27. values day(current timestamp);  
  28.  
  29. --獲取當前時   
  30. values hour(current timestamp);  
  31.  
  32. --獲取分鐘   
  33. values minute(current timestamp);  
  34.  
  35. --獲取秒   
  36. values second(current timestamp);  
  37.  
  38. --獲取毫秒   
  39. values microsecond(current timestamp);   
  40.  
  41. --從時間戳記單獨抽取出日期和時間  
  42.  
  43. values date(current timestamp);   
  44. values VARCHAR_FORMAT(current TIMESTAMP,'yyyy-mm-dd');   
  45. values char(current date);   
  46. values time(current timestamp);   
  47.  
  48. --執行日期和時間的計算  
  49.  
  50. values current date+1 year;      
  51. values current date+3 years+2 months +15 days;   
  52. values current time +5 hours -3 minutes +10 seconds;   
  53.  
  54. --計算兩個日期之間的天數  
  55.  
  56. values days(current date)- days(date('2010-02-20'));   
  57.  
  58. --時間和日期換成字符串  
  59.  
  60. values char(current date);   
  61. values char(current time);   
  62.  
  63. --要將字符串轉換成日期或時間值  
  64.  
  65. values timestamp('2010-03-09-22.43.00.000000');   
  66. values timestamp('2010-03-09 22:44:36');   
  67. values date('2010-03-09');   
  68. values date('03/09/2010');   
  69. values time('22:45:27');   
  70. values time('22.45.27');   
  71.  
  72. --計算兩個時間戳記之間的時差:  
  73.  
  74. --秒的小數部分爲單位   
  75. values timestampdiff(1,char(current timestamp - timestamp('2010-01-01-00.00.00')));   
  76. --秒爲單位   
  77. values timestampdiff(2,char(current timestamp - timestamp('2010-01-01-00.00.00')));   
  78. --分爲單位   
  79. values timestampdiff(4,char(current timestamp - timestamp('2010-01-01-00.00.00')));   
  80. --小時爲單位   
  81. values timestampdiff(8,char(current timestamp - timestamp('2010-01-01-00.00.00')));   
  82. --天爲單位   
  83. values timestampdiff(16,char(current timestamp - timestamp('2010-01-01-00.00.00')));   
  84. --周爲單位   
  85. values timestampdiff(32,char(current timestamp - timestamp('2010-01-01-00.00.00')));   
  86. --月爲單位   
  87. values timestampdiff(64,char(current timestamp - timestamp('2010-01-01-00.00.00')));   
  88. --季度爲單位   
  89. values timestampdiff(128,char(current timestamp - timestamp('2010-01-01-00.00.00')));   
  90. --年爲單位   
  91. values timestampdiff(256,char(current timestamp - timestamp('2010-01-01-00.00.
另外一篇比較詳細的相關介紹:

1 基礎知識
2 日期函數
3 修改日期格式
4 客戶化日期/時間格式
5 小節

這篇文章目的是讓DB2的初學者瞭解DB2中的日期和時間的應用,相信使用過其它數據庫的大部分人都會很驚喜地發現在DB2中操作日期和時間是多麼簡單。
本文適用於 IBM DB2 Universal Database for Linux、UNIX 和 Windows。

 
1 基礎知識
爲了用SQL語句得到當前的日期,時間和時間戳,可以使用相應的DB2寄存器:

SELECT current date FROM sysibm.sysdummy1
SELECT current time FROM sysibm.sysdummy1
SELECT current timestamp FROM sysibm.sysdummy1

sysibm.sysdummy1表是一個在內存中特殊的表,可以使用上面的語句得到DB2寄存器的值。您也還可以用關鍵字VALUES來獲取寄存器中的值。例如,在DB2命令行處理器中,可以用下面的SQL語句獲取同樣的信息:

VALUES current date
VALUES current time
VALUES current timestamp

在下面的示例中,我將只提供函數或表達式,而不再重複 SELECT ... FROM sysibm.sysdummy1 或使用VALUES子句。

要使當前時間或當前時間戳調整到格林威治標準時間(GMT/CUT),可以把當前的時間或時間戳減去當前時區寄存器:

current time - current timezone
current timestamp - current timezone

給定了日期、時間或時間戳,則使用適當的函數抽取出(如果適用的話)年、月、日、時、分、秒及微秒各部分:

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()函數:

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')

TIMESTAMP()、DATE()和TIME()函數接受更多種格式。上面幾種格式只是示例,我將把它作爲一個練習,讓讀者自己去發現其它格式。

警告: 
引用自Graeme Birchall著《 DB2 UDB V8.1 SQL Cookbook》 
(http://ourworld.compuserve.com/homepages/Graeme_Birchall).

如果在DATE函數中忘記加單引號會發生什麼呢?函數依然可以執行,可是結果是錯的:

SELECT DATE(2001-09-22) FROM SYSIBM.SYSDUMMY1;

結果: 
======
05/24/0006

爲什麼會有2000多年的差別呢?
當日期DATE函數讀取字符作爲輸入的時候,它會將它轉換爲相應的DB2日期;如果讀取的是數字,就會把其轉換爲從0001-01-01日起到該數字的那一天,上面的例子中,2001-09-22=1970,也就是0001-01-01後的第1970天。

2 日期函數
有時,您需要知道兩個時間戳記之間的時差。爲此,DB2 提供了一個名爲TIMESTAMPDIFF()的內置函數。但該函數返回的是近似值,因爲它不考慮閏年,而且假設每個月只有 30 天。以下示例描述瞭如何得到兩個日期的近似時差:

timestampdiff (<n>, char(
timestamp('2002-11-30-00.00.00')-
timestamp('2002-11-08-00.00.00')))

對於 <n>,可以使用以下各值來替代,以指出結果的時間單位:

1 = 秒的小數部分 
2 = 秒 
4 = 分 
8 = 時 
16 = 天 
32 = 周 
64 = 月 
128 = 季度 
256 = 年

當日期很接近時使用timestampdiff()比日期相差很大時精確。如果需要進行更精確的計算,可以使用以下方法來確定時差(按秒計):

(DAYS(t1) - DAYS(t2)) * 86400 + 
(MIDNIGHT_SECONDS(t1) - MIDNIGHT_SECONDS(t2))

爲方便起見,還可以對上面的方法創建SQL用戶自定義函數:

CREATE FUNCTION secondsdiff(t1 TIMESTAMP, t2 TIMESTAMP)
RETURNS INT
RETURN (
(DAYS(t1) - DAYS(t2)) * 86400 + 
(MIDNIGHT_SECONDS(t1) - MIDNIGHT_SECONDS(t2))
)
@

如果需要確定給定年份是否是閏年,這裏有一個很有用的SQL函數,您可以創建它來確定給定年份的天數:
CREATE FUNCTION daysinyear(yr INT)
RETURNS INT
RETURN (CASE (mod(yr, 400)) WHEN 0 THEN 366 ELSE 
CASE (mod(yr, 4)) WHEN 0 THEN 
CASE (mod(yr, 100)) WHEN 0 THEN 365 ELSE 366 END 
ELSE 365 END
END)@

最後,以下是一張用於日期操作的內置函數表。它旨在幫助您快速確定可能滿足您要求的函數,但未提供完整的參考。
有關這些函數的更多信息,請參考SQL Reference。

SQL日期和時間函數:


DAYNAME :返回一個大小寫混合的字符串,對於參數的日部分,用星期表示這一天的名稱(例如,Friday)。
DAYOFWEEK: 返回參數中的星期幾,用範圍在 1-7 的整數值表示,其中 1 代表星期日。
DAYOFWEEK:_ISO 返回參數中的星期幾,用範圍在 1-7 的整數值表示,其中 1 代表星期一。
DAYOFYEAR: 返回參數中一年中的第幾天,用範圍在 1-366 的整數值表示。
DAYS: 返回日期的整數表示。
JULIAN_DAY: 返回從公元前 4712 年 1 月 1 日(儒略日曆的開始日期)到參數中指定日期值之間的天數,用整數值表示。
MIDNIGHT_SECONDS: 返回午夜和參數中指定的時間值之間的秒數,用範圍在 0 到 86400 之間的整數值表示。
MONTHNAME: 對於參數的月部分的月份,返回一個大小寫混合的字符串(例如,January)。
TIMESTAMP_ISO: 根據日期、時間或時間戳記參數而返回一個時間戳記值。
TIMESTAMP_FORMAT: 從已使用字符模板解釋的字符串返回時間戳記。
TIMESTAMPDIFF: 根據兩個時間戳記之間的時差,返回由第一個參數定義的類型表示的估計時差。
TO_CHAR: 返回已用字符模板進行格式化的時間戳記的字符表示。TO_CHAR: 是 VARCHAR_FORMAT 的同義詞。
TO_DATE: 從已使用字符模板解釋過的字符串返回時間戳記。TO_DATE 是 TIMESTAMP_FORMAT 的同義詞。
WEEK: 返回參數中一年的第幾周,用範圍在 1-54 的整數值表示。以星期日作爲一週的開始。
WEEK_ISO: 返回參數中一年的第幾周,用範圍在 1-53 的整數值表示。

3 修改日期格式
我經常會收到關於日期格式的問題。默認的日期格式由數據庫的數據庫國家/地區代碼(TERRITORY CODE)決定(數據庫國家/地區代碼是在數據庫創建時確定的)。例如,在我的數據庫時由數據庫國家/地區代碼US創建的,時間格式的輸出如下:

values current date
1
----------
05/30/2003

1 record(s) selected.

即時間格式爲DD/MM/YYYY。如果希望修改格式,您需要使用不同的時間格式重新聯編DB2工具包。支持的格式有:

DEF 使用和數據庫國家/地區代碼相關的日期時間格式。
EUR 使用IBM歐洲標準日期時間格式。
ISO 使用ISO日期時間格式。
JIS 使用日本工業標準日期時間格式。
LOC 使用和數據庫國家/地區代碼結合的本地日期時間格式。
USA 使用IBM美國標準時間日期格式。


使用下面的步驟修改時間日期格式爲ISO格式(YYYY-MM-DD):

1. 在命令行下,更改到sqllib\bnd目錄。
例如: 
在Windows平臺: c:\program files\IBM\sqllib\bnd 
在UNIX平臺 : /home/db2inst1/sqllib/bnd

2.以SYSADM組成員的身份連接數據庫: 
db2 connect to 數據庫名
db2 bind @db2ubind.lst datetime ISO blocking all grant public

(您實際應用中,修改數據庫名和期望的時間格式)

上面工作完成後,您可以看到日期格式變更爲:

values current date
1
----------
2003-05-30

1 record(s) selected.

4 客戶化日期/時間格式
上面的例子,我們演示瞭如何修改DB2輸出日期格式爲那些本地化的格式。如果您的客戶希望日期格式爲YYYYMMDD怎麼辦呢?最好的方法時寫一個客戶化的格式化函數:

下面時就時用戶自定義函數的例子:
create function ts_fmt(TS timestamp, fmt varchar(20))
returns varchar(50)
return
with tmp (dd,mm,yyyy,hh,mi,ss,nnnnnn) as
(
select
substr( digits (day(TS)),9),
substr( digits (month(TS)),9) ,
rtrim(char(year(TS))) ,
substr( digits (hour(TS)),9),
substr( digits (minute(TS)),9),
substr( digits (second(TS)),9),
rtrim(char(microsecond(TS)))
from sysibm.sysdummy1
)
select
case fmt
when 'yyyymmdd'
then yyyy || mm || dd
when 'mm/dd/yyyy'
then mm || '/' || dd || '/' || yyyy
when 'yyyy/dd/mm hh:mi:ss'
then yyyy || '/' || mm || '/' || dd || ' ' || 
hh || ':' || mi || ':' || ss
when 'nnnnnn'
then nnnnnn
else
'date format ' || coalesce(fmt,' ') || 
' not recognized.'
end
from tmp


這個公式乍看起來比較複雜,細看一下,您會發現它還是很簡單易用的。首先,使用公共表表達式(Common Table Expression)將時間格式中每一個部分提取出來,然後根據用戶提供的日期格式重新組裝輸出。這個函數很靈活,用戶可以簡單地添加WHEN子句來加上期望的日期格式。使用函數時,如果輸入的日期格式沒有,函數還可以輸出出錯信息。

例如:
values ts_fmt(current timestamp,'yyyymmdd')
'20030818'
values ts_fmt(current timestamp,'asa') 
'date format asa not recognized.'

5 小節

這些示例回答了我在日期和時間方面所遇到的最常見問題。如果讀者的反饋中認爲我應該用更多示例來更新本文,那麼我會那樣做的。(事實上,我已經對本文更新了三次,感謝讀者對本文的反饋。)


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章