Informix數據庫由于其良好的動態擴展性,在各個行業得到了廣泛的使用和認可,但Informix數據庫自身也存在一點瑕疵(在比較新的Informix Online 9版本上仍然存在此問題)就是Informix的日期處理問題,只要需要處理日期邊界問題的時候,都會出錯!
比如你使用 SELECT DATE("20000229")- 1 UNITS YEAR FROM dual ,從“2000/02/29”往前推算1年,而1999年,不是閏年,其2月份只有28天,這時就會報錯(錯誤號1267)(出錯信息:1267: The result of a datetime computation is out of range.)
其它比如你從7月31日往前推1月,從1月31日/1月30日往后推1月,都會碰到日期邊界處理出錯的問題,給項目開發帶來一些困擾!
由于手頭的項目需要進行日期的靈活計算,所以我考慮針對這些日期邊界處理錯誤號(-1267、-1263、-1210)設置陷阱進行捕獲,發現日期邊界超限,則將日期往前推算,直到出現一個正常合法的日期為止!以下我改良的日期計算存儲過程算法,可以按照“日”“月”“季”“半年”“年”靈活的向前向后推算日期。
CREATE PROCEDURE p_random_date (
v_random_date DATE,
v_pass INT,
v_mode VARCHAR(1) DEFAULT 'M'
)
RETURNING DATE;
-- 參數 任意一天,經過月/天/年數,日期標度(月M,日D,年Y,半年H,季Q))
-- return 任意一天經過N月/天/年后的對應日,若對應日不存在,則往前推
DEFINE tmp_random_date DATE;
DEFINE rtndate DATE;
DEFINE v_pass1 INT;
DEFINE esql, eisam INT;
DEFINE etext VARCHAR(80);
ON EXCEPTION SET esql, eisam, etext
IF esql < 0 THEN
RAISE EXCEPTION esql, eisam, etext;
END IF
END EXCEPTION
LET tmp_random_date = v_random_date;
LET rtndate = NULL;
LET v_pass1 = 0;
IF v_mode = 'H' THEN
LET v_pass = v_pass*6;
ELIF v_mode = 'Q' THEN
LET v_pass = v_pass*3;
END IF;
{
SET DEBUG FILE TO "random.log";
TRACE ON;
}
WHILE 1 = 1
ON EXCEPTION SET esql
IF esql = -1267 THEN
LET tmp_random_date = tmp_random_date -1;
ELIF esql = -1263 THEN
--處理ONLINE7.3x BUG: 2004/02/20 -14(或15) UNITS MONTH出錯
LET v_pass1 = v_pass1 + 1;
ELIF esql = -1210 THEN
--處理ONLINE7.3x BUG: 2004/02/20 -14(或15) UNITS MONTH出錯
LET v_pass1 = v_pass1 + 1;
ELSE
RAISE EXCEPTION esql;
END IF;
END EXCEPTION;
IF v_mode = 'Y' THEN
LET rtndate = tmp_random_date+v_pass UNITS YEAR;
ELIF v_mode = 'D' THEN
LET rtndate = tmp_random_date+v_pass UNITS DAY;
ELSE -- v_mode IN ('M','H','Q')
LET rtndate = (tmp_random_date+(v_pass-v_pass1) UNITS MONTH)+
v_pass1 UNITS MONTH;
END IF
EXIT WHILE;
END WHILE;
RETURN rtndate;
END PROCEDURE;
調用舉例如下:
往前1個月 EXECUTE PROCEDURE p_random_date("20000229",-1,"M")
往后60天 EXECUTE PROCEDURE p_random_date("20000229",60,"D")
往前2 年 EXECUTE PROCEDURE p_random_date("20000229",-2,"Y")
新聞熱點
疑難解答