MySQL:ERROR 1067 - Invalid default value for 'end_time'


mysql版本:5.7.24

一、問題描述

創建表執行sql語句如下:

create table train_record (    
id int(11) not NULL AUTO_INCREMENT,    
user_name VARCHAR(20) NOT NULL COMMENT'用戶名稱',
train_name TINYINT(1) DEFAULT'2' NOT NULL COMMENT'訓練項目,1主動訓練 2引導訓練',    
start_time TIMESTAMP NOT NULL COMMENT'開始時間',
end_time TIMESTAMP NOT NULL COMMENT'結束時間',
train_duration INT(4) NOT NULL COMMENT'訓練時長',
train_times int(4) DEFAULT'1' NOT NULL COMMENT'訓練次數,1-16次 2-32次 3-48次 4-64次 5-80次 6-96次',
repeat_time TINYINT(1) DEFAULT'1' NOT NULL COMMENT'點擊后重復播放次數,1-1次 2-2次 3-3次',
volume int(3) DEFAULT'0' NOT NULL COMMENT'音量',
play_random TINYINT(1) DEFAULT'1' NOT NULL COMMENT'是否隨機播放,1是0否',
PRIMARY KEY(id)    
) COMMENT'訓練記錄表';

執行sql報錯結果:

1067 - Invalid default value for 'end_time', Time: 0.000000s

原因:mysql從5.7開始,默認是嚴格模式,嚴格遵從SQL92規范。

mysql> show variables like 'explicit_defaults_for_timestamp'; 

執行結果:變量explicit_defaults_for_timestamp的value值為off。

mysql> show variables like 'sql_mode';

執行結果如下:

ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,
ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

 1. 親測,創建表如果只有一個字段設為TIMESTAMP類型,默認情況下,沒有指明null屬性,該字段就會自動加上NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP屬性,如果給該字段插入null值,會自動給該字段設置為CURRENT_TIMESTAMP(當前時間)值。

說明:DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP表示:在創建新記錄和修改現有記錄的時候都對這個數據列刷新。

2. 親測,創建表如果有一個以上的字段指定TIMESTAMP類型,如果沒有指定null屬性或者沒有設置默認值,則第二個TIMESTAMP字段報Invalid錯誤。
> 這是因為:
  第一個TIMESTAMP字段會自動被加上DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP屬性。
  第一個TIMESTAMP之后的字段,會被自動加上DEFAULT ‘0000-00-00 00:00:00’屬性。而5.7版本的sql_mode變量中含有NO_ZERO_DATE,表示'0000-00-00 00:00:00'格式非法,這與嚴格模式有關。

二、解決辦法

修改全局變量explicit_defaults_for_timestamp

mysql> set global explicit_defaults_for_timestamp = ON;

說明:需要退出重新進入mysql,該變量才生效。

此時,執行創建表sql語句,親測執行成功。

1. 由於沒有指定默認值,假設start_time和end_time值為空,執行insert操作,受嚴格模式影響,執行語句報錯,報錯語句如下:

1364 - Field 'start_time' doesn't have a default value, Time: 0.000000s

如果將值設為0000-00-00 00:00:00,執行insert操作,報錯如下:

1292 - Incorrect datetime value: '0000-00-00 00:00:00' for column 'start_time' at row 1, Time: 0.001000s

這時候就需要修改全局變量sql_mode,去掉NO_ZERO_IN_DATE,NO_ZERO_DATE,執行sql語句如下:

mysql> set global sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';

再執行insert操作,親測成功。

insert into train_record (user_name, train_name, start_time, end_time, train_duration, train_times, repeat_time, volume, play_random) VALUES (
liulin', 2, '0000-00-00 00:00:00', '0000-00-00 00:00:00', 30, 4, 3, 50, 1);

因此可以在創建sql語句時,將start_time和end_time字段的not null屬性后面加上default '0000-00-00 00:00:00',如下所示:

start_time timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '創建時間',
end_time timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '創建時間',

這樣當TIMESTAMP字段值為空時,默認插入0000-00-00 00:00:00,執行語句不會再報錯。

2. 如果將start_time和end_time這兩個字段的not null去掉,執行sql語句,兩個字段會被自動加上DEFAULT DULL的屬性,執行insert操作的時候,若TIMESTAMP字段值為空,則記錄為null,不再是CURRENT_TIMESTAMP(當前時間)值。

三、總結
1. 之前公司項目使用MySQL版本為5.6.42,在備份遷移到本地數據庫就遇到了日期0000-00-00 00:00:00格式非法的問題,因為是導入SQL文件,批量替換有點麻煩,所以只要將sql_mode的NO_ZERO_IN_DATE, NO_ZERO_DATE去掉即可。

2. 關於explicit_default_for_timestamp的解釋可參考mysql官網的 Server System Variables 一文 ,右上角可切換版本查看不同mysql版本的系統變量介紹。

3. 業務需要精確到秒時,也可以考慮DateTime類型。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM