SQL 多条件查询
网上有不少人提出过类似的问题:“看到有人写了WHERE 1=1这样的SQL,到底是什么意思?”。其实使用这种用法的开发人员一般都是在使用动态组装的SQL。让我们想像如下的场景:用户要求提供一个灵活的查询界面来根据各种复杂的条件来查询员工信息,界面如下图:
界面中列出了四个查询条件,包括按工号查询、按姓名查询、按年龄查询以及按工资查询,每个查询条件前都有一个复选框,如果复选框被选中,则表示将其做为一个过滤条件。比如上图就表示“检索工号介于DEV001和DEV008之间、姓名中含有J并且工资介于3000元到6000元的员工信息”。如果不选中姓名前的复选框,比如下图表示“检索工号介于DEV001和DEV008之间并且工资介于3000元到6000元的员工信息”:
如果将所有的复选框都不选中,则表示表示“检索所有员工信息”,比如下图:
这里的数据检索与前面的数据检索都不一样,因为前边例子中的数据检索的过滤条件都是确定的,而这里的过滤条件则随着用户设置的不同而有变化,这时就要根据用户的设置来动态组装SQL了。当不选中年龄前的复选框的时候要使用下面的SQL语句:
WHERE FNumber BETWEEN 'DEV001' AND 'DEV008'
AND FName LIKE '%J%'
AND FSalary BETWEEN 3000 AND 6000
而如果不选中姓名和年龄前的复选框的时候就要使用下面的SQL语句:
WHERE FNumber BETWEEN 'DEV001' AND 'DEV008'
AND FSalary BETWEEN 3000 AND 6000
而如果将所有的复选框都不选中的时候就要使用下面的SQL语句:
要实现这种动态的SQL语句拼装,我们可以在宿主语言中建立一个字符串,然后逐个判断各个复选框是否选中来向这个字符串中添加SQL语句片段。这里有一个问题就是当有复选框被选中的时候SQL语句是含有WHERE子句的, 而当所有的复选框都没有被选中的时候就没有WHERE子句了,因此在添加每一个过滤条件判断的时候都要判断是否已经存在WHERE语句了,如果没有WHERE语句则添加WHERE语句。 在判断每一个复选框的时候都要去判断, 这使得用起来非常麻烦,“聪明的程序员是会偷懒的程序员”,因此开发人员想到了一个捷径:为SQL语句指定一个永远为真的条件语句(比如“1=1”),这样就不用考虑WHERE语句是否存在的问题了。伪代码如下:
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语句:
AND FNumber BETWEEN 'DEV001' AND 'DEV008'
AND FSalary BETWEEN 3000 AND 6000
而如果将所有的复选框都不选中的时候就会执行下面的SQL语句:
这看似非常优美的解决了问题,殊不知这样很可能会造成非常大的性能损失,因为使用添加了“1=1”的过滤条件以后数据库系统就无法使用索引等查询优化策略,数据库系统将会被迫对每行数据进行扫描(也就是全表扫描)以比较此行是否满足过滤条件,当表中数据量比较大的时候查询速度会非常慢。因此如果数据检索对性能有比较高的要求就不要使用这种“简便”的方式。下面给出一种参考实现,伪代码如下:
{
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金典》。
模糊查询时:
- 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+"%'";
- }
SQL 多条件查询的更多相关文章
- util-C# 复杂条件查询(sql 复杂条件查询)查询解决方案
ylbtech-funcation-util: C# 复杂条件查询(sql 复杂条件查询)查询解决方案 C# 复杂条件查询(sql 复杂条件查询)查询解决方案 1.A,Ylbtech.Model返回 ...
- Mybatis中动态SQL多条件查询
Mybatis中动态SQL多条件查询 mybatis中用于实现动态SQL的元素有: if:用if实现条件的选择,用于定义where的字句的条件. choose(when otherwise)相当于Ja ...
- SQL多条件查询安全高效比较
ALTER PROCEDURE _tmp @ID VARCHAR(50), @PN VARCHAR(50), @Type INT AS BEGIN /************************* ...
- Webform中linq to sql多条件查询(小练习)
多条件查询:逐条判断,从第一个条件开始判断,如果满足,取出放入集合,再从集合中查询第二个条件... aspx代码: <body> <form id="form1" ...
- C# SQL多条件查询拼接技巧
本文转载:http://blog.csdn.net/limlimlim/article/details/8638080 #region 多条件搜索时,使用List集合来拼接条件(拼接Sql) Stri ...
- SQL 变量 条件查询 插入数据
(本文只是总结网络上的教程) 在操作数据库时 SQL语句中难免会用到变量 比如 在條件值已知的情況下 INSERT INTO table_name (列1, 列2,...) VALUES (值1, 值 ...
- sql---如何把sql查询出来的结果当做另一个sql的条件查询,1、语句2、with as
'; -- table2 的 name 作为 table1的条件 select * from table1 where name in (select name from table2) --如果有多 ...
- qt sql多重条件查询简便方法
转载请注明出处:http://www.cnblogs.com/dachen408/p/7457312.html 程序设计过程中,经常要涉及到查询,并且有很多条件,且条件可为空,如果逐个判断,会有很多情 ...
- C# SQL 多条件查询技巧
#region 多条件搜索时,使用List集合来拼接条件(拼接Sql) StringBuilder sql = new StringBuilder("select * from PhoneN ...
随机推荐
- ZooKeeper场景实践:(6)集群监控和Master选举
1. 集群机器监控 这通经常使用于那种对集群中机器状态,机器在线率有较高要求的场景,可以高速对集群中机器变化作出响应.这种场景中,往往有一个监控系统,实时检測集群机器是否存活. 利用ZooKeeper ...
- DelphiTXT文档编辑器
EXE:http://files.cnblogs.com/xe2011/Text_EditorRelease2013-12-20-185320.rar Delphi XE5 PAS:http://fi ...
- linux 清空文件内容命令
清空文件内容命令 $ echo "" >log.log > 是重写,覆盖式 >>是尾部追加
- L2TP
点击查看详情>> 我的贡献 |退出 L2TP 编辑词条 L2TP是一种工业标准的Internet隧道协议,功能大致和PPTP协议类似,比如同样可以对网络数据流进行加密.不过也有不同之处 ...
- CentOS7上安装Pycharm
下载pycharm $ wget https://download.jetbrains.com/python/pycharm-professional-2016.1.2.tar.gz 解压 $ .ta ...
- su: cannot set user id: Resource temporarily unavailable
今天R&D所在主机出现su: cannot set user id: Resource temporarily unavailable资源不可用报错,直接通过其他机器ssh huyuh@xxx ...
- 企业级应用架构(三)三层架构之数据访问层的改进以及测试DOM的发布
在上一篇我们在宏观概要上对DAL层进行了封装与抽象.我们的目的主要有两个:第一,解除BLL层对DAL层的依赖,这一点我们通过定义接口做到了:第二,使我们的DAL层能够支持一切数据访问技术,如Ado.n ...
- jquery操作iframe中的js函数
关键字:jquery操作iframe中的js函数 1.jquery操作iframe中的元素(2种方式) var tha = $(window.frames["core_content&quo ...
- sublime中使用markdown
#为知笔记##为知笔记###为知笔记 1. 列表12. 列表23. 列表35. 顺序错了不用担心3. 写错的列表,会自动纠正 为知笔记---------------------- ```cpp int ...
- Linux操作系统搭建LAMP开发环境
Step1. 安装 Apache 在terminal中输入命令 sudo apt-get install apache2 打开浏览器,在地址栏输入:127.0.0.1,如果出现了 “It works! ...