黑客风云——风云网络
设为首页 加入收藏 我要投稿 网站地图
您现在的位置: 黑客风云 >> 黑客文章 >> 黑客进阶 >> 黑客编程 >> 文章正文
[推荐]delphi基础学堂-详细讲解delphi
        ★★★★★
delphi基础学堂-详细讲解delphi
文章整理发布:黑客风云 文章来源:www.05112.com 更新时间:2007-1-10
 
 
第四讲 数据库编程(一)
 
一、基础补充
    1 开域语句
    在面向对象的程序代码中,嵌套对象的现象十分普遍,我们经常会去引用很深层的对象。如:
form1.canvas.font。当对一个深层对象设多个属性的时候,要写很多重复的符号,麻烦且容易出错。为此,delphi设计了开域语句。
    格式: width 对象 do ...; 一般情况下都是跟随多条语句,所有几乎总是用复合语句,即
            width 对象 do begin ... end;
    例如: with form1.canvas.font do
            begin color := clRed; size := 15; name:='宋体' end;
    2 集合的使用
    delphi中的集合是对数学中集合的概念的简单实现。要求是集合中的元素必须同类型,且必须是序数类型,且集合中可能的元素个数不能大于255。
    定义: type 集合类型名 = set of 元素类型
    例如: type MySet = set of char; //注意 char 的个数本来就不超过255。
           type MyItem = (sun, moon, star); MyItem2 = 1..100;
           type MySet2 = set of MyItme; MySet3 = set of MyItem2;
    ◇我们可以测试给定的元素是否在某个集合中。 var A: MySet; 'a' in A ?
    ◇集合的常量表达法: ['a','x','c']; [1,2,4..10]; [sun, moon]
    ◇空集的表示法: []
    ◇集合间可以直接赋值。 A := []; A := [1,2,6]; A := B;
    ◇集合间可以进行标准的运算: A+B 并集; A-B 差集; A*B 交集
    我们经常使用集合来表达用户对多选控件的选择情况。因为delphi定义了标准的集合运算,就使得我们处理类似:“两个用户公共选择了哪些项?”“从选择中去掉固定的一组选则”这样问题变得十分简单容易。delphi的控件属性中,有很多的是集合类型的例子。比如
    with form1.canvas.font do style := style + [fsItalic] 就是增加了斜体特征。
 
二、数据库的知识
    1 数据库是按照一定的结构组织起来的数据。组织的目的是为了方便操作。操作包括查找,增添,修改,删除等。不同的组织方法形成了不同的数据库模型。流行最广的是关系模型。
    2 关系模型中,数据库由二维表构成。它的行叫记录。列叫域或字段。关系模型的数学基础是集合论。严格地说,表是记录的集合。也就是说,不能有每个字段都相同的记录;仅仅是记录排列的位置不同的表被看做是相同的表。
    3 常听说的E-R模型是实体-联系模型的缩写。它是关系型数据库设计的理想状态。就是说:一张表,要么表达的是实体,要么表达的是联系。我们在创建表的时候就首先要明确这个表的E-R属性。实体必须的要素是标识和属性。标识能把不同的实体分开,叫主键。联系的要素是被关联的实体和联系的属性。被关联的实体的标识联合决定了唯一的联系,可做主键。每一个实体标识代表了外部的一个实体,叫外键。
    【比较】表的设计的例子。学生,课程,成绩。典型的实体关系模型。
     药品出库表:药物号,药物名,单价,数量,出库量,库存剩余,出库日期,经办人,用途,发货单号,备注。是错误的方案。可以用词性分析的方法初步分析出实体和联系。一般名词表示实体,动词表示联系。 药品出库:o1 + v + o2。‘药品’和‘仓库’是两个实体,‘出’是联系。
    4 完整性规则。实体完整性,参照完整性。
    5 桌面库与大型库的区别。
    ◇区别的标志是DBMS在哪台机器上执行,而不是操作台离数据库文件的远近。
    ◇DBMS是管理数据关系的系统。
    ◇C/S模型的优势是:减小了网络负担;支持并发访问。
    ◇发展方向是B/S模型。就是浏览器做客户端的方式。
 
三、delphi的数据库访问原理
    1 BDE是borland公司提供的数据库引擎。目的是为了实现不同数据库的统一访问方式。BDE中内置了本地的DBMS,支持dbase,paradox,foxpro的直接访问。
    如图,BDE可以通过ODBC接口访问几乎所有数据库。另外,borland公司也提供了对大型数据库比如oracle,sybase,db2,sql-server等的SQL-Link连接访问方式。这中连接方式比ODBC速度快。
    ◇使用SQL-Link仍然需要安装大型库的客户端程序。
    ◇ADO是微软继ODBC之后推出的新的数据库访问标准,其技术基础是OLE DB,支持更丰富的数据类型,访问速度更快,尤其是考虑了internet应用的需要。使用ADO连接不需要通过BDE,delphi提供了一组ADO控件,它们的功能和用法与对应的BDE控件很相似。

应用程序
BDE别名
BDE引擎
ADO

SQL-Link

interbase,oracle
sybase,sql-server等大型库

各种支持
ADO的数据库

本地库
dbase,paradox...

ODBC

Access,foxpro,
oracle,sybase,
sql-server db2..

 【例】连接一个已经存在的dbase表。在设计阶段需要修改控件的若干属性,完成连接工作。

 
 
所在页
控件类
属性
说明
BDE
TTable
 代表了数据库中的一张表。是对数据库进行操作的核心控件
 
TTable
dbaseName
c:\mydbase\ttt
指定dbase表所在的目录
 
TTable
TableName
student.dbf
在该目录中选择一个表名
DataAccess
TDataSource
 作为数据表与可视化控件间的连接控件
 
TDataSource
dataSet
table1
把数据源连接在数据表上
Data Controls
TDBGrid
 用于以网格的方式显示数据
 
TDBgrid
dataSource
dataSource1
把网格控件连接到数据源
 
属性设置结束后,可以在设计阶段把Table1的Active属性设为True,则表格中显示数据,也可以通过一个按钮的触发事件,写:Table1.active:=true 或 Table1.open来完成。

BDE
table1
table2
dataSource1
dataSource21
dbgrid1
dbgrid2
其它可视控件

    当数据表被激活以后,我们就可以在网格中浏览数据,并且可以修改数据。有的时候,不希望用户改变数据。怎么实现只读设置呢?上图启发我们有三种方法。①table1.readOnly属性 为true
②dataSource1.autoEdit属性为false ③dbgrid1.options中的dgEditing:=false
    ◇凡是我们在设计阶段所做的选择,都可以用程序的方法实现,而且我们也鼓励这样做。因为我们读别人的程序的时候,从一大堆属性中要区分哪些是系统默认的,哪些是后来设定的是一件十分耗时且枯燥的工作。
    ◇如果我们的工作并不需要显示数据,则只要一个TTable控件就可以对表进行操作了。
    【例】通过TTable控件创建dbase数据表。
     table1.databaseName := 'c:\mydabse\tt'; table1.tableName := 'test.dbf';
     with table1.fieldDefs.addFieldDef do
begin name:='K'; dataType := ftString; size := 10; end;
     with table1.fieldDefs.addFieldDef do
begin name:='V'; dataType := ftInteger; end;
     table1.createTable;
    ◇我们甚至可以不同窗体上的table1控件,可以直接创建一个TTable对象,使用后,把它释放。var t: TTable ... t := TTable.creaet(self);try ... finally t.free end;
 
TTable是从TDataSet(数据集)类继承的。有许多对数据库操作的控件类都是从TDataSet继承的。TDataset从概括的高度,定义了对记录的导航,增,删,改等操作,它是数据操纵的核心。
 
四、核心对象TDataSet
    TDataSet代表一张二维表。表是记录的集合。记录是字段的数组。
    ◇只是记录的顺序不同的表被看做相同的表。字段的定位可以使用数组下标,而记录的定位是通过主键来实现的。
    怎么样访问表中某个记录的某个字段呢?指定行和列的号码么?不能!TDataSet提供了对一条记录的访问,它是记录的数组,就是:TFields对象。TFields好比是一个小窗口,当我们要访问某个数据时,先要把记录移动到相应的位置,再通过这个窗口来访问各个字段。
 
【例】把表中所有的V>100的K值写到memo1中。
table1.dababaseName := 'c:\mydbase\tt'; table1.tableName := 'test.dbf';
table1.open; table1.first;
while not table1.eof do
begin if table1.fieldByName('V').asInteger>100 then
memo1.lines.add(table1.fields[0].asStrig); table1.next;
end;
    ◇数据集控制当前记录移动的方法:first,last,next,prior,moveby(相对偏移)。
    ◇字段可用下标引用。也可以通过名字引用,通过名字是良好的书写风格。
    ◇除了用eof判断结尾的方法,也可以用recordCount总记录数来控制循环次数。
    ◇为了防止在移动记录时,视图跟随而耽误时间,可以暂时把视图断开,操作结束后在把视图连接起来。 table1.disableControls; ... table1.enableControls;
    【例】修改当前记录的V值为edit1中指定的数
 table1.edit;   table1.fieldByName('V').asInteger := strToInt(edit1.text); table1.post;
◇TDataSet有多种状态,dsBrowse(浏览) dsEdit(编辑) dsInactive(未打开)等。
    ◇修改记录前必须把数据集状态设定为edit状态。这时,TFields小窗口指向了要改动的记录。结束edit状态有很多方法。①调用post方法把数据写到数据库 ②调用cancel方法,放弃修改,数据恢复到原来的值 ③移动记录,这时相当与自动调用了post方法。edit状态结束后,数据集恢复到浏览状态。
    ◇TDataSet执行的很多任务都是通过TFields完成,一般的方法就是先把数据集设为某种模式,然后修改TFields值,作为操作的参数。再调用相应的方法完成操作。比如append方法用于添加数据,写法与edit极为类似。删除数据相对简单,只要调用delete就会删除当前的记录。
    查找是数据库操作中十分常见的任务。TdataSet提供了两种查找的方法。locate方法可以没有索引,setkey的方法则需要先建立并使用索引。
    【例】使用locate方法进行查找
     table1.locate('k',['abcd'],[loCaeInsensitive]);   //查找单个字段
     table1.locate('k;v',varArrayof(['abcd',125]),[]); //查找多个字段
    【例】用setkey方法进行查找
    先建立索引:table1.close; table1.Addindex('IDX_1', 'K', [ixUnique]);
    table1.indexName := 'IDX_1'; table1.open;
    table1.setKey; table1.fieldByName('K').asString := 'abcd';
    table1.gotokey;
    ◇索引一经建立,就一直存在,直到被删除;对同一表,可建立多个索引;每一个索引可以指定多个字段;索引不起作用,直到填写了表的索引属性;一个表同时只能打开一个索引。
    ◇setkey方法是数据集处于设置查找值状态,这时的TFields小窗口用来接受给定的被查数值。
    ◇调用gotokey方法会结束查找状态,把光标停留在匹配的记录上,数据集恢复到浏览模式。
    ◇只能查找索引中包含的字段。
    【思考】应当养成一个习惯,就是每进行一步操作的时候,都想一想,怎样回到原来的状态。比如,知道了建立表和索引,很自然地会想到怎样删除表,删除索引。
   可以调用方法: deleteTable; deleteIndex来实现。
 
五、TField对象
    这是一个抽象的数据类型,不能直接实例化。它代表字段。所有的字段类型都从它派生。如,TStringField, TFloatField。我们来看看它的常用属性。
    【例】改变列标题,列宽度,小数的显示格式
    table1.fields[0].displayLabel := '主键';
    table1.fields[0].displayWidth := 20;
    (table1.fields[1] as TFloatField).displayFormat := '###.00';
    ◇displayLabel是要显示的字段的标题。diaplayText是要显示的字段的内容,勿混淆。
    ◇只有TNumericField类型的字段才有displayformat一说,故需特化处理。
    【例】显示一个表的所有字段的名字。
    for i:=0 to table1.fieldCount-1 do    //fieldCount表示一共有多少字段
        memo1.lines.add(table1.fields[i].FieldName);
 
 

上一页  [1] [2] [3] [4] [5] [6] [7] [8] 下一页  

文章录入:cainiaowang    责任编辑:cainiaowang 
【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
VIP 专 区
Copyright @2006 黑客风云 ●业务联系:QQ 联系怪人 联系奇人 Email:给怪人发邮件 给奇人发邮件
ICP备案:冀06009886