程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 第十八章-Delphi客戶服務器應用開發(四)(2)

第十八章-Delphi客戶服務器應用開發(四)(2)

編輯:Delphi

18.4.1.2 數據庫結構介紹

 IBLOCAL數據庫的結構都是由InterBase服務器工具交互式SQL工具(ISQL)定義的。

用ISQL定義數據庫,首先要用Create Database命令建立數據庫,建立的新數據庫一般是以GDB為擴展名。建立好後,就可以用SQL語言定義數據庫表,例如建立EMPLOYEE表的SQL語句如下:

定義域名數據類型:

CREATE DOMAIN FIRSTNAME AS VARCHAR(15);

CREATE DOMAIN LASTNAME AS VARCHAR(20);

CREATE DOMAIN COUNTRYNAME AS VARCHAR(15);

CREATE DOMAIN EMPNO AS SMALLINT;

CREATE DOMAIN DEPTNO AS CHAR(3)

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

CREATE DOMAIN JOBCODE AS VARCHAR(5)

CHECK (VALUE > '99999');

CREATE DOMAIN JOBGRADE AS SMALLINT

CHECK (VALUE BETWEEN 0 AND 6);

CREATE DOMAIN SALARY AS NUMERIC(15, 2)

DEFAULT 0

CHECK (VALUE > 0);

建立EMPLOYEE表:

CREATE TABLE EMPLOYEE (EMP_NO EMPNO NOT NULL,

FIRST_NAME FIRSTNAME NOT NULL,

LAST_NAME LASTNAME NOT NULL,

PHONE_EXT VARCHAR(4),

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

各數據庫表中的內容如下:

表18.14 EmployeeDemoDB中各數據庫表的內容

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

  數據庫表名        表中內容

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

     EMPLOYEE 雇員信息

 CUSTOMER 客戶信息

DEPARTMENT 部門信息

EMPLOYEE_PROJECT 雇員負責的工程

PROJECT 工程信息

SALES 銷售信息

SALARY_HISTORY 雇員薪水調整的歷史信息

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

每個數據庫表中都定義了關鍵字段。關於數據庫表中的字段名、類型、大小,這裡不再贅述。

18.4.2 應用程序分析

18.4.2.1 TDatabase部件的使用

CSDEMO程序中定義了一個數據庫模塊部件——TDmEmployee,它是繼承於TDataModule。TDataModule是在Delphi2.0中才出現的專門放置數據訪問部件(如TDatabase、TTable和TQuery等)的框架。其它涉及數據庫訪問的窗體,只要在uses語句中插入數據庫模塊所在的庫單元,該窗體上的數據庫部件就可引用相應的數據庫訪問部件。

在TDmEmployee中定義了一個TDatabase類型的部件──EmployeeDatabase。EmployeeDatagase的主要屬性及屬性值如下:

表18.15 EmployeeDatabase部件主要屬性的取值

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

    屬性        屬性值

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

    AliasName IBLOCAL

DatabaseName EmployeeDemoDB

KeepConnection True

LoginPrompt False

TransIsolation tiReadCommitted

Params USERNAME = SYSDBA

PASSWORD = masterkey

Connected True

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

AliasName屬性所指定的IBLOCAL,必須已經在BDE中配置好,DatabaseName屬性指定要使用的數據庫名,該數據庫名是由應用程序自己定義的,因此不反應到BDE中,該屬性值被TTable、TQuery等DataSet部件引用,並且出現在DataSet部件的DatabaseName 下拉式列表框中。本例中的“EmployeeDemoDB”,被EmployeeTable,SalesTable等所有DataSet部件引用。

Connected為True表明,應用程序與數據庫將保持聯接。

KeepConnection屬性為True,表明多次打開和關閉EmployeeDemoDB數據庫中的任意表,應用程序將始終與數據庫保持聯接,這省卻了重復注冊的開銷。

LoginPrompt 屬性為False,表明應用程序自動處理與數據庫的聯接注冊,因此,Params屬性中定義了注冊的用戶名和口令:

USERNAME = SYSDBA

PASSWORD = masterkey

TransIsolation屬性為tiReadCommitted表明,如果存在多個同時事務,則某一事務只允許讀由其它事務提交了的數據。

程序中EmployeeDatabase的應用還與事務控制等有關。下文中會介紹這方面的內容。

18.4.2.2 不同數據庫表的切換

在許多數據庫應用中都要在不同數據庫表之間相互切換,以響應用戶輸入條件或系統狀態的變化。這時,往往需要特別的處理,例如改變光標形狀或隱藏數據改變等,尤其是在客戶/服務器應用程序中。因為是用SQL語句訪問遠程數據庫,有時還要在服務器端執行計算任務,所以客戶端的數據變化會有一定的間隔,因此應該讓用戶明白發生了什麼。下面是CSDEMO在數據庫表切換時的處理辦法:

procedure TFrmViewDemo.ShowTable( ATable: string );

begin

Screen.Cursor := crHourglass; { 向用戶提示當前操作狀態 }

VaryingTable.DisableControls; { 隱藏數據變化 }

VaryingTable.Active := FALSE; { 關閉原來的數據庫表 }

VaryingTable.TableName := ATable; { 更新數據庫表名 }

VaryingTable.Open; { 打開數據庫表 }

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

Screen.Cursor := crDefault; { 重新設置光標形狀 }

end;

crHourglass型光標表明正在執行SQL查詢。DisableControls和EnableControls的作用是隱藏和顯示數據變化。

18.4.2.3 InterBase觸發器(Trigger)的應用

在CSDEMO應用程序中,演示觸發器應用的窗體是TFromTriggerDemo;

在該窗體中包含兩個TDBGrid對象。DBGrid1顯示EmployeeTable中的數據,DBGrid2顯示SalaryHistoryTable中的數據。它們的主要屬性及屬性值如下:

表18.16 EmlpoyeeTable部件主要屬性的取值

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

    屬 性       屬 性 值

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

     DatabaseName EmployeeDemoDB

IndexFieldName Emp_No

TableName EMPLOYEE

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

表18.17 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: 0, Type: AFTER UPDATE, Active AS

BEGIN

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

INSERT INTO salary_history

(emp_no, change_date, updater_id, old_salary, percent_change)

VALUES (

old.emp_no,

'now',

user,

old.salary,

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

END

因為觸發器是相應於EMPLOYEE表上的數據修改由服務器自動觸發執行的,所以在客戶應用程序上沒有顯式的調用。在客戶端有打開並顯示數據庫表內容的程序和當SALARY_HISTORY表中數據變化時的更新顯示的操作。

procedure TFrmTriggerDemo.FormShow(Sender: TObject);

begin

DmEmployee.EmployeeTable.Open;

DmEmployee.SalaryHistoryTable.Open;

end;

procedure TDmEmployee.EmployeeTableAfterPost(DataSet: TDataSet);

begin

{ 一個雇員的薪水變化將觸發薪水調整歷史記錄的變化,

因此,如果SalaryHistory打開的話,就需要更新顯示 }

with SalaryHistoryTable do if Active then Refresh;

end;

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved