切换语言为:繁体

SQL中为什么不建议使用1=1进行判断,有什么好的替代方案?

  • 爱糖宝
  • 2024-05-22
  • 2083
  • 0
  • 0

在工作中的老项目中经常会看到代码中使用了1=1的情况,想起来之前自己也这个样子写过,感觉也没有啥影响就没有当回事,随着工作年限,工作经验的增加,对着一块有了更深的理解,下面我们就来看一看。

代码开发中,编写SQL语句其实就和家常炒菜差不多,每个条件语句就是一个调料,所以每一种调料都会影响菜的味道,对于SQL来说查询条件的增加,影响的就是执行SQL的效率。那么1=1这种为什么又会存在呢,存在即有它的道理,下面我们更深一层次的分析一下。

为什么会使用 1=1?

Java代码开发中,使用最多的 Mybatis框架,在判断条件的时候,会在条件前面增加AND连接,而有的条件不需要拼接,所以为了第一个条件是否要带AND连接符,出现了始终为真的1=1的条件。

就像下边这样:

SELECT * FROM table WHERE 1=1
<if test="username != null">
AND username = #{username}
</if>
<if test="age > 0">
AND age = #{age}
</if>

这样就不用在增加每个条件之前先判断是否需要添加“AND”。

1=1 带来的问题

性能问题?

对于数据库的查询优化器了解的就会知道,其实写了1=1这种条件,在SQL语句经过优化器的时候也会被优化掉,但是对于不同的数据库就有了不同的结果。

另一个点就是如果都是1=1,没有进行优化,相当于把表中的全部数据都要进行一遍循环,判断一下这个毫无用处的条件是否满足。

查询优化器就相当于是个图书管理员,他知道如何最快的查找到你所需要的书,当你告诉它你所需要的书的特征之后,他会根据这些信息选择一个最快定位到该图书的方式路径。

但是如果我们告诉它一些无关紧要的信息,这不就相当于废话了吗,加密??哈哈哈哈哈想起来废话文学了,听君一席话,胜听一席话啊。所以说的多不一定有用,只需要把关键信息提供出来就可以。一个带有“1=1”的查询可能就相当与让图书管理员一本书一本书的去比较来检查是不是你所需要的,显然这是不合理的。

你可能会说:数据库没有这么傻吧?

确实,现在都4202年了,数据库不会这点都没做好。数据库在执行查询的时候都会把这种1=1的始终为真的条件进行优化掉,对于数据库的性能也不会收到太多的影响。但是优化器也不是万能的,在个别的场景中还是有可能会造成全表扫描的,所以我们还是要避免的。

代码质量

在代码质量的角度来看,我们也是需要避免“1=1”这种写法的,可以从以下几点来考虑:

1、代码清晰性:在复杂的SQL中,避免“1=1”这种引起歧义。

2、习惯:代码规范。

3、兼容:跨数据的兼容性。避免有的数据库无法进行优化掉“1=1”这种条件造成的全表扫描。

编写尽可能高效、清晰和准确的SQL语句,不仅有助于保持代码的质量,也让代码具有更好的可维护性和可扩展性。

替代 1=1 的更佳做法

在代码开发中,使用MyBatis框架的居多,所以我们可以使用Where标签来进行优化SQL写法。

假设我们有一个用户信息表 user,并希望根据传入的参数动态地过滤用户。

首先是Mybatis:

<!-- MyBatis映射文件片段 -->
<select id="selectUsersByConditions" parameterType="map" resultType="com.example.User">
  SELECT * FROM user
<where>
<!-- 使用if标签动态添加条件 -->
<if test="username != null and username != ''">
      AND username = #{username}
</if>
<if test="age > 0">
      AND age = #{age}
</if>
<!-- 更多条件... -->
</where>
</select>

在 MyBatis 中,避免使用 1=1 的典型方法是利用动态SQL标签(如 <if>)来构建条件查询。<where> 标签会自动处理首条条件前的 AND 或 OR。当没有满足条件的 <if> 或其他条件标签时,<where> 标签内部的所有内容都会被忽略,从而不会生成多余的 AND 或 WHERE 子句。

再看看 Entity Framework 的方法:

var query = context.User.AsQueryable();
if (!string.IsNullOrEmpty(username))
{
    query = query.Where(b => b.UserName.Contains(username));
}
if (age>0)
{
    query = query.Where(b => b.Age = age);
}
var users = query.ToList();

这是一种函数式编程的写法,最终生成SQL时,框架会决定是否在条件前增加AND,而不需要人为的增加 1=1。

总结

“1=1”在SQL语句中可能看起来无害,但实际上它是一种不良的编程习惯,可能会导致性能下降。就像在做饭时不会无缘无故地多加调料一样,我们在编写SQL语句时也应该避免添加无意义的条件。

每一行代码都应该有它存在的理由,不要让人和数据库浪费时间在不必要的事情上。


作者:萤火架构
链接:https://juejin.cn/post/7337513754970095667


0条评论

您的电子邮件等信息不会被公开,以下所有项均必填

OK! You can skip this field.