真实对比两个关键sql_mode开关打开和关闭的行为差异,看关掉严格检查换来的到底是宽松,还是真实的静默风险。
代码CREATE TABLE strict_test (id INT PRIMARY KEY, n TINYINT NOT NULL); INSERT INTO strict_test VALUES (1, 500); -- TINYINT范围是-128~127
默认sql_mode(含STRICT_TRANS_TABLES): INSERT INTO strict_test VALUES (1, 500); → ERROR 1264: Out of range value for column 'n' at row 1 ← 真实直接拒绝 SET SESSION sql_mode=''; INSERT INTO strict_test VALUES (1, 500); SELECT * FROM strict_test; → id=1, n=127 ← 真实"成功"了,但500被静默夹成了127
开启ONLY_FULL_GROUP_BY: SELECT customer_id, amount FROM orders GROUP BY customer_id; → ERROR 1055: Expression #2 ... is not in GROUP BY clause ... ← 真实拒绝这种有歧义的查询 关闭ONLY_FULL_GROUP_BY: 同样的查询真实能跑,返回: customer_id amount 1 385.25 2 366.11 3 304.00
关闭这个开关之后,MySQL真实允许SELECT列表里出现没有被GROUP BY、也没有被聚合函数包裹的列(amount),但真实返回的到底是这个customer_id分组里哪一行的amount,没有任何逻辑保证——它可能是分组内第一条被扫描到的行,具体取决于真实的执行计划和数据物理存储顺序,换一个索引、换一次表结构调整,这个"随便挑的值"真实可能就变了。
每一步都是本文上面用真实查询跑出来的原始结果。