mysql 高级分组函数,炸裂!82张图进阶MySQL的高级玩法! - MySQL - dbaplus社群:围绕Data、Blockchain、AiOps的企业级专业社群。技术大咖、原创干货,每天精品...

SQL Mode 可以解决下面这几种问题

通过设置 SQL Mode,可以完成不同严格程度的数据校验,有效保障数据的准确性。

设置 SQL Mode 为ANSI模式,来保证大多数 SQL 符合标准的 SQL 语法,这样应用在不同数据库的迁移中,不需要对 SQL 进行较大的改变

数据在不同数据库的迁移中,通过改变 SQL Mode 能够更方便的进行迁移。

下面我们就通过示例来演示一下 SQL Mode 用法

我们可以通过

select @@sql_mode;

来查看默认的 SQL Mode,如下是我的数据库所支持的 SQL Mode

317aaca9c01a97c88dacd905c9765a38.png

涉及到很多 SQL Mode,下面是这些 SQL Mode 的解释

ONLY_FULL_GROUP_BY:这个模式会对 GROUP BY 进行合法性检查,对于 GROUP BY 操作,如果在SELECT 中的列,没有在 GROUP BY 中出现,那么将认为这个 SQL 是不合法的,因为列不在 GROUP BY 从句中

同样举个例子,我们现在查询一下 cxuan005 的 id 和 info 字段。

select id,info from cxuan005;

这样是可以运行的

a33feb0cd90a800ba5d752d9332f3e49.png

然后我们使用 GROUP BY 字句进行分组,这里只对 info 进行分组,我们看一下会出现什么情况

select id,info from cxuan005 group by info;

deeed5e8d18942f5be6d36d58e0fcaea.png

我们可以从错误原因中看到,这条 SQL 语句是不符合 ONLY_FULL_GROUP_BY 的这条 SQL Mode 的。因为我们只对 info 进行分组了,没有对 id 进行分组,我们把 SQL 语句改成如下形式

select id,info from cxuan005 group by id,info;

c6b00a2a7db9a7b87bb95221a5abf5a8.png

这样 SQL 就能正确执行了。

当然,我们也可以删除 sql_mode = ONLY_FULL_GROUP_BY 的这条 Mode,可以使用

SET sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));

来进行删除,删除后我们使用分组语句就可以放飞自我了。

select id,info from cxuan005 group by info;

38ce322edb0168acb67aa25d74efd3d6.png

但是这种做法只是暂时的修改,我们可以修改配置文件 my.ini 中的 sql_mode= STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

STRICT_TRANS_TABLES:这就是严格模式,在这个模式下会对数据进行严格的校验,错误数据不能插入,报error 错误。如果不能将给定的值插入到事务表中,则放弃该语句。对于非事务表,如果值出现在单行语句或多行语句的第1行,则放弃该语句。

当使用 innodb 存储引擎表时,考虑使用 innodb_strict_mode 模式的 sql_mode,它能增量额外的错误检测功能。

NO_ZERO_IN_DATE:这个模式影响着日期中的月份和天数是否可以为 0(注意年份是非 0 的),这个模式也取决于严格模式是否被启用。如果这个模式未启用,那么日期中的零部分被允许并且插入没有警告。如果这个模式启用,那么日期中的零部分插入被作为 0000-00-00并且产生一个警告。

这个模式需要注意下,如果启用的话,需要 STRICT_TRANS_TABLES 和 NO_ZERO_IN_DATE 同时启用,否则不起作用,也就是

set session sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE';

然后我们换表了,使用 cxuan003 这张表,表结构如下

7a6eeaa51745b3767dd66891811e201f.png

我们主要测试日期的使用,在 cxuan003 中插入一条日期为 0000-00-00 的数据

insert into cxuan003 values(111,'study','0000-00-00');

发现能够执行成功,但是把年月日各自变为 0 之后再进行插入,则会插入失败。

insert into cxuan003 values(111,'study','2021-00-00');

410e03fa319fcdadfb3c67219b25f97e.png

insert into cxuan003 values(111,'study','2021-01-00');

fde1e940b38557e85858c3350c0aa880.png

这些组合有很多,我这里就不再细致演示了,读者可以自行测试。

如果要插入 0000-00-00 这样的数据,必须设置 NO_ZERO_IN_DATE 和NO_ZERO_DATE。

ERROR_FOR_DIVISION_BY_ZERO:如果这个模式未启用,那么零除操作将会插入空值并且不会产生警告;如果这个模式启用,零除操作插入空值并产生警告;如果这个模式和严格模式都启用,零除从操作将会产生一个错误。

NO_AUTO_CREATE_USER:禁止使用 grant 语句自动创建用户,除非认证信息被指定。

NO_ENGINE_SUBSTITUTION:此模式指定当执行 create 语句或者 alter 语句指定的存储引擎没有启用或者没有编译时,控制默认存储引擎的自动切换。默认是启用状态的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值