sql_mode(二)宽松模式和严格模式的区别

目录

 

设置

一、插入字符串类型

 建表

总结

1、单插 NULL 到 NOT NULL 列(无默认值)

(1)严格模式

(2)宽松模式

2、单插 NULL 到 NOT NULL 列(有默认值)

(1)严格模式

(2)宽松模式

3、批量插入 NULL 到 NOT NULL 列

(1)严格模式

(2)宽松模式

二、插入数字类型

三、更新


设置

我这里的数据库实例的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

下面通过修改临时会话的sql mode:再打开一个script会话,设置该tab的session为宽松模式:

-- 只保留最基本模式,宽松但仍防止引擎替代
SET SESSION sql_mode = 'NO_ENGINE_SUBSTITUTION';

来对比下宽松模式和严格模式的区别。

一、not null

 建表
CREATE TABLE t_user_demo (
	id varchar(36) NOT NULL,
	user_id varchar(36) NOT NULL,
    user_name varchar(36) NOT NULL,
	PRIMARY KEY (`id`)
) 
CREATE TABLE t_user_demo_1 (
	id varchar(36) NOT NULL,
	user_id varchar(36) NOT NULL,
    user_name varchar(36) NOT null default 'abc',
	PRIMARY KEY (`id`)
) 
总结

case

严格模式

宽松模式

单插 NULL 到 NOT NULL 列(该列无默认值)

报错

报错

NOT NULL(该列无默认值),单插不指定该列

报错

报错

单插 NULL 到 NOT NULL 列(该列有default值)

报错

报错

NOT NULL(该列有默认值),单插不指定该列

成功,使用默认值

成功,使用默认值

批量插入 NULL 到 NOT NULL 列(该列无默认值)

报错

成功,转成空字符串

批量插入 NOT NULL 列(该列无默认值),不指定列

报错

成功,转成空字符串

批量插 NULL 到 NOT NULL 列(该列有default值)

报错

成功,转成空字符串

批量插入 ,不指定列NOT NULL(该列有默认值)

成功,使用默认值

成功,使用默认值

以下是验证的步骤:

1、单插 NULL 到 NOT NULL 列(无默认值)
(1)严格模式

 报错,插入不成功

不显示插入也报错

(2)宽松模式

显示插入Null同样报错,插入不成功

不显示插入会自动转成空字符串,插入成功

2、单插 NULL 到 NOT NULL 列(有默认值)
(1)严格模式

 报错,插入不成功

不显示指定字段则可以成功

(2)宽松模式

显示插入Null报错,插入不成功

不显示指定字段则可以成功

3、批量插入 NULL 到 NOT NULL
(1)严格模式

显示插入为Null,报错,插入不成功

对于有default值的字段不指定,则可以插入成功:

(2)宽松模式

  不管字段是否有默认值,不管是否显示插入Null,都成功插入。可见宽松模式下,单插显示指定Null会失败,只有不指定该字段可以生成默认值;而批量插入,不管该字段是否有默认值,不管有没有显示插入Null,都可以自动转成默认值插入成功。

chatGPT说的转化并不准确,实际上是批插才有转化。

INSERT INTO t_user_demo_1 (id,user_id,user_name)  VALUES 
('66',null, null),('88',null, null);

4、默认值对update不起作用

更新并不会转换为默认值。

(1)严格模式——直接报错

(2)宽松模式——不报错

但是全部更新成空字符串了,没有自动转换为default值。

二、超限裁剪

类型宽松严格

tinint

INSERT INTO test_int (id, age) VALUES (1, 300);

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

mysql> select * from test_int;

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

| id | age |

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

| 1 | 127 |

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

1 row in set (0.28 sec)

update test_int set age=-129 where id=1;

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

Rows matched: 1 Changed: 1 Warnings: 1

mysql> select * from test_int;

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

| id | age |

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

| 1 | -128 |

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

1 row in set (0.28 sec)

INSERT INTO test_int (id, age) VALUES (2, 300);

ERROR 1264 (22003): Out of range value for column 'age' at row 1

update test_int set age=-129 where id=1;

ERROR 1264 (22003): Out of range value for column 'age' at row 1

varchar

INSERT INTO test_varchar (id, name) VALUES (1, 'ABCDEFGH');

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

mysql> select * from test_varchar;

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

| id | name |

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

| 1 | ABCDE |

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

1 row in set (0.30 sec)

INSERT INTO test_varchar (id, name) VALUES (1, 'ABCDEFGH');

ERROR 1406 (22001): Data too long for column 'name' at row 1

三、类型转换

CREATE TABLE t (id INT NOT NULL);

严格模式,类型转换异常抛错ERROR 1366 (HY000): Incorrect integer value: 'abc' for column 'id' at row 1


宽松模式,给近值;

四、相同处理

case对比严格非严格

数字除以0

无差异

SELECT 10 / 0;

-- 返回 NULL,并生成警告

-- 返回 NULL,并生成警告

非法日期

无差异

INSERT INTO test_dates (event_date) VALUES ('0000-00-00');

无效值落库

无效值落库@Hubble Meng

索引长度超限

DDL差异

CREATE INDEX idx_long_text ON test_index (long_text);

报错[2025-06-13 15:22:09] [42000][1071] Specified key was too long; max key length is 3072 bytes

告警

[42000][1071] Specified key was too long; max key length is 3072 bytes

### 如何在MySQL 8.0中关闭严格模式 在MySQL 8.0中,可以通过修改`sql_mode`参数来关闭严格模式。具体方法包括直接修改配置文件或通过SQL语句动态调整。 #### 方法一:修改配置文件 1. 找到MySQL的配置文件。通常情况下,Linux系统中的配置文件路径为`/etc/my.cnf`或`/etc/mysql/my.cnf`,Windows系统中的配置文件路径为`my.ini`。 2. 在配置文件中找到或添加`[mysqld]`段落,并设置`sql_mode`参数。例如,如果需要关闭严格模式,可以将`sql_mode`设置为空值或移除与严格模式相关的选项: ```ini [mysqld] sql_mode=NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION ``` 这里需要注意的是,移除了`STRICT_TRANS_TABLES``ONLY_FULL_GROUP_BY`等严格模式相关的内容[^3]。 3. 保存配置文件后,重启MySQL服务以使更改生效。 #### 方法:通过SQL语句动态修改 如果无法修改配置文件,也可以通过SQL语句动态修改`sql_mode`参数。登录到MySQL客户端后,执行以下命令: ```sql SET GLOBAL sql_mode='NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'; ``` 此操作会立即生效,但需注意这种方式仅对当前会话有效,重启MySQL服务后会恢复默认设置。因此,建议结合方法一进行永久性修改。 #### 注意事项 - MySQL 5.65.7的默认`sql_mode`模式不同,5.6默认为`NO_ENGINE_SUBSTITUTION`,相当于宽松模式;而5.7默认为`STRICT_TRANS_TABLES`,即严格模式[^1]。 - 在MySQL 8.0中,默认启用了`STRICT_TRANS_TABLES``ONLY_FULL_GROUP_BY`等严格模式选项。如果需要完全关闭严格模式,必须确保这些选项被移除[^3]。 - 如果遇到类似“Variable ‘sql_mode’ can’t be set to the value of ‘NO_AUTO_CREATE_USER’”的错误,可能是因为尝试设置的值无效或语法错误[^2]。 ```python # 示例代码(动态修改sql_mode) import mysql.connector conn = mysql.connector.connect( host="localhost", user="root", password="password" ) cursor = conn.cursor() cursor.execute("SET GLOBAL sql_mode='NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';") conn.commit() cursor.close() conn.close() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

w_t_y_y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值