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取得字段值。

相关文章
相关标签/搜索