由一条create语句的问题对比mysql和oracle中的date差别

今天开发的同事提交过来一个sql变更,在部署的时候发现了一个问题。
语句是一个简单的create语句
CREATE TABLE `test_user` (
  `openid` varchar(64) NOT NULL,
  `amount` varchar(11) DEFAULT 0,
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`openid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
报错内容为:
ERROR 1067 (42000) at line 1: Invalid default value for 'create_time'
首先这个看起来不是一个语法问题,部署使用的环境是5.5
这个时候手头有一套虚拟机测试环境,立马实验了一下,发现在5.6中竟然没有任何问题。
得到的信息如下
Query OK, 0 rows affected (0.13 sec)
所以这个问题引起了我的注意。
我做了下面几个测试,首先current_timestamp肯定是可用的。看看时间的情况。
 select current_timestamp, current_timestamp();
+---------------------+---------------------+
| current_timestamp   | current_timestamp() |
+---------------------+---------------------+
| 2015-11-23 18:31:25 | 2015-11-23 18:31:25 |
+---------------------+---------------------+
1 row in set (0.00 sec)
我们创建一个测试表来简单测试一下看看问题到底在哪里。
create table test(col1 datetime DEFAULT CURRENT_TIMESTAMP);
ERROR 1067 (42000): Invalid default value for 'col1'
看起来似乎是添加default值的时候出了问题。
> create table test(col1 datetime DEFAULT '');
ERROR 1067 (42000): Invalid default value for 'col1'
添加空值,也是不可以。
> create table test(col1 datetime DEFAULT '2015-11-23 18:31:25');
Query OK, 0 rows affected (0.02 sec)
添加一个固定的静态默认值,这样就可以了。
同时查看了一些文章,有的说不能添加默认值,这个说法应该是不成立的,只能说是不能添加动态的默认值。还有一种说法是default的动态默认值是在5.6.5才开始支持。
这部分内容在MySQL官方文档中也有说明。http://dev.mysql.com/doc/refman/5.0/en/data-type-defaults.html
那么这个问题还是需要解决,怎么解决呢。首先不可能为了这个操作先把数据库升级到5.6
那么解决方法就有两个。
一个是就是取消默认值,一个就是字段类型改为timestamp
那么问题来了,datetime和timestamp有啥区别和联系,如果没有记错还有一个类型时date,这三种数据类型有啥区别和关系
我们创建一个表,含有三个字段,datetime,timestamp,date
create table test(date1 datetime,date2 timestamp,date3 date);
然后插入三个值,来看看有什么差别。
mysql> insert into test values(current_date,current_timestamp,current_date);
Query OK, 1 row affected (0.00 sec)
mysql> select *from test;
+---------------------+---------------------+------------+
| date1               | date2               | date3      |
+---------------------+---------------------+------------+
| 2015-11-23 00:00:00 | 2015-11-23 23:21:35 | 2015-11-23 |
+---------------------+---------------------+------------+
可以看出datetime和timestamp其实是精确到秒的,date是精确到日。
那么datetime和timestamp有啥区别。
datetime和timestamp的存储占用空间不同,datetime占用8个字节,timestamp占用4个字节,所以说timestamp支持的时间范围要窄一些。范围为:1970-01-01 08:00:01到2038-01-19 11:14:07  而datetime支持的时间范围则要大很多。1000-01-01 00:00:00 ~ 9999-12-31 23:59:59
简单来说,解放前的数据用timestamp就不合适了,而datetime则要更宽泛一些。
来简单验证一下。如果对timestamp列添加超过时间范围的值,则会报错。
mysql> insert into test values('2038-01-19 11:14:08','2038-01-19 11:14:08',current_date);
ERROR 1292 (22007): Incorrect datetime value: '2038-01-19 11:14:08' for column 'date2' at row 1
再次对timestamp插入最大值。
mysql> insert into test values('2038-01-19 11:14:08','2038-01-19 11:14:07',current_date);
mysql> select *from test;
+---------------------+---------------------+------------+
| date1               | date2               | date3      |
+---------------------+---------------------+------------+
| 2015-11-23 00:00:00 | 2015-11-23 23:21:35 | 2015-11-23 |
| 2038-01-19 11:14:08 | 2038-01-19 11:14:07 | 2015-11-23 |
+---------------------+---------------------+------------+
mysql> insert into test values('9999-12-31 23:59:59','2038-01-19 11:14:07',current_date);                   
Query OK, 1 row affected (0.00 sec)
对datetime插入最大值
mysql> insert into test values('9999-12-31 23:59:59','2038-01-19 11:14:07',current_date);                  
mysql> select *from test;
+---------------------+---------------------+------------+
| date1               | date2               | date3      |
+---------------------+---------------------+------------+
| 2015-11-23 00:00:00 | 2015-11-23 23:21:35 | 2015-11-23 |
| 2038-01-19 11:14:08 | 2038-01-19 11:14:07 | 2015-11-23 |
| 9999-12-31 23:59:59 | 2038-01-19 11:14:07 | 2015-11-23 |
+---------------------+---------------------+------------+
除此之外,datetime和timestamp还有一个区别,就是timestamp对于Insert,update操作会默认设置为current_timestamp
比如对datetime插入值,timestamp,date保留为空,结果如下:
mysql> insert into test(date1) values('2038-01-19 11:14:06');
mysql> select *from test;
+---------------------+---------------------+------------+
| date1               | date2               | date3      |
+---------------------+---------------------+------------+
| 2015-11-23 00:00:00 | 2015-11-23 23:21:35 | 2015-11-23 |
| 2038-01-19 11:14:08 | 2038-01-19 11:14:07 | 2015-11-23 |
| 9999-12-31 23:59:59 | 2038-01-19 11:14:07 | 2015-11-23 |
| 2038-01-19 11:14:06 | 2015-11-23 23:30:22 | NULL       |
+---------------------+---------------------+------------+
4 rows in set (0.00 sec)
如果只对timestamp输入值,datetime和date为空,效果就大大不同
insert into test(date2) values('2038-01-19 11:14:06');
mysql> select *from test;
+---------------------+---------------------+------------+
| date1               | date2               | date3      |
+---------------------+---------------------+------------+
| 2015-11-23 00:00:00 | 2015-11-23 23:21:35 | 2015-11-23 |
| 2038-01-19 11:14:08 | 2038-01-19 11:14:07 | 2015-11-23 |
| 9999-12-31 23:59:59 | 2038-01-19 11:14:07 | 2015-11-23 |
| 2038-01-19 11:14:06 | 2015-11-23 23:30:22 | NULL       |
| NULL                | 2038-01-19 11:14:06 | NULL       |
+---------------------+---------------------+------------+
这种类型的问题在oracle中就会是另外一种情况,oracle中对于timestamp的类型,精度要比date要高。
来简单做一个测试
SQL> create table test(date1 date,date2 timestamp);
Table created.
SQL> col name format a20
其实这个时候来查看timestamp,可以看到一个timestamp(6)字样的类型。
SQL> desc test
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 DATE1                                              DATE
 DATE2                                              TIMESTAMP(6)
SQL> alter session set nls_date_format = 'yyyy-mm-dd hh24:mi:ss';
SQL> insert into test values(sysdate,sysdate);
SQL> col date2 format a30
DATE1               DATE2
------------------- ------------------------------
2015-11-23 23:03:35 23-NOV-15 11.03.35.000000 PM
如果插入systimestamp,结果会有一些差别。
SQL> insert into test values(systimestamp,systimestamp);
1 row created.
SQL> select *from test;
DATE1               DATE2
------------------- ------------------------------
2015-11-23 23:03:35 23-NOV-15 11.03.35.000000 PM
2015-11-23 23:05:08 23-NOV-15 11.05.08.378586 PM

其实在oracle中时间的类型还有很多,比如timestamp with timezone等等,支持的幅度也更大。
如果上面的问题在oracle中,是否可以支持动态的默认值呢,肯定可以,因为我们似乎已经习惯这么用了。
可以用下面的方式来指定。
SQL> alter table test modify(date1 default sysdate);
Table altered.
SQL> alter table test modify(date2 default systimestamp);
Table altered.
通过这些小测试也发现了时间的类型在mysql和oracle中还是有很大的差别,可能在数据类型的划分上,mysql划分的类型更多,数据类型非常多,而oracle似乎一个Number就可以完全替代,其实内部也是做了很多的改进。通过对比来学习能够发现不少有意思的地方。

时间: 2024-10-27 05:09:24

由一条create语句的问题对比mysql和oracle中的date差别的相关文章

简单对比MySQL和Oracle中的一个sql解析细节

SQL的语法解析器是一个很强大的内置工具集,里面会涉及到很多的编译原理的相关知识,语法分析,词法分析..一大堆看起来很理论的东东,不过看起来枯燥之余,它们的价值也更加明显. 借用一下网络中的原话:如果我们考究一下历史,就会发现很多被称为程序设计大师的人都是编译领域的高手.写出第一个微型机上运行的Basic语言的比尔盖茨,设计出Delphi的Borland的"世界上最厉害的程序员", Sun的JAVA之父, 贝尔实验室的C++之父 起点提得有些高了,今天和大家分享的案例是一个很简单的sq

java-我如何配这条Java语句所要求的mysql数据库?

问题描述 我如何配这条Java语句所要求的mysql数据库? ct=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/virtual_lab_server","DBAdmin_KK","-1042^6857::mySQL"); RT,现在安装好了mysql并能正常使用,但是没有这个数据库,大大们能不能给出mysql的命令呀? 我已经加载好了数据库驱动,只是没有这个数据库,不知道怎么创

MySQL和Oracle中的delete,truncate对比

在MySQL和Oracle中的delete,truncate还是存在着一些差别,明白了这些差别可能对于处理问题,理解问题会有一些帮助. 我们来简单通过一些测试来说明.我们创建两个表test_del,test_tru来对比delete,truncate的操作.我们有一个临时表t_fund_info大概有几百万的数据量. 创建test_del > create table test_del select *from t_fund_info; Query OK, 1998067 rows affect

一条insert语句导致的性能问题分析(二)

今天对之前描述的问题一条insert语句导致的性能问题分析(一) 进行了进一步的补充. 有一条insert语句的主要性能瓶颈在于insert子句中的查询语句,查询中的主要资源消耗在于对两个表进行了多次关联 语句主要的结构如下: insert into xxxxx   (select * from TEST_vip_new minus select * from TEST_vip_new_bak         ) a left join TEST_vip_new_bak b         on

SQL语句oracle中如何插入Date类型的数据

在开发的时候,经常要写条SQL语句将信息插入表中,插入的数据如果字段是date类型,就必须将date类型转换成字符串String类型在通过sql语句插入数据库.这是我字段唯一的方法,如果有高人请另赐教! 我的解决方法是用oracle中的to_date()方法,具体看下面的例子   Oracle中插入date数据代码    insert into news(ID,MSG,SEND_TIME,TIMER)    Oracle中插入date数据代码    values(20110101,'你好',to

TPCH 22条SQL语句分析

使用TPC-H进行性能测试,需要有很多工作配合才能获得较高性能,如建立索引,表数据的合理分布(使用表空间和聚簇技术)等. 本文从查询优化技术的角度,对TPC-H的22条查询语句和主流数据库执行每条语句对应的查询执行计划进行分析,目的在于了解各个主流数据库的查询优化技术,以TPC-H实例进一步掌握查询优化技术,对比主流数据库的实现情况对查询优化技术融会贯通. 1.Q1:价格统计报告查询 Q1语句是查询lineItems的一个定价总结报告.在单个表lineitem上查询某个时间段内,对已经付款的.已

oracle中Delete与Truncate语句的对比

一.delete语句 (1)有条件删除    语法格式:delete [from]  table_name  [where condition]; 如:删除users表中的userid为'001'的数据:delete from users where userid='001'; (2)无条件删除整个表数据      语法格式:delete  table_name; 如:删除user表中的所有数据:delete users ; 二.Truncate语句 使用Truncate语句是删除表中的所有记录

使用一条INSERT语句完成多表插入

这是一条颠覆常规的插入方法,一条INSERT语句可以完成向多张表的插入任务.小小地展示一下这种插入方法. 1.创建表T并初始化测试数据,此表作为数据源. sec@ora10g> create table t (x number(10), y varchar2(10)); sec@ora10g> insert into t values (1,'a'); sec@ora10g> insert into t values (2,'b'); sec@ora10g> insert into

string-这条java语句也很复杂,求解析

问题描述 这条java语句也很复杂,求解析 SimpleAdapter adapter = new SimpleAdapter(this, getTripListData(),R.layout.listviewrow, new String[] { "img", "name", "money","zhe" }, new int[] { R.id.tripImg, R.id.phoneName,R.id.phoneMoney,