Tutorial: CRUD de Base de Datos
Este tutorial lo guia a traves de la construccion de una aplicacion de base de datos completa con operaciones de Crear, Leer, Actualizar y Eliminar usando SQLite. Conectara a una base de datos, mostrara registros en una cuadricula TBrowse y los navegara con TDBNavigator.
Paso 1: Crear el Proyecto
- Cree un nuevo proyecto llamado
ContactsDBmediante Archivo → Nuevo Proyecto. - Abra
main.prgen el Editor de Codigo. - Construiremos un gestor de contactos con campos de nombre, correo y telefono.
Paso 2: Conectar a SQLite
Coloque un componente TSQLite desde la pestania de paleta Acceso a Datos en el formulario, o creelo en codigo. El componente SQLite de HarbourBuilder maneja la conexion y ejecucion de consultas.
#include "hbbuilder.ch" function Main() local oDB, oForm // Abrir (o crear) el archivo de base de datos SQLite DEFINE SQLITE oDB FILE "contacts.db" if .not. oDB:lConnected MsgAlert( "Error al abrir la base de datos: " + oDB:cError ) return nil endif CreateTable( oDB ) BuildUI( oDB ) return nil
SQLite almacena toda la base de datos en un unico archivo. Esto lo hace perfecto para aplicaciones de escritorio — sin instalacion, sin configuracion, y funciona en todas las plataformas.
Paso 3: Crear la Tabla
Use Execute() para ejecutar una sentencia CREATE TABLE IF NOT EXISTS. Es seguro llamar a esto cada vez que la aplicacion se 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
Paso 4: Construir la Interfaz de Usuario
La UI consiste en una cuadricula TBrowse para mostrar registros, campos de entrada para edicion, un TDBNavigator para navegacion de registros y botones 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 "Gestor de Contactos" ; SIZE 800, 600 FONT "Segoe UI", 10 // --- Cuadricula de datos --- @ 10, 10 BROWSE oBrw ; OF oForm SIZE 760, 300 ; HEADERS { "ID", "Nombre", "Correo", "Telefono" } ; WIDTHS { 50, 200, 250, 150 } // --- Barra de navegacion --- @ 320, 10 DBNAVIGATOR oNav ; OF oForm SIZE 300, 32 ; BROWSE oBrw // --- Campos de entrada --- @ 370, 10 LABEL oLbl1 VALUE "Nombre:" OF oForm SIZE 60, 24 @ 370, 80 GET oGetName VAR cName OF oForm SIZE 250, 24 @ 400, 10 LABEL oLbl2 VALUE "Correo:" OF oForm SIZE 60, 24 @ 400, 80 GET oGetEmail VAR cEmail OF oForm SIZE 250, 24 @ 430, 10 LABEL oLbl3 VALUE "Telefono:" OF oForm SIZE 60, 24 @ 430, 80 GET oGetPhone VAR cPhone OF oForm SIZE 250, 24 // --- Botones CRUD --- @ 480, 80 BUTTON oBtnAdd PROMPT "Anadir" ; OF oForm SIZE 90, 32 ; ACTION DoInsert( oDB, oBrw, oGetName, oGetEmail, oGetPhone ) @ 480, 180 BUTTON oBtnUpdate PROMPT "Actualizar" ; OF oForm SIZE 90, 32 ; ACTION DoUpdate( oDB, oBrw, oGetName, oGetEmail, oGetPhone ) @ 480, 280 BUTTON oBtnDelete PROMPT "Eliminar" ; OF oForm SIZE 90, 32 ; ACTION DoDelete( oDB, oBrw ) // Cargar datos iniciales RefreshBrowse( oDB, oBrw ) // Cuando el usuario hace clic en una fila, poblar los campos de entrada oBrw:OnClick := { || OnRowSelect( oBrw, oGetName, oGetEmail, oGetPhone ) } ACTIVATE FORM oForm CENTERED return nil
Paso 5: Implementar Operaciones CRUD
INSERT — Anadir un Nuevo 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( "El nombre es obligatorio." ) return nil endif oDB:Execute( "INSERT INTO contacts (name, email, phone) VALUES (?, ?, ?)", ; { cName, cEmail, cPhone } ) RefreshBrowse( oDB, oBrw ) MsgInfo( "Contacto anadido." ) return nil
SELECT — Actualizar la Cuadricula
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 — Modificar el Registro Seleccionado
static function DoUpdate( oDB, oBrw, oGetName, oGetEmail, oGetPhone ) local nId := oBrw:GetValue( 1 ) // Columna 1 = id local cName := oGetName:GetValue() local cEmail := oGetEmail:GetValue() local cPhone := oGetPhone:GetValue() if nId == 0 MsgAlert( "Seleccione un contacto primero." ) return nil endif oDB:Execute( "UPDATE contacts SET name=?, email=?, phone=? WHERE id=?", ; { cName, cEmail, cPhone, nId } ) RefreshBrowse( oDB, oBrw ) MsgInfo( "Contacto actualizado." ) return nil
DELETE — Eliminar el Registro Seleccionado
static function DoDelete( oDB, oBrw ) local nId := oBrw:GetValue( 1 ) if nId == 0 MsgAlert( "Seleccione un contacto primero." ) return nil endif if MsgYesNo( "Eliminar este contacto?" ) oDB:Execute( "DELETE FROM contacts WHERE id=?", { nId } ) RefreshBrowse( oDB, oBrw ) MsgInfo( "Contacto eliminado." ) endif return nil
Seleccion de Fila — Poblar 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
Paso 6: Usar TDBNavigator
El control TDBNavigator proporciona botones de navegacion estandar (Primero, Anterior, Siguiente, Ultimo) que funcionan directamente con la cuadricula TBrowse. Coloquelo desde la pestania Acceso a Datos y establezca su propiedad oBrowse a su instancia TBrowse.
Siempre use marcadores ? y pase los valores como un arreglo. Nunca concatene entrada del usuario directamente en cadenas SQL. El componente SQLite de HarbourBuilder maneja el escape automaticamente.
Arquitectura de la Aplicacion
TForm + TBrowse + TGet"] --> B["Manejadores de Eventos
DoInsert / DoUpdate / DoDelete"] B --> C["Capa de Datos
Componente TSQLite"] C --> D["Archivo 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
Listo para servir datos por HTTP? Continue al tutorial de Servidor Web para construir una aplicacion web junto a su aplicacion de escritorio.