动态SQL语句的编程

 当通过SQL语句查询数据库服务器中的数据库表:

  ● 查询只能涉及到一个单独的表

  ● SQL语句中不能包含ORDER BY命令

  ● SQL语句中不能含聚集运算符SUM或AVG运算

  

  另外,如果是查询Sybase数据库中的表,那么被查询的表中只能有一个索引。

  如果在应用程序中要求TQuery部件返回一个“活动”的查询结果数据集,但是SQL 命令语句不满足上述约束条件时,对于本地数据库的SQL查询,BDE只能返回只读的数据集。对于数据库服务器中的SQL查询,只能返回错误的代码。当TQuery 部件返回一个“活动”的查询结果数据集时,它的CanModify属性的值会被设置成True。

  

  表17.1 TQuery部件返回查询结果数据的类型

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  RequestLive属性值 CanModify属性值 查询结果的类型

  ────────────────────────────────

  False False 只读数据

  True(SQL语句满足约束条件) True “活动”数据

  True(SQL语句不满足约束条件) False 只读数据

  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  

  当TQuery部件返回只读的查询结果数据集,而用户又 希望修改这只读的数据集时,一般这样来处理,在应用程序中另外增加一个 TQuery 部件 Query2( 假设获得只读结果的TQuery部件的名字是Query1),在Query2中设置修改语句UpDATE对Query1 中的数据进行修改操作,这样会实现对只读数据的修改。

  

  17.4 动态SQL语句的编程

  

  在17.3节中,我们已经介绍了动态SQL语句(又被称为参数化的SQL语句),在其中包含在程序过程中可以变化的参数,在实际的程序设计中使用得更多的是动态SQL语句,因而在这一节里我们重点介绍如何给动态SQL语句的参数赋值,以在应用程序中灵活地使用SQL语句。动态SQL语句的编写、执行等等与17.3节中介绍的SQL语句的编写、执行是一样的。

  动态SQL语句中的参数,我们可以通过两种途径来为它赋值:

  1. 利用参数编辑器(Parameter Editor)来为参数赋值

  具体方法是:选中TQuery部件,单击鼠标右键,然后从中选择Define Parameters 便可以打开参数编辑器。 

  例如,在TQuery部件的SQL属性中我们设置如下的SQL语句: 

  Setect * From Customer Where CustNO=:Number;

  

  TQuery的DatabaseName属性为DBDEMOS,其中Number为参数变量。我们便可以为参数Number赋值,在Datetype组合框中选择该参数的数据类型为整数Integer,在Value编辑框中可以为参数Number赋一个值,也可以单击Null Value检查框为参数Number赋一个空值Null。给参数赋值之后,单击OK按钮,这样TQuery部件中的SQL 查询便准备好了,而且参数值也被赋给了动态SQL语句中相应的参数,此时当把TQuery 部件的Active属性设置成True时,在与TQuery部件相连的数据浏览部件中会显示出查询结果,通过参数编辑器为参数赋值,这种方式缺乏应有的灵活性,在实际应用中用得较少,在实际应用中程序设计人员希望用更灵活方便的方式为参数赋值,那就是我们接下来要介绍的另一种途径:

  2. 在运行过程中,通过程序为参数赋值

  用这种方式为参数赋值有三种方法:

  ①根据参数在SQL语句中出现的顺序,设置TQuery部件的Params属性值为参数赋值。

  ②直接根据SQL语句中各参数的名字,调用ParamByName方法来为各参数赋值。

  ③将TQuery部件的DataSource属性设置为另一个数据源,这样将另一个数据源中与当前TQuery部件的SQL语句中的参数名相匹配的字段值赋给其对应的参数。

  这三种方法我们将在下面的三小节中具体地介绍

  17.4.1 使用Params属性为参数赋值

  

  TQuery部件具有一个Params属性,它们在设计时不可用,在程序运行过程中可用,并且是动态建立的,当为TQuery部件编写动态SQL 语句时, Delphi 会自动地建立一个数组Params,数组Params是以0下标开始的,依次对应动态SQL 语句中的参数, 也就是说动态SQL语句中第一个参数对应Params[0],第二个参数对应params[1],依此类推。

  例如:一个TQuery部件Query1,我们为它编写的动态SQL语句是:

  

  Insert Into Customer(CustNo,Name,Country)

  Values(:CustNo,:Name, : Country)

  

  对于上述这条动态SQL语句中的参数,我们可以利用TQuery部件的params 属性为参数赋值:

  

  Query1.params[0].AsString := "1988";

  Query1.params[1].AsString := "Lichtenstein";

  Query1.params[2].AsString := "USA";

  

  上述语句将把"1988"赋给参数:Cuse_No,"Lichtenstein"赋给参数:Name,"USA"赋给参数:Country。

  

  17.4.2 使用ParamByName方法为参数赋值

  

  ParamByName是一个函数,用动态SQL语句中的参数作为调用ParamByName函数的参数,这样便可以为它们赋值,使用这种赋值方法,必须要知道动态SQL语句参数的名字。

  例如在17.4.1节中的例子中,也可以用下述方法给参数赋值:

  

  Query1.ParamByName('CustNo').AsString := "1988";

  Query1.ParamByName('Name').AsString := "Lichtenstein";

  Query1.ParamByName('Country').AsString := "USA";

  

  使用这种方法同样可以为各参数赋值,而且更加直观一些。

  

  17.4.3 使用Datasource属性为参数赋值

  

  上述两种方法的共同特点是:我们在为各参数赋值时,我们是知道各参数对应的具体参数值的。而在具体的应用程序中,有些参数值常常是无法确定的,例如参数值来自于另一个查询结果,对于这种情况,Delphi提供了使用Datasource属性为动态SQL 语句中尚存在没有赋值的参数时, Delphi 会自动检查 TQuery 部件的 Datasource 属性, 如果为Datasource属性设置了属性值(该属性的值是另一个TDatasource部件的名字),Delphi 会把没有赋值的参数与TDatasource部件中的各字段比较,Delphi 会将相应的字段值赋给与其相匹配的参数,利用这种方法也能实现所谓的连接查询,我们在学习使用TTable部件时,便会创建主要--明细型数据库应用,用TQuery部件创建的连接查询与主要- -明细型应用是相似的。

  例如:在如图17.7所示的应用中,设置了下列部件:

  ● 一个TTable部件

  名字为Cust,它的DatabaseName属性为DEMOS,TableName属性为Customer。

  ● 一个TDatasource部件

  名字为Custsource,其Dataset属性被设置为Cust。

  ● 一个TQuery部件

  名字为ORDERS,其DatabaseName被设置为DEMOS,SQL属性值为:

  

  Select Orders.CustNo,Orders.OrderNo,Orders.SaleDate FROM Orders

  WHERE Orders.CustNo =: CustNo

  

  ORDERS的DataSouce属性被设置为CustSource

  ● 一个TDatasource部件

  名字为OrderSource,其DataSet属性被设置为Orders。

  ● 两个TDBGrid部件

  它们分别连接CustSource和OrderSource。

  TQuery部件Orders中的动态SQL语句中的参数:CustNo在程序设计过程中没有给它赋值,当该应用程序运行时Delphi会自动地到其Datasource属性中说明的数据源CustSource中查找与参数:CustNo匹配的字段,而CustSource中正好有一个名字为 CustNo 的字段与参数:CustNo匹配,这样Customer表中的CustNo字段值被赋给了参数 : CustNo , 而当每移动Customer表中的记录指针,参数:CustNo的值会随之改变,而参数:CustNo的值发生改变时,Orders中的动态SQL语句会根据新的参数值重新查询,从数据库表中获取相应的订单数据,这样也变实现了类似于主要--明细型应用。即连接查询。 

  17.4.4 Prepare方法的使用 

  在使用动态SQL语句编程时,常常用到一个很重要的方法prepare,调用prepare 方法之后,Delphi会将带参数的SQL语句传送给与其对应的数据库引擎,对动态SQL语句进行语法分析和优化。虽然在用动态SQL语句编程时,调用prepare方法并不是必须的,但是这里我们要极力推荐调用prepare方法,因为调用prepare方法后,会大大提高动态SQL 语句的执行性能,特别是当要反复多次执行同一条动态SQL语句时,其优越性会更加明显。如果在应用程序中执行一条SQL语句之前并没有显式地调用prepare方法,每次在执行SQL 语句时,Delphi会隐含地调用propare方法以准备这个查询。

  TQuery部件还有一个prepare属性,这是一个布尔型属性,当其属性值为True时,表明该查询已被准备好了( SQL 语句已被传送到数据库引擎中 ) ,当我们使用参数编辑器Parameters Editor来为动态SQL语句中的参数赋值时,当设置完相应的参数值并退出参数编辑器时,Delphi会隐含地调用prepare方法以准备好查询。

  当SQL语句执行完之后,要想准备下一个查询,首先必须调用close方法,然后才能调用prepare方法准备下一个查询。一般来说,在一个应用程序中应该调用一次prepare方法,常常在窗体的OnCreate事件处理过程中调用prepare方法,然后用上述介绍的方法为参数赋值,最后调用Open方法或ExecSQL方法执行SQL语句,以完成查询。

  当然在调用prepare方法准备好一个查询时,会消耗一些数据库资源,因而每当一个查询执行完毕之后,要养成调用Unprepare方法以撤消查询的好习惯。在运行程序过程中,通过程序改变TQuery部件的SQL属性值时,Delphi会自动地调用Close方法和Unprepare 方法,以撤消查询。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值