首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> DB2 資料庫 >> DB2 教學

DB2 基礎:日期時間操作完全指南

     編輯:DB2 教學

前言

DB2 對日期時間的支援極為直觀強大,初學者常驚喜於其簡潔語法。本文系統整理日期時間註冊器、擷取函數、運算技巧、格式轉換、自訂格式化函數等核心知識,並附上常見陷阱與內建函數速查表。

基礎註冊器與取值

-- 取得目前日期、時間、時間戳
SELECT current date FROM sysibm.sysdummy1;
SELECT current time FROM sysibm.sysdummy1;
SELECT current timestamp FROM sysibm.sysdummy1;

-- CLP 中可直接用 VALUES
VALUES current date;
VALUES current time;
VALUES current timestamp;

sysibm.sysdummy1 是特殊記憶體表,用於查詢註冊器值。

時區調整與元件擷取

-- 轉換為 GMT/UTC
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(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');

⚠️ 經典陷阱:遺漏引號導致邏輯錯誤

SELECT DATE(2001-09-22) FROM SYSIBM.SYSDUMMY1;
-- 結果:05/24/0006 (相差近 2000 年!)

原因:無引號時參數被視為數值運算 (2001-9)-22 = 1970,DATE(1970) 解釋為距公元元年 1970 天。日期字串務必加引號!

進階函數:TIMESTAMPDIFF 與精確秒差

TIMESTAMPDIFF(n, char(ts1-ts2)) 回傳近似差值(不考慮閏年、假設每月 30 天)。n 對應單位:1=秒微秒、2=秒、4=分、8=時、16=天、32=週、64=月、128=季、256=年。

精確秒差計算:

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

建議封裝為 UDF:

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

閏年判斷 UDF

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

內建日期時間函數速查表

函數說明
DAYNAME回傳星期名稱(如 Friday)
DAYOFWEEK星期幾(1=星期日)
DAYOFWEEK_ISOISO 星期幾(1=星期一)
DAYOFYEAR一年中的第幾天(1-366)
DAYS日期整數表示
JULIAN_DAY儒略日數(自公元前 4712-01-01)
MIDNIGHT_SECONDS午夜至指定時間的秒數(0-86400)
MONTHNAME月份名稱(如 January)
TIMESTAMP_ISO依日期/時間/時間戳回傳時間戳
TIMESTAMP_FORMAT依字元樣板解析字串為時間戳
TIMESTAMPDIFF兩時間戳近似差值
TO_CHAR / VARCHAR_FORMAT依樣板格式化時間戳為字串
TO_DATE / TIMESTAMP_FORMAT依樣板解析字串為時間戳
WEEK一年中的第幾週(1-54,週日為首)
WEEK_ISOISO 週數(1-53,週一為首)

資料庫層級日期格式變更

預設格式由建庫時的 territory 決定。可透過重新綁定工具包改變:

cd sqllib\bnd
db2 connect to DBNAME
db2 bind @db2ubind.lst datetime ISO blocking all grant public

支援格式:DEF(地區預設)、EUR、ISO(YYYY-MM-DD)、JIS、LOC、USA。

自訂格式化 UDF:ts_fmt

若需 yyyymmdd 等非標準格式,可自寫 UDF:

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@

使用範例:

VALUES ts_fmt(current timestamp,'yyyymmdd');  -- '20030818'
VALUES ts_fmt(current timestamp,'asa');       -- 'date format asa not recognized.'

結語

DB2 日期時間功能豐富且易用,掌握註冊器、擷取函數、自然語言運算、格式轉換與自訂 UDF,即能應對絕大多數業務場景。記住:字串字面值務必加引號,避免隱性數值運算導致驚人錯誤。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved