附:mysql中的date类型直接比较大小是按照字符串比较还是时间戳
Mysql在比较两种不同数据类型时,第一步是将他们转化为同一种类型,然后在比较。那么Date和String在比较的时候,一定是把String转化为Date吗?答案是Yes.
例子:
select * FROM test.orders where ceate_record_time > '2019'
结果截图:
为什么会出现 2018 的字符串?
再举个例子:如果是用字符串比较,“2004-04-31"这个string应该比2004-01-01这个date来得大,但是4-31是一个invalid的日期(4月是小月),会被转化成"0000-00-00”,所以2004-01-01 (日期) > “2014-04-31”。
所以,在存储方面:如果你是表示的时间,请尽量不要采用str类型来存储(虽然大多数情况下存入的效果一样,但不建议)。
在查询方面:如果你确实遇到的存储的是字符串,那么请用STR_TO_DATE函数转成日期格式在查询,形如:
select * from orders where date(str_to_date(`ceate_record_time`.`publish_date`,'%Y-%m-%d')) > '2019-0-0'
附:unsigned解释
整型的每一种都分有无符号(unsigned)和有符号(signed)两种类型(float和double总是带符号的),在默认情况下声明的整型变量都是有符号的类型。
如果需声明无符号类型的话就需要在类型前加上unsigned。无符号版本和有符号版本的区别就是无符号类型能保存2倍于有符号类型的正整数数据,比如16位系统中一个int能存储的数据的范围为-3276832767,而unsigned能存储的数据范围则是065535。由于在计算机中,整数是以补码形式存放的。根据最高位的不同,如果是1,有符号数的话就是负数;如果是无符号数,则都解释为正数。
简而言之就是由于Int型占4字节,也就是16位,2^16 = 65535,如果有符号位就+ -两边均分,如果没有就全给+
因此下面建表语句是被推荐的:
CREATE TABLE `fast_group_task` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键', ... PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='批量组建班级的任务';
Java中的 '0000-00-00 00:00:00’问题
在我们的数据库定义中,经常可以看到类似这样的定义:
`start_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
这样定义的隐患其实是比较大的。如果我们链接Mysql的Url参数上不作为,那么查询就会报错如下:
java.sql.SQLException: Value '0000-00-00 00:00:00' can not be represented as java.sql.Timestamp
通过此报错我们其实应该很敏感的得出两个结论:
1MySql是允许0000-00-00 00:00:00这样的值存在的(否则就会报SQL执行的错,而不是现在的封装成java.sql.Timestamp的错)
2.Java中(至少java.sql.Timestamp这个类)是不能支持到0000-00-00 00:00:00这个时间的。
// 这句语句报错,也能说明我们的Timestamp根本就不能表示这个时间~~~ // 最主要的是,这种时间没有任何实际意义,就连MySql存储它都采用的是假时间来存储的,强烈不建议使用 System.out.println(Timestamp.valueOf("0000-00-00 00:00:00"));
我们的解决方案有两种:
1、jdbc的url后面,追加上参数:?zeroDateTimeBehavior=convertToNull,这样子Sql查出来的结果是null,Java进行封装就没有问题了
2、修改timestamp字段的默认值,不再采用0000-00-00 00:00:00(一般用当前时间)
总的来说,不要给数据库字段默认值设置为0000-00-00 00:00:00,完全是给自己找麻烦。
另外,JDK8已经完全普及了,强烈建议不再使用Date和Timestamp来表示时间,而使用JSR310的新规范,比老的更好用且功能更强大