Acceso a base de datos SQLite desde Delphi Starter

Hola amigos,

En ésta entrada vamos a realizar la conexión con una base de datos SQLite utilizando Delphi Starter Edition, versión 10.2 Tokyo y como ya se habrán dado cuenta, ésta edición de Delphi no cuenta con los componentes necesarios para la conexión a bases de datos, sin embargo, si tenemos la posibilidad de instalar componentes de terceros para poder acceder a motores de base de datos y expandir las características de nuestra herramienta de desarrollo.

Los componentes que utilizaremos en éste tutorial son los componentes ZEOS que nos permitiran dar continuidad a ésta serie aprovechando las facilidades que nos ofrece Delphi Starter Edition.

Para realizar ésta entrada utilizaremos la aplicación que desarrollamos en el artículo anterior «Consumir un servicio web con Delphi 10.2 Starter y cURL« donde obtenemos información del tipo de cambio del día del peso mexicano contra monedas de otros países.

Una vez que obtenemos dicha información tendrémos la capacidad de almacenarla para efectos de mantener un histórico de «paridades» y poder consultar el valor de una moneda en un día determinado.

Para poder llevar a cabo éste tutorial necesitamos descargar el componente de acceso base de datos ZEOS el cual pueden descargar del siguiente enlace: ZeosLib versión 7.2.1 Release Candidate

El motor de base de datos que usarémos será SQLite donde crearemos dos tablas y una vista para utilizarlas en nuestra aplicación, dicha base de datos estará incluida en los archivos de descarga al final de éste tutorial, sin embargo, si deseas crearla tu mismo se entregarán los DDL para que las generes con el administrador SQLite de tu preferencia, si no conoces alguno puedes descargar SQLite Studio Database Manager que me parece un muy buen administrador.

Comenzaremos por instalar los componentes ZEOS versión 7.2.1 rc, el paquete que se usará para Delphi Starter es el contenido en el directorio DelphiXE10.

Carga el proyecto ZeosDbo.bpg en Delphi y compila todos los bpl’s en el siguiente orden:

• ZCore.bpl
• ZParseSql.bpl
• ZPlain.bpl
• ZDbc.bpl
• ZComponent.bpl

Para que puedan compilar los BPL’s es necesario agregar los siguientes directorios a la ruta de las librerias/bibliotecas que se localiza en el menu Tools -> Options -> Delphi Options -> Library -> Library Path.

C:\Compartidos\Starter\ZEOSDBO-7.2.1-rc\packages\DelphiXE10;
C:\Compartidos\Starter\ZEOSDBO-7.2.1-rc\src\component;
C:\Compartidos\Starter\ZEOSDBO-7.2.1-rc\src\dbc;
C:\Compartidos\Starter\ZEOSDBO-7.2.1-rc\src\parsesql;
C:\Compartidos\Starter\ZEOSDBO-7.2.1-rc\src\plain;
C:\Compartidos\Starter\ZEOSDBO-7.2.1-rc\src\Core

Una vez que compilamos correctamente el proyecto ZeosDbo aparecerá el grupo Zeos Access en la paleta de herramientas como se muestra en la siguiente imagen:

El siguiente paso es la creación de la base de datos SQLite que utilizaremos en ésta sección y como les comenté pueden usar la base de datos que está incluida en las descargas al final de éste tutorial o pueden crearla con el Lenguaje de Definición de Datos (DDL)  desde cualquier Administrador SQLite.

--
-- File generated with SQLiteStudio v3.1.1 on mar may 30 21:19:36 2017
--
-- Text encoding used: System
--
PRAGMA foreign_keys = off;
BEGIN TRANSACTION;

-- Table: TC_CATALOGO
DROP TABLE IF EXISTS TC_CATALOGO;

CREATE TABLE TC_CATALOGO (
    ID          INTEGER      NOT NULL
                             PRIMARY KEY AUTOINCREMENT,
    CLAVE       STRING (20)  NOT NULL,
    DESCRIPCION STRING (200) 
);


-- Table: TC_HISTORICO
DROP TABLE IF EXISTS TC_HISTORICO;

CREATE TABLE TC_HISTORICO (
    ID      INTEGER        NOT NULL,
    FECHA   DATE           NOT NULL,
    TIPCAMB DECIMAL (7, 4),
    PRIMARY KEY (
        ID,
        FECHA
    )
);


-- View: TC_LISTADO
DROP VIEW IF EXISTS TC_LISTADO;
CREATE VIEW TC_LISTADO AS
    SELECT CAT.CLAVE,
           HIST.FECHA,
           HIST.TIPCAMB,
           CAT.DESCRIPCION
      FROM TC_HISTORICO HIST
           INNER JOIN
           TC_CATALOGO CAT ON CAT.ID = HIST.ID;


COMMIT TRANSACTION;
PRAGMA foreign_keys = on;

Despues de crear las tablas vamos a inicializar el catálogo de monedas para que se tenga la información necesaria para enlazar la información que vamos a recibir del Servicio Web de Banxico.

INSERT INTO TC_CATALOGO (DESCRIPCION,CLAVE,ID)
VALUES	('Tipo de cambio pesos por dólar E.U.A. Fecha de liquidación.','DLL01',1),
		('Tipo de cambio Pesos por dólar E.U.A. Fecha de determinación (FIX)','DLL02',2),
		('Cotización de las divisas que conforman la canasta del DEG Respecto al peso mexicano Euro','EURO',3),
		('Cotización de la divisa Respecto al peso mexicano Dólar Canadiense','DLLCA',4),
		('Cotización de las divisas que conforman la canasta del DEG Respecto al peso mexicano Yen japonés','YEN',5),
		('Cotización de las divisas que conforman la canasta del DEG Respecto al peso mexicano Libra esterlina.','LIBRA',6);

En éste momento ya tenemos los componentes de acceso a base de datos y la base de datos listos, ahora comenzaremos a dar forma a nuestro proyecto.

Abra el proyecto wsStarter.dproj que se creo en el tutorial anterior (Si no lo has creado, puedes descargarlo siguiendo éste enlace).

Agregue los siguientes componentes a la forma principal.

• TButton
• TDataSource;
• TDateTimePicker
• TDBGrid
• TZConnection;
• TZQuery;

Después de organizar a tu gusto los componentes que se agregaron ya tendremos nuestra forma similar a la siguiente imagen:

Configuramos la conexión en el componente ZConnection1  asignando la ruta de la base de datos y el protocolo del motor de la base de datos que vamos a usar, en éste caso sqlite-3.

Ésta configuración de la base de datos está en tiempo de diseño pero lo recomendable es hacerlo en tiempo de ejecución ya que la base de datos puede ser colocada en cualquier lugar ya sea en la misma máquina o en otra máquina de la red. Para configurarla en tiempo de ejecución pueden hacer lo siguiente:

procedure TForm1.FormCreate(Sender: TObject);
begin
  ZConnection1.Database := ExtractFilePath(Application.ExeName) + 'base\TipoCambio.sqlite3';
end;

(También puede ser a través de la lectura de un archivo INI, XML o el mismo registro de windows, como mejor les parezca.)

Ahora vamos a decidir que vamos a hacer con la información que se reciba del Servicio Web de Banxico. Yo he decidido mostrar la información seleccionando la fecha deseada en el componente TDateTimePicker1 y mostrar los tipos de cambio de ese día (si ya se ha descargado), para ello utilizaremos la vista que previamente se creo en la base de datos llamada TC_LISTADO ejecutandola desde el componente ZQuery1 el cual ya debe estar enlazado al DataSource y a su vez el DataSource enlazado al DBGrid.

La consulta es muy simple y  es la siguiente:

select * from TC_LISTADO list
where list.FECHA = :fecha

Ya estamos listos para modifcar el proyecto y acceder a una base de datos. Comenzamos agregando las siguientes unidades a la sección USES de nuestra unidad uXMLclass.pas.

• ZDataset,
• ZAbstractConnection;

Posteriormente agregamos una variable y una propiedad a la clase TRequestResponse para la conexión con la base de datos.

• ZQryTC: TZQuery;

• Fconexion: TZAbstractConnection;

• property conexion: TZAbstractConnection read Fconexion write Fconexion;

Finalmente harémos una modificación al procedimiento TRequestResponse.BuscaTC() para leer el XML de Respuesta obteniendo la Moneda, la Fecha y el Tipo de Cambio y agregando ésta información a nuestra tabla de históricos para consultas posteriores.

function TRequestResponse.buscaTC(xml: IXMLDocument): TStrings;
var
  I: integer;
  nodoData: IXMLNode;
  Linea: string;
  valor: variant;
  moneda: integer;
begin
  Result := TStringList.Create;
  Result.Text := '';
  nodoData := xml.ChildNodes[1].ChildNodes[1];
  if nodoData <> nil then
  begin
    ZQryTC := TZQuery.Create(nil);
    ZQryTC.Connection := Fconexion;
    ZQryTC.SQL.Text := 'INSERT INTO TC_HISTORICO(ID, FECHA, TIPCAMB) ' + #13 +
                       'VALUES(:id, :periodo, :tc) ';
    for I := 0 to nodoData.ChildNodes.Count-1 do
    begin
      if nodoData.ChildNodes[I].NodeName = 'bm:Series' then
      begin
         if pos('FIX',nodoData.ChildNodes[I].Attributes['TITULO']) > 0 then
            ZQryTC.ParamByName('ID').Value := 2
         else
         if pos('Euro',nodoData.ChildNodes[I].Attributes['TITULO']) > 0 then
            ZQryTC.ParamByName('ID').Value := 3
         else
         if pos('Canadiense',nodoData.ChildNodes[I].Attributes['TITULO']) > 0 then
            ZQryTC.ParamByName('ID').Value := 4
         else
         if pos('Yen',nodoData.ChildNodes[I].Attributes['TITULO']) > 0 then
            ZQryTC.ParamByName('ID').Value := 5
         else
         if pos('Libra',nodoData.ChildNodes[I].Attributes['TITULO']) > 0 then
            ZQryTC.ParamByName('ID').Value := 6
         else
            ZQryTC.ParamByName('ID').Value := 1;

         moneda := ZQryTC.ParamByName('ID').Value;

         ZQryTC.ParamByName('PERIODO').AsString :=
                 nodoData.ChildNodes[I].ChildNodes[0].Attributes['TIME_PERIOD'];

         valor := NULL;
         if nodoData.ChildNodes[I].ChildNodes[0].Attributes['OBS_VALUE'] <> '' then
            ZQryTC.ParamByName('TC').AsString :=
                 nodoData.ChildNodes[I].ChildNodes[0].Attributes['OBS_VALUE']
         else
            ZQryTC.ParamByName('TC').Value := valor;

         ZQryTC.ExecSQL;

         Result.Add(Moneda.ToString + #9 +
                    nodoData.ChildNodes[I].ChildNodes[0].Attributes['TIME_PERIOD'] + #9 +
                    nodoData.ChildNodes[I].ChildNodes[0].Attributes['OBS_VALUE'] );

      end;
    end;
    ZQryTC.Free;
  end;
end;

Con el código anterior recorremos los nodos de XLM para obtener la información que necesitamos, la insertamos en la base de datos y finalmente regresamos un informe de lo descargado a la forma principal como se puede observar en las siguientes imagenes:

Pareciera que la información mostrada careciera de sentido, sin embargo, la parte final de éste tutorial es mostrar un listado de los tipos de cambio de una fecha dada utilizando la vista que creamos anteriormente la cual es disparada por la siguiente consulta.

select * from TC_LISTADO
where FECHA = :fecha

Para ejecutar la consulta utilizamos el evento OnClick del  botón [Listado] y escribimos el siguiente código:

procedure TForm1.Button3Click(Sender: TObject);
begin
  ZQuery1.Close;
  ZQuery1.ParamByName('FECHA').Value := DateTimePicker1.Date;
  ZQuery1.Open;
end;

Ya tenemos listo todo y solo presionamos el botón [Listado] para que la información sea presentada en el Grid de nuestra forma como se observa en la siguiente imagen.

Como pueden ver, acceder a una base de datos con Delphi Starter no tiene mayor complicación y las posibilidades que se nos presentan son muchas, solo recuerden, de acuerdo a la licencia de ésta edición de Delphi Starter se nos indica que si logran obtener una ganancia igual o mayor a 1,000 dólares deben de adquirir una versión de pago, los invito a que hagan el esfuerzo, les aseguro que no se arrepentiran.

Y bueno hemos llegado al final de éste tutorial, espero que sea de su agrado y sobre todo que sea de utilidad.

Hasta la próxima


Todo el código escrito aquí es de libre descarga y utilización solo te pido, si te parece correcto, que menciones su origen y claro cualquier mejora que le hagas publicala que se agradecerá enormemente.

Muchas gracias.

8 comentarios en «Acceso a base de datos SQLite desde Delphi Starter»

    • Muchas gracias a ti por leerme amigo Axesys, ya veremos hasta donde podemos llegar con ésta Edición de Delphi y comprobar que se puede obtener ganancias que nos permitan la compra de alguna de las versiones de pago que por supuesto nos dará mayores y mejores características.

      Saludos

      Responder
      • Felicitaciones nuevamente Eliseo. La verdad que es cierto que para mucha de las cosas que se hacen en Delphi, con Starter vas muy bien equipado. Solo que quiza tengas que usar algun componente no estandar como este es el caso, pero las Zeos me parecen muy maduras y tan buenas como las FireDAC

        Saludos

        Responder
        • Muchas gracias amigo Agustín, ciertamente trabajar con Delphi Starter tiene sus costos operativos, sin embargo, como lo dice su nombre para iniciar a descubrir el lenguaje y sus alcances me parece una muy buena opción.

          Responder
    • Muchas gracias amigo bitbow, de hecho los reportes son una de las entregas de la serie y le daré una revisión a ese reporteador, ya había probado otro pero no es compatible con Starter.

      Responder
  1. Excelente Eliseo, en un par de días estaré probando la conexión, oye por cierto ¿abra alguna entrega en la serie para el manejo de concurrencia con esta versión de Delphi? Muchas gracias. Saludos.

    Responder
    • Que tal amigo, pues la concurrencia la maneja el motor de base de datos con transacciones, no soy muy «ducho» con Zeos, pero supongo que tiene manejo de transacciones, si es así, debería poderse. 🙂

      Saludos

      Responder

Responder a Agustín Ortu Cancelar la respuesta