CREATE TABLE EMPLOYEE (EMP_NO EMPNO NOT NULL
FIRST_NAME FIRSTNAME NOT NULL
LAST_NAME LASTNAME NOT NULL
PHONE_EXT VARCHAR()
HIRE_DATE DATE DEFAULT NOW NOT NULL
DEPT_NO DEPTNO NOT NULL
JOB_CODE JOBCODE NOT NULL
JOB_GRADE JOBGRADE NOT NULL
JOB_COUNTRY COUNTRYNAME NOT NULL
SALARY SALARY NOT NULL
FULL_NAME COMPUTED BY (last_name || || first_name)
PRIMARY KEY (EMP_NO))
CHECK语句是给数据库字段取值范围加约束条件PRIMARY_KEY语句是给表建立关键字索引
如法炮制就可以定义IBLOCAL中的所有表
IBLOCAL中的表包括
EMPLOYEE CUSTOMER DEPARTMENT EMPLOYEE_PROJECT
PROJECT SALES SALARY_HISCORY
各数据库表中的内容如下
表 EmployeeDemoDB中各数据库表的内容
━━━━━━━━━━━━━━━━━━━━━━━━━━━
数据库表名 表中内容
───────────────────────────
EMPLOYEE 雇员信息
CUSTOMER 客户信息
DEPARTMENT 部门信息
EMPLOYEE_PROJECT 雇员负责的工程
PROJECT 工程信息
SALES 销售信息
SALARY_HISTORY 雇员薪水调整的历史信息
━━━━━━━━━━━━━━━━━━━━━━━━━━━
每个数据库表中都定义了关键字段关于数据库表中的字段名类型大小这里不再赘述
应用程序分析
TDatabase部件的使用
CSDEMO程序中定义了一个数据库模块部件TDmEmployee它是继承于TDataModuleTDataModule是在Delphi中才出现的专门放置数据访问部件(如TDatabaseTTable和TQuery等)的框架其它涉及数据库访问的窗体只要在uses语句中插入数据库模块所在的库单元该窗体上的数据库部件就可引用相应的数据库访问部件
在TDmEmployee中定义了一个TDatabase类型的部件──EmployeeDatabaseEmployeeDatagase的主要属性及属性值如下
表 EmployeeDatabase部件主要属性的取值
━━━━━━━━━━━━━━━━━━━━━━━
属性 属性值
───────────────────────
AliasName IBLOCAL
DatabaseName EmployeeDemoDB
KeepConnection True
LoginPrompt False
TransIsolation tiReadCommitted
Params USERNAME = SYSDBA
PASSWORD = masterkey
Connected True
━━━━━━━━━━━━━━━━━━━━━━━
AliasName属性所指定的IBLOCAL必须已经在BDE中配置好DatabaseName属性指定要使用的数据库名该数据库名是由应用程序自己定义的因此不反应到BDE中该属性值被TTableTQuery等DataSet部件引用并且出现在DataSet部件的DatabaseName 下拉式列表框中本例中的EmployeeDemoDB被EmployeeTableSalesTable等所有DataSet部件引用
Connected为True表明应用程序与数据库将保持联接
KeepConnection属性为True表明多次打开和关闭EmployeeDemoDB数据库中的任意表应用程序将始终与数据库保持联接这省却了重复注册的开销
LoginPrompt 属性为False表明应用程序自动处理与数据库的联接注册因此Params属性中定义了注册的用户名和口令
USERNAME = SYSDBA
PASSWORD = masterkey
TransIsolation属性为tiReadCommitted表明如果存在多个同时事务则某一事务只允许读由其它事务提交了的数据
程序中EmployeeDatabase的应用还与事务控制等有关下文中会介绍这方面的内容
不同数据库表的切换
在许多数据库应用中都要在不同数据库表之间相互切换以响应用户输入条件或系统状态的变化这时往往需要特别的处理例如改变光标形状或隐藏数据改变等尤其是在客户/服务器应用程序中因为是用SQL语句访问远程数据库有时还要在服务器端执行计算任务所以客户端的数据变化会有一定的间隔因此应该让用户明白发生了什么下面是CSDEMO在数据库表切换时的处理办法
procedure TFrmViewDemoShowTable( ATable: string )
begin
ScreenCursor := crHourglass; { 向用户提示当前操作状态 }
VaryingTableDisableControls; { 隐藏数据变化 }
VaryingTableActive := FALSE; { 关闭原来的数据库表 }
VaryingTableTableName := ATable; { 更新数据库表名 }
VaryingTableOpen; { 打开数据库表 }
VaryingTableEnableControls; { 显示所作的修改 }
ScreenCursor := crDefault; { 重新设置光标形状 }
end;
crHourglass型光标表明正在执行SQL查询DisableControls和EnableControls的作用是隐藏和显示数据变化
InterBase触发器(Trigger)的应用
在CSDEMO应用程序中演示触发器应用的窗体是TFromTriggerDemo;
在该窗体中包含两个TDBGrid对象DBGrid显示EmployeeTable中的数据DBGrid显示SalaryHistoryTable中的数据它们的主要属性及属性值如下
表 EmlpoyeeTable部件主要属性的取值
━━━━━━━━━━━━━━━━━━━━━
属 性 属 性 值
─────────────────────
DatabaseName EmployeeDemoDB
IndexFieldName Emp_No
TableName EMPLOYEE
━━━━━━━━━━━━━━━━━━━━━
表 SalaryHistoryTable部件主要属性的取值
━━━━━━━━━━━━━━━━━━━━━
属 性 属 性 表
─────────────────────
DatabaseName EmployeeDemoDB
IndexFieldName Emp_No
MasterFields Emp_No
MasterSource EmployeeSource
TableName SALARY_HISTORY
━━━━━━━━━━━━━━━━━━━━━
这两个表之间存在两种关系
● 连接关系
EmployeeTable的记录变化时SalaryHistoryTable的数据要作相应的变化这种连接关系是通过索引来实现的
● 数据一致性
对EmployeeTable中的Salary字段的值作修改必须反映到SalaryHistoryTable中SalaryHistoryTable维护的是Salary变化的历史信息这种数据一致性要求在本程序中是通过触发器实现的
触发器是在SQL服务器端执行的一段程序它在服务器端被触发执行完成一定的数据计算任务
下面是InterBase服务器上与Employee表相关的触发器程序
Triggers on Table EMPLOYEE:
SAVE_SALARY_CHANGE Sequence: Type: AFTER UPDATE Active AS
BEGIN
IF (oldsalary <> newsalary) THEN
INSERT INTO salary_history
(emp_no change_date updater_id old_salary percent_change)
VALUES (
oldemp_no
now
user
oldsalary
(newsalary oldsalary) * / oldsalary)
END
因为触发器是相应于EMPLOYEE表上的数据修改由服务器自动触发执行的所以在客户应用程序上没有显式的调用在客户端有打开并显示数据库表内容的程序和当SALARY_HISTORY表中数据变化时的更新显示的操作
[] [] [] []