oracle,mysql,sqlserver--java对日期字段的操作

最近工作中用到了这三种数据库对日期字段的操作,现做如下总结。

1.数据库字段与java类型的对应关系。

001949_xZzG_2345835.png

明白这对应关系,我们才能正确的使用PreparedStatement设置参数

2.关于日期字段的几点说明

首先任何的日期字段设置的时候都应尽量保持类型对应设置。

比如:oracle的date字段,如果你想保留年月日时分秒,那么就应该用

setTime(java.sql.Time)或者setTimestamp(java.sql.Timestamp)来设置值,这两个还是有区别的尽管执行结果会一样

再比如:如果是mysql的time字段设置值那么应该是

setTime(java.sql.Time)

 

虽然,其他的设置也可以执行成功,注意这里说的是成功,并不是说合理

比如:如果是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类型

004440_aagl_2345835.png

 

注意记录的样子,

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")),这句话的意思是内部函数进行了类型转换,然后匹配传过来的参数,注意这里转换的是字段,而不是传过来的值。

010143_0PvM_2345835.png

 

同样,我们通过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"),也就是说没有进行任何的类型转换,直接赋值了

010716_gqgs_2345835.png

 

再来说说,类型转换与不转换的区别。

类型转换,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取得字段值。

 

 

 

 

 

转载于:https://my.oschina.net/yibuliushen/blog/716822

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值