2.4.1 使用TSQLStoredProc调用MS SQL Server的存储过程
dbExpress 3.0版不但为MS SQL Server提供了Unicode的支持,也对调用MS SQL Server的存储过程提供了更好的支持,能够处理由MS SQL Server存储过程返回的结果数据集。
当使用TSQLStoredProc调用返回结果数据集的MS SQL Server的存储过程时,开发人员在调用存储过程时需要使用TSQLStoredProc的Open方法或设定TSQLStoredProc的Active属性值为True。当TSQLStoredProc调用完存储过程之后,存储过程执行的结果数据集可以借助TSQLStoredProc的Fields或是FieldByName方法存取返回的结果数据集。由于返回的结果是单向的数据集,因此开发人员可以调用Next方法一一地取得每一笔记录。
现在让我们使用一个实际的范例来说明如何使用TSQLStoredProc控件,来调用返回结果数据集的MS SQL Server存储过程。在MS SQL Server中有一个NorthWind数据库,其中包含了许多的存储过程,我们要展示调用的是其中称为"Ten Most Expensive Products"的存储过程,它的程序代码如下:
create procedure "Ten Most Expensive Products" AS
SET ROWCOUNT 10
SELECT Products.ProductName AS TenMostExpensiveProducts, Products.UnitPrice
FROM Products
ORDER BY Products.UnitPrice DESC
这个存储过程会返回一个包含10个最贵产品的结果数据集给客户端,现在就让我们说明如何借助dbExpress控件调用这个存储过程并且在客户端显示这些返回的数据。
步骤1 建立数据模块和dbExpress控件
在Delphi集成开发环境中点击File|New|VCL Forms Application建立一个新的Delphi应用程序。接着点击File|New|Others…|Data Module建立空白的数据模块。在数据模块中放入TSQLConnection控件,连接到范例Northwind数据库,设定Connected属性值为True,再放入一个TSQLStoredProc控件,设定它的SQLConnection属性值为加入的TSQLConnection,再点击它的StoredProcName属性。对象查看器便会显示目前数据库中所有可以调用的存储过程。请从其中选择Ten Most Expensive Products这个存储过程。此时数据模块看起来如图2-45所示。

图2-45 使用TSQLStoredProc调用返回数值的MS SQL Server存储过程
步骤2 建立主窗体
在范例应用程序的主窗体先点击File|Use Unit…菜单,选择使用刚才建立的数据模块。接着在主窗体中加入一个TClientDataSet控件,设定它的Name属性值为cdsData。再放入一个TDataSource控件,设定它的DataSet属性值为cdsData。再加入TDBNavigator控件和TDBGrid控件,设定它们的DataSource属性值为刚才加入的TDataSource。最后放入一个TButton控件,设定TButton控件的Caption属性值为“调用MS SQL Server存储过程”,此时主窗体看起来如图2-46所示。

图2-46 范例应用程序的主窗体
步骤3 实现范例应用程序
在主窗体的【调用MS SQL Server存储过程】按钮的OnClick事件处理函数中撰写如下的程序代码:
001 procedure TfrmMain.btnCallSPClick(Sender: TObject);
002 begin
003 CreateDataSet;
004 dmDemo.spMostExpensiveProducts.Active := True;
005 DoProcessSPData;
006 end;
007
008 procedure TfrmMain.CreateDataSet;
009 var
010 Defs : TFieldDefs;
011 aField : TFieldDef;
012 anIndex : TIndexDef;
013 begin
014 Defs := cdsData.FieldDefs;
015
016 aField := Defs.AddFieldDef;
017 aField.DataType := ftString;
018 aField.Size := 30;
019 aField.Name := '产品名称';
020
021 aField := Defs.AddFieldDef;
022 aField.DataType := ftCurrency;
023 aField.Name := '价格';
024
025
026 anIndex := cdsData.IndexDefs.AddIndexDef;
027 anIndex.Fields := '产品名称';
028 anIndex.Name := 'pnIndex';
029
030 cdsData.CreateDataSet;
031 end;
032
033 procedure TfrmMain.DoProcessSPData;
034 begin
035 try
036 cdsData.DisableControls;
037 while (not dmDemo.spMostExpensiveProducts.Eof) do
038 begin
039 cdsData.Insert;
040
cdsData.FieldByName('产品名称').Value :=
dmDemo.spMostExpensiveProducts.Fields[0].AsString;
041
cdsData.FieldByName('价格').Value :=
dmDemo.spMostExpensiveProducts.Fields[1].AsCurrency;
042 cdsData.Post;
043 dmDemo.spMostExpensiveProducts.Next;
044 end;
045 finally
046 cdsData.EnableControls;
047 end;
048 end;
在上面的程序代码中,btnCallSPClick首先调用CreateDataSet在cdsData中建立两个存储过程返回的结果数据集的字段类型,分别是字符串类型的产品名称,以及Currency类型的价格,最后调用TClientDataSet的CreateDataSet方法在cdsData中建立数据集以准备接受存储过程返回的结果数据集。
接着在004行设定spMostExpensiveProducts的Active属性值为True以调用MS SQL Server的存储过程,最后在005行调用DoProcessSPData显示存储过程返回的结果数据集。
DoProcessSPData方法在037行借助判断spMostExpensiveProducts的Eof属性值是否为True,来判断是否到达了返回结果数据集的结尾,接着,在040/041行借助存取spMostExpensiveProducts的Fields属性值取得返回结果数据集的字段数值,并且插入到cdsData的字段中,043行调用spMostExpensiveProducts的Next方法以跳到结果数据集的下一笔数据。
现在编译并且执行此范例应用程序,点击主窗体中【调用MS SQL Server存储过程】按钮,我们就可以看到如图2-47所示的执行结果画面。读者可以看到虽然“Ten Most Expensive Products”存储过程是MS SQL Server中的存储过程,我们仍然可以借助dbExpress调用它并且处理它返回的结果数据集,就好像它是dbExpress的原生数据集一样。

图2-47 范例应用程序执行的结果画面






