汇编 | Java | C# | Delphi | C/C++ |

DELPHI基础教程 第十八章 Delphi客户服务器应用开发(四)

第十八章 Delphi客户服务器应用开发(四) dedecms.com

18.3.4.1 适化概述 

copyright dedecms

  所谓适化就是将桌面应用转化为Client/Server应用。

织梦好,好织梦

  适化是一个很复杂的主题,这里不详细讲述。本节将介绍适化Delphi 应用程序中最重要的方面。 本文来自织梦

  适化的主要方面有:

本文来自织梦

  ● 将数据库从桌面平台到服务器的适化

内容来自dedecms

  将应用程序转化为Client/Server的适化 本文来自织梦

  内容来自dedecms

  适化还需要实现从桌面环境到Client/Server环境的转化。

织梦好,好织梦

  桌面数据库和SQL服务器数据库在许多方面有不同之处。例如: 内容来自dedecms

 ● 桌面数据库用于同一时刻单用户的访问,而服务器用于多用户访问

织梦好,好织梦

 ● 桌面数据库是面向记录的,而服务器是面向集合的 本文来自织梦

  桌面数据库将每个表存储在独立的文件中, 而服务器将所有的表存储在数据库中Client/Server应用必须解决更新的问题,最复杂的是联接、网络和事务控制 本文来自织梦

 

本文来自织梦

18.3.4.2 适化数据库

本文来自织梦

 

内容来自dedecms

  适化数据库包含下列步骤:

织梦内容管理系统

  ● 在桌面数据库结构的基础上,定义服务器上的元数据 copyright dedecms

  将数据从桌面转化到服务器中

内容来自dedecms

 ● 解决下列问题: dedecms.com

  数据类型差异 copyright dedecms

   ● 数据安全性和完整性 本文来自织梦

  事务控制

dedecms.com

   数据访问权 织梦内容管理系统

   ● 数据合法性 本文来自织梦

   ● 锁定 copyright dedecms

  dedecms.com

 Delphi提供了两种方法适化一个数据库。

dedecms.com

  使用Database Desktop工具,选择菜单Tools/Utilities/Copy to命令将数据库表从桌面方式拷贝到SQL格式

copyright dedecms

建立应用TBatchMove部件的应用程序

织梦好,好织梦

  织梦内容管理系统

  这两种方法都可以将表结构和数据从桌面数据源转化到服务器上。依靠这些数据库,可能需要改变结果表。例如,可能想进行不同数据类型的映射。 dedecms.com

  也可以将下列特征加入数据库: copyright dedecms

完整性约束 copyright dedecms

索引

本文来自织梦

  检测约束 dedecms.com

存储过程和触发器

织梦好,好织梦

  其它服务器特征 织梦好,好织梦

 

织梦内容管理系统

  如果用SQL脚本和服务器数据定义工具定义元数据会更有效。然后用前面介绍的两种方法转移数据。因为如果是手工定义数据库表,Database DesktopTBatchMove 部件将只拷贝数据。

dedecms.com

 

dedecms.com

18.3.4.3 适化应用程序

copyright dedecms

 

dedecms.com

  在理论上,设计用来访问局部数据的Delphi应用程序做很少的修改就可以访问远程服务器上的数据。如果在服务器上定义适合的数据源,你就能将应用程序指向访问它,这只需简单地改变应用程序中TTableTQuery部件的DatabaseName属性。 copyright dedecms

  实际上,在访问局部和过程数据源之间有许多重要的不同之处。Client/Server应用程序必须解决大量的在桌面应用中所没有的问题。

织梦好,好织梦

  任何Delphi应用程序都能用TTableTQuery部件访问数据。桌面应用程序通常都是使用TTable部件。当适化到SQL服务器上时,用TQuery会更有效,如果应用程序要检索大量记录,则TQuery部件要略胜一筹。 织梦内容管理系统

  如果应用程序使用统计或数学函数,那么在服务器上通过存储过程执行这些函数会更有效。因为存储过程执行更快,使用存储过程还可以减少网络负载,特别是大量行数据的函数。

内容来自dedecms

  例如,计算大量记录的标准差:

织梦好,好织梦

  ● 如果该函数在客户端执行,所有的值从服务器上检索出来并送到客户端,导致网络拥塞 copyright dedecms

  ● 如果该函数在服务器端执行,则应用程序只需要服务器上的答案

织梦内容管理系统

 

dedecms.com

  织梦内容管理系统

  织梦好,好织梦

  dedecms.com

 

织梦好,好织梦

  织梦好,好织梦

18.4 Delphi客户/服务器应用实例分析

织梦好,好织梦

  织梦好,好织梦

  本节中采用的实例是Delphi2.0数据库的例子CSDEMOCSDEMODelphi客户/服务器编程的示例程序,它采用的数据库服务器是Local InterBase Server 本文来自织梦

CSDEMO较好地示范了BDE环境的配置,InterBASE Server高级功能应用,SQL服务器联接,触发器应用、存储过程编程和事务控制技术等,具有较高的参考价值。本节讲述下列内容: 织梦内容管理系统

  数据库环境介绍

织梦内容管理系统

  ● TDatabase的应用

copyright dedecms

 ● 不同数据库表的切换

织梦内容管理系统

  触发器编程

织梦内容管理系统

  ● 存储过程编程

本文来自织梦

 ● 事务控制应用

copyright dedecms

 

织梦内容管理系统

18.4.1 数据库环境介绍

本文来自织梦

  内容来自dedecms

  本例中采用的数据库服务器是Local InterBase ServerLocal InterBaseInterBase Server的单用户版32位、兼容ANSI SQLLocal InterBase支持客户/服务器应用在单机上的开发和测试,并且可以很容易地适化到InterBase Server上。因此,开发客户/服务器应用采用Local InterBase作为原型开发环境是很方便的。

内容来自dedecms

  织梦内容管理系统

18.4.1.1 IBLOCALBDE参数

内容来自dedecms

  copyright dedecms

  本例中的SQL数据库是IBLOCAL。它是由BDE配置工具(BDECFG32.EXE)设置参数值。它的各项参数值列于下表:

织梦好,好织梦

  dedecms.com

18.13 IBLOCAL的各项参数值

内容来自dedecms

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

本文来自织梦

copyright dedecms

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

织梦内容管理系统

TYPE INTRBASE 织梦好,好织梦

PATH

dedecms.com

SERVER NAME C:\INTRBASE\EXAMPLES\EMPLOYEE.GDB

本文来自织梦

USER NAME SYSDBA

织梦好,好织梦

OPEN MODE READ/WRITE 内容来自dedecms

SCHEMA CACHE SIZE 8 copyright dedecms

LANGDRIVER

织梦好,好织梦

SQLQRYMODE

本文来自织梦

SQLPASSTHRU MODE SHARED AUTOCOMMIT

内容来自dedecms

SCHEMA CHCHE TIME -1

织梦内容管理系统

MAX ROWS -1 织梦内容管理系统

BATCH COUNT 200

dedecms.com

ENABLE SCHEMA CACHE FALSE

织梦好,好织梦

SCHEMA CACHE DIR 织梦内容管理系统

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

内容来自dedecms

  织梦内容管理系统

18.4.1.2 数据库结构介绍

本文来自织梦

  本文来自织梦

 IBLOCAL数据库的结构都是由InterBase服务器工具交互式SQL工具(ISQL)定义的。 copyright dedecms

  用ISQL定义数据库,首先要用Create Database命令建立数据库,建立的新数据库一般是以GDB为扩展名。建立好后,就可以用SQL语言定义数据库表,例如建立EMPLOYEE表的SQL语句如下: 内容来自dedecms

  织梦内容管理系统

定义域名数据类型: 织梦好,好织梦

  dedecms.com

CREATE DOMAIN FIRSTNAME AS VARCHAR(15); 织梦好,好织梦

CREATE DOMAIN LASTNAME AS VARCHAR(20); 内容来自dedecms

CREATE DOMAIN COUNTRYNAME AS VARCHAR(15); 内容来自dedecms

CREATE DOMAIN EMPNO AS SMALLINT; 内容来自dedecms

CREATE DOMAIN DEPTNO AS CHAR(3) dedecms.com

CHECK (VALUE = '000' OR (VALUE > '0' AND VALUE <= '999') OR VALUE IS NULL);

织梦内容管理系统

CREATE DOMAIN JOBCODE AS VARCHAR(5)

织梦好,好织梦

CHECK (VALUE > '99999'); copyright dedecms

CREATE DOMAIN JOBGRADE AS SMALLINT

本文来自织梦

CHECK (VALUE BETWEEN 0 AND 6);

内容来自dedecms

CREATE DOMAIN SALARY AS NUMERIC(15, 2) copyright dedecms

DEFAULT 0

内容来自dedecms

CHECK (VALUE > 0); 织梦好,好织梦

  内容来自dedecms

建立EMPLOYEE表: dedecms.com

  织梦好,好织梦

CREATE TABLE EMPLOYEE (EMP_NO EMPNO NOT NULL,

内容来自dedecms

FIRST_NAME FIRSTNAME NOT NULL,

copyright dedecms

LAST_NAME LASTNAME NOT NULL, 本文来自织梦

PHONE_EXT VARCHAR(4), dedecms.com

HIRE_DATE DATE DEFAULT 'NOW' NOT NULL, dedecms.com

DEPT_NO DEPTNO NOT NULL, copyright dedecms

JOB_CODE JOBCODE NOT NULL, 织梦内容管理系统

JOB_GRADE JOBGRADE NOT NULL,

内容来自dedecms

JOB_COUNTRY COUNTRYNAME NOT NULL,

织梦内容管理系统

SALARY SALARY NOT NULL, 织梦好,好织梦

FULL_NAME COMPUTED BY (last_name || ', ' || first_name), 织梦内容管理系统

PRIMARY KEY (EMP_NO));

copyright dedecms

  本文来自织梦

  CHECK语句是给数据库字段取值范围加约束条件。PRIMARY_KEY语句是给表建立关键字索引。 dedecms.com

  如法炮制,就可以定义IBLOCAL中的所有表。 内容来自dedecms

  IBLOCAL中的表包括:

织梦好,好织梦

  内容来自dedecms

EMPLOYEE CUSTOMER DEPARTMENT EMPLOYEE_PROJECT 本文来自织梦

PROJECT SALES SALARY_HISCORY

本文来自织梦

 

dedecms.com

各数据库表中的内容如下: 本文来自织梦

  本文来自织梦

18.14 EmployeeDemoDB中各数据库表的内容

dedecms.com

   ━━━━━━━━━━━━━━━━━━━━━━━━━━━ copyright dedecms

    数据库表名        表中内容 织梦内容管理系统

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

copyright dedecms

     EMPLOYEE 雇员信息

copyright dedecms

   CUSTOMER 客户信息

本文来自织梦

DEPARTMENT 部门信息 织梦好,好织梦

EMPLOYEE_PROJECT 雇员负责的工程

copyright dedecms

PROJECT 工程信息 织梦内容管理系统

SALES 销售信息

织梦内容管理系统

SALARY_HISTORY 雇员薪水调整的历史信息

织梦好,好织梦

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

dedecms.com

 

内容来自dedecms

每个数据库表中都定义了关键字段。关于数据库表中的字段名、类型、大小,这里不再赘述。 内容来自dedecms

 

copyright dedecms

18.4.2 应用程序分析

copyright dedecms

  本文来自织梦

18.4.2.1 TDatabase部件的使用 织梦好,好织梦

 

织梦内容管理系统

  CSDEMO程序中定义了一个数据库模块部件——TDmEmployee,它是继承于TDataModuleTDataModule是在Delphi2.0中才出现的专门放置数据访问部件(TDatabaseTTableTQuery)的框架。其它涉及数据库访问的窗体,只要在uses语句中插入数据库模块所在的库单元,该窗体上的数据库部件就可引用相应的数据库访问部件。 织梦好,好织梦

  在TDmEmployee中定义了一个TDatabase类型的部件──EmployeeDatabaseEmployeeDatagase的主要属性及属性值如下: 内容来自dedecms

  本文来自织梦

18.15 EmployeeDatabase部件主要属性的取值 dedecms.com

   ━━━━━━━━━━━━━━━━━━━━━━━ 织梦内容管理系统

    属性        属性值

dedecms.com

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

织梦内容管理系统

    AliasName IBLOCAL

织梦内容管理系统

DatabaseName EmployeeDemoDB

内容来自dedecms

KeepConnection True dedecms.com

LoginPrompt False

copyright dedecms

TransIsolation tiReadCommitted 织梦好,好织梦

Params USERNAME = SYSDBA 织梦内容管理系统

PASSWORD = masterkey

织梦好,好织梦

Connected True 织梦好,好织梦

  ━━━━━━━━━━━━━━━━━━━━━━━ 织梦内容管理系统

  dedecms.com

AliasName属性所指定的IBLOCAL,必须已经在BDE中配置好,DatabaseName属性指定要使用的数据库名,该数据库名是由应用程序自己定义的,因此不反应到BDE中,该属性值被TTableTQueryDataSet部件引用,并且出现在DataSet部件的DatabaseName 下拉式列表框中。本例中的“EmployeeDemoDB”,被EmployeeTableSalesTable等所有DataSet部件引用。 织梦好,好织梦

ConnectedTrue表明,应用程序与数据库将保持联接。 本文来自织梦

KeepConnection属性为True,表明多次打开和关闭EmployeeDemoDB数据库中的任意表,应用程序将始终与数据库保持联接,这省却了重复注册的开销。

织梦内容管理系统

LoginPrompt 属性为False,表明应用程序自动处理与数据库的联接注册,因此,Params属性中定义了注册的用户名和口令: dedecms.com

  copyright dedecms

  USERNAME = SYSDBA 本文来自织梦

PASSWORD = masterkey 内容来自dedecms

  织梦好,好织梦

TransIsolation属性为tiReadCommitted表明,如果存在多个同时事务,则某一事务只允许读由其它事务提交了的数据。

内容来自dedecms

  程序中EmployeeDatabase的应用还与事务控制等有关。下文中会介绍这方面的内容。

本文来自织梦

  织梦内容管理系统

18.4.2.2 不同数据库表的切换

织梦内容管理系统

 

织梦好,好织梦

  在许多数据库应用中都要在不同数据库表之间相互切换,以响应用户输入条件或系统状态的变化。这时,往往需要特别的处理,例如改变光标形状或隐藏数据改变等,尤其是在客户/服务器应用程序中。因为是用SQL语句访问远程数据库,有时还要在服务器端执行计算任务,所以客户端的数据变化会有一定的间隔,因此应该让用户明白发生了什么。下面是CSDEMO在数据库表切换时的处理办法:

内容来自dedecms

  copyright dedecms

procedure TFrmViewDemo.ShowTable( ATable: string );

本文来自织梦

begin

copyright dedecms

Screen.Cursor := crHourglass; { 向用户提示当前操作状态 }

内容来自dedecms

VaryingTable.DisableControls; { 隐藏数据变化 } 本文来自织梦

VaryingTable.Active := FALSE; { 关闭原来的数据库表 }

copyright dedecms

VaryingTable.TableName := ATable; { 更新数据库表名 }

copyright dedecms

VaryingTable.Open; { 打开数据库表 }

织梦好,好织梦

VaryingTable.EnableControls; { 显示所作的修改 }

本文来自织梦

Screen.Cursor := crDefault; { 重新设置光标形状 }

dedecms.com

end;

织梦好,好织梦

  dedecms.com

  crHourglass型光标表明正在执行SQL查询。DisableControlsEnableControls的作用是隐藏和显示数据变化。 内容来自dedecms

 

内容来自dedecms

18.4.2.3 InterBase触发器(Trigger)的应用

织梦好,好织梦

  本文来自织梦

  在CSDEMO应用程序中,演示触发器应用的窗体是TFromTriggerDemo 织梦好,好织梦

  copyright dedecms

在该窗体中包含两个TDBGrid对象。DBGrid1显示EmployeeTable中的数据,DBGrid2显示SalaryHistoryTable中的数据。它们的主要属性及属性值如下:

内容来自dedecms

  本文来自织梦

18.16 EmlpoyeeTable部件主要属性的取值

copyright dedecms

   ━━━━━━━━━━━━━━━━━━━━━ 本文来自织梦

    属 性      

dedecms.com

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

copyright dedecms

     DatabaseName EmployeeDemoDB

本文来自织梦

IndexFieldName Emp_No

织梦内容管理系统

TableName EMPLOYEE

织梦内容管理系统

━━━━━━━━━━━━━━━━━━━━━ 内容来自dedecms

  dedecms.com

18.17 SalaryHistoryTable部件主要属性的取值

织梦好,好织梦

   ━━━━━━━━━━━━━━━━━━━━━ dedecms.com

   属 性       属

dedecms.com

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

织梦内容管理系统

    DatabaseName EmployeeDemoDB dedecms.com

IndexFieldName Emp_No

本文来自织梦

     MasterFields Emp_No 织梦好,好织梦

MasterSource EmployeeSource

织梦内容管理系统

TableName SALARY_HISTORY

内容来自dedecms

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

dedecms.com

 

本文来自织梦

  这两个表之间存在两种关系:

织梦好,好织梦

  ● 连接关系 copyright dedecms

EmployeeTable的记录变化时,SalaryHistoryTable的数据要作相应的变化。这种连接关系是通过索引来实现的。

织梦内容管理系统

  ● 数据一致性 dedecms.com

EmployeeTable中的Salary字段的值作修改必须反映到SalaryHistoryTable中,SalaryHistoryTable维护的是Salary变化的历史信息。这种数据一致性要求在本程序中是通过触发器实现的。 织梦内容管理系统

  触发器是在SQL服务器端执行的一段程序,它在服务器端被触发执行完成一定的数据计算任务。

织梦好,好织梦

  下面是InterBase服务器上与Employee表相关的触发器程序:

织梦内容管理系统

 

织梦好,好织梦

Triggers on Table EMPLOYEE: dedecms.com

SAVE_SALARY_CHANGE, Sequence: 0, Type: AFTER UPDATE, Active AS

织梦内容管理系统

BEGIN

本文来自织梦

IF (old.salary <> new.salary) THEN

内容来自dedecms

INSERT INTO salary_history

copyright dedecms

(emp_no, change_date, updater_id, old_salary, percent_change)

本文来自织梦

VALUES (

dedecms.com

old.emp_no, 本文来自织梦

'now',

本文来自织梦

user, 内容来自dedecms

old.salary,

内容来自dedecms

(new.salary - old.salary) * 100 / old.salary);

织梦内容管理系统

END dedecms.com

  织梦内容管理系统

  因为触发器是相应于EMPLOYEE表上的数据修改由服务器自动触发执行的,所以在客户应用程序上没有显式的调用。在客户端有打开并显示数据库表内容的程序和当SALARY_HISTORY表中数据变化时的更新显示的操作。

织梦内容管理系统

 

织梦内容管理系统

procedure TFrmTriggerDemo.FormShow(Sender: TObject);

copyright dedecms

begin copyright dedecms

DmEmployee.EmployeeTable.Open;

内容来自dedecms

DmEmployee.SalaryHistoryTable.Open; 织梦内容管理系统

end;

织梦好,好织梦

  copyright dedecms

procedure TDmEmployee.EmployeeTableAfterPost(DataSet: TDataSet); 织梦内容管理系统

begin 内容来自dedecms

{ 一个雇员的薪水变化将触发薪水调整历史记录的变化,

copyright dedecms

因此,如果SalaryHistory打开的话,就需要更新显示 }

织梦好,好织梦

with SalaryHistoryTable do if Active then Refresh; dedecms.com

end; 织梦内容管理系统

 

dedecms.com

18.4.2.4 存储过程编程 内容来自dedecms

  本文来自织梦

  存储过程也是SQL服务器上的一段程序,它接收输入参数,在服务器端执行,并将结果返回客户端,存储过程是必须在客户应用程序中显式调用的。

内容来自dedecms

  对于数据库表中大量记录的统计和函数计算,存储过程是很有用,这样可以将重复性计算任务转换到服务器,提高数据库应用的性能。 织梦内容管理系统

  Delphi中有两个部件能操作远程数据库服务器上的存储过程:TQueryTStoredProc

织梦好,好织梦

1. TQuery的存储过程编程 本文来自织梦

CSDEMO中演示用TQuery调用存储过程的窗体是TFrmQueryProc 

dedecms.com

  TFrmQueryProc中有两个TDBGrid 部件。DBGrid1显示EmployeeTable中的数据。DBGrid2显示Project表中的数据。使用存储过程的TQuery部件名为EmployeeProjectsQuery,它的作用是建立Employee 表和Project 表的连接,以实现当DBGrid1中记录改变时,DBGrid2中的数据作相应的改变。具体的连接任务是由服务器上的存储过程Get_Emp_Proj完成。下面是Get_Emp_Proj的程序: 织梦好,好织梦

 

copyright dedecms

PROCEDURE Get_Emp_Proj 织梦内容管理系统

BEGIN

织梦好,好织梦

FOR SELECT proj_id 织梦好,好织梦

FROM employee_project 织梦好,好织梦

WHERE emp_no = :emp_no dedecms.com

INTO :proj_id

织梦好,好织梦

DO

织梦好,好织梦

SUSPEND;

内容来自dedecms

END 织梦好,好织梦

  dedecms.com

EMP_NO INPUT SMALLINT

织梦好,好织梦

PROJ_ID OUTPUT CHAR(5)

内容来自dedecms

  dedecms.com

  该过程带两个参数:

织梦好,好织梦

  EMP_NO是输入参数,类型是SMALLINT.

本文来自织梦

PROJ_ID是输出参数,类型是CHAR(5) copyright dedecms

  织梦内容管理系统

  相应地,EmployeeProjectsQuery的主要属性如下: copyright dedecms

  内容来自dedecms

18. 18 EmployeeProjectsQuery部件主要属性的取值

dedecms.com

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

dedecms.com

   属 性       属

copyright dedecms

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

内容来自dedecms

    DatabaseName EmployeeDemoDB

dedecms.com

Params EMP_No(输入参数,Smallint类型) dedecms.com

SQL Select * from

本文来自织梦

Get_Emp_Proj(:EMP_NO) 织梦好,好织梦

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

dedecms.com

  内容来自dedecms

TQuery部件是在SQL语句中直接调用存储过程。 内容来自dedecms

  下面是客户端的程序: 内容来自dedecms

 

内容来自dedecms

procedure TFrmQueryProc.FormShow(Sender: TObject);

织梦内容管理系统

begin copyright dedecms

DmEmployee.EmployeeTable.Open;

copyright dedecms

EmployeeSource.Enabled := True;

copyright dedecms

with EmployeeProjectsQuery do if not Active then Prepare;

织梦好,好织梦

end;

内容来自dedecms

  copyright dedecms

  用Prepare显式地准备SQL语句,虽非必须,但可以优化SQL的执行。 织梦好,好织梦

 

织梦好,好织梦

procedure TFrmQueryProc.EmployeeDataChange(Sender: TObject; Field: TField); 织梦好,好织梦

begin

本文来自织梦

EmployeeProjectsQuery.Close;

内容来自dedecms

EmployeeProjectsQuery.Params[0].AsInteger :=

dedecms.com

DmEmployee.EmployeeTableEmp_No.Value; 织梦内容管理系统

EmployeeProjectsQuery.Open;

内容来自dedecms

  织梦好,好织梦

WriteMsg('Employee ' + DmEmployee.EmployeeTableEmp_No.AsString + dedecms.com

' is assigned to ' + IntToStr(EmployeeProjectsQuery.RecordCount) +

织梦内容管理系统

' project(s).');

dedecms.com

end; 内容来自dedecms

 

dedecms.com

  该事件处理过程与EmployeeSourceOnDataChange属性相联。用于当EmployeeTable数据记录变化时,修正存储过程的输入参数,并执行SQL语句。

织梦好,好织梦

  2. TStoredProc部件的存储过程编程 织梦内容管理系统

  TStoredProc Delphi 专门用来使用服务器存储过程的部件。CSDEMO 中演示用TStoredProc调用存储过程的窗体是TFrmExecPr 本文来自织梦

  在程序运行中,当按下ShipOrder按钮,要求对ORED_STA_TUS等字段的内容作修改以维护数据库的一致性。字段内容的修改任务由服务器上的存储过程SHIP_ORDER完成。SHIP_ORDE的程序如下: 内容来自dedecms

 

织梦好,好织梦

PROCEDURE SHIP_ORDER 织梦内容管理系统

DECLARE VARIABLE ord_stat CHAR(7); dedecms.com

DECLARE VARIABLE hold_stat CHAR(1);

dedecms.com

DECLARE VARIABLE cust_no INTEGER; 本文来自织梦

DECLARE VARIABLE any_po CHAR(8); 织梦好,好织梦

BEGIN 织梦好,好织梦

SELECT s.order_status, c.on_hold, c.cust_no 本文来自织梦

FROM sales s, customer c

内容来自dedecms

WHERE po_number = :po_num 织梦好,好织梦

AND s.cust_no = c.cust_no dedecms.com

INTO :ord_stat, :hold_stat, :cust_no;

本文来自织梦

IF (ord_stat = "shipped") THEN

本文来自织梦

BEGIN

copyright dedecms

EXCEPTION order_already_shipped; dedecms.com

SUSPEND; 本文来自织梦

END 内容来自dedecms

ELSE IF (hold_stat = "*") THEN copyright dedecms

BEGIN 织梦内容管理系统

EXCEPTION customer_on_hold; 本文来自织梦

SUSPEND; dedecms.com

END dedecms.com

  本文来自织梦

FOR SELECT po_number

copyright dedecms

FROM sales 本文来自织梦

WHERE cust_no = :cust_no dedecms.com

AND order_status = "shipped"

内容来自dedecms

AND paid = "n" 织梦内容管理系统

AND ship_date < 'NOW' - 60 dedecms.com

INTO :any_po

dedecms.com

DO

dedecms.com

BEGIN 织梦内容管理系统

EXCEPTION customer_check; copyright dedecms

 

dedecms.com

UPDATE customer

copyright dedecms

SET on_hold = "*" 内容来自dedecms

WHERE cust_no = :cust_no; 本文来自织梦

  织梦好,好织梦

SUSPEND; dedecms.com

END

织梦内容管理系统

  copyright dedecms

UPDATE sales 织梦内容管理系统

SET order_status = "shipped", ship_date = 'NOW' dedecms.com

WHERE po_number = :po_num;

copyright dedecms

SUSPEND;

copyright dedecms

END

copyright dedecms

  织梦好,好织梦

Parameters:

dedecms.com

PO_NUM INPUT CHAR(8)

copyright dedecms

  织梦好,好织梦

  该过程只带有一个输入参数:PO_NUM,类型是CHAR(8)

dedecms.com

  在客户端使用该过程的TStoreProc部件是ShipOrderProc,其主要属性如下表: copyright dedecms

  copyright dedecms

18.19 ShipOrderProc部件主要属性的取值 dedecms.com

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

copyright dedecms

   属性名         

织梦好,好织梦

    ──────────────────────────── 织梦内容管理系统

    DatabaseName EmployeeDemoDB copyright dedecms

ParamBindMode pbByName 内容来自dedecms

Params PO_NUM(输入参数,String类型)

织梦内容管理系统

StoredProcName SHIP_ORDER

copyright dedecms

━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 内容来自dedecms

 

dedecms.com

  客户端执行SHIP_ORDER的程序如下:

copyright dedecms

 

本文来自织梦

procedure TFrmExecProc.BtnShipOrderClick(Sender: TObject); 内容来自dedecms

begin copyright dedecms

with DmEmployee do 织梦好,好织梦

begin 本文来自织梦

ShipOrderProc.Params[0].AsString := SalesTable['PO_NUMBER']; 本文来自织梦

ShipOrderProc.ExecProc; copyright dedecms

SalesTable.Refresh; 织梦好,好织梦

end; 织梦内容管理系统

end; 织梦内容管理系统

  内容来自dedecms

  当用户按ShipOrder按钮时,执行这段程序。程序中先准备输入参数,用ExecProc

织梦好,好织梦

法执行存储过程。调用SalesTable.Refresh方法刷新数据显示。 dedecms.com

  在CSDEMO应用程序中另一个使用存储过程的TStoredProc部件是DeleteEmployeeProc。它完成的任务是删除Employee表中的记录,并修改所有相关的表, 以维护数据的一致性。其属性如下: 内容来自dedecms

 

copyright dedecms

18.20 DeleteEmployeeProc部件主要属性的取值 内容来自dedecms

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

dedecms.com

   属性名          dedecms.com

  ────────────────────────── copyright dedecms

   DataBaseName EmployeeDemoDB 内容来自dedecms

ParamBindMode PbByName

dedecms.com

Params EMP_NUM(输入参数,整型) 本文来自织梦

StoredProcName DELETE_EMPLOYEE dedecms.com

━━━━━━━━━━━━━━━━━━━━━━━━━━ dedecms.com

 

织梦好,好织梦

  存储过程DELETE_EMPLOYEE的程序如下: copyright dedecms

  织梦好,好织梦

PROCEDURE DELETE_EMPLOYEE

本文来自织梦

DECLARE VARIABLE any_sales INTEGER;

本文来自织梦

BEGIN dedecms.com

any_sales = 0;

织梦好,好织梦

SELECT count(po_number)

dedecms.com

FROM sales copyright dedecms

WHERE sales_rep = :emp_num copyright dedecms

INTO :any_sales; 织梦内容管理系统

IF (any_sales > 0) THEN

本文来自织梦

BEGIN dedecms.com

EXCEPTION reassign_sales;

内容来自dedecms

SUSPEND; 本文来自织梦

END

织梦内容管理系统

UPDATE department

dedecms.com

SET mngr_no = NULL

本文来自织梦

WHERE mngr_no = :emp_num;

织梦好,好织梦

UPDATE project

copyright dedecms

SET team_leader = NULL 织梦内容管理系统

WHERE team_leader = :emp_num; 内容来自dedecms

DELETE FROM employee_project

织梦好,好织梦

WHERE emp_no = :emp_num; dedecms.com

DELETE FROM salary_history

copyright dedecms

WHERE emp_no = :emp_num; 织梦内容管理系统

DELETE FROM employee 本文来自织梦

WHERE emp_no = :emp_num;

本文来自织梦

SUSPEND;

dedecms.com

END

织梦好,好织梦

 

织梦好,好织梦

Parameters: copyright dedecms

EMP_NUM INPUT INTEGER

本文来自织梦

  dedecms.com

  从上述存储过程的例子中,我们看到存储过程在维护服务器上的数据一致性方面有很强的能力,它节省了系统开销,提高了客户端的性能。

copyright dedecms

 

dedecms.com

18.4.2.5 事务控制编程 织梦好,好织梦

  织梦内容管理系统

  在客户/服务器应用程序中,事务控制是一项很重要的技术。它对于提高系统的可靠性,维护数据一致性有着重要的意义。 织梦内容管理系统

  Delphi中提供了事务的隐式和显式两种控制方法。其中显式控制的性能较高,下面介绍Delphi事务显式控制的编程方法。

织梦内容管理系统

  Delphi担当事务控制任务的部件是TDatabase TDatabase 用于事务控制的属性是TransIsolation,方法有StartTranstionCommitRollback。关于这些属性和方法作用和使用方法请参阅客户/服务器事务管理。

本文来自织梦

  在CSDEMOTDatabase 部件为EMployeeDatabase,其TransIsolation属性值为tiReadCommitted,意为如果存在多个同时事务访问数据库,则其中任一事务只能读其它事务提交的了数据。 织梦好,好织梦

  CSDEMO中演示事务控制的窗体是TFrmTransDemo 织梦内容管理系统

  DBGrid1中显示EmployeeTable中的内容。当窗口显示时,EmployeeDatabase开始一次事务控制并激活EmployeeTable 内容来自dedecms

 

本文来自织梦

procedure TFrmTransDemo.FormShow(Sender: TObject); 内容来自dedecms

begin 本文来自织梦

DmEmployee.EmployeeDatabase.StartTransaction; 内容来自dedecms

DmEmployee.EmployeeTable.Open;

内容来自dedecms

end;

织梦内容管理系统

  dedecms.com

当窗口被关闭或隐藏时,EmployeeDatabase提交事务: 织梦好,好织梦

  dedecms.com

procedure TFrmTransDemo.FormHide(Sender: TObject); 织梦好,好织梦

begin 织梦好,好织梦

DmEmployee.EmployeeDatabase.Commit;

内容来自dedecms

end; 内容来自dedecms

  dedecms.com

  窗口中有两个按钮BtnCommitEditsBtnUndoEdits。按下BtnCommitEdits按钮将提交当前事务,并开始新的事务控制并刷新数据。

dedecms.com

  织梦好,好织梦

procedure TFrmTransDemo.BtnCommitEditsClick(Sender: TObject); 织梦好,好织梦

begin 织梦内容管理系统

if DmEmployee.EmployeeDatabase.InTransaction and copyright dedecms

(MessageDlg('Are you sure you want to commit your changes?', 织梦好,好织梦

mtConfirmation, [mbYes, mbNo], 0) = mrYes) then

copyright dedecms

begin

织梦内容管理系统

DmEmployee.EmployeeDatabase.Commit;

织梦好,好织梦

DmEmployee.EmployeeDatabase.StartTransaction;

copyright dedecms

DmEmployee.EmployeeTable.Refresh; 织梦内容管理系统

end else

内容来自dedecms

MessageDlg('Can''t Commit Changes: No Transaction Active', mtError, [mbOk], 0); 本文来自织梦

end;

dedecms.com

  织梦好,好织梦

  按下BtnUndoEdits按钮将返转当前事物,恢复原来的数据,开始新的事务控制,并刷新数据的显示。 内容来自dedecms

  dedecms.com

procedure TFrmTransDemo.BtnUndoEditsClick(Sender: TObject);

本文来自织梦

begin

织梦内容管理系统

if DmEmployee.EmployeeDatabase.InTransaction and 织梦内容管理系统

(MessageDlg('Are you sure you want to undo all changes made during the ' +

织梦内容管理系统

'current transaction?', mtConfirmation, [mbYes, mbNo], 0) = mrYes) then

内容来自dedecms

begin

dedecms.com

DmEmployee.EmployeeDatabase.Rollback; 内容来自dedecms

DmEmployee.EmployeeDatabase.StartTransaction; dedecms.com

DmEmployee.EmployeeTable.Refresh;

本文来自织梦

end else dedecms.com

MessageDlg('Can''t Undo Edits: No Transaction Active', mtError, [mbOk], 0);

织梦好,好织梦

end;  织梦内容管理系统

精彩推荐
热点内容
最近更新