DELPHI基础教程
第十八章 Delphi客户服务器应用开发(三)
3. 安装的软件项目 当你安装 InterBase SQL Link 驱动程序,下列项目将被安装于你的工作站上。 表 18.7 安装的文件名 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 项 目 描 述 ────────────────────────────────────── SQLD-IB.DLL 包含 InterBase 驱动程序和支持文件的动态链接库 SQLINT32.DLL INTRBASE 驱动类型 加在配置工具的驱动管理程序中以配置基本的 Borland InterBase SQL Link 驱动程序 INTRBASE 别名类型 加入配置文件的别名以使建立联接 SQL 服务器数据库的 别名 SQLD_IB.HLP 配置 InterBase 驱动程序的帮助文件 READLINK.TXT Borland SQL Links for Windows 自述文件 INTERBAS.MSG InterBase 消息文件,通常安装上 C:\INTERBAS CONNECT.EXE 测试工作站和 InterBase 服务器连接情况的工具 REMOTE.DLL 、 InterBase 的支持动态链接库 GDS.DLL 、 GDS32.DLL 将 InterBase 服务器描述 安装过程修改工作站的 SERVICES 文件以增加用于 加入 SERVICES 文件 InterBase 服务器访问所需的协议描述 , 如: gds- db 3050/tcp ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
软件项目中还应包括 TCP/IP 接口软件 下表列出的文件给 InterBase 客户端应用提供访问 Winsock 1.1 的接口
表 18.8 TCP/IP 接口软件 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 文 件 名 描 述 ──────────────────────────────── MVWASYNC.EXE 异步通信模块 VSL.INT TCP/1P 传输初始化文件 WINSOCK.DLL Windows Socket 动态链接库 MSOCKLIB.DLL 将 Windows Socket 调用映射到 VSL 驱动程序 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
如果 TCP/IP 产品不是 Winsock1.1 兼容, InterBase 客户端应用将也可采用其它 TCP/1P 驱动程序。 InterBase 服务器还可支持其它通信协议,如 SPX/1PX , NetBeIU 等。 4. 解决一般的联接问题 如果用 SQL Links 建立与 InterBase 服务器的连接有问题可采用下列步骤来分离问题原因: ⑴ 通过 Windows ISQL 工具测试能否与 InterBase 服务器联接 如果成功,状态信息会出现,并继续步骤⑵。 如果不成功,询问数据库管理员。 ⑵ 检验 InterBase SQL Links 驱动程序是否正确安装。 ⑶ 重新安装 SQL Links 。 ⑷ 检查 SERVICES ,文件中应有行:
gds_db 3050/tcp
如果不能正确安装,就请询问数据库管理员,否则继续步骤⑸。 ⑸ 测试底层协议 ① 输入 TELNET 命令,确认 TCP 库是否正确安装。 如果 TCP 库正确安装,注册提示符会出现。注册入网检查数据库是否存在。 如果消息是“ can't resolve hostname ” 出现,检查工作站的 HOSTS 文件是否有你 的主机名和 IP 地址的人口。如:
128.127.50.12 mis_server
如果用 TELNET 是成功的,但仍然无法正确联接,则没有正确安装 InterBase 。请寻 求数据库管理员的帮助。 ② PING 到服务器服务器上,测试 InterBase 服务器是否正常运行并且为桌面应用可见 ( 如果 PING 是成功的,消息“ servername is alive ”被显示 ) 。 PING 成功但 TELNET 不成功,则 inet daemon 可能有问题。 如果 PING 到服务器上不成功,则有网络路径问题,将问题报给网络管理员。
如果底层协议不正常,请询问数据库管理员,否则继续帮助⑹。 ⑹ 确认是否有 InterBase 服务器的访问权,如果有请继续步骤⑺。 ⑺ 检查 BDE 应用程序的 InterBase 别名是否正确安装。 如果能够直接从工作站上联接,但不能从 BDE 应用程序中,那么很有可能你的 IDAPI32.CFG 别名设置有问题。运行 BDE 配置工具检查 InterBase 别名。
18.3 Delphi Client/Server 编程
本节介绍如何运用 Delphi 可视化开发工具和 ObjectPascal 语言开发 Client\Server 的数据库应用程序,采用的例子是 CSDEMOS 。这是 Delphi2.0 自带的演示 Client\Server 开发的例子,它安装在 C:\Program Files\Borland\Delphi 2.0\Demos\DB\CSDemos 中 ( 缺省安装 ) 。 本节将包含以下内容: ● 使用 TDatabase 部件连接 SQL 服务器 ● 用 DataSet 部件(又称数据集部件),如 TTable 和 TQuery ,联接 TDatabase 部件并访问数据库以及各种表之间如何切换 ● 使用数据库连接 ● 触发器的使用方法 ● TStoredProc 部件的使用方法 ● 客户和服务器之间的事务控制 ● TStoredProc 部件的使用方法
18.3.1 使用 TDatabase 部件联接 SQL 服务器
18.3.1.1 TDatabase 部件概述
TDatabase 部件处理应用程序与单个数据库的联接。如果不需要控制数据库联接,可以不用创建 TDatabase 部件。当应用程序试图打开数据库表 (Table) 时,会自动创建一个临时的 TDatabase 部件。但如果你想控制数据库的持续联接、进入数据库服务器的注册和数据库别名的值或事务控制,那么你就必须为每个所需的联接创建一个 TDatabase 部件。 1. 创建 TDatabase 部件 TDatabase 部件在 Component Palette 中的 Data Access 页上,你能将其拖放在数据模块 (Data module) 或窗体中。在设计时创建 TDatabase 部件,用户可以设置初始值和编写 OnLogin 事件处理过程 (Event Handle) 。 OnLogin 事件给用户提供了第一次注册数据库服务器时定制服务器安全参数,如口令,的能力。 2. TDatabase 的关键属性 ⑴ DatabaseName 属性 DatabaseName 是所要联接的数据库名,并且用于 DataSet 软件,它将出现在 DataSet 部件的 DatabaseName 属性的下拉式列表框中。设置 DataBaseName 属性是定义数据库应用的特定别名。 DataSet 部件能引用该名字以取代直接使用 BDE 别名。当 TDatabase 部件的 Connected 属性为 True 时不能修改该属性。 ⑵ AliaName 属性 AliasName 是 BDE 配置工具定义的 BDE 别名的名字。 TDatabase 从中获取其缺省的设置。如果设置 DriveName 属性,则该属性将被清除,如果当 Connected 为 True 时强行设置 DriveName 属性将引发异常。 ⑶ DriveName 属性 DriveName 是 BDE 驱动程序,如 STANDARD 、 ORACLE 、 SYBASE 、 INFORMIX 或 INTERBASE 的名字。如果设置 AliasName ,则该属性值将被清除。 ⑷ Params 属性 Params 属性包含了打开 SQL 服务器上数据库时所需的参数。在缺省情况下,这些参数由 BDE 配置工具设置;用户也可以用数据库参数编辑器 (Database Parameters Editor) 修改这些参数。对于数据库服务器而言, Params 将描述一系列的参数,如服务器名、 数据库名、用户名和口令。 ⑸ Connected 属性 Connected 属性指明是否建立数据库的联接,当应用程序打开数据库中的一个表时 Connected 将被置为 True ;反之,关闭数据库表, Connected 将被置为 False ,除非 KeepConnection 为 True 。而将 Connected 置为 True 则可不需打开数据库表即可建立数据库联接。 TDatabase 的 KeepConnection 属性描述当数据库中没有表打开时是否维持数据库联连。 ⑹ KeepConnection 属性 KeepConnection 属性描述当数据库中没有打开表时是否要保持与服务器的联连, 如果数据库应用需要打开和关闭单个数据库中的多个表时,将 KeepConnection 设置为 True 是很有用的,那样,即使没有打开任何表,应用仍能保持与数据库的联接,它能够重复地打开和关闭数据库表,而不需要重复执行联接过程。如果 KeepConnection 置为 False ,当每次将 Connected 置为 True ,数据库都必须执行注册过程。 ⑺ LoginPrompt 属性 LoginPrompt 属性用于控制如何处理 SQL 数据库的安全性问题。如置为 True ,当应用程序试图建立数据库联接时屏幕上将出现标准 Delphi 注册对话框。用户必须输入正确的用户名和口令。如果置为 False ,则应用程序将寻找 TDatabase 部件的 Params 属性中的注册参数。下面是 USERNAME 和 PASSWORD 参数的例子:
USERNAME = SYSDBA PASSWORD = masterkey
⑻ TransIsolation 属性 TransIsolation 属性描述 SQL 服务器所有的事务控制独立级别。 tiDirtyRead 使所有修改都被返回,而不管记录是否已被提交。 tiReadCommitted 将只返回提交的记录,而提交的修改将不会在结果中反映出来。 tiRepeatableRead 将只返回事务过程中最初的记录,即使另一个应用程序将所作的修改提交。 各种数据库服务器可能不同程度地支持这些独立级别,或者根本不支持。 如果需要的独立级别不被服务器支持,那么 Dephi 将使用下一个更高的独立级别,如下表所示:
表 18.10 各类服务器 TransIsolation 设置 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 独立级别 Oracle Sybase 和 InterBase Microsoft SQL ────────────────────────────────────── Dirty Read Read Committed Read Committed Read Committed Read Committed Read Committed Read Committed Read Committed Repeatable read Repeatable read Not Supported Repeatable Read ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
各个独立级别的含义请见表 18.12 。
3. TDatabase 的关键方法 ⑴ StartTransaction 方法 StartTransartion 方法在由 TaransIsolation 属性指定的独立级别下开始事务控制。如果在一个事务已被激活的情况下调用该方法, Delphi 将引发异常。 调用了该方法后,对数据库所做的修改一直由数据库服务器维持到调用 Commmit 方法提交数据或调用 Rollback 方法取消修改为止。只有当联接数据库服务器时,才能调用该方法。 ⑵ Rollback 方法 Rollback 方法返转当前事务控制,并且取消自最近一次调用 StartTransaction 以来对数据库所做的所有修改。 ⑶ Commit 方法 Commit 方法提交当前事务控制,并且将自最近一次调用 StartTransaction 以来所有数据修改存入数据库。 4. TDatabase 的 OnLogin 事件的处理 OnLogin 事件的触发条件是当联接 SQL 数据库的 TDatabase 部件被打开并且 LoginPrompt 属性为 True 。使用 OnLogin 事件处理过程可以在运行时设置注册参数。 OnLogin 事件处理过程得到 TDatabase 的注册参数数组 Params ,并且使用 Values 属性改变这些参数。 例如:
LoginParams.Vaiues['SERVER NAME'] := 'MYSERVERNAME'; LoginParams.Values['USER NAME'] := 'MYUSERNAME'; LoginParams.Values[PASSWORD'] := 'MYAPSSWORD';
当控制从 OnLogin 事件处理过程中返回时,应用程序用这些参数来建立联接。 OnLogin 事件处理过程的声明是这样的:
TLoginEvent = procedure(Database: TDatabase; LoginParam: TStrings) of Object; property OnLogin: TLoginEvent;
TLoginEvent 类型是处理 OnLogin 事件的方法头。 Database 参数是要联接的数据库。 LoginParams 是 TStrings 类型的对象,包含用户名和口令,以及打开数据库时所用的其它参数。用户名是形如 USER NAME = John.Doe 的字符串,口令是形如 PASSWORD = is_Password 的字符串。当 OnLogin 事件处理过程被调用时应当在 LoginParams 中加入用户名和口令。
18.3.1.2 定制数据库服务器的注册参数
大多数数据库服务器都包含限制数据库访问的安全特征。通常,在用户能访问数据库之前,服务器都要求注册的用户名和口令。 如果服务器需要注册,在设计阶段, Delphi 会在你试图联接时提示你,诸如在会 TTable 部件描述数据库表名时。 在缺省情况下, Delphi 应用在打开数据库服务器的联接时,显示标准注册对话框。如果联接已建立,则注册对话框不会出现。 可以用下列方法处理服务器注册: 1. 将 TDatabase 部件的 LoginPrompt 属性置为 True 。这样,当应用程序试图建立数据库联接时,标准注册对话框会打开。 2. 将 LoginPrompt 属性置为 False ,在 TDatabase 部件的 Params 属性中包含用户名和口令参数。例如:
USERNAME = SYSDBA PASSWORD = mosterkey
但不推荐使用该方法,因为这会危害数据库安全 3. 使用 TDatabase 部件的 OnLogin 事件设置注册参数。 OnLogin 事件得到 TDatabase 注册参数数组的拷贝,并利用 Values 属性改变这些参数。如:
LoginParams.Values['SERVER NAME'] := 'MYSERVERNAME'; LoginParams.Values['USER NAME'] := 'MYUERNAME'; LoginParams.Values['PASSWORD'] := 'MYPASSWORD';
当控制从数据库注册事件处理过程中返回时,这些参数被用来建立联接。
18.3.1.3 建立应用程序特定的别名
TDatabase 的 Aliases 描述了数据库表的位置和数据库服务器的联接参数。通常都是在 Delphi 之外,运用 BDE 配置工具 (BDECFG32.EXE) 创建别名,并且别名被存在 BDE 配置文件 IDAPI32.CFG 中。 用户也可以用 TDatabase 创建只在应用程序中可用的别名,用 TDatabase 创建的别名不会加进 BDE 配置文件中。任何 DataSet 部件可通过描述 DatabaseName 属性来使用这些别名。为了定制这些局部别名的参数,用鼠标左键双击 TDatabase 部件或从 TDatabase 部件中选择 Database Editor , Delphi 就会打开数据库属性编辑器 (Database Properties Editor) 。
18.3.1.4 控制数据库的联接
TDatabase 部件的 Connected 属性,指示 TDatabase 部件是否建立与数据库服务器的联接。当应用程序打开数据库中的表时, Connected 被设置为 True 。将 Connected 设为 True 就建立了数据库的联接。 1. 保持数据库联接 TDatabase 的 KeepConnection 属性描述当没有数据库表打开时是否要与保持数据库的联接。 如果应用程序需要在单个数据库中多次打开关闭多个表时,将 KeepConnection 置为 True 能使应用程序具备更好的性能。 当 KeepConnection 为 True 时,即使没有表打开,应用程序也能保持数据库的联接。那么就能重复打开和关闭数据库表而不需每次进行联接注册。 2. 使用 TSesstion 控制联接 TSesstion 部件有一个面向整个应用程序的 KeepConnections 属性。如果 Session.KeepConnections 为 True ,那么用于所有 TDatabase 部件的数据库联接都是持久的。 TSession 为应用程序提供数据库联接的全局控制。 TSession 中的 Databases 属性是 Session 中所有活跃数据库组成的数组, DatabasesCount 属性描述活跃数据库的数目。 3. 描述 Net 和 Private 目录 TSession 的 NetFileDir 属性描述 BDE 网络控制目录的路径。 TSession 的 PrivateDir 属性描述存储诸述处理局部 SQL 表达式的临时文件的目录的路径。
18.3.1.5 获取数据库信息
TSession 拥有许多让用户获取数据库有关的信息,每个方法都以 TStringList 部件作为传入参数,并将信息返回 TStringList 中。 1. GetAliasNames 方法 声明: procedure GetAliasNames(List: TStringList); GetAliasNames 方法消除 List 中的参数,并将所有已定义的 BDE 别名的名字写入 List 。应用程序生成的别名不包括在内。 2. GetAliasParams 方法 声明: procedure GetAliasParams(const AliasName: String; List: TStringList); GetAliasParams 方法清除 List 的内容,并将 BDE 别名为 AliaName 的参数写入 List 。 3. GetDatabaseNames 方法 声明: procedure GetDatabaseNames(List: TStrings); GetDatabaseNames 方法清除 List 的内容并将所有 BDE 别名和应用程序定义的别名的名字写入 List 。 4. GetDriverNames 方法 声明: procedure GetDriverNames(List: TStrings); GetDriverNames 方法清除 List 中的内容,并将 BDE 当前安装的驱动程序名写入 List 。 5. GetDriverParams 方法 声明: procedure GetDriverParams(const DriverName: String; List: TStrings); GetDriverParams 方法消除 List 中的内容,并将名为 DriveName 驱动程序缺省参数写入 List 。 6. GetTableNames 方法 声明: procedure GetTableNames(const DatabaseName, Pattern: Strings; Extensions, SystemTable: Boolean; List: TStrings); GetTableNames 方法消除 List 中的内容,并将名为 DatabaseName 的数据库中的所有表的名字写入 List 。 Pattern 参数将限制表名。对于 SQL 服务器,将 SystemeTables 设为 True 将获取系统表和用户表。对非 SQL 数据库,将 Extensions 设为 True 将在表名中包含扩展名。
18.3.2 处理 Client/Server 事务控制
使用隐式控制和显示控制的数据库应用中有两种方法管理事务控制: ● 运用 TDatabase 部件的属性和方法进行显式控制 ● 运用 TQuery 部件的传递式 SQL 控制事务
Delphi 还支持 Paradox 和 dBASE 表的局部事务处理
18.3.2.1 事务控制概述
当用 Delphi 创建数据库应用时, Delphi 提供了用为所有数据库访问的事务控制。 事务是这样一组操作,在被提交前,它们对一个或多个数据库的操作,必须全部执行成功。如果其中一个操作失败,则所有操作失败,即事务具有原子性。 即使发生硬件失败,事务也要保证数据库一致性。当允许多用户并发访问时,事务还要维持数据完整性。 例如:一个应用程序可能更新 ORDERS 表以指明接受购买某一项目的定单,那么也要更新 INNENTORY 表以反映库存的减少。如果在第一个更新之后,第二个更新之前发生硬件错误,数据库就会处于不一致状态,因为库存情况没有反映定单情况。在事务控制下,两个表达式将在同一时间提交,如果其中一个表达式失败,则被返转 (Rolled Back) 。
18.3.2.2 使用隐式控制
在缺省情况下, Delphi 通过 BDE 为应用程序提供隐式事务控制。当应用程序处于隐式事务控制时 Delphi 为 DataSet 中的写每个记录进行隐式事务控制。它提交每一个独立的写操作,如 Post 和 Append Record 。 使用隐式事务控制是容易的,它保证最小的记录更新冲突和数据库的一致性视图。另一方面,因为写入数据库的数据的每一行都要进行事务控制, 所以隐式事务控制将导致网络过忙和应用程序性能下降。 如果采用显式事务控制,就能选择最有效的时机来开始、提交和终止事务,特别是在开发多用户环境下的客户应用程序运行访问远程 SQL 服务器,就更应该采用显式控制。
18.3.2.3 使用显式事务控制
有两种协作又独立的方式可运用于 Delphi 数据库应用的事务控制: ● 使用 TDatabase 部件的方法和属性 ● 使用 TQuery 部件中的传递式 SQL 。这种方式只有在 Delphi Client/Server Suite 版中才有效, SQL Links 将 SQL 表达式直接传给过程 SQL 或 ODBC 服务器
使用 TDatabase 部件的方法和属性的好处是提供了清晰的、轻便的、与特定数据库或服务器无关的应用能力。 使用传递式 SQL 的主要好处在于可以运用特定服务器的先进事务管理能力。 1. 使用 TDatabase 的方法和属性 下表中列出了 TDatabase 部件中用于事务管理的方法和属性以及它们的使用方法:
表 18.11 TDatabase 用于事务显式控制的方法表 ━━━━━━━━━━━━━━━━━━━━━━━━ 方法或属性 作 用 ──────────────────────── Commit 提交数据的修改并终止事务 Rollback 取消数据的修改并终止事务 StartTransaction 开始一个事务 TransIsolation 表述事务的独立性级别 ━━━━━━━━━━━━━━━━━━━━━━━━
StartTransaction , Commit 和 Rollback 是供应用程序在运行时调用开始事务,控制事务并且保存或放弃所做数据修改的方法。 TransIsolation 是 TDatabase 部件的用于控制作用于相同表的不同事务之间如何交互的属性。 ⑴ 开始一个事务 当你开始一个事务时,后来的所有读写数据库的表达式都发生在那次事务的环境中。每个表达式都是其中一部分。任何表达式所做的修改,要么成功地提交给数据库,要么每一个修改都被取消。考虑一个在 ATM 上的银行传输问题。当顾客决定将钱从存款帐户转到支付帐户时,在银行数据库记录上必须发生两个修改: ● 存款帐户必须记入借方 ● 支付帐户必须记入贷方
如果出于某种原因,其中的一个操作不能被完成,那么任何一个操作都不应该发生。因为这些操作是相关的,它们应该发生在同一个事务中。 为了开始 Delphi 应用程序中的一个事务,需要调用 TDatabase 部件中的 StartTransaction 方法:
DatabaseInterBase.StartTransaction;
此后的所有数据操作都发生在最近一个事务的环境中,直到该次事务通过调用 Commit 或 Rollback 显式地终止为止。 那么,应当将事务保持多久呢?理想状态下,只要需要,多久都行。事务的活跃状态越长,同时访问数据库的用户越多,在你的事务的生命其中,更多的并发、同时的事务开始和终止,于是当试图提交修改时,与其它事务冲突的可能性更大。 ⑵ 提交一个事务 为了做永久性修改,事务必须使用 TDatabase 部件的 Commit 方法提交。执行提交表达式将保存数据库的修改并终止事务。例如,下列表达式将终止在上例中开始的事务:
DatabaseInterBase.Commit
Commit 的调用应当置于 try … except 表达式中。如果一个事务不能成功提交,你就能处理错误,并重试操作。 ⑶ 返转一个事务 为了取消数据库修改,必须用 Rollback 方法返转一个事务。 Rollback 复原一个事务的修改,并终止事务,例如:下列表达式将返转一个事务: DatabaseInterBase.Rollback;
Rollback 通常发生在: ● 异常处理代码 ● 按钮或菜单事件代码,如用户点按了 Cancel 按钮
⑷ 使用 TransIsolation 属性 TransIsolation 属性描述 TDatabase 部件事务的独立级别,事务的独立级别决定了事务与其它作用于相同表的事务是如何相互作用的。在改变或设置 TransIsolation 的值之前,应当相当熟悉 Delphi 中的事务和事务管理。 TransIsolation 的缺省值是 tiReadCommitted 。下表中总结了 TransIsolation 的可能值并描述了它们的含义:
表 18.12 TransIsolation 属性值的含义 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 独立级别 含 义 ────────────────────────────────────── tiDirtyRead 允许读由其它同时事务写入数据库的未提交的修改。未提交的 修改不是永久性的,可能在任何时候被复原。 在这个级别你 的事务与其它事务所做的修改具有最低独立度。 tiReadCommitted 只允许读由其它同时事务提交的数据库修改。这是缺省的独 立级别。 tiRepeatableRead 允许单个的数据库读事务无法看见其它同时事务对相同数据做 的修改。这个独立级别保证了你的事务一次读一个记录,记录 的视图不会改变, 在这个级别你的事务与其它事务做的修改完 全独立。 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
各种数据库服务器不同程度地支持这些独立级别,有的根本不支持。 如果请求的隔离级别不被服务器支持, Delphi 将采用更高的独立级别。各种服务器支持的独立级别请参见表 18.10 。 如果应用程序使用 ODBC 与服务器交互, ODBC 驱动程序必须支持独立级别。 2. 使用传递式 SQL 为了能使用传递式 SQL 控制事物,必须: ● 使用 Delphi Client/Server Suite ● 安装正确的 SQL Links 驱动程序 ● 正确配置网络协议 ● 访问远程服务器上数据库的能力 ● 用 BDE 配置工具将 SQLPASSTHROUGH MODE 设置为 NOT SHARED
通过传递式 SQL ,你可以使用 TQuery 、 TStoredProc 、或 TUpdateSQL 部件直接发送一个 SQL 事务控制表达式给远程数据库服务器; BDE 本身并不处理 SQL 表达式,采用传递式 SQL 可使用户直接获得 SQL 服务器提供了事务控制优点,尤其是当那些控制是非标准的时。 SQL PASS THROUGHMODE 描述 BDE 和传递式 SQL 是否共享相同的数据库联接。在大多数情况下, SQLPASSTHROUGHMODE 被设置 SHARED AUTOCOMMIT 。然而,如果你想将 SQL 事务控制传递给服务器,你就必须用 BDE 配置工具,将 BDE 的 SQLPASSTHROUGHMODE 设置为 NOT SHARED 。此外,还必须为传递 SQL 事务控制表达式的 TQuery 部件建立独立的 TDatabase 部件。 3. 使用本地事务 BDE 还支持 Paradox 和 dBASE 上的本地事务。从代码角度而言,在本地事务和远程数据库服务器的事务之间没有什么差别。 当作用于本地数据库表的事务开始时,更新操作被记录在日志中,每个日志记录包含旧的记录缓冲区。当事务处于活跃状态,更新的记录被锁定,直到事务被提交或返转,在返转过程中,旧的记录被应用于将更新的记录恢复到原先的状态。
18.3.3 使用存储过程
18.3.3.1 TStoredProc 部件概述
存储过程是以数据库服务器为基础的接受输入参数,并将结果返回给应用程序的一段程序。 TStoredProc 部件操作远程服务器上的数据库中的存储过程。存储过程是一连串表达式的集合,作为服务器的一部分存储。存储过程在服务器上执行一系列重复性的与数据库相关的任务,并将结果传给客户应用程序,如 Delphi 数据库应用程序。 TStaredProc 部件使 Delphi 数据库应用程序能执行服务器上的存储过程。 通常,作用于数据库表中大量记录并且使用统计或数学函数的操作都是存储过程的首选对象。通过将这些重复计算任务转移到服务器,可以提高数据库应用程序的性能。 ● 充分利用服务器的处理能力和速度 ● 减少网络传输的数量
例如,考虑一个需要计算单个值的应用程序,在大批记录中的标准差值。如果在 Delphi 应用程序中执行这项功能就必须从服务器中得到所有在计算中用到的记录,这必将导致网络拥塞。因为应用程序所需的只是代表标准差的最终返回值。因此,由服务器上的存储过程来读数据,执行计算和将值传给应用程序将更有效。 1. TSoredProc 的关键属性 ⑴ DatabaseName 属性 DatabaseName 属性描述要访问的数据库的名字。该属性可以为: ● 已定义的 BDE 别名 ● 本地型数据库的目录 ● Local InterBase 服务器的目录路径和文件名 ● TDatabase 定义的应用程序别名
在改变 DatabaseName 之前要使用 Close 方法将 Dataset 部件置为非活跃状态。 ⑵ StoredProcName 属性 StoredProcName 属性表示服务器上的存储过程名。 Oracle 服务器允许多个具有相同名字的存储过程。因此要设置 Overload 属性来描述执行在 Oracle 服务器上的存储过程名。 ⑶ Overload 属性 Oracle 服务器允许 Oracle 软件包中存储过程的重载。就是说具有相同名字的不同过程,设置 Overload 属性用来描述执行在 Oracle 服务器上的存储过程。如果 Overload 值为零,则假定没有重载,如果 Overload 为 1 ,则 Delphi 执行具有同名的第一个存储过程;如果值为 2 ,则执行第二个存储过程。 ⑷ Params 属性 Params 属性包含传给存储过程的参数。 2. 关键方法 ⑴ ParamByName 方法 声明: function ParamByName(const Value: String): TParam; ParamByName 方法返回 Params 属性中具有名为 Value 的元素值。一般用该方法在动态查询中给参数赋值。 ⑵ Prepare 方法 PrePare 方法准备要执行的存储过程,这允许服务器载入存储过程,否则准备处理异常。 ⑶ ExecProc 方法 ExecProc 方法执行服务器上的存储过程。 ⑷ Open 方法 Open 方法打开 DataSet 部件,并将其置于浏览状态。这相当于将 Active 属性置为 True 。对于 TStoredProc 如果存储过程返回一个结果集,则使用 Open 执行存储过程。如果存储过程返回单行,早使用 ExecProc 执行存储过程。
18.3.3.2 TStoreProc 使用方法
1. 建立一个 StoredProc 部件 为数据库服务器上的存储过程建立一个 TStoredProc 部件的步骤如下: ⑴ 从 Component Palette 的 Data Access 页选择 TStoredProc 部件放在数据模块上。 ⑵ 将 TStoredProc 部件的 DatabaseName 属性设置为存储过程所在的数据库名。 DatabaseName 必须是 BDE 别名。 ⑶ 将 TStoredProc 部件的 StoredProcName 属性设为所用的存储过程名,或者从下拉式 列表框中选择。 ⑷ 在 TStoredProc 部件的 Params 属性中描述输入参数。可以使用参数编辑器来设置输 入参数。参数编辑器也可让用户察看存储过程返回给应用程序的值。
2. 设置存储过程的输入参数,察看输出结果参数 许多存储过程需要给它们传入一系列的输入参数,以确定处理什么和怎样处理,在 Params 属性中描述这些参数。所描述的输入参数的顺序是很重要的,它由服务器上的存储过程来确定。在设计时,最容易和最安全的方法是激活 TStoredProc 参数编辑器,编辑输入参数。参数编辑器以正确的次序列出输入参数,让你给它们赋值。 要激活 TStoredProc 的参数编辑器: ① 选择 TStoredProc 部件。 ② 按鼠标右键激活加速菜单 (Speed Menu) 。 ③ 选择 Define Parameters 。
参数名列表框显示过程的所有输入,输出和结果参数。有关输入、输出参数的信息从服务器中获得。对于某些服务器而方,参数信息是不可访问的,如 Sybase ,在这种情况下,列表框是空的,因此必须自己按过程要求的顺序增加输入输出参数。 参数类型复选框中描述所选的参数是输入、输出,还是结果参数。如果服务器支持参数可以既是输入又是输出。如果在列表框中增添参数,就必须设置参数类型。 数据类型复选框,列出列表框中所选参数的数据类型。如果给列表框真善美参数,必须设置数据类型。 在值编辑框中给输入参数赋值。 如果服务器不传递存储过程信息给 Delphi ,则可以用 Add 按钮给存储过程增添参数。 Delete 按钮则是将增添的参数删除, Clear 按钮将清除列表框中所有参数。 设置完参数后,选择 OK 按钮。
3. 在运行时建立参数和参数值 在运行时建立参数,可直接访问 Params 属性。 Params 属性是参数字符串的数组。例如,下列代码将编辑框的文本赋给数组的第一个字串:
StaredProc1.Params[0].Asstring := Edit1.Text
也能够用 ParamsByName 方法通过名字访问参数:
StoredProc1.ParamsByName('Company') Asstring := Edit1.Text;
4. 准备和执行存储过程 要使用存储过程还必须准备并执行它。可以有两种方式准备一个存储过程: ● 在设计时,通过选择参数编辑器的 OK 按钮 ● 在运行时,通过调用 TStoredProc 的 Prepare 方法
例如,下面的代码准备存储过程的执行:
StoredProc1.Prepare;
要执行准备好的存储过程,调用 TStroedProc 部件的 ExecProc 方法。下列代码演示了准备和执行存储过程:
StoredProc1.Params[0] Asstring := Edit1.Text; StoredProc1.prepare; StoredProc1.ExecProc;
当你执行一个存储过程,它返回输出参数或结果集,有两种可能的返回类型:单个返回,如单值或值集,和一群结果集,返回很多值。 5. 访问输出参数和结果集 存储过程在输出参数数组中返回值。如果服务器支持返回值可以是单个结果或者结果集。 在运行时访问存储过程的输出参数,可以索引 Params 属性或者用 ParamByName 方法访问这些值。下列表达式都用输出参数设置了编辑框的值:
Edit1.Text := StoredProc1.Params[6].AsString; Edit1.Text := StoredProc1.ParamsByName('Contact').AsString;
如果存储过程返回结果集,则用标准数据相关控制访问和显示值会更有用。 在某些服务器上如 Sybase ,存储过程能象查询语句那样返回结果集,应用程序可以使用数据相关控制一显示这些存储过程的输出。 用数据相关控制显示存储过程返回结果的方法如下: ① 将 DataSource 部件放在数据模块上。 ② 将 DataSource 部件的 DataSet 属性设置为接收数据的 TStoredProc 部件的名字。 ③ 将数据相关控制的 DataSource 属性设为 DataSource 部件的名字。 这样,当用于 TStoredProc 部件和 Active 属性为 True 时,数据相关控制就能显示从存储过程返回的结果。 18.3.4 从开发平台到服务器的向上适化 |