黑客风云——风云网络
设为首页 加入收藏 我要投稿 网站地图
您现在的位置: 黑客风云 >> 黑客文章 >> 黑客进阶 >> 黑客编程 >> 文章正文
[推荐]delphi基础学堂-详细讲解delphi
        ★★★★★
delphi基础学堂-详细讲解delphi
文章整理发布:黑客风云 文章来源:www.05112.com 更新时间:2007-1-10
 
第六讲 数据库编程(三)
 
一、基础补充
    1 变体类型 variant
    变体类型就是其数据类型在运行期间允许发生变化的类型。
    定义: var v: variant; //定义后其值为:unassigned
    ◇unassigned与NULL是有区别的。NULL表示该值未知,unassigned表示未赋值。
    ◇variant类型在赋值和运算的时候,系统自动实施类型转换。
    【例】赋值和判断类型
    2 变体数组 可以包含不同的数据类型元素的数组。
    定义:var a: variant; a := VarArrayCreate([0,9],varVariant);
          a := VarArrayof([1,'myname',12.4]);
    ◇数组类型仍然是variant。
    ◇可变数组允许它的元素是不同的类型。因为实际上它们都被转换成统一的variant类型。
 
二、使用别名
    1 使用别名的好处是方便数据库的移植。
    2 别名是一个名字,一个字符串。它代表了一组与数据库连接有关的设置。比如驱动程序名,数据库名,连接参数等等。
    3 可通过delphi附带的配置工具来配置别名。配置的目的就是生成一个配置文件。
    4 在ODBC数据源中添加的ODBC配置会自动反映在BDE别名配置中
    【例】配置一个dbase表的别名,并通过它打开表。
     开始|程序|borland6|BDE Administrator 启动配置程序。选databases页,在databases上鼠标右键|new..., driver name中选STANDARD,按OK。在左边起一个名字作为别名,在右边,default driver 选dbase,path中填写希望dbase表所在的目录。存盘,退出。
    ◇一般来说,别名代表一个数据库。在dbase系统中,数据库就是一个目录;对Access,数据库则是一个独立的文件,所有的表都存在这个文件中;对有些大型库,数据库表现为硬盘分区,无法直接看到;甚至有的数据库是按自己定义的方式存在于整个硬盘上。
 
三、连接多种类型的数据库
    1 通过ODBC连接Access
    在控制面板中找到“数据源(ODBC)”,双击打开;选系统DSN页;选添加;选microsoft Access driver (*.mdb);按完成;给数据源起个名字,就是要生成的别名;选“选择”或“创建”,来指定一个Access数据库;按确定。
◇在ODBC中配置的数据源会自动地作为别名添加在BDE Administrator中。
◇有时,在delphi程序打开的时候,刚刚配置的ODBC无法立刻反映在控件中,只要先关闭,在重新启动delphi即可看到新添的别名。
    2 通过ODBC连接SQL-Server
    基本步骤与连接Access相同。只是driver要选SQL Server,服务器如在本机可以选(local),登陆方式可以是选NT登陆(不需要用户名和密码)或用户登陆(必须知道用户名和密码),下一步,选中“更改默认数据库”,通过下拉列表选一个数据库,以下都确认即可。
    ◇有时,在服务器下拉列表中没有反映(沙漏光标),可以直接手填服务器的名字(单击任务栏上的服务器图标会看到本机服务器的名字)。
    ◇建议在最后确认前,使用“测试数据源”检查一下是否配置正确。
    ◇有时,使用用户登陆方式,密码和用户名都正确,但就是连接不上。这可能是因为在SQL Server中设置了只允许NT登陆方式造成的。改变的方法是:启动SQL Server企业管理器,选要操作的服务器,鼠标右键|属性,选Security页,把Authentication项选在“Sql server and windows”上。
    3 通过ADO连接Access
    在ADO页上,把ADOConnection控件放在Form上,双击打开|按build,选microsoft Jet 4.0 OLE DB ...,下一步,选数据库名字,连接测试,确认。放ADOTable在Form上,connection属性指向ADOConnection,选择表名等。其他操作与Table类似。
    ◇ADOConnection的配置过程实质上是形成一个串,赋给它的connectionString属性。
    ◇如果不希望每次都弹出一个密码对话框,可以在配置过程中指定密码,然后把它的loginPromt属性改为false。
    ◇实际上,我们完全可以不通过配置过程,直接在connectString中填写适当内容来完成上述的工作。也可以把配置存在一个文件里,启动时程序时从那个文件中读入。
    4 通过SQL-Link连接SQL-Server
    SQL-Link是borland公司提供的连接大型数据库的方法。这种方法比使用ODBC要快。
    启动BDE Administrator,新建一个别名,选MSSQL,确认。左边起名字;右边需要修改三项:databaseName:Sql server 上已经存在的数据库的名字;host name:服务器所在的主机的名字(如果是本机,此项可空);server name:服务器的名字。
    ◇虽然使用SQL-Link,在本机上仍然要安装大型库的客护端软件。
    ◇如果要屏蔽密码输入框,需要在form上放TDataBase控件。把它的loginPrompt设为false,填写它的params属性:user name=XXXX, password=XXXX
 
四、使用TDataBase
    1 TDatabase代表了一个数据库。
    多个TTable, TQuery等代表数据集的控件可以指向数据库控件。我们在没有使用TDatabase控件的时候也完成了数据库的操作是因为,系统替我们使用了一个默认的TDatabase对象。
    ◇注意,指向TDatabase的方法与在数据敏感控件中使用的方法不一样。先为TDatabase控件选择一个别名,再为它的DatabaseName起一个名字。其他数据集控件中的DataName一项要填写刚刚起的那个DatabaseName名字,而不是TDatabase控件的名字(一般为database1)。
    2 可以使用它自动传递用户名和密码,而不弹出登录提示框。
    database1.loginPrompt:=false
    database1.params.clear
    database1.params.add('user name=sa')
    database1.params.add('password=abcd')
    ◇注意user name的拼写,中间有一个空格。名字和密码都不使用引号。
    3 通过TDataBase使用显式定义的事务功能。
    database1.StartTransaction
    try 进行多次数据库的操作; database1.Commit;
    except database1.Rollback;end;
    ◇在没有显式地使用事务操作的时候,相当于每一个SQL语句是一个独立的事务。
    ◇一般来说,一定要使用try..except..end的结构来防止一个事务开始后,没有后续的动作。很多大型库并不会自动地取消一个事务,即便它在一周前就开始了。悬浮的事务会一直锁住某些表,使其他用户的操作无法进行。
    4 通过它,可以在不打开表的情况下,取得库中所有的表名,以及指定表的所有字段的名字。
    database1.GetTableNames(memo1.lines)
    这一命令会把当前库中的所有表的名字写在一个memo中。
    database1.GetFieldNames用来取得指定的表中的所有字段名,用法与上边类似。
    5 通过它,可以直接执行SQL语句。
    database1.Execute('update stu set name="aaa" where ...')
 
五、再谈多表联合查询
    1 多表联合的实质是集合的笛卡儿积运算。
    2 随着联合的表的数目的增加,积的记录数目呈指数式增长。虽然大型数据库在这方面作了大量的优化工作,多表联合仍然十分耗费服务器的资源(时间和空间)。
    3 “代码-描述名”的定义方式有很多优点,因而是数据库设计时广泛采用的方案。但在查询的时候,不可避免地用到多表联合。在多表查询的时候,只要其中一个表的记录数目很大,很可能会影响查询的性能。
    4   解决的方法:①当发现查询性能下降的时候,就要建立临时表,通过多步进行查询。仅仅通过建立视图的方法不能解决性能的问题。因为视图不是真的表,数据库中只保存了视图定义。
②当“代码-描述”表较小的时候,用多表联合十分不和算,我们可以把这些表先读到本地,再通过动态的翻译的方法实现最终的显示效果。
    【例】使用动态翻译的例子。对性别和班级进行动态翻译。
     实际上就是前边onGetText技巧的翻版。我们先打开代码对照表,读到本地一个TStringList中,然后在myGet过程里,通过查找TStringList来动态地提供text的值。
     5 多表联合是数学基础是集合论,它的功能十分强大。实际上,只要是表中存在的数据,无论要求怎样的输出结果,总能通过SQL语句来实现。有的时候,我们需要用到一个表和它自己的联合来解决一些特殊的问题。
    【例】求出一个表中某列数据有重复值的所有项(下表为横向排列)
    K 1 2 3 4 5 6 8 9 34
    V 2 2 3 5 6 6 7 9 10
    结果应为: k 1 2 5 6
    分析这类问题的方法是先写出笛卡儿积的所有行,再选择需要的行,看它们有什么特征。
    再看类似的例子:
    【例】求上面表中K值不连续的项(只找向上不连续即可)
     结果: K 1 8 34
 
六、报表的使用
    1 使用QuickReport粗略地打印报表
    QuickReport并非borland公司的产品。其设计很粗糙,功能很难适应中国报表。
    先在form中放QuickRep控件,代表一张纸。放入若干Band代表数据区。可以改变bandtype来指定band的类型。要与数据相连需放入数据集控件,把QuickRep的dataset属性指向该控件。
可以用鼠标右键|preview来预览报表。
    ◇表格线需要放图形控件实现。band的边框线控制不准确。
    ◇用鼠标拖动的方式几乎很难完成对齐工作。需要直接调节属性,或在程序中设置。
    2 使用F1Book控件完成复杂报表输出
    F1book功能十分强大,几乎就是电子表格的翻版。如果用过Excel则极易上手。
    在ActiveX页中找到F1book,放在form上。鼠标右键|workbook Designer 可以可视化地设计表格的属性(和Excel的功能很类似)。
    单元格的表示法:A1表示一个单元,A1:C1表示一行单元格,A1:C10表示一片单元格。
    当前的活动单元:.col .row
    当输入字符串的时候,自动左对齐;当输入数字的时候,自动右对齐。怎样输入一个数字,并把它看作是字符串呢?输入时,用'123就可以了。
    可以指定某个单元为计算值。方法是:=sum(A1:C10)以等号开始一个函数
   所有在设计阶段的功能都能用代码的方式完成。
    F1book提供数百个方法可共调用,滋举其要:
    给一个单元格赋字符串值 f.textRC[row,col]   := 'abcd'
    给一个单元格赋数字值    f.numberRC[row,col] := 123
    设置需要打印的区域:    f.printArea := 'A2:F15'
    重新计算所有计算字段: f.Recalc;
    f.printHCenter := true; 水平居中   f.printVCenter .. 垂直
    f.printLandscape := true; 横向打印
    f.prinLeftMargin,f.printfRightMargin 左右边距
    f.setPrintScale(nScale, bFittopage, nVPages, nHPages)
        nScale: 10-400 放大率 100 表示原样大小
        bFitToPage: true 满纸打印(不一定满一张纸,而是可以满一组纸)
        nVPages: 垂直纸页数    nHPages: 水平...
    f.FilePrint(true); 打印输出。显示对话框否?
    ◇缺少打印预览的功能。
    3 完全自己控制打印
    TCanvas对象封装了windows的绘图环境,可以在抽象的设备上进行绘图。
    在打印机上绘图:
        printer是全局对象,代表当前的打印机。 printer.canvas是TCanvas对象,代表打印机的绘图环境。
        printer.pageHeight,printer.pageWidth 代表纸高和宽,单位是象素。
    TCanvas 内含了许多有用的对象
      pen: TPen 笔对象,用来画线或其他图形
      brush: TBrush 用来填充颜色
      font: TFont 用来设置字体的特征
      【例】在form的canvas上输出的例子
       canvas.pen.color := clRed; canvas.pen.width := 2;
       canvas.moveTo(10,10); canvas.lineTo(100,100);
       canvas.brush.color := RGB(10,20,100);
       canvas.rectangle(20,20,250,100)
    ◇在默认的情况下,canvas输出的计量单位是象素。使用这种方式存在一个问题,就是打印机的分辨率一般比屏幕要高出许多倍,同样的语句,在打印机上可能就变成了“缩微图象”。怎样实现自由缩放?这涉及到windows下的设备映射方式问题。Windows提供多种设备映射方式,缺省的方式是:MM_TEXT,即象素映射方式。
    【例】改变缺省的映射方式,实现设图形的整体放缩。
    setMapMode(canvas.handle,MM_ANISOTROPICD); //不等轴映射
    setWindowExtex(canvas.handle,1000,1000,nil)
    setViewportExtex(canvas.handle,200,200,nil);
    .... // 绘图过程
    setMapMode(canvas.handle, MM_TEXT); //恢复原来的模式
    ◇canvas是对windows绘图场境的封装,设备场境是易失资源,所以对canvas的设定和操作要在一个紧凑的代码中完成,而不能期望其设置的持久性。
    我们在form中输出时,为了把输出限制在一个矩形区域内,可以使用控件来完成(比如system 页中的TPaintBox),但对打印机的输出却不能使用控件,怎样把输出限定在一个区域中呢?可以利用windows中提供的剪切区的功能来实现。
    【例】使用剪切区控制输出的范围
    var myR: HRgn; //剪切区对象句柄
    myR := creaetRectRgn(50,50,300,300); // 创建剪切区
    selectClipRgn(printer.canvas.handle, myR);
    .... // 绘图操作
    selectClipRgn(printer.canvas.handle, 0); //使用原来的剪切区
    deleteObject(myR); // 删除对象
    ◇与绘图有关的很多对象都是系统的敏感资源,我们应当遵循如下规则:
    ①使用的时候才申请,而不是储备待用。
    ②不用的时候立即释放。
 
 
 

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

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