Tutorial: CRUD de Banco de Dados
Este tutorial orienta voce na construcao de uma aplicacao completa de banco de dados com operacoes Create, Read, Update e Delete usando SQLite. Voce conectara a um banco de dados, exibira registros em uma grade TBrowse e os navegara com TDBNavigator.
Passo 1: Criar o Projeto
- Crie um novo projeto chamado
ContactsDBvia Arquivo → Novo Projeto. - Abra
main.prgno Editor de Codigo. - Vamos construir um gerenciador de contatos com campos de nome, email e telefone.
Passo 2: Conectar ao SQLite
Arraste um componente TSQLite da aba de paleta Acesso a Dados para o formulario, ou crie no codigo. O componente SQLite do HarbourBuilder gerencia a conexao e execucao de consultas.
#include "hbbuilder.ch" function Main() local oDB, oForm // Abrir (ou criar) o arquivo de banco de dados SQLite DEFINE SQLITE oDB FILE "contacts.db" if .not. oDB:lConnected MsgAlert( "Falha ao abrir banco de dados: " + oDB:cError ) return nil endif CreateTable( oDB ) BuildUI( oDB ) return nil
O SQLite armazena todo o banco de dados em um unico arquivo. Isso o torna perfeito para aplicacoes desktop — sem instalacao, sem configuracao, e funciona em todas as plataformas.
Passo 3: Criar a Tabela
Use Execute() para executar uma declaracao CREATE TABLE IF NOT EXISTS. E seguro chamar
toda vez que a aplicacao inicia.
static function CreateTable( oDB ) oDB:Execute( "CREATE TABLE IF NOT EXISTS contacts (" + ; "id INTEGER PRIMARY KEY AUTOINCREMENT," + ; "name TEXT NOT NULL," + ; "email TEXT," + ; "phone TEXT" + ; ")" ) return nil
Passo 4: Construir a Interface do Usuario
A interface consiste em uma grade TBrowse para exibir registros, campos de entrada para edicao, um TDBNavigator para navegacao de registros e botoes CRUD.
static function BuildUI( oDB ) local oForm, oBrw, oNav local oGetName, oGetEmail, oGetPhone local oBtnAdd, oBtnUpdate, oBtnDelete local cName := "", cEmail := "", cPhone := "" DEFINE FORM oForm TITLE "Gerenciador de Contatos" ; SIZE 800, 600 FONT "Segoe UI", 10 // --- Grade de dados --- @ 10, 10 BROWSE oBrw ; OF oForm SIZE 760, 300 ; HEADERS { "ID", "Nome", "Email", "Telefone" } ; WIDTHS { 50, 200, 250, 150 } // --- Barra de navegacao --- @ 320, 10 DBNAVIGATOR oNav ; OF oForm SIZE 300, 32 ; BROWSE oBrw // --- Campos de entrada --- @ 370, 10 LABEL oLbl1 VALUE "Nome:" OF oForm SIZE 60, 24 @ 370, 80 GET oGetName VAR cName OF oForm SIZE 250, 24 @ 400, 10 LABEL oLbl2 VALUE "Email:" OF oForm SIZE 60, 24 @ 400, 80 GET oGetEmail VAR cEmail OF oForm SIZE 250, 24 @ 430, 10 LABEL oLbl3 VALUE "Telefone:" OF oForm SIZE 60, 24 @ 430, 80 GET oGetPhone VAR cPhone OF oForm SIZE 250, 24 // --- Botoes CRUD --- @ 480, 80 BUTTON oBtnAdd PROMPT "Adicionar" ; OF oForm SIZE 90, 32 ; ACTION DoInsert( oDB, oBrw, oGetName, oGetEmail, oGetPhone ) @ 480, 180 BUTTON oBtnUpdate PROMPT "Atualizar" ; OF oForm SIZE 90, 32 ; ACTION DoUpdate( oDB, oBrw, oGetName, oGetEmail, oGetPhone ) @ 480, 280 BUTTON oBtnDelete PROMPT "Excluir" ; OF oForm SIZE 90, 32 ; ACTION DoDelete( oDB, oBrw ) // Carregar dados iniciais RefreshBrowse( oDB, oBrw ) // Quando usuario clicar em uma linha, preencher campos de entrada oBrw:OnClick := { || OnRowSelect( oBrw, oGetName, oGetEmail, oGetPhone ) } ACTIVATE FORM oForm CENTERED return nil
Passo 5: Implementar Operacoes CRUD
INSERT — Adicionando um Novo Registro
static function DoInsert( oDB, oBrw, oGetName, oGetEmail, oGetPhone ) local cName := oGetName:GetValue() local cEmail := oGetEmail:GetValue() local cPhone := oGetPhone:GetValue() if Empty( cName ) MsgAlert( "Nome e obrigatorio." ) return nil endif oDB:Execute( "INSERT INTO contacts (name, email, phone) VALUES (?, ?, ?)", ; { cName, cEmail, cPhone } ) RefreshBrowse( oDB, oBrw ) MsgInfo( "Contato adicionado." ) return nil
SELECT — Atualizando a Grade
static function RefreshBrowse( oDB, oBrw ) local aRows := oDB:QueryToArray( "SELECT id, name, email, phone FROM contacts ORDER BY name" ) oBrw:SetArray( aRows ) oBrw:Refresh() return nil
UPDATE — Modificando o Registro Selecionado
static function DoUpdate( oDB, oBrw, oGetName, oGetEmail, oGetPhone ) local nId := oBrw:GetValue( 1 ) // Coluna 1 = id local cName := oGetName:GetValue() local cEmail := oGetEmail:GetValue() local cPhone := oGetPhone:GetValue() if nId == 0 MsgAlert( "Selecione um contato primeiro." ) return nil endif oDB:Execute( "UPDATE contacts SET name=?, email=?, phone=? WHERE id=?", ; { cName, cEmail, cPhone, nId } ) RefreshBrowse( oDB, oBrw ) MsgInfo( "Contato atualizado." ) return nil
DELETE — Removendo o Registro Selecionado
static function DoDelete( oDB, oBrw ) local nId := oBrw:GetValue( 1 ) if nId == 0 MsgAlert( "Selecione um contato primeiro." ) return nil endif if MsgYesNo( "Excluir este contato?" ) oDB:Execute( "DELETE FROM contacts WHERE id=?", { nId } ) RefreshBrowse( oDB, oBrw ) MsgInfo( "Contato excluido." ) endif return nil
Selecao de Linha — Preenchendo Campos de Entrada
static function OnRowSelect( oBrw, oGetName, oGetEmail, oGetPhone ) oGetName:SetValue( oBrw:GetValue( 2 ) ) oGetEmail:SetValue( oBrw:GetValue( 3 ) ) oGetPhone:SetValue( oBrw:GetValue( 4 ) ) return nil
Passo 6: Usando TDBNavigator
O controle TDBNavigator fornece botoes de navegacao padrao (Primeiro, Anterior, Proximo, Ultimo)
que funcionam diretamente com a grade TBrowse. Arraste da paleta Acesso a Dados e defina a
propriedade oBrowse para sua instancia TBrowse.
Sempre use marcadores ? e passe valores como um array. Nunca concatene entrada do usuario
diretamente em strings SQL. O componente SQLite do HarbourBuilder trata o escape automaticamente.
Arquitetura da Aplicacao
TForm + TBrowse + TGet"] --> B["Manipuladores de Eventos
DoInsert / DoUpdate / DoDelete"] B --> C["Camada de Dados
Componente TSQLite"] C --> D["Arquivo SQLite
contacts.db"] D --> C C --> B B --> E["RefreshBrowse
QueryToArray + SetArray"] E --> A style A fill:#58a6ff,stroke:#388bfd,color:#0d1117 style B fill:#d2a8ff,stroke:#bc8cff,color:#0d1117 style C fill:#3fb950,stroke:#2ea043,color:#0d1117 style D fill:#f0883e,stroke:#d18616,color:#0d1117
Pronto para servir dados via HTTP? Continue para o tutorial Servidor Web para construir uma aplicacao web junto com sua aplicacao desktop.