Delphi数据库编程新手指南(11)

页面导航:首页 > 软件编程 > Delphi > Delphi数据库编程新手指南(11)

Delphi数据库编程新手指南(11)

来源: 作者: 时间:2016-01-18 15:41 【

数据定义语言(Data definitionlanguage)通过编程创建一个数据库并不是大多数开发人员每天都在做的事情 - 大家都使用某种可视化工具,如MSAccess维护一个MDB文件。不幸的是,有时你需要通

数据定义语言(Data definitionlanguage)

通过编程创建一个数据库并不是大多数开发人员每天都在做的事情 - 大家都使用某种可视化工具,如MSAccess维护一个MDB文件。不幸的是,有时你需要通过代码创建和销毁数据库以及数据库对象。现今使用的最基本的技术是结构化查询语言数据定义语言(SQL DDL)。数据定义语言(DDL)语句是支持数据库对象的定义或声明的SQL语句(例如CREATE TABLE,DROP TABLE,CREATE INDEX和类似声明)。

在这里我的目的不是教大家DDL语言,如果你熟悉SQL DML,对DDL应该没有障碍。需要注意的是使用DDL可是相当棘手的,因为每个数据库供应商通常会提供自己扩展的SQL。

让我们来看看一个简单的CREATETABLE语句:


[sql]
CREATE TABLE PhoneBook( 
  Name TEXT(50) 
  Tel TEXT(50) 

CREATE TABLE PhoneBook(
  Name TEXT(50)
  Tel TEXT(50)
)上述DDL语句(MS Access)在执行时,将创建一个名为PhoneBook的新表。该表具有两个字段,Name及Tel。两个字段都是字符串(文本)类型,大小为50个字符。

 


TFieldDef.DataType

显然,在Access中string类型用TEXT表示,Paradox则为string。为了将Paradox表导入Access中,我们必须知道哪些数据类型可用,以及字段名是什么。在BDE及Paradox表中,TFieldDef.DataType属性指定字段(数据集)类型。要成功将Paradox表迁移到Access,你需要一个函数将Paradox字段类型“转换”为Access相应类型。

下面的函数用于检查字段(FD)类型,并返回Access的相应类型和字段大小,提供给CREATE TABLE DDL语句。


[delphi]
function AccessType(fd:TFieldDef):string; 
begin 
 case fd.DataType of 
  ftString:Result:='TEXT('+IntToStr(fd.Size)+')'; 
  ftSmallint: Result:='SMALLINT'; 
  ftInteger: Result:='INTEGER'; 
  ftWord: Result:='WORD'; 
  ftBoolean: Result:='YESNO'; 
  ftFloat : Result:='FLOAT'; 
  ftCurrency: Result := 'CURRENCY'; 
  ftDate, ftTime, ftDateTime: Result :='DATETIME'; 
  ftAutoInc: Result := 'COUNTER'; 
  ftBlob, ftGraphic: Result := 'LONGBINARY'; 
  ftMemo, ftFmtMemo: Result := 'MEMO'; 
 else 
  Result:='MEMO'; 
 end; 
end; 

function AccessType(fd:TFieldDef):string;
begin
 case fd.DataType of
  ftString:Result:='TEXT('+IntToStr(fd.Size)+')';
  ftSmallint: Result:='SMALLINT';
  ftInteger: Result:='INTEGER';
  ftWord: Result:='WORD';
  ftBoolean: Result:='YESNO';
  ftFloat : Result:='FLOAT';
  ftCurrency: Result := 'CURRENCY';
  ftDate, ftTime, ftDateTime: Result :='DATETIME';
  ftAutoInc: Result := 'COUNTER';
  ftBlob, ftGraphic: Result := 'LONGBINARY';
  ftMemo, ftFmtMemo: Result := 'MEMO';
 else
  Result:='MEMO';
 end;
end;


TADOCommand

在ADOExpress中,TADOCommand是具有代表性的ADO Command对象VCL组件。 Command对象表示一个可以由数据源处理的指令(作为查询或语句),可以通过ADOCommand的Execute方法来执行。 TADOCommand常用于执行数据定义语言(DDL)SQL指令。 CommandText属性用于指定需要执行的命令;CommandType属性用于判断如何解释CommandText属性;cmdText type用于指定DDL语句。你也可以用ADOCommand组件来检索表、执行查询或存储过程等等,虽然这没有任何意义。

以下为项目示范:

l  得到一个BDE alias中所有表的列表;

l  使用TFieldDefs检索表中各字段的定义(名称、数据类型、大小等);

l  创建CREATE TABLE语句;

l  从BDE/ Paradox表将数据复制到ADO/ Access表。

基本上,我们要做的就是从DBDEMOS中复制几个表到我们的Access数据库—aboutdelphi.mdb。

让我们一步一步来:

启动Delphi——这会创建一个带有空白窗体的新项目;然后添加两个Button、一个ComboBox和Memo组件;接着增加一个TTable、TADOTable、TADOConnection和TADOCommand组件;之后在Object Inspector中按照下述示例设置属性(其他属性保持默认——例如Memo组件保持默认名:Memo1):


[delphi] 
Button1.Caption := 'ConstructCreate command' 
Button2.Caption := 'CreateTable and copy data' 
ComboBox.Name :=cboBDETblNames; 
//如同第二章中所描述的  
ADOConnection1.ConnectionString:= ... 
TADOTable.Name := ADOTable 
ADOTable.Connection :=ADOConnection1 
TADOCommand.Name := ADOCommand 
ADOCommand.Connection :=ADOConnection1 
TTable.Name := BDETable 
BDETable.DatabaseName :='DBDEMOS' 

Button1.Caption := 'ConstructCreate command'
Button2.Caption := 'CreateTable and copy data'
ComboBox.Name :=cboBDETblNames;
//如同第二章中所描述的
ADOConnection1.ConnectionString:= ...
TADOTable.Name := ADOTable
ADOTable.Connection :=ADOConnection1
TADOCommand.Name := ADOCommand
ADOCommand.Connection :=ADOConnection1
TTable.Name := BDETable
BDETable.DatabaseName :='DBDEMOS'


Code

为了检索一个给定数据库(DBDEMOS)相关表的列表,我们使用下面的代码(窗体OnCreate事件中):


[delphi]
procedure TForm1.FormCreate(Sender: TObject); 
begin 
 Session.GetTableNames('DBDEMOS', '*.db', False,False, cboBDETblNames.Items); 
end; 

procedure TForm1.FormCreate(Sender: TObject);
begin
 Session.GetTableNames('DBDEMOS', '*.db', False,False, cboBDETblNames.Items);
end;
当你启动工程,ComboBox将获得DBDEMOS别名目录中所有的(Paradox)表名。下面的代码,我们将挑选country表。

接下来的任务是创建一个CREATETABLE DDL语句,放在  'Construct Create command'按钮的OnClick事件中:


[delphi]
procedure TForm1.Button1Click(Sender: TObject); 
//'Construct Create command'button  
var i:integer; 
    s:string; 
begin 
 BDETable.TableName:=cboBDETblNames.Text; 
 BDETable.FieldDefs.Update; 
  
 s:='CREATE TABLE ' + BDETable.TableName + '('; 
 with BDETable.FieldDefs do begin 
  for i:=0 to Count-1 do begin 
   s:=s + ' ' + Items[i].Name; 
   s:=s + ' ' + AccessType(Items[i]); 
   s:=s + ','; 
  end; //for  
  s[Length(s)]:=')'; 
 end;//with  
  
 Memo1.Clear; 
 Memo1.lines.Add (s); 
end; 

procedure TForm1.Button1Click(Sender: TObject);
//'Construct Create command'button
var i:integer;
    s:string;
begin
 BDETable.TableName:=cboBDETblNames.Text;
 BDETable.FieldDefs.Update;
 
 s:='CREATE TABLE ' + BDETable.TableName + '(';
 with BDETable.FieldDefs do begin
  for i:=0 to Count-1 do begin
   s:=s + ' ' + Items[i].Name;
   s:=s + ' ' + AccessType(Items[i]);
   s:=s + ',';
  end; //for
  s[Length(s)]:=')';
 end;//with
 
 Memo1.Clear;
 Memo1.lines.Add (s);
end;
上述代码简单解析了选定表(cboBDETblNames)中字段的定义,而后生成一个字符串供TADOCommand组件的CommandText属性使用。

例如,当选择country表时Memo组件显示如下内容:


[sql] 
CREATE TABLE country ( 
  Name TEXT(24), 
  Capital TEXT(24), 
  Continent TEXT(24), 
  Area FLOAT, 
  Population FLOAT) 

CREATE TABLE country (
  Name TEXT(24),
  Capital TEXT(24),
  Continent TEXT(24),
  Area FLOAT,
  Population FLOAT)最后,是“CreateTable and copy data”按钮的相关代码。删除表(DROP..EXECUTE)、创建表(CREATE..EXECUTE),然后将数据复制到新表(INSERT...POST),以及一些错误处理代码。但代码仍可能失败——例如(新)表已经存在(在删除表之后)。


[delphi] 
procedure TForm1.Button2Click(Sender: TObject); 
//'Create Table and copy data'button  
var i:integer; 
    tblName:string; 
begin 
 tblName:=cboBDETblNames.Text; 
  
//refresh  
 Button1Click(Sender); 
  
//drop & create table  
 ADOCommand.CommandText:='DROP TABLE ' +tblName; 
 ADOCommand.Execute; 
  
 ADOCommand.CommandText:=Memo1.Text; 
 ADOCommand.Execute; 
  
 ADOTable.TableName:=tblName; 
  
//copy data  
 BDETable.Open; 
 ADOTable.Open; 
 try 
  while not BDETable.Eof do begin 
   ADOTable.Insert; 
   for i:=0 to BDETable.Fields.Count-1 do begin 
    ADOTable.FieldByName 
   (BDETable.FieldDefs[i].Name).Value := 
      BDETable.Fields[i].Value; 
   end;//for  
   ADOTable.Post; 
   BDETable.Next 
  end;//while  
 finally 
  BDETable.Close; 
  ADOTable.Close; 
 end;//try  
end; 

procedure TForm1.Button2Click(Sender: TObject);
//'Create Table and copy data'button
var i:integer;
    tblName:string;
begin
 tblName:=cboBDETblNames.Text;
 
//refresh
 Button1Click(Sender);
 
//drop & create table
 ADOCommand.CommandText:='DROP TABLE ' +tblName;
 ADOCommand.Execute;
 
 ADOCommand.CommandText:=Memo1.Text;
 ADOCommand.Execute;
 
 ADOTable.TableName:=tblName;
 
//copy data
 BDETable.Open;
 ADOTable.Open;
 try
  while not BDETable.Eof do begin
   ADOTable.Insert;
   for i:=0 to BDETable.Fields.Count-1 do begin
    ADOTable.FieldByName
   (BDETable.FieldDefs[i].Name).Value :=
      BDETable.Fields[i].Value;
   end;//for
   ADOTable.Post;
   BDETable.Next
  end;//while
 finally
  BDETable.Close;
  ADOTable.Close;
 end;//try
end;这样,你的Access数据库中也有了一个Country表,并且所有的数据都来源于DBDEMOS。


现在,你可以将整个Paradox表都导入Access中(下载代码)。但是,仍然有几个问题没有解决。首先:如何在表中添加索引(CREATEINDEX ON ...);其次:如何创建一个空的Access数据库。这些问题(以及其他你能想到的),将留在或新章节中解决。

 

Tags:

文章评论

最 近 更 新
热 点 排 行
Js与CSS工具
代码转换工具

<