潘婷婷
(汕头职业技术学院,广东汕头 515078)
基于List集合的多条件查询优化算法研究
潘婷婷
(汕头职业技术学院,广东汕头 515078)
在数据库应用程序的研发过程中,经常涉及到对数据表的任意字段进行任意形式的组合查询,这样可以大大缩小查询范围,这就是多条件查询。文章首先对多条件查询的常用方法予以介绍,包括枚举法、递进法;最后笔者给出防止注入攻击的基于List集合的多条件查询优化算法。同时,为了提高性能,避免产生垃圾内存,SQL语句都使用StringBuilder类来创建字符串实例进行拼接,文中的代码均在VS2008平台下运行通过。
多条件查询;List集合;SQL;注入攻击;StringBuilder
随着信息技术和软件产业的不断发展,近年来越来越多的政府、企业以及社会生产和服务的各个部门都引入了各种信息管理系统对数据和信息进行管理,在使用信息管理系统对数据进行管理时,查询功能是用户使用频率最高的功能,查询模块是信息管理系统中的重要软件模块,查询模块的设计是系统设计的关键环节,查询功能设计的好坏直接关系到信息管理系统效率的大小以及人机结合密切关系的程度,而且将在很大程度上影响系统的可维护性和可修改性[1]。
传统的信息管理系统中的查询模块对操作人员的要求较高,需要使用者对数据库的结构有清楚的了解并能熟练的使用相关的查询命令,而且在进行查询时一般只能选择设计好的关键词段进行查询,不能输入随机字段进行查询操作,也不能使用多条件组合查询的功能,查询交互式界面不够直观、简洁[2]。
多条件查询是指有多个组合条件的查询。由于信息量的不断膨胀,数据记录在数据库中存储越来越多,对于特定记录的获取,通过一个条件往往无法进行准确定位,常常需要2个以上查询条件的组合来筛选满足条件的数据记录。
确切地说,多条件查询是指数据表或视图中的多个字段、值按照一定的运算关系和逻辑关系构成符合数据库管理系统规则的条件表达式,并从指定的数据库 (表)或视图中提取满足条件的数据。就是用户根据已经知道的多种信息来查询数据库,从而缩小范围得到更精确更符合用户需要的查询结果。在利用数据库管理系统开发应用软件时,多条件查询是重要的功能之一,其核心是条件表达式的构成。
以图1原始数据图中的表为例子,来实现各种构建条件表达式的算法:
图1 原始数据
枚举法是一一列举所有情况,该方法在组合条件较少时比较适用,因为用这种方法思路比较简单。这种枚举法的缺点就是当查询条件增加的时候,枚举的情况就会以2n增长,如果组合查询的条件为3个时,那么需要列举出来的情况就是8种,如果组合条件是4个,需要列举出来的情况就是16种。因此组合查询条件超过4个时,程序的代码量会变得非常大,实现难度也大,效率低下。
本实例中,我们要查询的是姓名中的姓是“陈”并且电话号码以“189”开头的所有学生的记录(此处仅以2个条件为例,列举出4种情况,后面的例子都是以3个条件为例)。因为这里的查询条件有2个,所以,可能的情况就要分为22(4)种。程序中依次做如下判断:当姓名和电话搜索条件都为空的时候,这时sql语句为"Select*from student";当姓名为空并且电话不为空的时候,sql语句为"Select*from student where Tel like'%"+txtSearchPhone.Text.Trim()+"%'";当姓名不为空且电话为空的时候,sql语句为"Select*from student where Name like'%" +txtSearchName.Text.Trim()+"%'";当姓名和电话都不为空的时候,sql语句为"Select*from student where Name like'%"+txtSearchName.Text.Trim()+"%'and Tel like'%"+txtSearchPhone.Text.Trim()+"%'"。
以下是实现的代码:
图2 枚举法执行界面图
递进法完全克服了枚举法的缺点,有N个条件仅需要列举出N种情况即可,不像枚举法那样需要列举出2N种情况,程序代码的复杂性大大降低,其执行效率也大大提高。与枚举法相比只有核心部分不同,递进法的搜索核心,是依次判断条件为是否为空,如果不为空,则加入搜索条件[3]。为了避免当查询条件全部都为空的时候而导致sql语句出错,在where子句中预先设定一个恒成立的条件“1=1”。
以下代码是以查询条件为“姓陈并且电话号码以189开头并且地址是在广州”的所有学生的记录,与枚举法例子中的查询条件不同的是,这里的查询条件有3个。
单从语句的长短,就可以看出递进法相比枚举法是一个有较大改进的算法。这个算法的关键部分在与where子句后面的恒成立条件“1=1”,它防止了所有查询条件都为空的情况导致的错误。这种方法相比较枚举法不管是编程技巧还是代码量都提升了一个台阶。
代码执行后,效果如图3递进法和优化算法执行界面图如图3所示。
图3 递进法和优化算法执行界面图
从实例中可以看出,当每个条件都为空的时候,sql语句为"select*from student where 1=1",因为1=1是恒成立的,所以sql语句相当于select*from student,就是选择整张表;如果姓名不为空,则sql语句为"select*from student where 1=1"+"and Name like '%" +txtSearchName.Text.Trim()+"%'",就是相当于"select*from student where 1=1 and Name like '%"+txtSearchName.Text.Trim()+"%'",其他条件不为空时,依次类推。
递进法比起枚举法,在性能方面,的确有了很大的提高,但是,递进法也存在自身不足的地方。首先,递进法仍然是拼接的SQL语句,仍然存在注入漏洞攻击,而防止注入漏洞攻击的有效方法,就是通过参数赋值,带参数的SQL语句内部是调用了存储过程。其次,多条件搜索where 1=1并不高效,使用这种方式,在数据库中会做全表扫描,对每行数据都进行扫描和比对,这样,数据库会无法使用索引等优化查询的策略,建立的索引页将会失效。由于存在以上两个缺点,所以,递进法用起来,仍然不是那么高效。
此时,我们可以定义2个集合,一个集合叫listTiaoJian,里面存储的是string类型,如果相应的条件不为空,就用Add方法添加字符串元素,例如,如果查询姓名的文本框不为空,就是说姓名这一项有相应的查询条件,就把“Name like@Name”字符串作为该集合的一个元素添加进去。同理,如果电话和地址有相应的查询条件,就把“Tel like@Tel”和“Address like@Address”添加进listTiaoJian集合。然后再判断用户是否选择了条件,只要有选择了条件,不管是选择了1个、2个还是3个,通过执行string tj=string.Join(“and”,listTiaoJian.ToArray());这条语句,把 listTiaoJian里面的各个元素用“and”连接起来,最后在前面补上一个where,就实现了查询条件表达式的构成。如果用户一个条件都没有选择的话,那么,以下代码中的4个if语句均不执行,sql语句就是“select*from student”,相当于进行全表查询。
为了防止注入漏洞攻击,使用了带参数的SQL语句,此时,listParameter集合里面存储的是SqlParameter类型,如果相应的条件不为空,在给listTiaoJian集合添加字符串元素的同时,也给listParameter集合添加元素,通过语句listParameter.Add(new SqlParameter(“ @Name” ,“%” +txtSearchName.Text.Trim()+ “%”));实现把用户在文本框的输入传给SQL语句里面的@Name,这样能够有效的防止注入漏洞攻击。
以下是实现的代码:
代码执行后,效果与递进法一样,如图3递进法和优化算法执行界面图所示。
本文首先介绍了实现多条件查询的枚举法,这种方法虽然思路简单,但是在查询条件多的时候,实现语句呈指数级增长,实现难度大,效率低。接着介绍了实现多条件查询的递进法,这种算法虽然克服了枚举法的缺点,但是存在注入漏洞攻击的安全隐患,并且由于存在恒成立条件where 1=1而进行全表扫描,效率不高。最后介绍了这种新型的算法,优化的基于List集合的防注入攻击的带参数的SQL语句来构建多条件查询表达式,这种算法很好地克服了枚举法和递进法的缺点。
[1]赵大伟,陈刚.基于.Net的多条件组合查询技术的设计与实现[J].电脑知识与技术,2012,8(25):6045-6048.
[2]朱晓钟,刘宪成.组合条件查询的设计与实现[J].电脑知识与技术,2007,15(1):674-676.
[3]姚剑芳.基于SQL Server的多条件模糊匹配查询[J].福建电脑,2010(4):88-89.
Research on multi-conditional query optimization algorithms based on List Set
PAN Ting-ting
(Shantou Polytechnic College,Shantou,Guangdong,China 515078)
The development of database application programs often involves any form of combination query of any field of the data table,which can greatly reduce the query range.And that is called multi-conditional query.This paper first introduces the commonly used methods of multi-conditional query,including enumeration method and progressive method.Finally,the author gives the multiconditional query optimization algorithm based on List Set to prevent injection attack.At the same time,in order to improve the performance and avoid producing waste memory,SQL sentence uses StringBuilder class to create a string instance and the codes in the text run through the VS2008 platform.
multi-conditional query;List Set;SQL;injection attack;StringBuilder
10.3969/j.issn.1671-9581.2014.01.007】
TP312
A
1671-9581(2014)01-0025-04
2013-10-28
潘婷婷(1982-),女,广东汕头人,汕头职业技术学院讲师,硕士,研究方向:计算机应用。