oracle,mysql,sqlserver--java對日期字段的操做

最近工做中用到了這三種數據庫對日期字段的操做,現作以下總結。java

1.數據庫字段與java類型的對應關係。mysql

明白這對應關係,咱們才能正確的使用PreparedStatement設置參數sql

2.關於日期字段的幾點說明數據庫

首先任何的日期字段設置的時候都應儘可能保持類型對應設置。oracle

好比:oracle的date字段,若是你想保留年月日時分秒,那麼就應該用函數

setTime(java.sql.Time)或者setTimestamp(java.sql.Timestamp)來設置值,這兩個仍是有區別的儘管執行結果會同樣sqlserver

再好比:若是是mysql的time字段設置值那麼應該是spa

setTime(java.sql.Time)code

 

雖然,其餘的設置也能夠執行成功,注意這裏說的是成功,並非說合理orm

好比:若是是mysql的time字段設置值,你經過

setTimestamp(java.sql.Timestamp)設置值,那麼其實到數據庫裏只會用到時分秒字段。這中方式還能夠理解,並且還算合理(由於畢竟有時分秒而且這個時分秒是有效的)

若是經過setDate(java.sql.Date)來設置值,那麼問題就大了,由於你設置了java.sql.Date,而這麼設置,數據庫只會拿到時分秒,而這個Date類型是沒有時分秒的,也就是說我取時分秒字段,而你沒有時分秒字段,那還了得,確定不合理。

 

因此,爲啥說,不一樣的數據庫,必定要根據不一樣數據庫的不一樣字段對應的字段關係來合理使用setDate,setTime,setTimestamp方法,請參照第一點說的

 

3.oracle的日期字段,這個至關特別

從第一點java與數據庫的對應關係上看,發現一個難以想象的問題。那就是java.sql.Time對應了oracle中的date類型。別人都是java.sql.Timestamp類型對應日期字段(包含年月日時分秒的),並且別人java.sql.Time對應的都是時分秒字段(沒有年月日)

咱們都知道oracle的date類型包含了年月日時分秒(固然也能夠存儲沒有時分秒的),而java.sql.Time只是存儲了時間信息(至少對於mysql,sqlserver都是這麼用的,只用到了時分秒。但實際上java.sql.Time可定會存儲年月日信息,不然oracle怎麼能準確獲取到年月日信息)

沒錯,oracle經過setTime字段設置的參數,到數據庫中仍然會準確的保存到年月日信息(前提是你的數據庫字段得是date或者timestamp類型)

 

你覺得這麼就完了嗎?

錯,oracle還有個使人噁心的,你說你java.sql.Time對應數據的date字段就對應吧,獲取的時候若是經過getTime()獲取日期date字段,那麼恭喜你你上當了,獲取到的日期變成了1970-01-01 xx:xx:xx 時分秒是對的,可是日期是什麼啊。

正確的獲取方式是經過getTimestamp()方法來獲取

舉個oracle的例子,t_1表中有四個字段

id number類型

tdate1 date類型

tdate2 timestamp類型

tdate3 date類型

 

注意記錄的樣子,

tdate1我是經過setDate(java.sql.Date)設置的

tdate2我是經過setTimestamp(java.sql.Timestamp)設置的

tdate3我是經過setTime(java.sql.Time)設置的(固然也能夠經過setTimestamp(java.sql.Timestamp)設置值)

 

可是查詢這條記錄的時候:

tdate1字段值的獲取經過getDate()

tdate2字段值的獲取經過getTimestamp()

tdate3字段值的獲取經過getTimestamp(),注意這裏千萬不能使用getTime()獲取

 

3.說一說oracle中,setTimestamp和setTime的區別(mysql,sqlserver沒有這種區別,由於他們的java.sql.Time不會對應日期字段(包含年月日時分秒的日期字段))

要說區別,對於結果可能沒什麼區別或者說區別不大(不管是更新仍是插入,結果都是同樣的,都年月日時分秒),可是執行效率確實不同的,怎樣肯定執行效率,那就須要查詢oracle的執行計劃才能明白。

實驗:仍是第二點的表,咱們如今更新一下id字段,where條件是tdate3=?

String sql="update t_1 set id=12 where tdate3=?";

		PreparedStatement ps= conn.prepareStatement(sql);
		java.util.Date d=new java.util.Date(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2016-07-23 21:31:19").getTime());
		ps.setTimestamp(1, new Timestamp(d.getTime()));
	    System.out.println(ps.executeUpdate());

查看該條語句執行計劃:查看方法不在這裏提了

關鍵點在於filter(INTERNAL_FUNCTION("TDATA3")),這句話的意思是內部函數進行了類型轉換,而後匹配傳過來的參數,注意這裏轉換的是字段,而不是傳過來的值。

 

一樣,咱們經過setTime試試
 

String sql="update t_1 set id=13 where tdate3=?";
		
		System.out.println(conn);
		PreparedStatement ps= conn.prepareStatement(sql);
		java.util.Date d=new java.util.Date(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2016-07-23 21:31:19").getTime());
		ps.setTime(1, new Time(d.getTime()));
	    System.out.println(ps.executeUpdate());

查詢執行計劃:filter("TDATE3"),也就是說沒有進行任何的類型轉換,直接賦值了

 

再來講說,類型轉換與不轉換的區別。

類型轉換,oracle會調用內部的函數對字段進行轉換,而後匹配,這種訪問速度確定沒有不進行任何類型轉換的速度快,這就涉及到了執行效率問題。

特別注意,若是時間字段是索引字段,那麼這兩種訪問速度差距會很大。

一樣,也能夠進行試驗。

那就是將tdate3字段做爲主鍵,id做爲普通字段。

而後執行上述試驗過程,會發現:

經過setTimestamp設置的參數,走的是全表掃描 TABLE ACCESS FULL|

而經過setTime設置的參數,走的是INDEX UNIQUE SCAN    惟一鍵索引,這速度確定要比全表掃描快得多。

 

4.mysql,sqlserver說明

mysql,sqlserver沒有oracle這種變態的問題

對應什麼類型就是什麼類型,setTimestamp設置的參數,就經過getTimestamp獲取,

setDate設置的參數就經過getDate獲取,setTime設置的參數,就經過getTime獲取

 

5.總結

不一樣字段的類型參數設置必定要按照對應的java類型來設置參數,儘管不一樣的類型也可能設置成功,可是大部分都是不合理的,或者說即使是合理的,執行效率也會有必定的影響。尤其注意的是oracle

設置的時候setTime(java.sql.Time)設置參數,getTimestamp取得字段值。

相關文章
相關標籤/搜索