关于 where 1 = 1 的思考

166 阅读1分钟
本文已参与「新人创作礼」活动,一起开启掘金创作之路。
关于 where 1 = 1 的思考

刚开始编程时第一次碰见 where 1 = 1感到很困惑,不知道为什么这样写,因此通过查阅资料得到了一些感悟。

为什么要这么使用

主要是为了解决动态构建SQL语句的问题。加上 where 1 = 1,使where条件语句永远为真,虽然加上where条件,但实际上永远为真,也就相当于没有添加任何的查询条件。

String sql = "select * from student where 1 = 1";
if (name != null){
	sql += "and name = ' " + name + " ' ";
}

在上述语句拼写时,使用where 1=1,当name不等于空时,可以直接拼接“and”语句,而不会导致语法错误。如果没有where 1=1,原来的SQL语句就变成(假设name传入了"小帅"):

select * from student where and name = '小帅'

很明显,上述SQL语句会有语法错误。所以,之所以添加1=1,就是为了方便SQL拼接。 从另外一个角度来讲,不仅仅1=1可以这样使用,像:1<>2、2>1、'a'='a'等表达式,只要结果为true,都可以如此使用。

where 1 < > 1 的应用

只获取表结构而不取数据的情况

create table student as select * from user where 1<>1

上述语句,创建了一个与user表结构一样但没有任何数据的新表student学生表。当然,除了表结构,其他的结构也可以如此使用。

where 1 = 1 的性能问题(可以使用查询语句前面加上 explain 关键字进行比较)

1 = 1 这样的条件,并不影响索引和性能,没有本质的区别,产生相同结果的原因是因为MySQL进行了优化处理,MySQL在处理指令时,会对 1 = 1 这类无效的条件进行优化处理,这个和Java的编译器很相似,很多无效的判断或语句,在编译成字节码时,编译器会进行优化处理。从而提高性能。

where 1 = 1 的改进

虽然 1 = 1 这样的条件会被优化器优化掉,但优化也是会消耗性能的,如果我们在开发时使用了 Mybatis 或者 Mybatisplus 等ORM框架的话,可以使用框架包括的标签把这个问题解决。 下面以Mytais为例:

<select id="queryUser" parameterType="com.example.entity.User" resultType="java.lang.Integer">
  select count(id) from user u where 1=1
<if test="username !=null and username !='' ">
  AND u.username = #{username} 
</if> 
<if test="userNo !=null and userNo !='' ">
  AND u.user_no = #{userNo}
</if> 
</select>

为了解决上述问题,可以使用 Mybatis 的 where 标签替换 where 1 = 1

<select id="queryUser" parameterType="com.example.entity.User" resultType="java.lang.Integer">
  select count(id) from user u
<where>
<if test="username !=null and username !='' ">
 u.username = #{username} 
</if>
<if test="userNo !=null and userNo !='' "> 
 AND u.user_no = #{userNo}
</if>
</where> 
</select>

通过这种方式,在查询数据比较大的情况下,可减少MySQL为了优化1=1这样的条件而损失的性能。

总结:不断的思考和学习。