oracle對時區的支持比較完美了,有timestamp with time zone和timestamp with local time zone兩種數據類型。所謂timestamp with time zone,也就是把時區信息保存在列數據中,而timestamp with local time zone,會將用戶輸入的時間轉換爲數據庫服務器所在時區的時間,保存在列中,這樣能稍稍減少一點保存的數據量。因爲timestamp with local time zone中不會保存時區信息(時區與數據庫服務器所在時區相同),所以當數據庫中有表存在timestamp with local time zone 時,數據庫不能更改時區。如果有可能將數據庫跨時區遷移,最好還是用timestamp with time zone好了,該數據類型最具有擴展性。
說起時區,不得不提及幾個關於timestamp的函數了:
systimestamp 數據庫服務器當前的時間以及時區;
localtimestamp 客戶端當前時間,不包含時區;
current_timestamp 客戶端當前時區,包含客戶端的時區。
說了這麼多,下面看個例子,爲了看到例子的效果,我們首先修改客戶端的時區爲西五區(美國東部時間),實驗當前時間爲北京時間2010年01月03日早晨11點左右。
alter session set TIME_ZONE='-5:00';
然後新建一個表
CREATE TABLE TEST(ID number(2), time_tz timestamp with time zone, time_lc_tz timestamp with local time zone);
向表中插入幾行看看:
insert into test values (1,localtimestamp,localtimestamp); insert into test values (2,systimestamp,systimestamp); insert into test values (3,current_timestamp,current_timestamp); insert into test values (3,current_timestamp,current_timestamp); insert into test values(4,to_timestamp('2010-01-03 11:09:00','YYYY-MM-DD HH24:MI:SS'), to_timestamp('2010-01-03 11:09:00','YYYY-MM-DD HH24:MI:SS')); insert into test values(5,to_timestamp_tz('2010-01-03 11:09:00 +0:00','YYYY-MM-DD HH24:MI:SS TZH:TZM'), to_timestamp_tz('2010-01-03 11:09:00 +0:00','YYYY-MM-DD HH24:MI:SS TZH:TZM'));
提交插入的數據:COMMIT;
在當前session查詢看看:(當前session時區爲-5:00)
select * from test;
ID | TIME_TZ | TIME_LC_TZ |
---|---|---|
1 | 02-1月 -10 09.58.45.106141 下午 -05:00 | 02-1月 -10 09.58.45.106141 下午 |
2 | 03-1月 -10 10.58.45.130013 上午 +08:00 | 02-1月 -10 09.58.45.130013 下午 |
3 | 02-1月 -10 09.58.45.146003 下午 -05:00 | 02-1月 -10 09.58.45.146003 下午 |
4 | 03-1月 -10 11.09.00.000000 上午 -05:00 | 03-1月 -10 11.09.00.000000 上午 |
5 | 03-1月 -10 11.09.00.000000 上午 +00:00 | 03-1月 -10 06.09.00.000000 上午 |
ID TIME_TZ TIME_LC_TZ 1 02-1月 -10 09.58.45.106141 下午 -05:00 02-1月 -10 09.58.45.106141 下午 (localtimestamp不帶時區,所以這裏將session時區加上去了。)
2 03-1月 -10 10.58.45.130013 上午 +08:00 02-1月 -10 09.58.45.130013 下午 (systimestamp帶服務器所在時區,東八區)
3 02-1月 -10 09.58.45.146003 下午 -05:00 02-1月 -10 09.58.45.146003 下午 (current_timestamp 帶session所在時區)
4 03-1月 -10 11.09.00.000000 上午 -05:00 03-1月 -10 11.09.00.000000 上午 (插入timestamp 不帶時區,默認將session所在時區作爲時區) 5 03-1月 -10 11.09.00.000000 上午 +00:00 03-1月 -10 06.09.00.000000 上午 (插入timestamp with time zone帶時區)
不管如何插入,TIME_LC_TZ都會轉化爲數據庫所在的時區在表中保存,查詢時會轉化爲session所在的時區時間進行顯示。
打開另外一個客戶端,查詢test表,此時TIME_TZ列的顯示不變,TIME_LC_TZ列的顯示會轉換爲session所在的時區進行顯示(目前爲東八區)
select * from test;
ID | TIME_TZ | TIME_LC_TZ |
---|---|---|
1 | 02-1月 -10 09.58.45.106141 下午 -05:00 | 03-1月 -10 10.58.45.106141 上午 |
2 | 03-1月 -10 10.58.45.130013 上午 +08:00 | 03-1月 -10 10.58.45.130013 上午 |
3 | 02-1月 -10 09.58.45.146003 下午 -05:00 | 03-1月 -10 10.58.45.146003 上午 |
4 | 03-1月 -10 11.09.00.000000 上午 -05:00 | 04-1月 -10 12.09.00.000000 上午 |
5 | 03-1月 -10 11.09.00.000000 上午 +00:00 | 03-1月 -10 07.09.00.000000 下午 |
綜上,如果不喜歡自己換算時間,則用timestamp with local time zone,這樣只需將自己session所在的時區設置正確就OK了。如果喜歡保存原本的時區信息,則用timestamp with time zone。如果數據庫可能跨時區遷移,或者需要根據時區統計一些信息,則要用timestamp with time zone。