在MySQL 5.7版本之前,且在MySQL 5.6.6版本之后(explicit_defaults_for_timestamp參數(shù)在MySQL 5.6.6開始加入)的版本中,如果沒有設(shè)置explicit_defaults_for_timestamp=1的情況下:
1)在默認情況下渡嚣,如果TIMESTAMP列沒有顯示的指明null屬性变抽,那么該列會被自動加上not null屬性(而其他類型的列如果沒有被顯示的指定not null亚皂,那么是允許null值的)这橙,如果往這個列中插入null值,會自動的設(shè)置該列的值為current timestamp值扭粱。
2)表中的第一個TIMESTAMP列,如果沒有指定null屬性或者沒有指定默認值震檩,也沒有指定ON UPDATE語句琢蛤。那么該列會自動被加上DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP屬性。
3)第一個TIMESTAMP列之后的其他的TIMESTAMP類型的列抛虏,如果沒有指定null屬性博其,也沒有指定默認值,那么該列會被自動加上DEFAULT ‘0000-00-00 00:00:00’屬性迂猴。如果insert語句中沒有為該列指定值慕淡,那么該列中插入’0000-00-00 00:00:00’,并且沒有warning沸毁。
在MySQL 5.6.6及以后的版本和MySQL 5.7之前的版本中峰髓,如果在配置文件中沒有指定explicit_defaults_for_timestamp參數(shù),啟動時error日志中會報如下警告:
[Warning] TIMESTAMP with implicit DEFAULT value is deprecated.
Please use --explicit_defaults_for_timestamp server option (see
documentation for more details).
如果我們在啟動的時候在配置文件中指定了explicit_defaults_for_timestamp=1息尺,MySQL會按照如下的方式處理TIMESTAMP列:
1)此時如果TIMESTAMP列沒有顯示的指定not null屬性携兵,那么默認的該列可以為null,此時向該列中插入null值時搂誉,會直接記錄null眉孩,而不是current timestamp。
2)不會自動的為表中的第一個TIMESTAMP列加上DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP屬性,除非你在建表的時候顯示的指明浪汪。
3)如果TIMESTAMP列被加上了not null屬性巴柿,并且沒有指定默認值。這時如果向表中插入記錄死遭,但是沒有給該TIMESTAMP列指定值的時候广恢,如果strict ?sql_mode被指定了,那么會直接報錯呀潭。如果strict sql_mode沒有被指定钉迷,那么會向該列中插入’0000-00-00 00:00:00’并且產(chǎn)生一個warning。
這里為什么一直強調(diào)版本呢钠署?主要還是因為這個參數(shù)explicit_defaults_for_timestamp在MySQL 5.6.6開始加入糠聪,并且MySQL 5.6跟MySQL 5.7的默認SQL模式不同了。MySQL 5.7的SQL模式更加嚴格了谐鼎,限制了不合法的日期輸入舰蟆,比如”0000-00-00 00:00:00″。詳情可以看:MySQL 5.7默認SQL模式帶來的問題總結(jié)狸棍。
一身害、啟動mysql時未設(shè)置explicit_defaults_for_timestamp=1
1)創(chuàng)建測試表test_time
mysql> set session sql_mode='';
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> create table test_time(time1 timestamp,time2 timestamp,id int);
Query OK, 0 rows affected (0.01 sec)
這里關(guān)閉了SQL模式,是因為MySQL 5.7默認SQL模式加入了NO_ZERO_DATE和NO_ZERO_IN_DATE模式草戈,這兩個模式的意思如下:
NO_ZERO_DATE
在嚴格模式塌鸯,不要將’0000-00-00’做為合法日期。你仍然可以用IGNORE選項插入零日期唐片。在非嚴格模式丙猬,可以接受該日期,但會生成警告费韭。
NO_ZERO_IN_DATE
在嚴格模式茧球,不接受月或日部分為0的日期(也就是說比NO_ZERO_DATE),對年不限制揽思。如果使用IGNORE選項袜腥,我們?yōu)轭愃频娜掌诓迦搿?000-00-00’。在非嚴格模式钉汗,可以接受該日期羹令,但會生成警告。
所以如果不去掉這兩個SQL模式损痰,那么根據(jù)我們上面所說的表中的第一個TIMESTAMP列福侈,如果沒有指定null屬性或者沒有指定默認值,也沒有指定ON UPDATE語句卢未。那么該列會自動被加上DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP屬性肪凛。第一個TIMESTAMP列之后的其他的TIMESTAMP類型的列堰汉,如果沒有指定null屬性,也沒有指定默認值伟墙,那么該列會被自動加上DEFAULT ‘0000-00-00 00:00:00’屬性翘鸭。所以第二個timestamp添加默認值時就會報錯的,錯誤如下:
mysql> create table test_time1(time1 timestamp,time2 timestamp,id int);
ERROR 1067 (42000): Invalid default value for 'time2'
表創(chuàng)建好了之后戳葵,下面來查看表結(jié)構(gòu)信息就乓,如下:
mysql> show create table test_time\G
*************************** 1. row ***************************
?????? Table: test_time
Create Table: CREATE TABLE `test_time` (
??`time1` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
??`time2` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
??`id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
1 row in set (0.00 sec)
從表結(jié)構(gòu)中可以看到表中timestamp列被自動設(shè)置為not null,并且表中第一個timestamp列被設(shè)置了DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP默認值拱烁,第二個字段默認值為”0000-00-00 00:00:00″生蚁。
2)插入測試
mysql> insert into test_time select null,null,1;
Query OK, 1 row affected (0.00 sec)
Records: 1??Duplicates: 0??Warnings: 0
mysql> select * from test_time;
+---------------------+---------------------+------+
| time1?????????????? | time2?????????????? | id?? |
+---------------------+---------------------+------+
| 2017-02-22 15:42:11 | 2017-02-22 15:42:11 |????1 |
+---------------------+---------------------+------+
1 row in set (0.00 sec)
往timestamp列插入null值時,會自動為該列設(shè)置為current?time戏自。
插入時未指定值的timestamp列中被插入了0000-00-00?00:00:00(非表中第一個timestamp列)邦投。
mysql> select * from test_time;
+---------------------+---------------------+------+
| time1?????????????? | time2?????????????? | id?? |
+---------------------+---------------------+------+
| 2017-02-22 15:42:11 | 2017-02-22 15:42:11 |????1 |
| 2017-02-22 15:45:09 | 0000-00-00 00:00:00 |????1 |
+---------------------+---------------------+------+
2 rows in set (0.00 sec)
二、啟動mysql時設(shè)置explicit_defaults_for_timestamp=1
1)創(chuàng)建表(不需要改變sql mode)
mysql> create table test_time(time1 timestamp,time2 timestamp,id int);
Query OK, 0 rows affected (0.00 sec)
mysql> show create table test_time\G
*************************** 1. row ***************************
?????? Table: test_time
Create Table: CREATE TABLE `test_time1` (
??`time1` timestamp NULL DEFAULT NULL,
??`time2` timestamp NULL DEFAULT NULL,
??`id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
1 row in set (0.00 sec)
通過表結(jié)構(gòu)我們看到擅笔,2個timestamp列都被設(shè)置為null志衣,并且設(shè)置了默認值為null。
2)插入測試
mysql> insert into test_time select null,1;
Query OK, 1 row affected (0.00 sec)
Records: 1??Duplicates: 0??Warnings: 0
mysql> select * from test_time;
+-------+-------+------+
| time1 | time2 | id?? |
+-------+-------+------+
| NULL??| NULL??|????1 |
+-------+-------+------+
1 row in set (0.00 sec)
為timestamp列指定了not?null屬性剂娄,在strict SQL mode時蠢涝,如果插入時該列沒有指定值玄呛,會直接報錯阅懦。
mysql> create table test_time(time1 timestamp,time2 timestamp not null,id int);
Query OK, 0 rows affected (0.01 sec)
mysql> insert into test_time select null,null,1;
ERROR 1048 (23000): Column 'time2' cannot be null
如果為timestamp列指定not?null屬性,在非stric?sql_mode模式下徘铝,如果插入的時候該列沒有指定值耳胎,那么會向該列中插入0000-00-00?00:00:00,并且產(chǎn)生告警惕它。
mysql> set session sql_mode='';
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> insert into test_time select null,null,1;
Query OK, 1 row affected, 1 warning (0.00 sec)
Records: 1??Duplicates: 0??Warnings: 1
mysql> show warnings;
+---------+------+-------------------------------+
| Level?? | Code | Message?????????????????????? |
+---------+------+-------------------------------+
| Warning | 1048 | Column 'time2' cannot be null |
+---------+------+-------------------------------+
1 row in set (0.00 sec)
mysql> select * from test_time;
+-------+---------------------+------+
| time1 | time2?????????????? | id?? |
+-------+---------------------+------+
| NULL??| 0000-00-00 00:00:00 |????1 |
+-------+---------------------+------+
1 row in set (0.00 sec)
上面說的都是關(guān)于timestamp類型的怕午,如果是datetime呢?
mysql> create table time1(id int,time1 datetime,time2 datetime);
Query OK, 0 rows affected (0.03 sec)
mysql> show create table time1\G
*************************** 1. row ***************************
?????? Table: time1
Create Table: CREATE TABLE `time1` (
??`id` int(11) DEFAULT NULL,
??`time1` datetime DEFAULT NULL,
??`time2` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
mysql> insert into time1(id) values(1);
Query OK, 1 row affected (0.00 sec)
mysql> select * from time1;
+------+-------+-------+
| id?? | time1 | time2 |
+------+-------+-------+
|????1 | NULL??| NULL??|
+------+-------+-------+
1 row in set (0.00 sec)
可以看到跟普通類型一樣淹魄。
轉(zhuǎn)自:http://www.ywnds.com/?p=8309