Sign in Join
Wiki copytemporary

Lazarus Tdbf Tutorial/pt: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11## Visão Geral
22
33Este tutorial é sobre o desenvolvimento básico de banco de dados usando o componente [TDbf](https://tdbf.sf.net) (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!
44
55Para a documentação em PDF vá ao [SourceForge](https://sourceforge.net/project/showfiles.php?group_id=34085&package_id=26371). Isto pode ser útil para manter esse PDF ao lado desta documentação enquanto a lê.
66
77### Do que você vai precisar
88
99Sem 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.
1010
1111O pacote DbfLaz (versão 0.9.13) é agora instalado por padrão.
1212
1313### O que a TDbf fornece
1414
1515A 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.
1616
1717## Como criar tabelas de banco de dados
1818
1919Como não existe uma aplicação "Database Desktop" para Lazarus ainda, nós precisamos criar um novo banco de dados por código.
2020
2121### Configurando o caminho
2222
2323É 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.
2424
2525### Escolhendo um nível de tabela ("TableLevel")
2626
2727Por 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:
2828
2929- nível 3 - dBase III+;
3030- nível 4 - dBase IV;
3131- nível 7 - Visual dBase VII;
3232- nível 25 - FoxPro.
3333
3434Você escolhe o tipo de tabela configurando a propriedade nível de tabela ("TableLevel") adequadamente.
3535
3636### Adicionando campos
3737
3838Criar 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:
3939
40-`MyDbf.FilePathFull := '/lugar/em que/meus arquivos/estão';`\
41-`MyDbf.TableLevel := 7;`\
42-`MyDbf.TableName := 'customers.dbf'; // observação: a extensão .dbf é realmente necessária?`\
43-`With MyDbf.FieldDefs do begin`\
44-`  Add('Id', ftAutoInc, 0, True);`\
45-`  Add('Name', ftString, 80, True);`\
46-`End;`
40+``` pascal
41+MyDbf.FilePathFull := '/lugar/em que/meus arquivos/estão';
42+MyDbf.TableLevel := 7;
43+MyDbf.TableName := 'customers.dbf'; // observação: a extensão .dbf é realmente necessária?
44+With MyDbf.FieldDefs do begin
45+ Add('Id', ftAutoInc, 0, True);
46+ Add('Name', ftString, 80, True);
47+End;
48+```
4749
4850Os tipos de campo estão definidos como:
4951
5052- ftUnknown
5153- **ftString**
5254- **ftSmallInt**
5355- **ftInteger**
5456- **ftWord**
5557- **ftBoolean**
5658- **ftFloat**
5759- **ftCurrency** (Nível de tabela 25)
5860- **ftBCD** (Nível de tabela 25)
5961- **ftDate**
6062- ftTime
6163- **ftDateTime**
6264- **ftBytes** (Nível de tabela 25)
6365- ftVarBytes
6466- **ftAutoInc** (Nível de tabela 7 ou 25)
6567- **ftBlob**
6668- **ftMemo**
6769- ftGraphic
6870- ftFmtMemo
6971- ftParadoxOle
7072- **ftDBaseOle**
7173- ftTypedBinary
7274- ftCursor
7375- **ftFixedChar**
7476- **ftWideString**
7577- **ftLargeInt**
7678- ftADT
7779- ftArray
7880- ftReference
7981- ftDataSet
8082- ftOraBlob
8183- ftOraClob
8284- ftVariant
8385- ftInterface
8486- ftIDispatch
8587- ftGuid
8688- ftTimeStamp
8789- ftFMTBcd
8890
8991Os tipos em negrito são os que estão implementados atualmente.
9092
9193### Vá em frente e crie-o!
9294
9395Once you have defined the fields you wish to use in your new table, you can go ahead and create it with:
9496
95-`   MyDbf.CreateTable;`
97+```text
98+ MyDbf.CreateTable;
99+```
96100
97101## Como adicionar índices a uma tabela
98102
99103Se 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.
100104
101-`       MyDbf.Exclusive := True;`\
102-`       MyDbf.Open;`
105+``` pascal
106+ MyDbf.Exclusive := True;
107+ MyDbf.Open;
108+```
103109
104110Agora, nos só temos que adicionar o indice.
105111
106-`       MyDbf.AddIndex('custid', 'Id', [ixPrimary, ixUnique]);`\
107-`       MyDbf.AddIndex('custname','Name', [ixCaseInsensitive]);`\
108-`       MyDbf.Close;`
112+```text
113+ MyDbf.AddIndex('custid', 'Id', [ixPrimary, ixUnique]);
114+ MyDbf.AddIndex('custname','Name', [ixCaseInsensitive]);
115+ MyDbf.Close;
116+```
109117
110118## Junte tudo e o resultado é...
111119
112120O 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. ;-)
113121
114122Observação: crie o diretório relativo "data" antes de rodar este exemplo, ou a execução falhará.
115123
116-`{$MODE OBJFPC}`\
117-`Program DatabaseTest;   `\
118-`{ Precisaremos que as seguintes unidades estejam na cláusula USES: }`\
119-`uses Dbf, db, Dbf_Common;                                   `\
120-`{ A uniadde Dbf é colocada ali quando você põe a TBDF em um formulário. }`\
121-`{ No entanto, você precisará do banco de dados para o objeto DataSet e de Dbf_Common }`\
122-`{ para coisas como as definições de campo. }`\
123-`var`\
124-`  MyDbf: TDbf;`\
125-`begin`\
126-`  MyDbf := TDbf.Create(nil);`\
127-`  try`\
128-`    { use o caminho relativo para o diretório "data }`\
129-`    MyDbf.FilePath := 'data/'; `\
130-`    { queremos utilizar tabelas compatíveis com Visual dBase VII }`\
131-`    MyDbf.TableLevel := 7;`\
132-`    MyDbf.Exclusive := True;`\
133-`    MyDbf.TableName := 'customers.dbf';`\
134-`    With MyDbf.FieldDefs do begin`\
135-`      Add('Id', ftAutoInc, 0, True);`\
136-`      Add('Name', ftString, 80, True);`\
137-`    End;`\
138-`    MyDbf.CreateTable;`\
139-`    MyDbf.Open;`\
140-`    MyDbf.AddIndex('custid', 'Id', [ixPrimary, ixUnique]);`\
141-`    { add a secondary index }`\
142-`    MyDbf.AddIndex('custname','Name', [ixCaseInsensitive]);`\
143-`    MyDbf.Close;`\
144-`  finally`\
145-`    MyDbf.Free;`\
146-`  end;`\
147-`end;`
124+``` pascal
125+{$MODE OBJFPC}
126+Program DatabaseTest;
127+{ Precisaremos que as seguintes unidades estejam na cláusula USES: }
128+uses Dbf, db, Dbf_Common;
129+{ A uniadde Dbf é colocada ali quando você põe a TBDF em um formulário. }
130+{ No entanto, você precisará do banco de dados para o objeto DataSet e de Dbf_Common }
131+{ para coisas como as definições de campo. }
132+var
133+ MyDbf: TDbf;
134+begin
135+ MyDbf := TDbf.Create(nil);
136+ try
137+ { use o caminho relativo para o diretório "data }
138+ MyDbf.FilePath := 'data/';
139+ { queremos utilizar tabelas compatíveis com Visual dBase VII }
140+ MyDbf.TableLevel := 7;
141+ MyDbf.Exclusive := True;
142+ MyDbf.TableName := 'customers.dbf';
143+ With MyDbf.FieldDefs do begin
144+ Add('Id', ftAutoInc, 0, True);
145+ Add('Name', ftString, 80, True);
146+ End;
147+ MyDbf.CreateTable;
148+ MyDbf.Open;
149+ MyDbf.AddIndex('custid', 'Id', [ixPrimary, ixUnique]);
150+ { add a secondary index }
151+ MyDbf.AddIndex('custname','Name', [ixCaseInsensitive]);
152+ MyDbf.Close;
153+ finally
154+ MyDbf.Free;
155+ end;
156+end;
157+```
148158
149159## Arquivos de índice externos
150160
151161A 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'.
152162
153-`    MyDbf.AddIndex('custname.ndx','Name', [ixCaseInsensitive]);`
163+```text
164+ MyDbf.AddIndex('custname.ndx','Name', [ixCaseInsensitive]);
165+```
154166
155167O índice precisa ser recarregado todas as vezes que a TDdf é aberta.
156168
157-`    MyDbf.OpenIndexFile('custname.ndx');`
169+```text
170+ MyDbf.OpenIndexFile('custname.ndx');
171+```
158172
159173Além disso, índices precisam ser chamados com o nome completo (incluindo a exntesão).
160174
161-`    MyDbf.IndexName := 'custname.ndx';`
175+``` pascal
176+ MyDbf.IndexName := 'custname.ndx';
177+```
162178
163179Esses arquivos também são empacotados separadamente, usando:
164180
165-`    MyDbf.CompactIndexFile('custname.ndx');`
181+```text
182+ MyDbf.CompactIndexFile('custname.ndx');
183+```
166184
167185## Como ligar a TDbf aos componentes que acessam os dados
168186
169187Os exemplos abaixo mostram como criar uma nova tabela de banco de dados no código. Usá-la é ainda mais simples.
170188
171189Esses 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:
172190
173-`TDbEdit-------`\
174-`             |`\
175-`TDbEdit------|-->TDataSource-->TDbf`\
176-`             |`\
177-`TDbNavigator--`
191+```text
192+TDbEdit-------
193+ |
194+TDbEdit------|-->TDataSource-->TDbf
195+ |
196+TDbNavigator--
197+```
178198
179199Certifique-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.
180200
181201TDbf.Active := True;
182202
183203Há 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.
184204
185205## Empacotando e reconstruindo as tabelas
186206
187207Quando 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.
188208
189-`MyDbf.Exclusive := True;`\
190-`MyDbf.Open;`\
191-`MyDbf.PackTable;`\
192-`// vamos reconstruir todos os índices também`\
193-`MyDbf.RegenerateIndexes;`\
194-`MyDbf.Close;`\
195-`MyDbf.Exclusive := False;`
209+``` pascal
210+MyDbf.Exclusive := True;
211+MyDbf.Open;
212+MyDbf.PackTable;
213+// vamos reconstruir todos os índices também
214+MyDbf.RegenerateIndexes;
215+MyDbf.Close;
216+MyDbf.Exclusive := False;
217+```
196218
197219## Relações entre tabelas-mestras
198220
199221O 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\].
200222
201223Um exemplo disso é quando duas tabelas estão interligadas:
202224
203-`[fregueses]`\
204-`Id       <----| Número de identidade`\
205-`Name          | Nome`\
206-`Phone         | Telefone`\
207-`Address       | Endereço`\
208-`              |  `\
209-`[lista de     | O número do freguês em listas de compras ("CustID") faz `\
210-` compras ]    | referência a um campo primário de freguês`\
211-`Id            | Identidade`\
212-`Amount        | Quantidade`\
213-`CustID   -----| [Identidade do freguês?] * Esse último campo é indexado como "idxcustid" `
225+```text
226+[fregueses]
227+Id <----| Número de identidade
228+Name | Nome
229+Phone | Telefone
230+Address | Endereço
231+ |
232+[lista de | O número do freguês em listas de compras ("CustID") faz
233+ compras ] | referência a um campo primário de freguês
234+Id | Identidade
235+Amount | Quantidade
236+CustID -----| [Identidade do freguês?] * Esse último campo é indexado como "idxcustid"
237+```
214238
215239Se 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.
216240
217241Nos componentes de listas de compras TDbf, coloque os seguintes valores:
218242
219-`InvDbf.IndexName := 'idxcustid'; // Nosso campo que servirá para pesquisar a tabela`\
220-`                                 // de identidade dos fregueses.`
243+``` pascal
244+InvDbf.IndexName := 'idxcustid'; // Nosso campo que servirá para pesquisar a tabela
245+ // de identidade dos fregueses.
246+```
221247
222-`InvDbf.MasterSource := dsCustomers; // Base de dados ligada aos fregueses em TDbf.`\
223-`InvDbf.MasterFields := 'Id'; // Campo na tabela dos fregueses que nós usaremos para `\
224-`                             // pesquisar no índice.`
248+``` pascal
249+InvDbf.MasterSource := dsCustomers; // Base de dados ligada aos fregueses em TDbf.
250+InvDbf.MasterFields := 'Id'; // Campo na tabela dos fregueses que nós usaremos para
251+ // pesquisar no índice.
252+```
225253
226254## Como Filtar Datas em Branco com TDbf
227255
228256Eu estarei mostrando aqui como podemos filtrar as datas em branco com o componente Lazarus TDbf.
229257
230258Considere-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.
231259
232260A maneira mais fácil de fazer isso é usando o evento OnFilterRecord colocando o seguinte código:
233261
234262if not dadosab.FieldByName('DT_ENCERRA').IsNull then Accept := False;
235263
236264Quando 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.
237265
238266Também é necessário colocar o banco de dados de propriedade Filtered para true, mas fora desse evento.
239267
240268## Como Filtrar Valores com TDbf
241269
242270Imagine 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"
243271
244272Temos duas formas de filtrar. A primeira delas seria usar o seguinte código:
245273
246274dados.filter := 'ID_PRODUTO' = "B019"' dados.filtered := true;
247275
248276Acontece que isso funciona muito bem com vários componentes, mas não funciona com o LazReport.
249277
250278Para resolver o problema com o LazReport você pode usar o Evento OnFilterRecord e usar o seguinte código:
251279
252280Accept := Copy(Trim(dadosNot.FieldByName('ID_PRODUTO').AsString),1,4) = 'B019';
253281
254282É necessário, colcoar-se dados.filtered como true, fora do referido evento.
255283
256284Como 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.
257285
258286## Amostra de aplicativo - Navegador que utiliza um banco de dados
259287
260288Escrevi 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:
261289
262290[tony.maro.net](http://tony.maro.net/mod.php?mod=downloads&op=showcat&id=3&level=1)
263291
264292## Coisas em que você precisa estar atento
265293
266294Atualmente não há suporte para integridade referencial ou arquivos .dbf internamente codificados.
267295
268296## See also
269297
270298- [[Example: TDbf (creating table and indexes, selecting of index)]]
271299
272300---
273301*From the Free Pascal wiki, page "Lazarus Tdbf Tutorial/pt", as it stood on 2016-01-23 after a change by FTurtle, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history