Difference between revisions of "Lazarus Tdbf Tutorial/zh CN"

From Lazarus wiki
Jump to navigationJump to search
(added link to example)
 
(8 intermediate revisions by 3 users not shown)
Line 13: Line 13:
  
 
=== TDbf 组件能提供什么 ===
 
=== TDbf 组件能提供什么 ===
TDbf 为Lazarus(等)提供访问 dBase 或 FoxPro 数据表。它允许读、写和创建 dBase III+, dBase IV, Visual dBase VII and FoxPro 版本的表。它做这些不需要额外库文件或者数据引擎。 简单地拖动 TDbf 组件到你的表单,你就立刻拥有操作一个跨平台数据库的环境。TDbf 通过Lazarus能够工作在 Windows 和 Linux。
+
TDbf 为Lazarus(等)提供访问 dBase 或 FoxPro 数据表。它允许读、写和创建 dBase III+, dBase IV, Visual dBase VII and FoxPro 版本的数据库文件。它工作并不需要额外库文件或者数据引擎。 你要做只是简单地拖动 TDbf 组件到你的表单,你就立刻拥有操作一个跨平台数据库的环境。TDbf 通过Lazarus能够工作在 Windows 和 Linux。
  
 
== 如何创建一个新的数据表 ==
 
== 如何创建一个新的数据表 ==
  
As there is no "Database Desktop" application for Lazarus yet, we must create a new database in code.
+
Lazarus没有提供 "Database Desktop" 这样的桌面数据库应用程序, 我们将在程序中建一个新的Dbase表.
=== Setting the path ===
+
=== 设置数据文件路径 ===
 
It's a good idea to give your application's database it's own directory. This simplifies making backups of the data. There are two ways to set the path. You can set the full path using the FilePathFull property, or you can set a path relative to the current application path with FilePath. For instance, setting "FilePath" at runtime to "data/" would use a data subdirectory just below the executable file. Setting the "FilePathFull" property to "/var/data/" would place everthing in that exact folder, ignoring the application's location.
 
It's a good idea to give your application's database it's own directory. This simplifies making backups of the data. There are two ways to set the path. You can set the full path using the FilePathFull property, or you can set a path relative to the current application path with FilePath. For instance, setting "FilePath" at runtime to "data/" would use a data subdirectory just below the executable file. Setting the "FilePathFull" property to "/var/data/" would place everthing in that exact folder, ignoring the application's location.
=== Choosing a TableLevel ===
+
=== 选择数据库版本 ===
By default, the TDbf will create dBase IV tables. While this is very compatible, there are features you may wish to use that are not supported. To support auto-incrementing fields, you must use something newer. The table types are:
+
缺省情况下, TDbf 会自动创建 dBase IV 格式的dbf数据库文件. 虽然这种格式的数据库兼容很强, 但有些功能可能不被支持. 如果你需要auto-incrementing fields自动递增字段, 你就必须使用更高级别的.  
 +
 
 +
TDbf 支持的数据库格式:
  
 
*3 dBase III+
 
*3 dBase III+
Line 28: Line 30:
 
*25 FoxPro
 
*25 FoxPro
  
You choose a table type by setting the TableLevel property appropriately.
+
你选择一个正确的数据库格式,应用适当属性.
  
=== Adding fields ===
+
=== 添加字段 ===
 
Creating fields for your new table at runtime pretty much follows the old Delphi standard. Once you have set your FilePath, TableLevel, and TableName properties, manipulate the FieldDefs property to set up the structure. For example:
 
Creating fields for your new table at runtime pretty much follows the old Delphi standard. Once you have set your FilePath, TableLevel, and TableName properties, manipulate the FieldDefs property to set up the structure. For example:
  
Line 91: Line 93:
 
== 如何向表增加索引 ==
 
== 如何向表增加索引 ==
  
If your database is larger than a few records, chances are you will want to have indexes defined to make searching faster. To change the index structure of a table, we will want to have exclusive access to the table - which we would have while creating it anyway.
+
如果你的数据库有大量数据记录,那么你就需要建索引文件来加快搜索的速度。定义表的索引字段,在创建数据库索引文件时,数据库被独占锁定。
  
 
         MyDbf.Exclusive := True;
 
         MyDbf.Exclusive := True;
 
         MyDbf.Open;
 
         MyDbf.Open;
  
Now, we just have to add the index.
+
现在,我们要为数据库添加索引
  
 
         MyDbf.AddIndex('custid', 'Id', [ixPrimary, ixUnique]);
 
         MyDbf.AddIndex('custid', 'Id', [ixPrimary, ixUnique]);
Line 106: Line 108:
 
The following sample creates a new table "customers" in code. This of course only needs done once, and after that you just OPEN the table, don't create it ;-)
 
The following sample creates a new table "customers" in code. This of course only needs done once, and after that you just OPEN the table, don't create it ;-)
  
 +
{$MODE OBJFPC}
 +
Program DatabaseTest; 
 
  { We will require the following units be in the USES clause: }
 
  { We will require the following units be in the USES clause: }
{ uses Dbf, db, Dbf_Common                                  }
+
  uses Dbf, db, Dbf_Common;                                    
 
  { The Dbf is put there when you drop the TDbf on a form...  }
 
  { The Dbf is put there when you drop the TDbf on a form...  }
 
  { but you will need db for the DataSet object and Dbf_Common }
 
  { but you will need db for the DataSet object and Dbf_Common }
Line 158: Line 162:
 
     MyDbf.CompactIndexFile('custname.ndx');
 
     MyDbf.CompactIndexFile('custname.ndx');
  
== 如何连接 TDbf 组件到 数据感知(data-aware)组件 ==
+
== 如何连接 TDbf 组件到 数据感知组件 ==
  
The above examples show how to create a new database table in code. Using that table is even more simple.
+
上面的例子显示了如何创建一个新的数据表,通过代码方式。使用这个表更为简单。
  
Data aware components in Lazarus (such as the TDbEdit control) link to a TDataSource component using their "DataSource" and "DataField" properties. The TDataSource component handles communication between the database engine and the data aware components. A TDataSource then links to the TDbf component using it's "DataSet" property. The connection looks like this:
+
Lazarus的数据感知组件(data-aware,象TDbEdit,在Data Controls面板)连接到一个 TDataSource 组件,使用它们的"DataSource" "DataField" 属性。TDataSource 组件会处理数据库引擎 和 数据感知组件 这二者之间的通信。一个 TDataSource then 连接到 the TDbf component 使用它的 "DataSet" 属性。这种(组件之间的)连接看起来象这样:
  
 
  TDbEdit-------
 
  TDbEdit-------
Line 171: Line 175:
  
  
Be sure to set the FilePath (or FilePathFulll), TableLevel, and TableName properties of your TDbf component before calling
+
请确认 FilePath (FilePathFulll), TableLevel, TableName 等属性,在你的 TDbf 组件,然后调用(before calling):
  
 
  TDbf.Active := True;
 
  TDbf.Active := True;
  
 +
还有很多可以说的,关于Lazazrus中的数据库编程,并且我建议,一本好的 Delphi 数据库编程书籍 或 two as the underlying concepts are the same. I constantly refer to my copy of "Delphi 2 Unleashed" because the concepts and basic code haven't changed much in 8 years.
  
There is much more that can be said about programming with databases in Lazarus, and I would recommend a good Delphi database programming book or two as the underlying concepts are the same. I constantly refer to my copy of "Delphi 2 Unleashed" because the concepts and basic code haven't changed much in 8 years.
+
== 压缩和重建 DBF 数据库表 ==
 
 
== Packing and rebuilding the tables ==
 
  
When a record is deleted, it's not truly removed from the physical table. Periodically you must "pack" a table to recover that lost space. This should be done with exclusive mode set.
+
因为 DBF 文件结构特性,在使用数据删除操作时,并没有真正的从物理表中删除数据,只是会给这条数据打上一个删除标记。这时你必须对数据库表进行“pack”操作,回收占用的空间。这应以独占模式设置。
  
 
  MyDbf.Exclusive := True;
 
  MyDbf.Exclusive := True;
 
  MyDbf.Open;
 
  MyDbf.Open;
 
  MyDbf.PackTable;
 
  MyDbf.PackTable;
  // let's also rebuild all the indexes
+
  // 同时重建数据库索引文件
 
  MyDbf.RegenerateIndexes;
 
  MyDbf.RegenerateIndexes;
 
  MyDbf.Close;
 
  MyDbf.Close;
Line 223: Line 226:
  
 
Currently there is no support for referential integrity, or internally encrypted .dbf files.
 
Currently there is no support for referential integrity, or internally encrypted .dbf files.
 +
 +
== See also ==
 +
*[[Example: TDbf (creating table and indexes, selecting of index)]]
 +
  
 
[[Category:zh]]
 
[[Category:zh]]

Latest revision as of 22:37, 23 January 2016

Deutsch (de) English (en) español (es) français (fr) português (pt) русский (ru) 中文(中国大陆)‎ (zh_CN)

概览

该教程是关于基础的数据库开发,使用Lazarus的 TDbf 组件 (by Micha Nelissen)。 针对TDbf 还有额外的文档可用。本页英文由 Tony Maro创建,欢迎大家修订!

需要 TDbf 的pdf文档可以去这个SourceForge 网站。It may be useful to keep that pdf alongside this document while reading.

你需要什么

TDbf 组件已经在 Lazarus 0.913版本后默认安装(Data Access标签)。

No doubt this will soon be easier as FreePascal releases the next version 2.0, however currently you will need a recent CVS edition of FPC 1.9.X in order to properly use the TDbf component. It may be possible to download just the TDbf component by itself and use it with the 1.1 version of FreePascal, however this document was written with 1.9.X in mind, partly due to bug fixes in the other database components used in Lazarus.

TDbf 组件能提供什么

TDbf 为Lazarus(等)提供访问 dBase 或 FoxPro 数据表。它允许读、写和创建 dBase III+, dBase IV, Visual dBase VII and FoxPro 版本的数据库文件。它工作并不需要额外库文件或者数据引擎。 你要做只是简单地拖动 TDbf 组件到你的表单,你就立刻拥有操作一个跨平台数据库的环境。TDbf 通过Lazarus能够工作在 Windows 和 Linux。

如何创建一个新的数据表

Lazarus没有提供 "Database Desktop" 这样的桌面数据库应用程序, 我们将在程序中建一个新的Dbase表.

设置数据文件路径

It's a good idea to give your application's database it's own directory. This simplifies making backups of the data. There are two ways to set the path. You can set the full path using the FilePathFull property, or you can set a path relative to the current application path with FilePath. For instance, setting "FilePath" at runtime to "data/" would use a data subdirectory just below the executable file. Setting the "FilePathFull" property to "/var/data/" would place everthing in that exact folder, ignoring the application's location.

选择数据库版本

缺省情况下, TDbf 会自动创建 dBase IV 格式的dbf数据库文件. 虽然这种格式的数据库兼容很强, 但有些功能可能不被支持. 如果你需要auto-incrementing fields自动递增字段, 你就必须使用更高级别的.

TDbf 支持的数据库格式:
  • 3 dBase III+
  • 4 dBase IV
  • 7 Visual dBase VII
  • 25 FoxPro

你选择一个正确的数据库格式,应用适当属性.

添加字段

Creating fields for your new table at runtime pretty much follows the old Delphi standard. Once you have set your FilePath, TableLevel, and TableName properties, manipulate the FieldDefs property to set up the structure. For example:

MyDbf.FilePathFull := '/location/to/my/data';
MyDbf.TableLevel := 7;
MyDbf.TableName := 'customers.dbf'; // note: is the .dbf really required?
With MyDbf.FieldDefs do begin
  Add('Id', ftAutoInc, 0, True);
  Add('Name', ftString, 80, True);
End;

Field types are defined as:

  • ftUnknown
  • ftString
  • ftSmallInt
  • ftInteger
  • ftWord
  • ftBoolean
  • ftFloat
  • ftCurrency (TableLevel 25)
  • ftBCD (TableLevel 25)
  • ftDate
  • ftTime
  • ftDateTime
  • ftBytes (TableLevel 25)
  • ftVarBytes
  • ftAutoInc (TableLevel 7 or 25)
  • ftBlob
  • ftMemo
  • ftGraphic
  • ftFmtMemo
  • ftParadoxOle
  • ftDBaseOle
  • ftTypedBinary
  • ftCursor
  • ftFixedChar
  • ftWideString
  • ftLargeInt
  • ftADT
  • ftArray
  • ftReference
  • ftDataSet
  • ftOraBlob
  • ftOraClob
  • ftVariant
  • ftInterface
  • ftIDispatch
  • ftGuid
  • ftTimeStamp
  • ftFMTBcd

Bold types are currently supported

Go ahead and create it!

Once you have defined the fields you wish to use in your new table, you can go ahead and create it with:

   MyDbf.CreateTable;

如何向表增加索引

如果你的数据库有大量数据记录,那么你就需要建索引文件来加快搜索的速度。定义表的索引字段,在创建数据库索引文件时,数据库被独占锁定。

       MyDbf.Exclusive := True;
       MyDbf.Open;

现在,我们要为数据库添加索引

       MyDbf.AddIndex('custid', 'Id', [ixPrimary, ixUnique]);
       MyDbf.AddIndex('custname','Name', [ixCaseInsensitive]);
       MyDbf.Close;

Put it all together and you get...

The following sample creates a new table "customers" in code. This of course only needs done once, and after that you just OPEN the table, don't create it ;-)

{$MODE OBJFPC}
Program DatabaseTest;  
{ We will require the following units be in the USES clause: }
 uses Dbf, db, Dbf_Common;                                   
{ The Dbf is put there when you drop the TDbf on a form...   }
{ but you will need db for the DataSet object and Dbf_Common }
{ for things such as the field type definitions              }
var
  MyDbf: TDbf;
begin
  MyDbf := TDbf.Create(nil);
  try
    { use relative path to "data" directory }
    MyDbf.FilePath := 'data/'; 
    { we want to use Visual dBase VII compatible tables }
    MyDbf.TableLevel := 7;
    MyDbf.Exclusive := True;
    MyDbf.TableName := 'customers.dbf';
    With MyDbf.FieldDefs do begin
      Add('Id', ftAutoInc, 0, True);
      Add('Name', ftString, 80, True);
    End;
    MyDbf.CreateTable;
    MyDbf.Open;
    MyDbf.AddIndex('custid', 'Id', [ixPrimary, ixUnique]);
    { add a secondary index }
    MyDbf.AddIndex('custname','Name', [ixCaseInsensitive]);
    MyDbf.Close;
  finally
    MyDbf.Free;
  end;
end;

外部索引文件

The TDbf also supports storing secondary indexes in a separate file. This might be helpful if the database is expected to be very large. Secondary index files are created almost identically to normal indexes, but with the addition of the '.ndx' file extension:

    MyDbf.AddIndex('custname.ndx','Name', [ixCaseInsensitive]);


Each time the TDbf is opened, the index file must be loaded:

    MyDbf.OpenIndexFile('custname.ndx');


And indexes must be referenced including the extension:

    MyDbf.IndexName := 'custname.ndx';


Index files are packed separately using:

    MyDbf.CompactIndexFile('custname.ndx');

如何连接 TDbf 组件到 数据感知组件

上面的例子显示了如何创建一个新的数据表,通过代码方式。使用这个表更为简单。

Lazarus的数据感知组件(data-aware,象TDbEdit,在Data Controls面板)连接到一个 TDataSource 组件,使用它们的"DataSource" 和 "DataField" 属性。TDataSource 组件会处理数据库引擎 和 数据感知组件 这二者之间的通信。一个 TDataSource then 连接到 the TDbf component 使用它的 "DataSet" 属性。这种(组件之间的)连接看起来象这样:

TDbEdit-------
             |
TDbEdit------|-->TDataSource-->TDbf
             |
TDbNavigator--


请确认 FilePath (或 FilePathFulll), TableLevel, 和 TableName 等属性,在你的 TDbf 组件,然后调用(before calling):

TDbf.Active := True;

还有很多可以说的,关于Lazazrus中的数据库编程,并且我建议,一本好的 Delphi 数据库编程书籍 或 two as the underlying concepts are the same. I constantly refer to my copy of "Delphi 2 Unleashed" because the concepts and basic code haven't changed much in 8 years.

压缩和重建 DBF 数据库表

因为 DBF 文件结构特性,在使用数据删除操作时,并没有真正的从物理表中删除数据,只是会给这条数据打上一个删除标记。这时你必须对数据库表进行“pack”操作,回收占用的空间。这应以独占模式设置。

MyDbf.Exclusive := True;
MyDbf.Open;
MyDbf.PackTable;
// 同时重建数据库索引文件
MyDbf.RegenerateIndexes;
MyDbf.Close;
MyDbf.Exclusive := False;

Master table relations

Real power in database programming begins when you have multiple tables that reference each other. While TDbf does not yet support referential integrity, it does support a master / detail relationship between TDbf's.

When there are two tables related, for instance:

[customers]
Id       <----|
Name          |
Phone         |
Address       |
              |  The CustID in invoices references a customer primary  field
[invoices]    |
Id            |
Amount        |
CustID   -----|  * This field indexed as "idxcustid"


If you wanted to display all invoices for a given customer, the detail table (invoices) can stay in sync with the master table (customers) automatically.

On the invoices TDbf component set the following:

InvDbf.IndexName := 'idxcustid'; // our field that will match the customers table ID
InvDbf.MasterSource := dsCustomers; // datasource that is linked to the customers TDbf
InvDbf.MasterFields := 'Id'; // field on the customers table we are matching against our index


示例应用 - DB Browser

I've written a simple application that will use the TDbf to open and display database tables using the dbGrid control. The Linux executable along with project sources which should compile fine in Windows is available from: tony.maro.net

你需要关心的其他事情

Currently there is no support for referential integrity, or internally encrypted .dbf files.

See also