Summary of problems caused by MySQL 5.7 default SQL mode

Original address: http://www.ywnds.com/?p=8865

 

When using MySQL 5.7 version, I have encountered two problems caused by the change of SQL_MODE. The reason is that MySQL 5.7 controls more strictly, so some SQL statements in MySQL 5.6 or MySQL 5.5 cannot be used in MySQL 5.7 is executed (it will bring a very strange problem to the development, that is, the code is the same, the environment is the same, the SQL is the same, how can the test report an error with the formal?).

 

Let me tell you about two incidents I encountered:

1. Some GROUP BY SQL statements cannot be executed.

2. When creating a table, the default value specified by the date data type is 0000-00-00 and an error is reported.

Let's take a look first, the default SQL mode of MySQL 5.6 & MySQL 5.7.

# MySQL 5.6 Default SQL_MODE;

mysql> select @@sql_mode;

+--------------------------------------------+

| @@sql_mode                                 |

+--------------------------------------------+

| STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION |

+--------------------------------------------+

1 row in set (0.00 sec)



# MySQL 5.7 Default SQL_MODE;

mysql> select @@sql_mode;

+-------------------------------------------------------------------------------------------------------------------------------------------+

| @@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 row in set (0.00 sec)


ONLY_FULL_GROUP_BY first briefly explain the meaning of each parameter:

In strict mode, do not let queries in the GROUP BY section point to unselected columns, otherwise an error will be reported.

  • NO_ZERO_DATE

In strict mode, do not use '0000-00-00' as a valid date. You can still insert zero dates with the IGNORE option. In non-strict mode, the date is acceptable, but a warning is generated.

  • NO_ZERO_IN_DATE

In strict mode, dates with a month or day part of 0 are not accepted, and there is no limit to the year. If the IGNORE option is used, we insert '0000-00-00' for similar dates. In non-strict mode, the date is acceptable, but a warning is generated.

  • ERROR_FOR_DIVISION_BY_ZERO

In strict mode, during an INSERT or UPDATE, if division by zero (or MOD(X, 0) ) produces an error (otherwise a warning). If this mode is not given, MySQL returns NULL on division by zero. If used in INSERT IGNORE or UPDATE IGNORE, MySQL generates a division-by-zero warning, but the result of the operation is NULL.

  • NO_AUTO_CREATE_USER

In strict mode, prevents GRANT from automatically creating new users unless a password is also specified.

  • NO_ENGINE_SUBSTITUTION

Prevents automatic replacement of storage engines if a required storage engine is disabled or not compiled.

  • STRICT_TRANS_TABLES

Strict mode is enabled for transactional storage engines and possibly non-transactional storage engines, and illegal data values ​​are rejected, as detailed below.

Strict mode controls how MySQL handles invalid or missing input values. A value can be illegal for several reasons. For example, the data type is wrong, does not fit in the column, or is out of range. When a newly inserted row does not contain a value for a column that does not explicitly define the DEFAULT clause, the value is lost.

For transactional tables, when STRICT_ALL_TABLES or STRICT_TRANS_TABLES mode is enabled, an error occurs if there are illegal or missing values ​​in the statement. Statements are discarded and rolled.

For non-transactional tables, if row 1 of an insert or update has a bad value, both modes behave the same. The statement is abandoned and the table remains unchanged. If the statement inserts or modifies multiple rows, and the bad value occurs on the 2nd or later row, the result depends on which strict option is enabled:

For STRICT_ALL_TABLES, MySQL returns an error and ignores the remaining rows. However, in this case the previous row has already been inserted or updated. This says that you can partially update, which is probably not what you want. To avoid this, it's best to use a single-line statement, as it can be discarded without changing the table.

For STRICT_TRANS_TABLES, MySQL converts the illegal value to the closest legal value for the column and inserts the adjusted value. If the value is missing, MySQL inserts an implicit default value in the column. In any case, MySQL will generate a warning instead of giving an error and continue executing the statement.

Strict mode does not allow illegal dates such as '2004-04-31'. It does not allow forbidden dates with "zero" parts, such as '2004-04-00' or "zero" dates. To disable, the NO_ZERO_IN_DATE and NO_ZERO_DATE SQL modes should be enabled on the basis of strict mode.

If you do not use strict mode (i.e. do not enable STRICT_TRANS_TABLES or STRICT_ALL_TABLES mode), MySQL will insert the adjusted value with a warning for invalid or missing values. In strict mode, you can do this with INSERT IGNORE or UPDATE IGNORE.

 

To answer the two questions posed at the beginning?

1. Some GROUP BY SQL statements cannot be executed.

This is because MySQL 5.7 added the ONLY_FULL_GROUP_BY parameter by default. When MySQL's sql_mode is non-ONLY_FULL_GROUP_BY semantics. A select statement. MySQL allows the expression output in the target list to be an expression other than aggregate function or group by column. The value of this expression may become undefined after the group by operation, for example:

select * from tt group by id;

For many databases with strict semantic restrictions, such as SQL Server, Oracle, and PostgreSql, they do not support columns with ambiguous semantics in the select target list. Such statements will be reported in these databases. Therefore, from MySQL 5.7 version Begin to correct this semantics, which is what we call ONLY_FULL_GROUP_BY semantics. The correct spelling is as follows:

select id from tt group by id;

select id,max(age) from tt group by id;

Therefore, the semantics of ONLY_FULL_GROUP_BY is to determine that the values ​​of all columns in the select target list are clear semantics. In short, in the ONLY_FULL_GROUP_BY mode, the values ​​in the target list are either the result of the aggregate function or the group by The value of the expression in the list. For more details, please see: MySQL 5.7 default ONLY_FULL_GROUP_BY semantic introduction

 

2. When creating a table, the default value specified by the date data type is 0000-00-00 and an error is reported.

This is because MySQL 5.7 added the NO_ZERO_DATE and NO_ZERO_IN_DATE parameters by default. Through the above introduction, there are some differences between these two parameters. NO_ZERO_DATE is limited when it completely matches the default value of 0000-00-00, while NO_ZERO_IN_DATE is limited when the month or day is arbitrarily 00 (no limit for year) .

When the data type is date or datetime and the NO_ZERO_IN_DATE restriction is used, there will be the following situations:

# 不合法默认值;

CREATE TABLE `test` (`time` datetime NOT NULL DEFAULT '1111-00-01 00:00:00'

) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;



# 合法默认值;

CREATE TABLE `test` (`time` datetime NOT NULL DEFAULT '1111-01-01 00:00:00'

) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;



# 合法默认值;

CREATE TABLE `test` (`time` datetime NOT NULL DEFAULT '0000-01-01 00:00:00'

) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

If the data type is timestamp is used, it is a bit different.
The value range of timestamp type: 1970-01-01 00:00:00 to 2037-12-31 23:59:59. That is to say, the default value needs to be adjusted to 1970-01-02 00:00:00 at least.

CREATE TABLE `test` (

  `mid` int(11) unsigned NOT NULL AUTO_INCREMENT,

  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,

  `start_time` timestamp NOT NULL DEFAULT '1970-01-02 00:00:00',

  `end_time` timestamp NOT NULL DEFAULT '2037-12-31 23:59:59',

  PRIMARY KEY (`mid`)

) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

The maximum or minimum value is within the legal range of timestamp. Looking around on the Internet, some people encounter this problem when the database is upgraded, and the old table structure cannot be applied in MySQL 5.7. If you want to adjust the SQL mode, you can directly write the sql_mode parameter in the configuration file to keep up with the corresponding mode parameter.


3. An error will be reported when the modified field type is less than or less than the longest field.

Controls how MySQL handles invalid or missing input values ​​when "STRICT_TRANS_TABLES or STRICT_ALL_TABLES" is enabled when strict mode is enabled. A value can be illegal for several reasons. For example, the data type is wrong, does not fit in the column, or is out of range. When a newly inserted row does not contain a value for a column that does not explicitly define the DEFAULT clause, the value is lost.

mysql> select * from dd;

+--------------------------------+

| log                            |

+--------------------------------+

| 一二三四五六七八九十              |

+--------------------------------+

1 row in set (0.00 sec)
mysql> set sql_mode='STRICT_TRANS_TABLES';

Query OK, 0 rows affected (0.00 sec)



mysql> alter table dd change column log log varchar(9);        

ERROR 1265 (01000): Data truncated for column 'log' at row 1

                                

mysql> set sql_mode='';                                

Query OK, 0 rows affected (0.00 sec)



mysql> alter table dd change column log log varchar(9);

Query OK, 1 row affected, 1 warning (0.02 sec)    

Records: 1  Duplicates: 0  Warnings: 1
MariaDB [dkey]> select * from dd;                              

+-----------------------------+

| log                         |

+-----------------------------+

| 一二三四五六七八九             |

+-----------------------------+

1 row in set (0.00 sec)

You can see the non-strict mode, and the excess data is truncated by default.

In order to facilitate everyone to communicate, I have opened a WeChat public account and a QQ group, QQ group: 291519319, let’s communicate with those who like technology

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324424708&siteId=291194637