問題背景:
線上的linux服務器上的mysql服務器中導出數據庫的結構。想要在本地創建一個測試版本
導出后再本地mysql上運行卻報錯 1067 - Invalid default value for
mysql數據庫中需要使用timestamp列來存儲數據的創建時間和更新時間
例如,創建后台管理菜單表,只看created_at和updated_at兩個字段
DROP TABLE IF EXISTS `admin_menu`; CREATE TABLE `admin_menu` ( `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, `parent_id` int(11) NOT NULL DEFAULT 0, `order` int(11) NOT NULL DEFAULT 0, `title` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, `icon` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL, `uri` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL, `permission` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL, `created_at` datetime DEFAULT NULL, `updated_at` timestamp(0) DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 15 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Compact;
執行后發現報錯
1067 - Invalid default value for 'updated_at'。updated_at字段的默認值無效。而created_ad字段類型是datetime日期時間類型默認值為NULL沒有發生報錯
一開始以為是sql_mode模式問題,然而在sql_mode模式為嚴格或者寬松模式情況下,都會報錯。
本地和線上服務器相同的模式也不行
sql_mode="STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
接着,查看線上服務器版本和本地版本對比,
使用select VERSION()
線上mysql版本:5.7.22-log
本地mysql版本:5.7.23-log
版本相差不大,排除版本問題。那只能找資料了。
解決方法:
方法1
既然timestamp會報錯,就直接用datetime來保存時間就可以解決的。
將updated_at類型timestamp改為datetime,這個創建表的過程能夠正常運行
方法2
既然不能為NULL,那我改為一個固定值不就可以了嗎
`updated_at` timestamp(0) DEFAULT '1970-01-01 08:00:00',
將時間設置為unix時間戳為0對應的日期(默認是1970-01-01 00:00:00,中國時間要加8)。
方法3
網上查找,在mysql配置文件中增加配置參數
[mysqld]節點下添加
explicit_defaults_for_timestamp = ON
重啟mysql數據庫試配置生效。
之后就可以正常執行上面的數據的
下面是方法三的具體解釋,僅作記錄,可以不需要知道
網上搜索資料,
mysql5.6.6之前,timestamp時間類型有一個默認行為: TIMESTAMP列如果沒有明確聲明NULL屬性,默認為NOT NULL。(而其他數據類型,如果沒有顯示聲明為NOT NULL,則允許NULL值。) insert插入一條數據,TIMESTAMP的列值為NULL,會自動存儲時候,會將當前timestamp存儲到這個timestamp列中。
也就是說會自動分配 DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP 屬性。
每次更新記錄都會將timestamp列更新為當前的時間戳對應的時間值
現在mysql5.6版本以后,timestamp字段的默認行為發生的變化,多了一些限制。
如果timestamp列設置默認值為NULL,
Default NULL 這會發生報錯 1067 - Invalid default value for
如果需要讓timestamp列在創建表時可以為NULL值,需要將explicit_defaults_for_timestamp設為ON
explicit_defaults_for_timestamp默認為OFF關閉狀態,打開后可以阻止timestamp的默認行為。