Lazarus - Acessando banco de dados com SQLdb

Propaganda
Lazarus - Acessando banco de dados com SQLdb - Parte I
Para fazer nossa primeira aplicação usando banco de dados no Lazarus vamos
usar o SQLite e o conjunto de componentes nativo SQLdb. Inicialmente vamos
apresentar passo como essa aplicação foi criada. Essa foi a maneira que eu fiz, e
eu agradeço sugestões e questionamentos que pessoas que já passaram por essa
experiência. Depois irei fazer algumas considerações sobre o uso do SQLdb.
SQLite
SQLite é uma biblioteca que implementa um motor de banco de dados SQL. É livre
para qualquer finalidade, seja uso particular ou comercial. Lê e escreve em um
único arquivo que pode ter além de tabelas, índices, gatilhos e visões. Executa em
várias plataformas e é indicado para aplicações embarcadas. Maiores detalhes
podem ser encontrados no site oficial. Para usá-lo, baixe-o do site e faça a
instalação adequada para o seu sistema operacional. No Windows isso é muito
simples, apenas copie sqlite3.dll para o system32 da pasta do sistema operacional.
Existe uma ferramenta de linha de comando chamada sqlite3 que podemos usar
para criar o banco de dados e as tabelas. Pode ser baixada no próprio site oficial
do SQLite. Depois de instaladas a dll e a ferramenta de criação do banco executea digitando o seguinte comando no console do sistema operacional:
sqlite3 banco.db
Se o banco já existir ele será aberto para operações como criar/alterar tabelas e
consultar/inserir/atualizar/deletar dados nas tabelas existentes. Depois disso digite
os comandos SQL para a criação de duas tabelas necessárias para nossa
aplicação:
create table cidade (id_cidade integer primary key, nome varchar(30));
create table cliente (id_cliente integer primary key, nome varchar(40), endereco
varchar(40), id_cidade integer, telefone varchar(14), tipo char(1), status boolean);
Feito isso digite .quit para sair e voltemos ao nosso IDE.
SQLdb
Esse é o pacote para acessar bancos de dados no Lazarus. Você o encontra na
aba SQLdb. Algumas informações estão em
http://wiki.freepascal.org/SQLdb_Package. Com esse pacote podemos conectar ao
PostgreSQL, Oracle, MySQL, Firebird, SQLite e ODBC. Para cada um desses
existe um componente TXXXConnection. Para conectar ao Firebird, por exemplo,
existe o componente TIBConnection. Para executar as operações sobre tabelas
temos o TSQLQuery e o TSQLTransaction. A seguir iremos criar a aplicação e
mostraremos como utilizar esses componentes.
A aplicação exemplo
Vamos então iniciar o Lazarus e criar uma nova aplicação. No primeiro form crie
um menu com a seguinte estrutura. Se for necessário leia o artigo sobre criação de
menus em
Arquivo
Sair
Cadastros
Cidade
Cliente
Consultas
Cidade
Cliente
Mude a propriedade Name desse form para frmPrincipal. Mande salvar tudo.
Escolha u_principal para nome da unit e Clientes para nome do projeto.
É fortemente aconselhado que os componentes de conexão e acesso ao banco de
dados estejam agrupados em um repositório denominado DataModule. Para criar
um DataModule no Lazarus selecione o menu Arquivo -> Novo. Selecione Data
Module abaixo do grupo Módulo e pressione o botão OK. Mude a propriedade
Name para dmDados, mande salvar e dê o nome u_dmdados para esta unit.
Agora selecione a aba de componentes SQLdb e coloque um TSQLite3Connection
no DataModule. Na propriedade DatabaseName informe o nome do arquivo do
banco de dados com o caminho. Mude a propriedade Name para dbCliente. Neste
momento podemos mudar a propriedade Connected para True. Se nenhum erro
acontecer o componente de conexão está corretamente configurado. Volte a
propriedade Connected para False. Coloque um componente TSQLTransaction no
DataModule. Na propriedade Database selecione dbCliente e em Name digite
trGeral. Retorne ao SQLite3Connection e selecione trGeral na propriedade
Transaction. TSQLTransaction é o componente que controla as transações no
banco de dados. Em um banco de dados as operações ocorrem no contexto de
uma transação. Uma transação finaliza com sucesso através de um COMMIT e
ROLLBACK desfaz as operações realizadas anteriormente.
Selecione um TSQLQuery e coloque no DataModule. Na propriedade Database
selecione dbCliente. Na propriedade Name digite queCidade e em SQL informe
select * from cidade. Na propriedade Transaction defina trGeral. Agora localize a
aba Data Access. Selecione um componente TDataSource e coloque no
DataModule. Defina Name como dsCidade e em DataSet selecione queCidade.
Resumindo, fizemos a conexão com o banco de dados usando
SQLite3Connection, em seguida definimos um componente para controlar as
transações, definimos uma conexão com uma tabela do banco usando
TSQLQuery, e criamos uma ligação entre a tabela e os componentes que terão a
função de ler os campos dessa tabela usando TDataSource. Esse é um
procedimento repetitivo para novas tabelas nessa aplicação e mesmo quando
usarmos outros conjuntos de componentes. O DataModule terá essa aparência, já
com os componentes para acesso à tabela Cliente.
Repita os mesmos passos para a tabela Cliente, inserindo mais um TSQLQuery e
um TDataSource. Selecione o form principal e, no editor de código, digite abaixo
de Implementation:
uses u_dmdados;
Localize o evento OnShow na aba Eventos do Inspetor de objetos. Dê um duplo
clique à direita e digite:
dmDados.dbCliente.Open;
Assim, sempre que o programa for iniciado a conexão com o banco de dados será
aberta.
Form de Cidade
Insira um novo form na aplicação. Ele será desenhado para fazer as atualizações
na tabela Cidade. Defina o Name do form como frmCidade e o Caption como
Cidades. Salve a unit e defina seu nome como u_cidade. O desenho deste form
deve ter a seguinte aparência.
Antes de começar a desenhar a janela, acesse o código da unit e insira o seguinte
código abaixo de Implementation:
uses u_dmdados;
Isso permite que esta unit acesse os objetos do DataModule.
Pegue um componente TPanel na aba Standard e coloque no form. Defina a
propriedade Align como alTop. Exclua o conteúdo de Caption. As propriedades
BevelInner e BevelOuter são usadas para definir contornos para o painel. Deixe,
por exemplo, como bvLowered e bvRaised respectivamente.
Agora selecione um TDBNavigator na aba Data Controls e o coloque no form sobre
o painel. Na propriedade DataSource do navegador selecione dsCidade.
Dessa mesma aba selecione TDBEdit e coloque dois deles no form. No primeiro
defina Name como edIdCidade, em DataSource selecione dsCidade e em
DataField digite ID_CIDADE. Essa última atribuição irá provocar um erro, mas isso
não vai interferir no resultado. No segundo TDBEdit defina Name como edNome,
DataSource como dsCidade e em DataField digite NOME. Selecione TLabel na
aba Standard e coloque um à esquerda de cada TDBEdit para identificá-los. Defina
suas propriedades Caption como ID e Nome, respectivamente. Para finalizar o
desenho coloque um TSpeedButton da aba Additional sobre o painel. Defina Name
como btnSair e escolha um ícone apropriado para ele usando a propriedade Glyph.
No evento OnClick deste botão digite:
Close;
É necessário programar a abertura e o fechamento da Query no form. A abertura
será programada no evento OnShow e o fechamento será programado no evento
OnClose, ambos de form. Com o form selecionado selecione da aba Eventos no
Inspetor de Objetos. Localize o evento OnShow, dê um duplo clique na caixa à
direita e digite o seguinte:
dmDados.queCidade.Open;
Faça o mesmo para o evento OnClose e digite:
dmDados.queCidade.Close;
Agora precisamos programar a chamada do form frmCidade a partir no form
principal. Selecione o form principal, mude para o editor de código e digite abaixo
de Implementation:
uses u_cidade;
Volte para o form e clique no menu Cadastros -> Cidades. No editor de código
digite:
frmCidade.Show;
Se você compilar e executar o programa verificará que não consegue ainda inserir
dados na tabela Cidade. Todos os dados que são inseridos ficam em cache. É
necessário enviar os dados para o banco e finalizar a transação.
Isso será feito no evento AfterPost da Query. Este evento ocorre após um registro
ser gravado no banco. Selecione o DataModule e em seguida queCidade. Clique
na aba Eventos do Inspetor de Objetos. Localize o evento AfterPost, dê um duplo
clique à direita dele e digite o seguinte:
Vamos esclarecer o código:
linha 42 - declara um TBookMark, que é um ponteiro para um registro.
linha 45 - try, juntamente com except consiste em um tratamento de exceção. Se
algo falhar no bloco try, o código em except é executado.
linha 46 - guarda o ponteiro do registro atual.
linha 47 - envia para o banco de dados o que estiver no cache.
linha 48 - verifica se existe uma transação ativa.
linha 50 - executa um COMMIT no banco, mas mantém a transação aberta.
linha 51 - desvia para o ponteiro salvo na linha 46.
linha 54 - executa um ROLLBACK se algo sair errado no bloco try.
Localize o evento AfterDelete da Query. Clique no botão da caixa à direita para
selecionar um método existente. Selecione queCidadeAfterPost. Assim
reaproveitamos o código que executa a mesma operação necessária no
AfterDelete.
Compile e execute o programa. No post seguinte daremos seguimento ao
desenvolvimento dessa aplicação.
Lazarus - Acessando banco de dados com SQLdb - Parte II
Form de Cliente
No DataModule já deve ter uma TSQLQuery e um TDataSource devidamente
configurados para acesso à tabela Cliente. Vamos então inserir um novo form no
programa definindo Name como frmCliente, Caption como Clientes. Mande salvar
e informe u_cliente no nome da unit. Acesse o editor de código referente a esse
form e abaixo de Implementation, para permitir que a unit u_cliente tenha acesso
aos objetos do DataModule, digite:
uses u_dmdados;
Volte ao form e inclua um TPanel da mesma forma que foi feito para o form de
Cidade. Selecione um TDBNavigator da aba Data Controls e coloque sobre o
painel. Defina a propriedade DataSource como dsCliente. Insira um TSpeedButton
da aba Additional no painel e o configure semelhante ao que fizemos no form de
Cidade, inclusive definindo o código do evento OnClick para fechar o form. O form
de Cliente deverá ter essa aparência:
Coloque dois TDBedit no form, o primeiro deve ter Name definido como
edIdCliente, DataSource como dsCliente e DataField como ID_CLIENTE. No
segundo defina Name como edNome, DataSource como dsCliente e DataField
como NOME. Coloque dois TLabel para identificar esse campos e defina os
Caption de acordo com a figura anterior.
O componente TDBLookupComboBox é usado para que, no caso de uma chave
estrangeira (ID_CIDADE na tabela Cliente), o usuário possa escolher o registro na
tabela referenciada (Cidade). Neste componente os dados da tabela referenciada
são mostrados em uma lista. Pegue então um componente desses na aba Data
Controls e coloque no form abaixo do segundo TDBEdit. Defina Name como
dblIdCidade, DataSource como dsCliente e DataField como ID_CIDADE. Para
definir a lista primeiramente defina a propriedade ListSource como dsCidade, na
propriedade ListField (campo que será visualizado na lista) defina NOME e
KeyField (campo chave) defina como ID_CIDADE. Existe ainda a propriedade
Sorted que define se a lista estará ordenada e Style que define o comportamento
do controle. Deixe Sorted como True e Style como dsDropDownList (o usuário não
poderá digitar no controle, apenas selecionar da lista). Coloque um TLabel para
identificar este campo.
Coloque mais um TDBEdit abaixo do LookupComboBox. Defina Name como
edTelefone, DataSource como dsCliente e DataField como TELEFONE. Coloque
um TLabel para fazer a identificação do campo.
O campo TIPO da tabela Cliente é usado para informar se o cliente é pessoa física
- representado pela letra F - ou pessoa jurídica - representado pela letra J. Para
este controle vamos usar um TDBRadioGroup, que permite que sejam definidas
opções para serem selecionadas. Pegue um componente desses e o coloque no
form. Defina a propriedade Caption como Tipo e Name como rgTipo. DataSource
será dsCliente e DataField será TIPO. Clique no botão da propriedade Items. Será
aberta uma janela com o editor de strings. Digite Pessoa física na primeira linha e
Pessoa jurídica na segunda e pressione OK. Na propriedade Columns digite 2 para
que as opções apareçam em linha. Clique no botão da propriedade Values - onde
estão os valores correspondentes às opções definidas em Items. Digite F na
primeria linha e J na segunda. Desta forma quando for selecionada a opção
Pessoa física será gravado F no banco de dados, e J caso contrário.
Redimensione o componente adequadamente.
Finalmente coloque um TDBCheckBox no form. Defina Caption como Ativo e
Name como chxStatus. DataSource é definido como dsCliente e em DataField
digite STATUS. As propriedades ValueChecked e ValueUnchecked são usadas
para definir o que será gravado no campo quando o componente estiver marcado
ou não marcado. Como nosso campo no banco de dados é boolean, não é
necessário alterar nada.
Para programar a abertura e o fechamento da Query faça de forma análoga ao que
foi feito no form de Cidade. Escreva os códigos correspondentes nos eventos
OnShow e OnClose de frmCliente.
Mude para o DataModule e selecione queCliente. Selecione a aba Eventos do
Inspetor de objetos e dê um duplo clique ao lado do evento AfterPost. Digite o
código como na figura:
Note que esse código é ligeiramente diferente do que fizemos para queCidade. Em
vez de usarmos CommitRetaining, agora usamos Commit. Commit fecha todas as
tabelas abertas, por isso a Query é aberta na linha 68. Na linha 63 guardamos as
chave primária do registro atual na variável chave. E depois que a Query é aberta,
usamos Locate para localizar o registro correspondente à variável chave. Esta é
outra forma de fazer o COMMIT na transação.
Localize o evento AfterDelete da Query. Clique no botão da caixa à direita para
selecionar um método existente. Selecione queClienteAfterPost para que a
transação seja encerrada da mesma forma quando um registro for excluído.
Agora vamos ao form principal. Na linha uses abaixo de Implementation
acrescente u_cliente para que ela fique assim:
uses u_cidade, u_cliente;
Clique no menu Cadastros -> Clientes e no código do evento OnClick digite:
frmCliente.Show;
Execute o programa e chame o form de Cliente para fazer os testes.
Consultas
O próximo passo do desenvolvimento será criar as telas de consulta às tabelas
Cidade e Cliente. Neste artigo mostraremos a criação da consulta de cidades.
Supomos que a consulta de clientes é análoga e não haverá dificuldade em criá-la.
Para iniciar vamos ao DataModule inserir dois componentes necessários: um
TSQLQuery e um TDataSource. Na Query mude Name para queConsCidade. Na
propriedade Database selecione dbCliente. Certifique-se que a propriedade
Transaction está corretamente definida como trGeral. No TDataSource mude
Name para dsConsCidade e DataSet para queConsCidade.
Uma interface de consulta é necessária, portanto deve-se inserir um novo form.
Defina Name como frmConsCidade e Caption como Consulta de cidades. Salve e
digite u_conscidade no nome da unit.
A consulta irá oferecer duas opções de consulta - pela chave primária ou por parte
do nome. Então insira um TRadioGroup da aba Standard. Defina Caption como
Campo. Na propriedade Items inclua as linhas Código e Nome. Na propriedade
Name digite rgCampo. Redimensione o componente adequadamente.
Observe a figura acima para orientar o seu desenho. Inclua um TEdit da aba
Standard. Defina Name como edDado e delete o conteúdo da propriedade Text.
Coloque um TLabel para identificar o campo. Defina Caption como Dado a
consultar.
Insira um TButton. Defina Name btnConsultar. Localize o componente TDBGrid na
aba Data Controls. Insira um no form. Defina sua propriedade Name com
dbgDados. Abra o editor de código e digite abaixo de Implementation:
uses u_dmdados;
Volte ao form e na propriedade DataSource da TDBGrid selecione dsConsCidade.
Dê um duplo clique no botão btnConsultar e digite o código:
Analisando o código:
linha 39 - define que propriedades e métodos sem referência a um objeto são
considerados como sendo de queConsCidade.
linha 41 - fecha a Query.
linha 42 - limpa o conteúdo da propriedade SQL.
linha 43 - verifica que campo foi selecionado no RadioGroup.
linhas 45 e 46 - definem um comando SELECT para buscar linhas na tabela pela
chave primária. pIdCidade é um parâmetro definido na linha 46.
linhas 50 e 51 - definem um comando SELECT para buscar linhas na tabela por
parte do nome da cidade.
linha 53 - abre a Query.
Mude para o form principal. No editor de código inclua a unit u_conscidade na linha
uses abaixo de Implementation. Clique na opção Consultas -> Cidades. Digite o
código:
frmConsCidade.Show;
Execute o programa e faça testes de consulta. Falta validar edDado para que
aceite apenas dígitos numéricos quando a consulta for direcionada para o campo
chave. Deixamos essa tarefa e a criação da consulta de clientes como um
exercício.
Baixe aqui o código completo do programa.
Algumas considerações
Durante a criação dessa pequena aplicação encontramos dificuldade em achar
relatos de experiências usando os componentes SQLdb. Já utilizamos outros
componentes tanto em Lazarus quando no Delphi e sentimos algumas dificuldades
principalmente no que diz respeito ao controle de transações. SQLdb só permite
um objeto SQLTransaction na aplicação. Isso torna-se um obstáculo quando é
necessário abrir mais de um form simultaneamente, pois quando fechamos uma
transação todas as tabelas são fechadas. Outra dificuldade refere-se ao ponteiro
TBookmark. Antes de encerrar uma transação guardamos o ponteiro do registro
atual. Após encerrar a transação, quando o método GotoBookmark() é chamado
para posicionar o registro no ponteiro salvo anteriormente ocorre uma exceção.
Vale observar que chamar o GotoBookmark() antes de encerrar a transação
funciona normalmente. Por esses motivos nos próximos artigos usaremos os
componentes ZeosLib.
Download