VB中利用SQL语句实现高效数据处理

软件世界

VB具有强大的数据库处理能力,无论是原来的DAO,还是现在的ADO,都能够简单快速设计出数据库应用,因而成为当前数据库开发的重要工具。但是,在VB中被使用得最多的DAO和ADO控件都是基于记录集的,也就是说处理过程基本都是针对单条记录进行的,因而在一些需要对大数据库进行批量处理、多表间操作的应用中显得效率低下。笔者曾经用ADO控件开发一个数据库应用,对一个有四千余条记录的数据库逐条判断处理,结果竟需要十多分钟。考虑到SQL语言的强大能力,于是准备改用SQL语句来进行处理。笔者通过不断的努力,自己摸索着完成了用SQL语句来处理数据的程序,结果将原来的处理时间大大降低,达到5秒以下。在下面的文章里,将把SQL编程中遇到的一些具体问题及其解决方法列举出来,与大家共同探讨。
准备工作:笔者的环境是Win98+VB6+ADO+MDB,由于调用SQL语句必须用ADO对象来调用,因此请先在“工程-->引用”菜单中选择“Microsoft ActiveX Data Objects 2.1 Library”。

一、打开数据库

通过以下代码,可以打开一个应用程序路径下的test.mdb库文件:
Dim oCn As New ADODB.Connection
oCn.ConnectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=test.mdb;Persist Security Info=False "
oCn.Open
代码很简单,声明一个数据库连接对象oCn,指定一个连接字符串,再Open即可。注意,在选择OLE DB提供者时用Jet引擎,它较ODBC的好处在于,不用手工添加数据源,只要数据库放在相对路径上就行了。如果你的数据库是其他类型的,不妨用ODBC的方式,连接字符串为:
“Provider=MSDASQL.1;Persist Security Info=False;Data Source=mydsn”
其中,mydsn为手工添加的数据源。
关于连接字符串,一个省事的办法是先插入一个ADO控件,用它们的属性中的向导自动生成连接字符串后,复制过来即可。
如果你的数据库设了密码,用Jet引擎的话,连接字符串中还应加入以下内容:
jet oledb:Database Password=mypass
一旦数据库成功打开,以后就可以用oCn对象来执行各种SQL语句了,执行需要用到oCn的Execute方法,如下所示:
oCn.Execute "select * from Table1"
所有SQL语句都是按照这种方式来执行的,所以下面的讨论中只写出相关的SQL语句。

二、数据查询

这个大家都知道,不就是SELECT * FROM … WHERE …嘛,那……那我就不废话了。

三、表的连接

三种连接方式:内联(INNER JOIN)、左联接(LEFT JOIN)、右联接(RIGHT JOIN)常常让人迷惑,这里可以用一个示意图来表示三种连接方式的区别。假设两个表A和B的结构如下,对它们分别进行三种连接,使用的SQL语句及得到的记录集如下所示:
内联:Select A.Key , B.key From A Inner Join B On A.Key=B.Key
左联:Select A.Key , B.key From A Left Join B On A.Key=B.Key
右联:Select A.Key , B.key From A Right Join B On A.Key=B.Key((图1)

图1
图1

简单地说,内联就是取同时满足条件的行,左联取前面表中的所有行,右联取后面表中的所有行,当另一个表中没有数据时以NULL填充。

四、数据的移动

数据库编程中,常常需要一次性地将大量的数据移动,SQL语句中有两种语句可以实现这种要求:Select Into和Insert Into 。
Select Into语句可以将一个查询的结果直接生成一个新的表,无须事先创建表。这一点特别适用于临时表,在处理过程中用Select Into被创建,用过之后再用Drop Table语句将表删除,轻松又简单!一个Select Into的例子如下:
Select * Into temp From (Select * From table)
From后面的括号不能省略,里面放一个查询语句。还记得刚刚讲的连接吧,它的语句就可以放到括号里,然后你就可以在temp表中操作连接的结果了。
再说Insert Into,功能是将一些数据插入到一个现有表中,格式如下:
Insert Into temp From Select * From table
注意它与Select Into语句的区别:不用指定字段,不用括号。后面跟的查询语句同样也可以是一个连接查询语句。
跟这两个语句有关系的语句:
删除表语句:Drop Table temp
删除记录语句:Delete * From temp Where …

五、数据的更新

当我们用控件对数据库编程时,要更新数据,就不得不对每行记录都要先EDIT,再修改,再UPDATE,既繁琐又慢。SQL语句就省事了,一个语句就解决了,如:
Update Table1 Set Field1=Field1+1 Where Field1>100
但是,显而易见,这种方式过于简单,缺乏灵活性。在数据处理中,这种只是在原来的基础上改变的更新操作往往很少,更多的可能是根据一个表的数据来更新另一个表。在这一点上,ADO有一个非常强大的功能:可以对连接表进行更新。也就是说,你可以将两个表按某种条件连接起来,并更新连接起来的表中的某个字段,ADO会自动地将更新结果写到相应的表中。下面例子演示了这个特性:将数学表中的得分加到总分中,同时,将两个表中涉及到的记录作标记,用于意外情况的处理,判断两个表中被漏掉的记录。
Update (Select 成绩.姓名,总分,成绩.标记,数学.姓名,得分,数学.标记 From 成绩 Inner Join 数学On 成绩.姓名=数学.姓名) Set 总分=总分+数学.得分,成绩.标记=1,数学.标记=1
表结构:
可以用一个括号将连接查询括起来,并在其后面进行更新。注意,如果字段名不重复,就不用在前面指定表名了。有了这么强大的更新功能,数据库中的很多复杂的更新都可以轻松解决了。

六、统计

统计同样是数据库编程中常常用到的功能之一,常用的统计函数有合计函数Sum(),记录总数Count(),平均值Avg(),最大值Max()最小值Min()等。在SQL语句中,只要很简单的一句,就可以计算出需要的统计值:
Select Sum(Field1) From Table1 Where …
但问题是,这个统计结果我们怎样才能在程序中使用,也就是说,怎样才能把它保存到一个变量中。以下是笔者的一个解决办法:
Dim fSum '用来保存统计结果的变量
Dim otmpRs As ADODB.Recordset '临时记录集,记录统计值
Set otmpRs = oCn.Execute("select sum(Field1) from Table1")
fSum= otmpRs.Fields(0)
因为一个统计语句的结果是一个只读的记录集,第一条记录中的第一个字段中就是统计的结果。因此,可以用一个临时记录集对象保存结果,再用记录集的操作将结果取出保存到变量中。
以上讨论了数据库编程过程中最常遇到的几个环节中的SQL语句的应用,也是笔者在编程过后的个人感受。限于篇幅,很多细节性的内容无法给出,在此强力推荐两个帮助文件:ADO210.CHM、JETSQL40.CHM。可能大家都有此感受:MSDN虽好,但范围太广,对某个主题的搜索,往往受到很多干扰,无法找到真正需要的内容。而单独使用这两个文件帮助,打开后就可以找到关于ADO特性以及JET引擎的SQL语言的各种用法和示例,对于解决问题非常有用。