在MySQL查询中,你可能会不经意的掉入某些坑中,甚至某些坑可能让你不死也掉半条命。下面罗列一下常见的坑。
1、 多表操作时不写别名
掉坑现场重现:
mysql> select * from t1;
+------+
| Id |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 rows in set (0.00 sec)
mysql> select * from t2;
Empty set (0.00 sec)
mysql> select * from t3;
+------+
| ld |
+------+
| 10 |
+------+
1 row in set (0.00 sec)
mysql> delete from t1 where Id in(select Id from t2);
Query OK, 0 rows affected (0.00 sec)
mysql> delete from t1 where Id in(select Id from t3);
Query OK, 3 rows affected (0.03 sec)
t1表有3条记录(记录值不重复),t2表没有记录,t3表有1条记录。所以第一个DELETE语句不会删除任何记录,这是符合预期的。
可是第2个DELETE语句为什么删除了3条记录呢?t3表只有一条记录,t1的记录值也是不重复的,所以是不是应该最多只删除一条记录呢?
眼神好的同学可能发现了,t3表压根就没有Id列,t3表的列名是ld。没错,问题就在这里了。在子查询中,列可以是父表的列,也可以是子表的列,当你不写列名所属表的时候,MySQL根据表结构来确定列所属的表,悲剧就发生在这里,由于没有写列所属的表,所以实际上的条件是t1.Id=t1.Id,这个自然就是把t1表的数据都删除了。如果这个情况发生的生产环境,其后果可想而知。
我们在DB规范中,明确要求多表查询语句中,一定要写清楚列所属的表,它不单纯是让阅读清晰,更重要的是防止掉坑。
注意,这个坑可不是专属于MySQL。
2、 不支持FULL JOIN
DBA一直跟我说,MySQL不支持FULL JOIN,可是我觉得不太可能嘛,好歹MySQL也是一个发展了这么多年,用户群也非常大的成熟产品,不至于连这个都不支持。于是我自己写了个FULL JOIN的查询,看看下面的执行现场,妥妥的执行了嘛。
mysql> select * from t1 full join t3 on Id=ld;
Empty set (0.00 sec)
找DBA理论去,然后DBA让我自己看下执行计划(只截取了部分):
+----+-------------+--