濮阳杆衣贸易有限公司

主頁 > 知識庫 > MySQL5.7中的sql_mode默認值帶來的坑及解決方法

MySQL5.7中的sql_mode默認值帶來的坑及解決方法

熱門標簽:如何在高德地圖標注新地址 高德地圖標注模式 高德地圖標注中心個人注冊 電銷機器人針對的 湘潭電銷機器人咨詢電話 400電話辦理都選易號網(wǎng) 寶應(yīng)電信400電話辦理費用 外呼系統(tǒng)防封號違法嗎 外呼系統(tǒng)服務(wù)

在正常項目開發(fā)過程中,如果MySQL版本從5.6升級到5.7版本。作為DBA在考慮數(shù)據(jù)庫版本升級帶來的影響時,一般會有幾個注意點:

sql_mode
optimizer_switch

本文主要內(nèi)容是MySQL升級到5.7版本之后,由于默認的 sql_mode 值帶來的坑以及對應(yīng)的解決方案。

案例一:ONLY_FULL_GROUP_BY

問題描述

MySQL版本從5.6升級至5.7之后,部分SQL執(zhí)行報錯,報錯信息如下:

ERROR 1055 (42000): Expression #3 of XXXXXX list is not in GROUP BY clause and contains nonaggregated column ‘XXXXX.XXXXXX' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

這個問題原因在于從5.6升級至5.7版本后 sql_mode 默認值發(fā)生了改變,在5.7版本的 sql_mode 默認值中有意向 ONLY_FULL_GROUP_BY ,該選項的含義表示:對于使用 GROUP BY 進行查詢的SQL,不允許 SELECT 部分出現(xiàn) GROUP BY 中未出現(xiàn)的字段,也就是 SELECT 查詢的字段必須是 GROUP BY 中出現(xiàn)的或者使用聚合函數(shù)的。

解決方案

方案一(不推薦):修改5.7版本 sql_mode 值,將 ONLY_FULL_GROUP_BY 去掉

ONLY_FULL_GROUP_BY 是加強SQL規(guī)范的,其目的是讓SQL查詢出來的結(jié)果更符合規(guī)范,更準確。

如果沒有 ONLY_FULL_GROUP_BY 規(guī)范限制,那么則能允許以下SQL的執(zhí)行: SELECT a,b,c FROM t GROUP BY a 。SQL按照a字段值進行分組,當同一個a字段值對應(yīng)多個b或者c值時,查詢結(jié)果中的b,c值是不確定的。

方案二:改寫SQL

案例二:NO_ZERO_DATE NO_ZERO_IN_DATE time_zone

問題描述

排錯階段一

MySQL版本從5.6升級至5.7之后,創(chuàng)建表的過程中失敗:

mysql> CREATE TABLE `t_manager` (
  .....
  ->  `CREATE_DATETIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
  ->  `MODIFIER` varchar(32) DEFAULT NULL COMMENT '更新人',
  ->  `MODIFY_DATETIME` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP COMMENT '修改時間',
  ->  `IS_DELETED` bit(1) DEFAULT b'0' COMMENT '刪除狀態(tài) 1:刪除 0:未刪除',
  ->  `IS_ENABLE` bit(1) DEFAULT b'1' COMMENT '啟用狀態(tài) 1:啟用 0:禁用',
  ->  PRIMARY KEY (`CACHE_ID`)
  -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ERROR 1067 (42000): Invalid default value for 'MODIFY_DATETIME'

錯誤提示 MODIFY_DATETIME 字段設(shè)置的默認值是無效的,考慮到剛從5.6版本升級到5.7版本,于是又去翻了翻5.7中默認的 sql_mode 值。結(jié)果發(fā)現(xiàn)了兩個可能存在影響的選項:

NO_ZERO_DATE
NO_ZERO_IN_DATE

排錯階段二

于是解決方案就是按照 NO_ZERO_DATE 以及 NO_ZERO_IN_DATE 的要求設(shè)置默認值,將 MODIFY_DATETIME 字段默認值設(shè)置為'1001-01-01 01:01:01',結(jié)果發(fā)現(xiàn)還是無法成功創(chuàng)建表:

mysql>CREATE TABLE `t_manager` (
  .....
  ->  `CREATE_DATETIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
  ->  `MODIFIER` varchar(32) DEFAULT NULL COMMENT '更新人',
  ->  `MODIFY_DATETIME` timestamp NOT NULL DEFAULT '1001-01-01 01:01:01' ON UPDATE CURRENT_TIMESTAMP COMMENT '修改時間',
  ->  `IS_DELETED` bit(1) DEFAULT b'0' COMMENT '刪除狀態(tài) 1:刪除 0:未刪除',
  ->  `IS_ENABLE` bit(1) DEFAULT b'1' COMMENT '啟用狀態(tài) 1:啟用 0:禁用',
  ->  PRIMARY KEY (`CACHE_ID`)
  -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ERROR 1067 (42000): Invalid default value for 'MODIFY_DATETIME'

查看了所有的 sql_mode 值,都符合規(guī)范,但是表還是創(chuàng)建不成功。只好去官方手冊上找找timestamp介紹:

The TIMESTAMP data type is used for values that contain both date and time parts. TIMESTAMP has a range of ‘1970-01-01 00:00:01' UTC to ‘2038-01-19 03:14:07' UTC.

排錯階段三

可以看到官方定義中timestamp字段值的范圍是'1970-01-01 00:00:01'到'2038-01-19 03:14:07',原來是我們設(shè)置的默認值不在timestamp范圍之內(nèi)。于是再次修改默認值:

mysql>CREATE TABLE `t_manager` (
  .....
  ->  `CREATE_DATETIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
  ->  `MODIFIER` varchar(32) DEFAULT NULL COMMENT '更新人',
  ->  `MODIFY_DATETIME` timestamp NOT NULL DEFAULT '1970-01-01 00:00:01' ON UPDATE CURRENT_TIMESTAMP COMMENT '修改時間',
  ->  `IS_DELETED` bit(1) DEFAULT b'0' COMMENT '刪除狀態(tài) 1:刪除 0:未刪除',
  ->  `IS_ENABLE` bit(1) DEFAULT b'1' COMMENT '啟用狀態(tài) 1:啟用 0:禁用',
  ->  PRIMARY KEY (`CACHE_ID`)
  -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ERROR 1067 (42000): Invalid default value for 'MODIFY_DATETIME'

邪了門,居然還是無法成功創(chuàng)建表。實在是沒轍了,向同事求救,同事說他在機器上試試,結(jié)果同樣的語句在他的MySQL上執(zhí)行成功,同樣是5.7.23版本。

百思不得其解。

一氣之下將兩邊的參數(shù)值拿出來對比了一下,果然找到了不同的根本。

測試環(huán)境 同事環(huán)境
system_time_zone=CST system_time_zone UTC
time_zone='+08:00' time_zone=SYSTEM

回過頭來看timestamp字段定義的范圍:

The TIMESTAMP data type is used for values that contain both date and time parts. TIMESTAMP has a range of ‘1970-01-01 00:00:01' UTC to ‘2038-01-19 03:14:07' UTC.

這個時間范圍指的是UTC時區(qū)的時間范圍,測試環(huán)境設(shè)置了CST東八區(qū)的時區(qū),則對應(yīng)的時間范圍上也需要對應(yīng)的加8小時。所以將timestamp字段默認值修改為'1970-01-01 08:00:01',表終于創(chuàng)建成功。

mysql>CREATE TABLE `mn_cache_refresh_manager` (
  ......
  ->  `CREATE_DATETIME` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
  ->  `MODIFIER` varchar(32) DEFAULT NULL COMMENT '更新人',
  ->  `MODIFY_DATETIME` timestamp NOT NULL DEFAULT '1970-01-01 08:00:01' ON UPDATE CURRENT_TIMESTAMP COMMENT '修改時間',
  ->  `IS_DELETED` bit(1) DEFAULT b'0' COMMENT '刪除狀態(tài) 1:刪除 0:未刪除',
  ->  `IS_ENABLE` bit(1) DEFAULT b'1' COMMENT '啟用狀態(tài) 1:啟用 0:禁用',
  ->  PRIMARY KEY (`CACHE_ID`)
  -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.02 sec)

總結(jié)

以上所述是小編給大家介紹的MySQL5.7中的sql_mode默認值帶來的坑及解決方法,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!

您可能感興趣的文章:
  • MySQL sql_mode修改不生效的原因及解決
  • 詳解MySQL的sql_mode查詢與設(shè)置
  • MySQL中SQL Mode的查看與設(shè)置詳解
  • mysql中的sql_mode模式實例詳解
  • Django2 連接MySQL及model測試實例分析
  • 關(guān)于MySQL的sql_mode合理設(shè)置詳解
  • MySQL關(guān)于sql_mode解析與設(shè)置講解
  • MySql版本問題sql_mode=only_full_group_by的完美解決方案
  • 解決MySQL 5.7.9版本sql_mode=only_full_group_by問題
  • Mysql之SQL Mode用法詳解
  • mysql sql_mode="" 的作用說明
  • MySQL sql_mode的使用詳解

標簽:黃山 佛山 賀州 南充 蘭州 馬鞍山 宿遷 黔南

巨人網(wǎng)絡(luò)通訊聲明:本文標題《MySQL5.7中的sql_mode默認值帶來的坑及解決方法》,本文關(guān)鍵詞  MySQL5.7,中的,sql,mode,默認值,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《MySQL5.7中的sql_mode默認值帶來的坑及解決方法》相關(guān)的同類信息!
  • 本頁收集關(guān)于MySQL5.7中的sql_mode默認值帶來的坑及解決方法的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    祁连县| 札达县| 新竹县| 塔河县| 德令哈市| 嘉鱼县| 鸡西市| 昭平县| 隆安县| 太白县| 玉林市| 珲春市| 化德县| 涞源县| 兴仁县| 镇远县| 太仆寺旗| 海晏县| 池州市| 城固县| 黄大仙区| 岚皋县| 封开县| 高青县| 永丰县| 景谷| 新河县| 宁波市| 中西区| 洪泽县| 绍兴县| 巴林左旗| 图片| 全州县| 调兵山市| 瓦房店市| 乌拉特后旗| 城口县| 南阳市| 平安县| 沽源县|