Difference between revisions of "Lazarus Tdbf Tutorial/pt"

From Lazarus wiki
Jump to navigationJump to search
(added link to example)
 
(37 intermediate revisions by 5 users not shown)
Line 3: Line 3:
 
== Visão Geral==
 
== Visão Geral==
  
Este tutorial é sobre desenvolvimento básico de banco de dados usando o componente [https://tdbf.sf.net TDbf] (de Micha Nelissen) no Lazarus.  Doumentação adicional para o TDbf está disponível.  Esta página foi criada por [[User:Tonymaro | Tony Maro]], mas outros contribuidores são bem-vindos!
+
Este tutorial é sobre o desenvolvimento básico de banco de dados usando o componente [https://tdbf.sf.net TDbf] (de Micha Nelissen) no Lazarus.  Doumentação adicional para o TDbf está disponível.  Esta página foi criada por [[User:Tonymaro | Tony Maro]], mas outros contribuidores são bem-vindos!
  
Para a documentação em PDF vá ao [https://sourceforge.net/project/showfiles.php?group_id=34085&package_id=26371  SourceForge]. Isto pode ser útil para manter esse PDF ao lado desta documntação enquanto a lê.
+
Para a documentação em PDF vá ao [https://sourceforge.net/project/showfiles.php?group_id=34085&package_id=26371  SourceForge]. Isto pode ser útil para manter esse PDF ao lado desta documentação enquanto a lê.
  
 
=== Do que você vai precisar ===
 
=== Do que você vai precisar ===
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.
+
Sem dúvida logo vai ser mais fácil quando o Free Pascal publicar a próxima versão 2.0, no entanto atualmente você vai precisar de uma edição CVS recente do FPC 1.9.x para usar adequadamente o componente TDbf. Isto pode ser feito baixando só o componente TDbf e usando-o com a versão 1.1 do Free Pascal, mas esta documentação foi escrita com a versão 1.9.x em mente, parcialmente por causa dos reparos no código, para que os componentes de banco de dados pudessem ser usados no Lazarus.
  
The DbfLaz package is now (version 0.9.13) installed by default.
+
O pacote DbfLaz (versão 0.9.13) é agora instalado por padrão.
  
=== What the TDbf provides ===
+
=== O que a TDbf fornece===
The TDbf provides access to dBase and FoxPro database tables for Lazarus (and others). It allows for reading, writing and creation of dBase III+, dBase IV, Visual dBase VII and FoxPro tables. It does all of this without the need for additional libraries or database engines. Simply drop the TDbf on your form and you have instant access to a cross-platform database environment. The TDbf works in both Windows and Linux using Lazarus.
+
A TDbf fornece acesso às tabelas de banco de dados do dBase e do FoxPro para  Lazarus (e outros). Isto permite ler, escrever e criar tabelas de dBase III+, dBase IIV, Visual dBase VII e FoxPro. Ela faz tudo isso sem precisar de bibliotecas adicionais ou engines de bancos de dados. Simplesmente coloque-a no seu formulário e você vai ter acesso instantâneo a um ambiente de banco de dados multiplataforma. A TDbf funciona em Windows e Linux usando o Lazarus.
  
== How to create a new database table ==
+
== Como criar tabelas de banco de dados ==
  
As there is no "Database Desktop" application for Lazarus yet, we must create a new database in code.
+
Como não existe uma aplicação "Database Desktop" para Lazarus ainda, nós precisamos criar um novo banco de dados por código.
=== 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.
 
=== 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:
 
  
*3 dBase III+
+
=== Configurando o caminho ===
*4 dBase IV
+
É uma boa idéia dar ao banco de dados da sua aplicação um diretório próprio.  Isto simplifica a feitura de backups dos dados. Existem  duas maneiras de configurar o caminho. Você pode configurar o caminho completo usando a propriedade FilePathFull ou pode configurar um caminho relativo ao caminho atual da aplicação com FilePath. Por exemplo, configurar FilePath em tempo de execução como "data/" usaria um subdiretório de dados bem abaixo do executável. Configurar a propriedade FilePathFull como "/var/data/" colocaria tudo nesta pasta, ignorando a localização da aplicação.
*7 Visual dBase VII
 
*25 FoxPro
 
  
You choose a table type by setting the TableLevel property appropriately.
+
=== Escolhendo um nível de tabela ("TableLevel") ===
  
=== Adding fields ===
+
Por padrão, a TDbf criará tabelas dBase IV. Enquanto garante compatibilidade muito grande com os outros níveis de tabela, existem características que você pode querer usar que esse nível não possui. Para utilizar campos auto-incrementados, por exemplo, você precisa de um nível de tabela maior. Eles estão listados abaixo:
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';
+
*nível 3 - dBase III+;
 +
*nível 4 - dBase IV;
 +
*nível 7 - Visual dBase VII;
 +
*nível 25 - FoxPro.
 +
 
 +
Você escolhe o tipo de tabela configurando a propriedade nível de tabela ("TableLevel") adequadamente.
 +
 
 +
=== Adicionando campos ===
 +
Criar campos para a sua nova tabela em tempo de execução segue bastante o antigo padrão do Delphi. Uma vez que você tenha configurado as propriedades caminho de arquivo ("FilePath"), nível de tabela ("TableLevel") e nome de tabela "(TableName"), manipule a propriedade definição de campos ("FieldDefs") para configurar a estrutura. Por exemplo:
 +
 
 +
  MyDbf.FilePathFull := '/lugar/em que/meus arquivos/estão';
 
  MyDbf.TableLevel := 7;
 
  MyDbf.TableLevel := 7;
  MyDbf.TableName := 'customers.dbf'; // note: is the .dbf really required?
+
  MyDbf.TableName := 'customers.dbf'; // observação: a extensão .dbf é realmente necessária?
 
  With MyDbf.FieldDefs do begin
 
  With MyDbf.FieldDefs do begin
 
   Add('Id', ftAutoInc, 0, True);
 
   Add('Id', ftAutoInc, 0, True);
Line 41: Line 44:
 
  End;
 
  End;
  
Field types are defined as:
+
Os tipos de campo estão definidos como:
  
 
*    ftUnknown
 
*    ftUnknown
Line 50: Line 53:
 
*    '''ftBoolean'''
 
*    '''ftBoolean'''
 
*    '''ftFloat'''
 
*    '''ftFloat'''
*    '''ftCurrency''' (TableLevel 25)
+
*    '''ftCurrency''' (Nível de tabela 25)
*    '''ftBCD''' (TableLevel 25)
+
*    '''ftBCD''' (Nível de tabela 25)
 
*    '''ftDate'''
 
*    '''ftDate'''
 
*    ftTime
 
*    ftTime
 
*    '''ftDateTime'''
 
*    '''ftDateTime'''
*    '''ftBytes''' (TableLevel 25)
+
*    '''ftBytes''' (Nível de tabela 25)
 
*    ftVarBytes
 
*    ftVarBytes
*    '''ftAutoInc''' (TableLevel 7 or 25)
+
*    '''ftAutoInc''' (Nível de tabela 7 ou 25)
 
*    '''ftBlob'''
 
*    '''ftBlob'''
 
*    '''ftMemo'''
 
*    '''ftMemo'''
Line 82: Line 85:
 
*    ftFMTBcd
 
*    ftFMTBcd
  
Bold types are currently supported
+
Os tipos em negrito são os que estão implementados atualmente.
  
=== Go ahead and create it! ===
+
=== Vá em frente e crie-o! ===
 
Once you have defined the fields you wish to use in your new table, you can go ahead and create it with:
 
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.CreateTable;
  
== How to add indexes to a table ==
+
== Como adicionar índices a uma tabela ==
  
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.
+
Se sua base de dados for maior do que alguns registros, você deverá ter índices definidos para fazer procuras mais rapidamente. Para mudar a estrutura do índice de uma tabela, precisamos ter o acesso exclusivo à tabela - que nós teríamos ao criar de qualquer maneira.
  
 
         MyDbf.Exclusive := True;
 
         MyDbf.Exclusive := True;
 
         MyDbf.Open;
 
         MyDbf.Open;
  
Now, we just have to add the index.
+
Agora, nos só temos que adicionar o indice.
  
 
         MyDbf.AddIndex('custid', 'Id', [ixPrimary, ixUnique]);
 
         MyDbf.AddIndex('custid', 'Id', [ixPrimary, ixUnique]);
Line 102: Line 105:
 
         MyDbf.Close;
 
         MyDbf.Close;
  
== Put it all together and you get... ==
+
== Junte tudo e o resultado é... ==  
 +
O fragmento de código a seguir cria uma nova tabela chamada "customers" (clientes) no
 +
código. Isso, é claro, precisa ser feito somente uma vez, e depois que você '''abre''' uma tabela não precisa criá-la novamente. ;-)
  
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 ;-)
+
Observação: crie o diretório relativo "data" antes de rodar este exemplo, ou a execução
 +
falhará.
  
  { We will require the following units be in the USES clause: }
+
  {$MODE OBJFPC}
  { uses Dbf, db, Dbf_Common                                  }
+
Program DatabaseTest; 
  { The Dbf is put there when you drop the TDbf on a form...   }
+
{ Precisaremos que as seguintes unidades estejam na cláusula USES: }
  { but you will need db for the DataSet object and Dbf_Common }
+
  uses Dbf, db, Dbf_Common;                                    
  { for things such as the field type definitions              }
+
  { A uniadde Dbf é colocada ali quando você põe a TBDF em um formulário. }
 +
  { No entanto, você precisará do banco de dados para o objeto DataSet e de Dbf_Common }
 +
  { para coisas como as definições de campo. }
 
  var
 
  var
 
   MyDbf: TDbf;
 
   MyDbf: TDbf;
Line 116: Line 124:
 
   MyDbf := TDbf.Create(nil);
 
   MyDbf := TDbf.Create(nil);
 
   try
 
   try
     { use relative path to "data" directory }
+
     { use o caminho relativo para o diretório "data }
 
     MyDbf.FilePath := 'data/';  
 
     MyDbf.FilePath := 'data/';  
     { we want to use Visual dBase VII compatible tables }
+
     { queremos utilizar tabelas compatíveis com Visual dBase VII }
 
     MyDbf.TableLevel := 7;
 
     MyDbf.TableLevel := 7;
 
     MyDbf.Exclusive := True;
 
     MyDbf.Exclusive := True;
Line 137: Line 145:
 
  end;
 
  end;
  
== External Index Files ==
+
== Arquivos de índice externos ==
  
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:
+
A TDbf também possibilita o armazenamento de índices secundários em um arquivo separado. Isso pode ser útil caso se espere que o banco de dados seja grande. Índices secundários
 +
são muito similares aos índices normais, com a adição da extensão de arquivos '.ndx'.
  
 
     MyDbf.AddIndex('custname.ndx','Name', [ixCaseInsensitive]);
 
     MyDbf.AddIndex('custname.ndx','Name', [ixCaseInsensitive]);
  
  
Each time the TDbf is opened, the index file must be loaded:
+
O índice precisa ser recarregado todas as vezes que a TDdf é aberta.
  
 
     MyDbf.OpenIndexFile('custname.ndx');
 
     MyDbf.OpenIndexFile('custname.ndx');
  
  
And indexes must be referenced including the extension:
+
Além disso, índices precisam ser chamados com o nome completo (incluindo a exntesão).
  
 
     MyDbf.IndexName := 'custname.ndx';
 
     MyDbf.IndexName := 'custname.ndx';
  
  
Index files are packed separately using:
+
Esses arquivos também são empacotados separadamente, usando:
  
 
     MyDbf.CompactIndexFile('custname.ndx');
 
     MyDbf.CompactIndexFile('custname.ndx');
  
== How to link the TDbf to data-aware components ==
+
== Como ligar a TDbf aos componentes que acessam os dados ==
 +
 
 +
 
 +
Os exemplos abaixo mostram como criar uma nova tabela de banco de dados no código. Usá-la
 +
é ainda mais simples.
 +
 
 +
Esses componentes no Lazarus (como exemplo o controle TDbEdit) se ligam a um componente
 +
TDataSource usando suas propriedades "DataSource" e "DataField". O componente TDataSource
 +
cuida da comunicação entre o motor (engine) do banco de dados e dos componentes acessados.
 +
Uma TDataSource então se liga à TDbf usando sua propriedade "DataSet". A conexão se parece
 +
com isso:
  
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:
 
  
 
  TDbEdit-------
 
  TDbEdit-------
Line 171: Line 188:
  
  
Be sure to set the FilePath (or FilePathFulll), TableLevel, and TableName properties of your TDbf component before calling
+
Certifique-se de configurar as propriedades "caminho do arquivo" (FilePath, ou FilePathFull), o "nível da tabela" (TableLevel) e o "nome da tabela" (TableName)da sua TDbf
 
+
antes de chamá-la.
TDbf.Active := True;
 
  
 +
TDbf.Active := True;
  
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.
+
Há muito mais que pode ser dito sobre programar com bancos de dados no Lazarus, e eu
 +
recomendaria um ou dois bons livros de programação de banco de dados em Delphi, já que
 +
os conceitos por trás disso tudo são os mesmos. Eu constantemente refiro-me à minha cópia
 +
de "Delphi 2 Unleashed" [nome do livro em português] porquê os conceitos e o código
 +
básico não mudam muito há 8 anos.
  
== Packing and rebuilding the tables ==
+
== Empacotando e reconstruindo as tabelas ==
  
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.
+
Quando um campo é apagado, ele não é de fato removido da tabela física. Periodicamente, você
 +
precisa "empacotar" uma tabela para recuperar o espaço perdido. Isso deve ser feito com
 +
o modo exclusivo acionado.
  
 
  MyDbf.Exclusive := True;
 
  MyDbf.Exclusive := True;
 
  MyDbf.Open;
 
  MyDbf.Open;
 
  MyDbf.PackTable;
 
  MyDbf.PackTable;
  // let's also rebuild all the indexes
+
  // vamos reconstruir todos os índices também
 
  MyDbf.RegenerateIndexes;
 
  MyDbf.RegenerateIndexes;
 
  MyDbf.Close;
 
  MyDbf.Close;
 
  MyDbf.Exclusive := False;
 
  MyDbf.Exclusive := False;
  
== Master table relations ==
+
== Relações entre tabelas-mestras ==
 +
 
 +
O verdadeiro poder em programar com banco de dados começa quando você tem tabelas múltiplas
 +
que chamam umas às outras. Enquanto a TDbf ainda não possui integridade referencial, ela
 +
possui uma relação mestre / detalhe entre TDbfs [Última frase confusa].
 +
 
 +
Um exemplo disso é quando duas tabelas estão interligadas:
 +
 
 +
[fregueses]
 +
Id      <----| Número de identidade
 +
Name          | Nome
 +
Phone        | Telefone
 +
Address      | Endereço
 +
              | 
 +
[lista de    | O número do freguês em listas de compras ("CustID") faz
 +
  compras ]    | referência a um campo primário de freguês
 +
Id            | Identidade
 +
Amount        | Quantidade
 +
CustID  -----| [Identidade do freguês?] * Esse último campo é indexado como "idxcustid"
 +
 
 +
Se você quisesse mostrar todas as listas de compras para um determinado freguês, a tabela
 +
em detalhe (invoices) poderia ficar em sincronia com a tabela-mestra de fregueses
 +
(customers) automaticamente.
 +
 
 +
Nos componentes de listas de compras TDbf, coloque os seguintes valores:
 +
 
 +
InvDbf.IndexName := 'idxcustid'; // Nosso campo que servirá para pesquisar a tabela
 +
                                  // de identidade dos fregueses.
 +
 
 +
InvDbf.MasterSource := dsCustomers; // Base de dados ligada aos fregueses em TDbf.
 +
InvDbf.MasterFields := 'Id'; // Campo na tabela dos fregueses que nós usaremos para
 +
                              // pesquisar no índice.
 +
 
 +
 
 +
== Como Filtar Datas em Branco com TDbf ==
 +
 
 +
Eu estarei mostrando aqui como podemos filtrar as datas em branco com o componente Lazarus TDbf.
 +
 
 +
Considere-se que, neste exemplo, o componente TDbf é chamado de dados e seu banco de dados tem um campo DT_ENCERRA que indica quando o caso foi concluído.  Imagine também que você precisa para criar um relatório usando LazReport que lista todos os casos que ainda estão em aberto (com o campo DT_ENCERRA) em branco.
 +
 
 +
A maneira mais fácil de fazer isso é usando o evento OnFilterRecord colocando o seguinte código:
 +
 
 +
if not dadosab.FieldByName('DT_ENCERRA').IsNull then Accept := False;
 +
 
 +
 
 +
Quando colocamos o valor do Accept como Falso todos os registros que não satisfaçam essa condição em particular são desconsiderados, ou seja, não são exibidos no relatório.
 +
 
 +
Também é necessário colocar o banco de dados de propriedade Filtered para true, mas fora desse evento.
 +
 
 +
 
 +
== Como Filtrar Valores com TDbf ==
 +
 
 +
Imagine que você tem um banco de dados que identifique os produtos por um código, por exemplo: B019 e que você precisa filtrar apenas os produtos que são deste código (B019, neste exemplo) para que seja gerado um relatório com LazReport. O componente TDbf é chamado de dados aqui. O campo que armazena o valor chama-se "ID_PRODUTO"
 +
 
 +
Temos duas formas de filtrar. A primeira delas seria usar o seguinte código:
 +
 
 +
dados.filter := 'ID_PRODUTO' = "B019"'
 +
dados.filtered := true;
 +
 
 +
Acontece que isso funciona muito bem com vários componentes, mas não funciona com o LazReport.
  
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.
+
Para resolver o problema com o LazReport você pode usar o Evento OnFilterRecord e usar o seguinte código:
  
When there are two tables related, for instance:
+
Accept := Copy(Trim(dadosNot.FieldByName('ID_PRODUTO').AsString),1,4) = 'B019';
  
[customers]
+
É necessário, colcoar-se dados.filtered como true, fora do referido evento.
Id      <----|
 
Name          |
 
Phone        |
 
Address      |
 
              |  The CustID in invoices references a customer primary  field
 
[invoices]    |
 
Id            |
 
Amount        |
 
CustID  -----|  * This field indexed as "idxcustid"
 
  
 +
Como dito antes, quando o valor de Accept é false os registros são desconsiderados e desta forma é possível exibir-se todos os produtos com o referido código no relatório do LazReport.
  
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:
+
== Amostra de aplicativo - Navegador que utiliza um banco de dados ==
  
InvDbf.IndexName := 'idxcustid'; // our field that will match the customers table ID
+
Escrevi um aplicativo bem simples que usará a TDbf para abrir e mostrar tabelas de bancos
InvDbf.MasterSource := dsCustomers; // datasource that is linked to the customers TDbf
+
de dados usando o controle dbGrid. O executável Linux, junto com o código-fonte dos projetos
InvDbf.MasterFields := 'Id'; // field on the customers table we are matching against our index
+
que provavelmente compilarão bem no Windows estão disponíveis em:  
  
 +
[http://tony.maro.net/mod.php?mod=downloads&op=showcat&id=3&level=1 tony.maro.net]
  
== Sample application - DB Browser ==
+
== Coisas em que você precisa estar atento ==
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:  [http://tony.maro.net/mod.php?mod=downloads&op=showcat&id=3&level=1 tony.maro.net]
 
  
== Things you need to be aware of ==
+
Atualmente não há suporte para integridade referencial ou arquivos .dbf internamente codificados.
  
Currently there is no support for referential integrity, or internally encrypted .dbf files.
+
== See also ==
 +
*[[Example: TDbf (creating table and indexes, selecting of index)]]

Latest revision as of 22:36, 23 January 2016

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

Visão Geral

Este tutorial é sobre o desenvolvimento básico de banco de dados usando o componente TDbf (de Micha Nelissen) no Lazarus. Doumentação adicional para o TDbf está disponível. Esta página foi criada por Tony Maro, mas outros contribuidores são bem-vindos!

Para a documentação em PDF vá ao SourceForge. Isto pode ser útil para manter esse PDF ao lado desta documentação enquanto a lê.

Do que você vai precisar

Sem dúvida logo vai ser mais fácil quando o Free Pascal publicar a próxima versão 2.0, no entanto atualmente você vai precisar de uma edição CVS recente do FPC 1.9.x para usar adequadamente o componente TDbf. Isto pode ser feito baixando só o componente TDbf e usando-o com a versão 1.1 do Free Pascal, mas esta documentação foi escrita com a versão 1.9.x em mente, parcialmente por causa dos reparos no código, para que os componentes de banco de dados pudessem ser usados no Lazarus.

O pacote DbfLaz (versão 0.9.13) é agora instalado por padrão.

O que a TDbf fornece

A TDbf fornece acesso às tabelas de banco de dados do dBase e do FoxPro para Lazarus (e outros). Isto permite ler, escrever e criar tabelas de dBase III+, dBase IIV, Visual dBase VII e FoxPro. Ela faz tudo isso sem precisar de bibliotecas adicionais ou engines de bancos de dados. Simplesmente coloque-a no seu formulário e você vai ter acesso instantâneo a um ambiente de banco de dados multiplataforma. A TDbf funciona em Windows e Linux usando o Lazarus.

Como criar tabelas de banco de dados

Como não existe uma aplicação "Database Desktop" para Lazarus ainda, nós precisamos criar um novo banco de dados por código.

Configurando o caminho

É uma boa idéia dar ao banco de dados da sua aplicação um diretório próprio. Isto simplifica a feitura de backups dos dados. Existem duas maneiras de configurar o caminho. Você pode configurar o caminho completo usando a propriedade FilePathFull ou pode configurar um caminho relativo ao caminho atual da aplicação com FilePath. Por exemplo, configurar FilePath em tempo de execução como "data/" usaria um subdiretório de dados bem abaixo do executável. Configurar a propriedade FilePathFull como "/var/data/" colocaria tudo nesta pasta, ignorando a localização da aplicação.

Escolhendo um nível de tabela ("TableLevel")

Por padrão, a TDbf criará tabelas dBase IV. Enquanto garante compatibilidade muito grande com os outros níveis de tabela, existem características que você pode querer usar que esse nível não possui. Para utilizar campos auto-incrementados, por exemplo, você precisa de um nível de tabela maior. Eles estão listados abaixo:

  • nível 3 - dBase III+;
  • nível 4 - dBase IV;
  • nível 7 - Visual dBase VII;
  • nível 25 - FoxPro.

Você escolhe o tipo de tabela configurando a propriedade nível de tabela ("TableLevel") adequadamente.

Adicionando campos

Criar campos para a sua nova tabela em tempo de execução segue bastante o antigo padrão do Delphi. Uma vez que você tenha configurado as propriedades caminho de arquivo ("FilePath"), nível de tabela ("TableLevel") e nome de tabela "(TableName"), manipule a propriedade definição de campos ("FieldDefs") para configurar a estrutura. Por exemplo:

MyDbf.FilePathFull := '/lugar/em que/meus arquivos/estão';
MyDbf.TableLevel := 7;
MyDbf.TableName := 'customers.dbf'; // observação: a extensão .dbf é realmente necessária?
With MyDbf.FieldDefs do begin
  Add('Id', ftAutoInc, 0, True);
  Add('Name', ftString, 80, True);
End;

Os tipos de campo estão definidos como:

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

Os tipos em negrito são os que estão implementados atualmente.

Vá em frente e crie-o!

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

   MyDbf.CreateTable;

Como adicionar índices a uma tabela

Se sua base de dados for maior do que alguns registros, você deverá ter índices definidos para fazer procuras mais rapidamente. Para mudar a estrutura do índice de uma tabela, precisamos ter o acesso exclusivo à tabela - que nós teríamos ao criar de qualquer maneira.

       MyDbf.Exclusive := True;
       MyDbf.Open;

Agora, nos só temos que adicionar o indice.

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

Junte tudo e o resultado é...

O fragmento de código a seguir cria uma nova tabela chamada "customers" (clientes) no código. Isso, é claro, precisa ser feito somente uma vez, e depois que você abre uma tabela não precisa criá-la novamente. ;-)

Observação: crie o diretório relativo "data" antes de rodar este exemplo, ou a execução falhará.

{$MODE OBJFPC}
Program DatabaseTest;   
{ Precisaremos que as seguintes unidades estejam na cláusula USES: }
uses Dbf, db, Dbf_Common;                                   
{ A uniadde Dbf é colocada ali quando você põe a TBDF em um formulário. }
{ No entanto, você precisará do banco de dados para o objeto DataSet e de Dbf_Common }
{ para coisas como as definições de campo. }
var
  MyDbf: TDbf;
begin
  MyDbf := TDbf.Create(nil);
  try
    { use o caminho relativo para o diretório "data }
    MyDbf.FilePath := 'data/'; 
    { queremos utilizar tabelas compatíveis com Visual dBase VII }
    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;

Arquivos de índice externos

A TDbf também possibilita o armazenamento de índices secundários em um arquivo separado. Isso pode ser útil caso se espere que o banco de dados seja grande. Índices secundários são muito similares aos índices normais, com a adição da extensão de arquivos '.ndx'.

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


O índice precisa ser recarregado todas as vezes que a TDdf é aberta.

    MyDbf.OpenIndexFile('custname.ndx');


Além disso, índices precisam ser chamados com o nome completo (incluindo a exntesão).

    MyDbf.IndexName := 'custname.ndx';


Esses arquivos também são empacotados separadamente, usando:

    MyDbf.CompactIndexFile('custname.ndx');

Como ligar a TDbf aos componentes que acessam os dados

Os exemplos abaixo mostram como criar uma nova tabela de banco de dados no código. Usá-la é ainda mais simples.

Esses componentes no Lazarus (como exemplo o controle TDbEdit) se ligam a um componente TDataSource usando suas propriedades "DataSource" e "DataField". O componente TDataSource cuida da comunicação entre o motor (engine) do banco de dados e dos componentes acessados. Uma TDataSource então se liga à TDbf usando sua propriedade "DataSet". A conexão se parece com isso:


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


Certifique-se de configurar as propriedades "caminho do arquivo" (FilePath, ou FilePathFull), o "nível da tabela" (TableLevel) e o "nome da tabela" (TableName)da sua TDbf antes de chamá-la.

TDbf.Active := True;

Há muito mais que pode ser dito sobre programar com bancos de dados no Lazarus, e eu recomendaria um ou dois bons livros de programação de banco de dados em Delphi, já que os conceitos por trás disso tudo são os mesmos. Eu constantemente refiro-me à minha cópia de "Delphi 2 Unleashed" [nome do livro em português] porquê os conceitos e o código básico não mudam muito há 8 anos.

Empacotando e reconstruindo as tabelas

Quando um campo é apagado, ele não é de fato removido da tabela física. Periodicamente, você precisa "empacotar" uma tabela para recuperar o espaço perdido. Isso deve ser feito com o modo exclusivo acionado.

MyDbf.Exclusive := True;
MyDbf.Open;
MyDbf.PackTable;
// vamos reconstruir todos os índices também
MyDbf.RegenerateIndexes;
MyDbf.Close;
MyDbf.Exclusive := False;

Relações entre tabelas-mestras

O verdadeiro poder em programar com banco de dados começa quando você tem tabelas múltiplas que chamam umas às outras. Enquanto a TDbf ainda não possui integridade referencial, ela possui uma relação mestre / detalhe entre TDbfs [Última frase confusa].

Um exemplo disso é quando duas tabelas estão interligadas:

[fregueses]
Id       <----| Número de identidade
Name          | Nome
Phone         | Telefone
Address       | Endereço
              |  
[lista de     | O número do freguês em listas de compras ("CustID") faz 
 compras ]    | referência a um campo primário de freguês
Id            | Identidade
Amount        | Quantidade
CustID   -----| [Identidade do freguês?] * Esse último campo é indexado como "idxcustid" 

Se você quisesse mostrar todas as listas de compras para um determinado freguês, a tabela em detalhe (invoices) poderia ficar em sincronia com a tabela-mestra de fregueses (customers) automaticamente.

Nos componentes de listas de compras TDbf, coloque os seguintes valores:

InvDbf.IndexName := 'idxcustid'; // Nosso campo que servirá para pesquisar a tabela
                                 // de identidade dos fregueses.
InvDbf.MasterSource := dsCustomers; // Base de dados ligada aos fregueses em TDbf.
InvDbf.MasterFields := 'Id'; // Campo na tabela dos fregueses que nós usaremos para 
                             // pesquisar no índice.


Como Filtar Datas em Branco com TDbf

Eu estarei mostrando aqui como podemos filtrar as datas em branco com o componente Lazarus TDbf.

Considere-se que, neste exemplo, o componente TDbf é chamado de dados e seu banco de dados tem um campo DT_ENCERRA que indica quando o caso foi concluído. Imagine também que você precisa para criar um relatório usando LazReport que lista todos os casos que ainda estão em aberto (com o campo DT_ENCERRA) em branco.

A maneira mais fácil de fazer isso é usando o evento OnFilterRecord colocando o seguinte código:

if not dadosab.FieldByName('DT_ENCERRA').IsNull then Accept := False;


Quando colocamos o valor do Accept como Falso todos os registros que não satisfaçam essa condição em particular são desconsiderados, ou seja, não são exibidos no relatório.

Também é necessário colocar o banco de dados de propriedade Filtered para true, mas fora desse evento.


Como Filtrar Valores com TDbf

Imagine que você tem um banco de dados que identifique os produtos por um código, por exemplo: B019 e que você precisa filtrar apenas os produtos que são deste código (B019, neste exemplo) para que seja gerado um relatório com LazReport. O componente TDbf é chamado de dados aqui. O campo que armazena o valor chama-se "ID_PRODUTO"

Temos duas formas de filtrar. A primeira delas seria usar o seguinte código:

dados.filter := 'ID_PRODUTO' = "B019"' dados.filtered := true;

Acontece que isso funciona muito bem com vários componentes, mas não funciona com o LazReport.

Para resolver o problema com o LazReport você pode usar o Evento OnFilterRecord e usar o seguinte código:

Accept := Copy(Trim(dadosNot.FieldByName('ID_PRODUTO').AsString),1,4) = 'B019';

É necessário, colcoar-se dados.filtered como true, fora do referido evento.

Como dito antes, quando o valor de Accept é false os registros são desconsiderados e desta forma é possível exibir-se todos os produtos com o referido código no relatório do LazReport.


Amostra de aplicativo - Navegador que utiliza um banco de dados

Escrevi um aplicativo bem simples que usará a TDbf para abrir e mostrar tabelas de bancos de dados usando o controle dbGrid. O executável Linux, junto com o código-fonte dos projetos que provavelmente compilarão bem no Windows estão disponíveis em:

tony.maro.net

Coisas em que você precisa estar atento

Atualmente não há suporte para integridade referencial ou arquivos .dbf internamente codificados.

See also