因为以前在本身电脑上搭建了mysql 5.6的数据库,可是在服务器上搭建的是mysql 5.7的环境,在运行过程当中出现了以下错误:html
Data truncation: Out of range value for column 'quanity' at rowmysql
因为安装的时候没有将STRICT_TRANS_TABLES
关闭致使的sql
show variables like "sql_mode";
发现其中有STRICT_TRANS_TABLES
数据库
将该字段去除便可服务器
set sql_mode='NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
官方手册专门有一节介绍 https://dev.mysql.com/doc/refman/5.6/en/sql-mode.html 。 SQL Mode 定义了两个方面:MySQL应支持的SQL语法,以及应该在数据上执行何种确认检查。session
SQL语法支持类并发
ONLY_FULL_GROUP_BY
对于GROUP BY聚合操做,若是在SELECT中的列、HAVING或者ORDER BY子句的列,没有在GROUP BY中出现,那么这个SQL是不合法的。是能够理解的,由于不在 group by 的列查出来展现会有矛盾。
在5.7中默认启用,因此在实施5.6升级到5.7的过程须要注意:oracle
Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column '1066export.ebay_order_items.TransactionID' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
ANSI_QUOTES
启用 ANSI_QUOTES 后,不能用双引号来引用字符串,由于它被解释为识别符,做用与 同样。 设置它之后,
update t set f1="" ...`,会报 Unknown column ‘’ in ‘field list 这样的语法错误。函数
PIPES_AS_CONCAT
将 ||
视为字符串的链接操做符而非 或 运算符,这和Oracle数据库是同样的,也和字符串的拼接函数 CONCAT() 相相似工具
NO_TABLE_OPTIONS
使用 SHOW CREATE TABLE
时不会输出MySQL特有的语法部分,如 ENGINE
,这个在使用 mysqldump 跨DB种类迁移的时候须要考虑。
NO_AUTO_CREATE_USER
字面意思不自动建立用户。在给MySQL用户受权时,咱们习惯使用 GRANT ... ON ... TO dbuser
顺道一块儿建立用户。设置该选项后就与oracle操做相似,受权以前必须先创建用户。5.7.7开始也默认了。
数据检查类
NO_ZERO_DATE
NO_ZERO_DATE
,效果与上面同样,’0000-00-00’容许但显示warning;若是没有设置NO_ZERO_DATE
,no warning,当作彻底合法的值。NO_ZERO_IN_DATE
状况与上面相似,不一样的是控制日期和天,是否可为 0 ,即 2010-01-00
是否合法。NO_ENGINE_SUBSTITUTION
ALTER TABLE
或CREATE TABLE
指定 ENGINE 时, 须要的存储引擎被禁用或未编译,该如何处理。启用NO_ENGINE_SUBSTITUTION
时,那么直接抛出错误;不设置此值时,CREATE用默认的存储引擎替代,ATLER不进行更改,并抛出一个 warning .STRICT_TRANS_TABLES
STRICT_TRANS_TABLES
不是几种策略的组合,单独指 INSERT
、UPDATE
出现少值或无效值该如何处理:上面并无囊括全部的 SQL Mode,选了几个表明性的,详细仍是 看手册。
sql_mode通常来讲不多去关注它,没有遇到实际问题以前不会去启停上面的条目。咱们常设置的 sql_mode 是 ANSI
、STRICT_TRANS_TABLES
、TRADITIONAL
,ansi和traditional是上面的几种组合。
ANSI
:更改语法和行为,使其更符合标准SQLTRADITIONAL
:更像传统SQL数据库系统,该模式的简单描述是当在列中插入不正确的值时“给出错误而不是警告”。ORACLE
:至关于 PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS, NO_AUTO_CREATE_USER不管何种mode,产生error以后就意味着单条sql执行失败,对于支持事务的表,则致使当前事务回滚;但若是没有放在事务中执行,或者不支持事务的存储引擎表,则可能致使数据不一致。MySQL认为,相比直接报错终止,数据不一致问题更严重。因而 STRICT_TRANS_TABLES
对非事务表依然尽量的让写入继续,好比给个”最合理”的默认值或截断。而对于 STRICT_ALL_TABLES
,若是是单条更新,则不影响,但若是更新的是多条,第一条成功,后面失败则会出现部分更新。
5.6.6 之后版本默认就是NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
,5.5默认为 ‘’ 。
查看
查看当前链接会话的sql模式: mysql> select @@session.sql_mode; 或者从环境变量里取 mysql> show variables like "sql_mode"; 查看全局sql_mode设置: mysql> select @@global.sql_mode; 只设置global,须要从新链接进来才会生效
设置
形式如 mysql> set sql_mode=''; mysql> set global sql_mode='NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES'; 若是是自定义的模式组合,能够像下面这样 Adding only one mode to sql_mode without removing existing ones: mysql> SET sql_mode=(SELECT CONCAT(@@sql_mode,',<mode_to_add>')); Removing only a specific mode from sql_mode without removing others: mysql> SET sql_mode=(SELECT REPLACE(@@sql_mode,'<mode_to_remove>',''));
配置文件里面设置sql-mode=""
。
updated: 2017-12-10
现网作数据迁移测试时报另外一个错误,起因是这样的:一个1.8亿的表里面,由于某种缘由须要把字段定义null改成not null,避免下游服务(如ES)处理特殊数据时异常状况。但这是一个并发dml很是高又达到100多G的大表,online ddl针对这种修改字段类型简直一筹莫展,pt-osc也慢的很。
恰好有一个作数据迁移的契机,本来打算在新库上把字段改好,再经过dts或相似的数据迁移工具,同步过去。在非严格模式下,本来是null的值也会变成0或’’,但仍是报错了:
set sql_mode=''; -- 置为非严格模式 insert into t(id, a) values(1, null); [Err] 1048 - Column 'a' cannot be null 然而 insert into t(id, a) values(1, null),(2, null),; Affected rows: 2
找到官方文档上的原话,能够解释:
If you are not using strict mode, then whenever you insert an “incorrect” value into a column, such as a NULL into a NOT NULL column or a too-large numeric value into a numeric column, MySQL sets the column to the “best possible value” instead of producing an error
If you try to store NULL into a column that doesn’t take NULL values, an error occurs for single-row INSERT statements. For multiple-row INSERT statements or for INSERT INTO … SELECT statements, MySQL Server stores the implicit default value for the column data type
非严格模式下,单行插入 null 到 not null 列,会失败;多行插入则只是warning。规则是这样,也就无需解释。