SQL 多条件查询去掉影响效率的where 1=1

简介:


网上有不少人提出过类似的问题:“看到有人写了WHERE 1=1这样的SQL,到底是什么意思?”。其实使用这种用法的开发人员一般都是在使用动态组装的SQL。让我们想像如下的场景:用户要求提供一个灵活的查询界面来根据各种复杂的条件来查询员工信息,界面如下图:图片描述

界面中列出了四个查询条件,包括按工号查询、按姓名查询、按年龄查询以及按工资查询,每个查询条件前都有一个复选框,如果复选框被选中,则表示将其做为一个过滤条件。比如上图就表示“检索工号介于DEV001和DEV008之间、姓名中含有J并且工资介于3000元到6000元的员工信息”。如果不选中姓名前的复选框,比如下图表示“检索工号介于DEV001和DEV008之间并且工资介于3000元到6000元的员工信息”:
图片描述

如果将所有的复选框都不选中,则表示表示“检索所有员工信息”,比如下图:
图片描述

如果想学习java可以来这个群,首先是二二零,中间是一四二,最后是九零六,里面有大量的学习资料可以下载。
这里的数据检索与前面的数据检索都不一样,因为前边例子中的数据检索的过滤条件都是确定的,而这里的过滤条件则随着用户设置的不同而有变化,这时就要根据用户的设置来动态组装SQL了。当不选中年龄前的复选框的时候要使用下面的SQL语句:

SELECT * FROM T_Employee 
WHERE FNumber BETWEEN 'DEV001' AND 'DEV008' 
AND FName LIKE '%J%' 
AND FSalary BETWEEN 3000 AND 6000
而如果不选中姓名和年龄前的复选框的时候就要使用下面的SQL语句:
SELECT * FROM T_Employee 
WHERE FNumber BETWEEN 'DEV001' AND 'DEV008' 
AND FSalary BETWEEN 3000 AND 6000
而如果将所有的复选框都不选中的时候就要使用下面的SQL语句: 
SELECT * FROM T_Employee

要实现这种动态的SQL语句拼装,我们可以在宿主语言中建立一个字符串,然后逐个判断各个复选框是否选中来向这个字符串中添加SQL语句片段。这里有一个问题就是当有复选框被选中的时候SQL语句是含有WHERE子句的, 而当所有的复选框都没有被选中的时候就没有WHERE子句了,因此在添加每一个过滤条件判断的时候都要判断是否已经存在WHERE语句了,如果没有WHERE语句则添加WHERE语句。 在判断每一个复选框的时候都要去判断, 这使得用起来非常麻烦,“聪明的程序员是会偷懒的程序员”,因此开发人员想到了一个捷径:为SQL语句指定一个永远为真的条件语句(比如“1=1”),这样就不用考虑WHERE语句是否存在的问题了。伪代码如下:

String sql = " SELECT * FROM T_Employee WHERE 1=1"; 
if(工号复选框选中) 

sql.appendLine("AND FNumber BETWEEN '"+工号文本框1内容+"' AND '"+工号文本框2内容+"'"); 

if(姓名复选框选中) 

sql.appendLine("AND FName LIKE '%"+姓名文本框内容+"%'"); 

if(年龄复选框选中) 

sql.appendLine("AND FAge BETWEEN "+年龄文本框1内容+" AND "+年龄文本框2内容); 

executeSQL(sql);
这样如果不选中姓名和年龄前的复选框的时候就会执行下面的SQL语句:
SELECT * FROM T_Employee WHERE 1=1 
AND FNumber BETWEEN 'DEV001' AND 'DEV008' 
AND FSalary BETWEEN 3000 AND 6000
而如果将所有的复选框都不选中的时候就会执行下面的SQL语句:
SELECT * FROM T_Employee WHERE 1=1

这看似非常优美的解决了问题,殊不知这样很可能会造成非常大的性能损失,因为使用添加了“1=1”的过滤条件以后数据库系统就无法使用索引等查询优化策略,数据库系统将会被迫对每行数据进行扫描(也就是全表扫描)以比较此行是否满足过滤条件,当表中数据量比较大的时候查询速度会非常慢。因此如果数据检索对性能有比较高的要求就不要使用这种“简便”的方式。下面给出一种参考实现,伪代码如下:

private void doQuery() 

Bool hasWhere = false; 
StringBuilder sql = new StringBuilder(" SELECT * FROM T_Employee"); 
if(工号复选框选中) 

hasWhere = appendWhereIfNeed(sql, hasWhere);
sql.appendLine("FNumber BETWEEN '"+工号文本框1内容+"' AND '"+工号文本框2内容+"'"); 

if(姓名复选框选中) 

hasWhere = appendWhereIfNeed(sql, hasWhere); 
sql.appendLine("FName LIKE '%"+姓名文本框内容+"%'"); 

if(年龄复选框选中) 

hasWhere = appendWhereIfNeed(sql, hasWhere); 
sql.appendLine("FAge BETWEEN "+年龄文本框1内容+" AND "+年龄文本框2内容); 

executeSQL(sql); 

private Bool appendWhereIfNeed(StringBuilder sql,Bool hasWhere) 

if(hasWhere==false) 

sql. appendLine("WHERE"); 

else 

sql. appendLine("AND"); 

}

以上内容由博主摘自《程序员的SQL金典》。

模糊查询时:

[java] view plain copy
String name = request.getParameter("name");  //姓名  
String rank= request.getParameter("age");  //年龄  
String address= request.getParameter("address");  //地址  
String sql = "select * from  student where 1=1 ";  
if(name!=null && !name.equals("")){  
    sql += "t.name like '%"+name+"%'";  
}  
if(rank!=null && !rank.equals("")){  
    sql += "t.age like '%"+age+"%'";  
}  
if(address!=null && !address.equals("")){  
    sql += "t.address like '%"+address+"%'";
相关文章
|
6月前
|
SQL 数据库
SQL 查询优化指南:SELECT、SELECT DISTINCT、WHERE 和 ORDER BY
SQL的SELECT语句用于从数据库中选择数据。SELECT语句的基本语法如下:
108 1
|
8天前
|
SQL 关系型数据库 MySQL
惊呆:where 1=1 可能严重影响性能,差了10多倍,快去排查你的 sql
老架构师尼恩在读者交流群中分享了关于MySQL中“where 1=1”条件的性能影响及其解决方案。该条件在动态SQL中常用,但可能在无真实条件时导致全表扫描,严重影响性能。尼恩建议通过其他条件或SQL子句命中索引,或使用MyBatis的`<where>`标签来避免性能问题。他还提供了详细的执行计划分析和优化建议,帮助大家在面试中展示深厚的技术功底,赢得面试官的青睐。更多内容可参考《尼恩Java面试宝典PDF》。
|
2月前
|
SQL XML Java
mybatis复习03,动态SQL,if,choose,where,set,trim标签及foreach标签的用法
文章介绍了MyBatis中动态SQL的用法,包括if、choose、where、set和trim标签,以及foreach标签的详细使用。通过实际代码示例,展示了如何根据条件动态构建查询、更新和批量插入操作的SQL语句。
mybatis复习03,动态SQL,if,choose,where,set,trim标签及foreach标签的用法
|
2月前
|
SQL 数据处理 数据库
python 提取出sql语句中where的值
python 提取出sql语句中where的值
|
3月前
|
SQL 数据库
|
3月前
|
SQL
访问者模式问题之构造一个包含 select、from 和 where 子句的 SQL 节点树,如何解决
访问者模式问题之构造一个包含 select、from 和 where 子句的 SQL 节点树,如何解决
|
4月前
|
SQL 监控 关系型数据库
PolarDB产品使用问题之SQL防火墙怎么拦截没有指定WHERE条件的特定表的SQL语
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
4月前
|
SQL 数据库
SQL WHERE 子句
【7月更文挑战第10天】SQL WHERE 子句。
42 4
|
4月前
|
SQL
自定义SQL,可以利用MyBatisPlus的Wrapper来构建复杂的Where条件,如何自定义SQL呢?利用MyBatisPlus的Wrapper来构建Wh,在mapper方法参数中用Param注
自定义SQL,可以利用MyBatisPlus的Wrapper来构建复杂的Where条件,如何自定义SQL呢?利用MyBatisPlus的Wrapper来构建Wh,在mapper方法参数中用Param注
|
6月前
|
SQL 数据库
SQL WHERE 子句
SQL WHERE 子句
57 1