Páginas

terça-feira, 23 de fevereiro de 2010

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 execute-a 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 http://professorcarlos.blogspot.com/2010/01/lazarus-criando-menus.html:

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.

41 comentários:

Lucia Terra disse...

Deparei com seu post "Lazarus - Acessando banco de dados com SQLdb Segui todos os passos deste post e consegui compilar e executar o programa. Fiz esta mesma experiencia só ao invés de conectar ao SQlite, usei o Mysql, que tambem funcionou perfeitamente.

Porem estou tendo um problema: o dbnavigator aparece destivado. Sendo assim não consigo inserir nenhum dado no banco. Onde será que estou errando?

BkBrasil disse...

Verifique se o DataSource do dbNavigator está vazio. Se estiver, escolha a tabela na qual ele irá operar.

Anônimo disse...

Ambiente WinXP, Postgres 8.3, MySQl 5, Lazarus 0.9.28.2

Usando Zeos não conseguir conectar com nenhum banco. Nos dois dá erro procurando por DLL, No Mysql pergunta por libmysql51, libmysql50, libmysql, já no PG procura por uma SSLeay32.dll.

Professor Carlos disse...

No post http://professorcarlos.blogspot.com/2010/05/lazarus-conectando-mysql.html tem um link pra baixar as dlls necessárias pro MySql. Para o PG copie a dll que está na pasta bin de instalação do PG para o diretório system. Qualquer dúvida me escreva.

Roberto Dutra disse...

Muito bom seus posts. Já usava o delphi mas agora estou ingressando no lazarus. Estou tendo problemas em compreender. Não sei qual o ambiente para criar o banco de dados. Então criei um pelo Database desktop do delphi (*.db tipo paradox), linkei na aplicação, mas no momento de ativar o qcidade aparede "file is encrypted or is not database". Onde crio o banco de dados com suas tabelas? Somente ler extensão db? E .mdb como me conecto?
Agradeço muito.

Professor Carlos disse...

Roberto

Você está tentanto abrir uma tabela Paradox. O Lazarus só tem componentes para abrir essas tabelas para leitura. Mas você pode usar SQLite, Firebird, PostgreSQL, MS SQL, Oracle e até o Access. Para o Firebird existe a ferramenta IBExpert, para o PostgreSQL existe o pgAdmin, e assim por diante. Mas você precisa ter o SGBD instalado. Acesse o site do SQLite e lá pode baixar a dll e uma ferramenta para criar o banco e as tabelas. Para ver como conectar ao Access leia o post http://professorcarlos.blogspot.com/2010/03/lazarus-conectando-msaccess-com-odbc.html

Pucka disse...

Caro professor Carlos, obrigado por nos brindar com dicas muito interessantes e importantes. Desde há algum tempo estava à procura de um BD leve e finalmente o encontrei no SQLite. Estou fazendo alguns testes juntamente com o Lazarus e estou muito esperançoso de breve poder dominá-los razoavelmente. No momento, deparei-me com um problema crucial na comparação trivial entre strings. Imagine que um campo Edit tenha sido preenchido com um campo da tabela e, em seguida, faça uma comparação entre estes dois campos, ambos do tipo string. O resultado esperado, seria obviamente a igualdade de ambos (pois não sofreram nenhuma alteração). Entretanto, o resultado da comparação indica que os dois campos são diferentes. Será que o senhor poderia me dar uma dica de como devo proceder para obter o resultado esperado ? Detalhe: isso somente ocorre em campos onde contenha acentos, cedilhas ou algum outro sinal diferente de letras e/ou algarismos.
Só fui detectar isso, após vários testes frustrados de SQL que não executava o esperado.
Desde já agradeço a atenção.

Professor Carlos disse...

Mude a propriedade CharSet do SQLite3Connection para utf8. Me dê um retorno se funcionou.

Pucka disse...

Olá professor Carlos,

Infelizmente o SQLiteConnection não consigo utilizar pois faltam os outros componentes para gerenciar a tabela e o SQL. Não consegui encontrá-los na Internet e, acreditando que o que estão no Lazarus fossem funcionais, (imaginei que fossem
como o Lazreport e me dei mal: compilei os lpks e, a partir de então, não consegui mais rodar o Lazarus.
Não teve outro jeito. Tive que becapear o HD e formatá-lo, reinstalar o Windows (XP SP-3) e em
seguida reinstalar o Lazarus.
Depois deste susto, resolvi utilizar o ZEOS. Será que o senhor poderia me ajudar para configurar o ZEOS para esta tarefa ?

Grato pela atenção,
Pucka

Professor Carlos disse...

Veja se consegue fazer seguindo esses passos:
http://professorcarlos.blogspot.com/2010/03/lazarus-conectando-postgresql-com.html

Artur disse...

Olá, professor!

Não consigo encontrar o TSQLite3Conection na aba SQLdb.

O que devo fazer?

Professor Carlos disse...

Oi Artur

Na aba SQLdb, o último componente é o TIBConnection (para Firebird), o penúltimo é o TSQLite3Connection. Ok?
Se não estiver aparecendo você deve ter um problema na instalação do Lazarus. Se você achar que tem mesmo um problema, use a Clean Up + Build All no menu Tools para recompilar o Lazarus.

Anônimo disse...

Segui os passos e quando tento ativar a tabela no DataModule1/SQLite3Connection1 esta dando o seguinte erro

[Window Title]
Erro

[Content]
Can not load SQLite client library "sqlite3.dll". Check your installation.

[OK]

mas a dll ja esta na pasta do sql e na pasta do system 32. Windows 7 64x

Professor Carlos disse...

Copie a dll para a pasta da sua aplicação

Yindi disse...

Olá Professor,

Gostei muito do seu tutorial.

Estou tentando conectar o Lazarus ao Mysql5.1 a versao mais nova, só quando tento conectar e diz que falta uma biblioteca chamada libmysqlclient.so.15.0.0 (uso o linux ubuntu) eu baixei essa biblioteca e coloquei na pasta só que mesmo assim o lazarus nao consegue conectar. Eu nao sei mais o que eu faço, tá dificil de lidar com o Mysql. To até pensando em mudar de banco de dados.

Professor Carlos disse...
Este comentário foi removido pelo autor.
Professor Carlos disse...

Tente copiar a biblioteca para a pasta /lib ou /usr/lib

Professor Carlos disse...

Yindi
Eu baixei esse deb aqui http://automation.binarysage.net/?dl_id=6 e instalei com dpkg -i

Yindi disse...

Olá Professor,

Copiar a dll para a pasta da minha aplicação resolveu meu problema no windows. Obrigada pela ajuda.

O Sr. poderia dar uma dica de como eu uso as TBEdit para armazenar os dados que o usuario inserir neste banco do SQLite?

Professor Carlos disse...

Oi Yindi

Você se refere ao TEdit ou ao TDBEdit? Se for TDBEdit este mesmo post não esclarece sua dúvida? Se for TEdit você pode usar um SQL parametrizado e depois chamar ExecSQL. Por exemplo, se neste post os TDBEdits fossem substituidos por TEdit, então você poderia usar um código assim:
queCidade.SQL.Add('insert into cidade values (id_cidade = :pId, nome = :pNome)');
queCidade.ParamByName('pId').Value := StrToInt(Edit1.Text);
queCidade.ParamByName('pNome').Value := Edit2.Text;
queCidade.ExecSQL;

Yindi disse...

Bom dia professor,

Eu me referia mesmo a uma TDBEdit. Neste caso, para inserção de dados no banco de dados seria mesmo mais aconselhável usar as TEdit mesmo? Neste caso, eu não precisaria usar uma TSQLQuery, certo?

Também estou tendo problemas com a minha TSQLQuery da minha aplicação. Pois, quando vou escolher o DataSource referente a ele dá uma erro assim: "Error. Consulta: Circular DataSource not allowed" . O que poderia estar acontecendo?

Professor Carlos disse...

Pode usar tanto um quanto outro. Em ambos precisa de TSQLQuery.
No caso desse é provável que você esteja definindo algo na propriedade DataSource da TSQLQuery. Isso não deve ser feito. A ligação entre TDataSource e TSQLQuery se dá apenas pela propriedade DataSet de TDataSource.

Yindi disse...

Bom dia prof Carlos,

Neste caso, referente ao codigo q postou para inserir no BD:

queCidade.SQL.Add('insert into cidade values (id_cidade = :pId, nome = :pNome)');
queCidade.ParamByName('pId').Value := StrToInt(Edit1.Text);
queCidade.ParamByName('pNome').Value := Edit2.Text;
queCidade.ExecSQL;

uso o lazarus v0.9.28, tenho q usar a propriedade params, sendo que em queCidade.ParamByName('pId').Value := StrToInt(Edit1.Text); por exemplo, 'pId' é declarado onde? 'pId' é o campo da minha tabela ou apenas um codnome?

Professor Carlos disse...

Bom dia

Observe que no comando SQL tem dois identificadores precedidos por :. Isso são parâmetros que são usados em ParamByName. Mas na versão que você está usando isso não funciona assim. No lugar de ParamByName('pId') digite Params[0] e Params[1] no lugar de ParamByName('pNome')

papa hacker disse...

PROFESSOR EU GOSTEI DO TUTORIAL MA SEU QUERIA TE PEDIR PARA FAZER UM TUTORIAL EM VÍDEO PARA NÓS QUE CURTIMOS O FREE PASCAL SE VC FIZER ME OU SABE DE ALGUM LINK É SÓ ME ADD NO MSN LUCIANOFOREVERMSN@HOTMAIL.COM ABRIGADO.

Professor Carlos disse...

Opa

Prometo que vou fazer os vídeos. Assim que os tiver postado ponho os links aqui no blog. Mas procure no youtube, que alguns colegas postaram alguma coisa.

O pai de João Victor disse...

Professor, boa tarde.

Estou começando o desenvolvimento com lazarus. Coisas pequenas por enquanto. Tenho um projeto pequeno em delphi que eu queria migrar para Lazarus, mas não encontrei componente de conexão ao MSSQ (posso usar o sql server expess 2005 ou 2008) mas teria que ser MSSLQ mesmo não dá pra migrar o banco, por enquanto. Existe alguma forma de conectar ao SQL Server? O Zeos eu tenho, mas não vi opção de acesso ao MSSQL. O Sr. conhece alguma forma? Obrigado pelo seu tempo e parabéns pelo blog.

Professor Carlos disse...

Olá

No pacote SQLdb você pode usar o ODBCConnection, pra fazer a conexão através de driver ODBC. No Zeos, o ZConnection tem a propriedade protocol. Nela você define MSSQL.

João disse...

Boa tarde, como eu faria para criar uma tabela e o seguinte: Criei no form2, um formulário para inserção de dados de alunos, tipo matricula, nome, pai,mãe, etc. So que no Delphi eu tinha a opção Table e paradox, criava uma tabela dentro do proprio Delphi, estou usando o lazarus 0.9.30, ele já vem com sqldb instalado, agora, como criar esse banco de dados, a mascara do form, está criado e agora como inserir esses dados?????

Professor Carlos disse...

Penso que você está se referindo a um assistente que existe no Delphi. Isso não existe no Lazarus. Você precisa criar o banco de dados usando outra ferramenta. Os bancos de dados compatíveis são Firebird, MySQL, SQLite, PostgreSQL e Oracle. Você pode usar a ferramenta que eu descrevo em http://professorcarlos.blogspot.com.br/2011/07/lazarus-o-lazarus-data-desktop.html, mas sempre vai precisar de um SGBD instalado. O único que não precisa é o SQLite.

Nicole Stodulski disse...

Bom Dia Professor,
Gostaria de saber se o senhor já fez conexão do lazarus com o SQL Server?
Grata pela atenção.

Professor Carlos disse...

Já fiz usando o ZeosLib (http://zeos.firmos.at/)

Pucka disse...

Olá Professor, utilizo o Lazarus e o BD SQlite, versão 3.xx. Até alguns dias atrás, trabalhava com o Lazarus 0.9.28.2, o ZEOSDBO 6.6.6 stable e o sqlite3.dll v:3.t7.3 e tudo ia as mil. Agora, atualizei o Lazarus para a v:1.0.4, o ZEOSDBO 7.0.3stable e acontecia um problema durante a compilação. Consegui superar isso. Consigo ler a tabela, mas ao tentar atualizá-lo, simplesmente não está fazendo a gravação (atualizando o registro). A propriedade CachedUpdates do TZQuery está true e o AutoCommit do TZConnection está em false. Onde será que estou falhando ? Será que o senhor poderia me ajudar ? Desde já agradeço a atenção.

Professor Carlos disse...

Se o AutoCommit está em False você deve fazer o commit explicitamente em algum evento tal como AfterPost, por exemplo, ou incluir um botão para fazer isso em todos os registros do cache.

Pucka disse...

Olá Professor Carlos,
Antes de mais nada, gostaria de agradecer pelo carinho com que tem sempre nos atendido. Desta vez, após os insucessos, fiz alguns testes para tentar desvendar o quê poderia estar provocando o erro. Por sorte, tinha uma cópia reserva do programa. Assim, instalei em um micro, o Lazarus 0.9.30 e o ZEOS 6.6.6 stable. Compilei o programa, rodei beleza ! Tudo certinho. Assim, apesar de poucos testes, estou chegando à conclusão que: ao fazermos a atualização do Lazarus (talvez possa ser válido também para os componentes que gerenciam os BDs como o ZEOS -> não posso afirmar, apenas é uma suspeita). Precisamos substituir também no programa, todos objetos do novo componente antes de recompilar.
OBS.: pessoal, façam o backup sempre, se não tivesse o meu, estava lascado, pois virou um perfeito zumbi...
De qualquer modo, muito obrigado
pelas dicas. Certamente serão úteis adiante. [ ].
Dica: se alguém desenvolve sistemas pelo Lazarus e faz a manutenção. Não saia atualizando simplesmente. Poderá ter uma grande dor-de-cabeça. Faça alguns testes antes, com uma cópia de segurança, claro!

Leonardo Rômulo disse...

tem como deletar o banco de dados criado no sqlite3 banco.db?

Professor Carlos disse...

Sim. Pode deletar e criar outro

Leonardo Rômulo disse...

estou com uma duvida na chamada de formularios pelo formulario principal
no caso para programar a chamada do form frmCidade
eu tenho que digitar abaixo de Implementation:

uses u_cidade;
porem nesse formulario principal ja tem programado a chamada do formulario u_dmDados;
então a implemetation do formulario principal teria que ficar assim
implemetation
uses u_dmDados;
uses u_cidade;

a minha duvida e se eu tenho que digitar o uses de novo e se um mesmo formulario pode chamar mais de 1 formulario adicional

Professor Carlos disse...

deve ter apenas uma linha uses:
uses u_dmDados, u_cidade;

Sempre vai adicionando as units nessa linha separando-as com virgula
Um form pode chamar quantos outros forem necessários

Robson Souza disse...

Professor, Grato pelas dicas. Como faço para pesquiasr no banco usando o contúdo de um Tedit. Ja tenho configurado o datasource, trans.,query e conexão com o banco que é mysql. Sou do interior de São Paulo e queria saber se você aplicar cursos em alguma instituição..

Professor Carlos disse...

Oi Robson

Na parte 2 desse post eu explico como fazer consultas http://professorcarlos.blogspot.com.br/2010/02/lazarus-acessando-banco-de-dados-com_24.html
Eu trabalha em uma instituição de ensino superior em Santarém no Pará.

 
Creative Commons License
This work by Carlos Alberto P. Araújo is licensed under a Creative Commons Atribuição-Uso não-comercial-Compartilhamento pela mesma licença 3.0 Brasil License.