AprendiendoBORLAND Delphi. Marta Sananes. Universidad de Los Andes, Venezuela. Mayo 2002.

Ejemplo de aplicación de Base de Datos
 
Este ejemplo es una versión modificada del ejemplo Fishfact suministrado por Borland en ......\Delphi4\Demos\Fishfact.

En este ejemplo se muestra el uso de componentes y controles para acceso, navegación y consulta de una Base de Datos. El contenido de los archivos que conforman la aplicación se muestra en forma de tablas, en la columna izquierda el código en ObjectPascal y en la derecha explicaciones y comentarios. 

En los archivos de programa (.dpr y .pas), las líneas que son generadas automáticamente por Delphi están en color amarillo; en blanco sólo las que el programador tuvo que agregar. Aparecen resaltadas en ambos casos las palabras reservadas de ObjectPascal, tal como lo hace el Editor de Delphi.

Son tres los archivos que conforman la aplicación: 

MiFishFact.dpr: es el archivo raíz o índice del proyecto, de extensión .dpr (Delphi PRoject); MiFFactWin.pas: es la Unit que contiene la programación correspondiente a la forma de interfaz de usuario; MiFFactWin.dfm: es parte de la visualización en modo texto de la Forma diseñada por el programador como interfaz de usuario. 

El archivo de extensión .dfm (Delphi ForM) contiene las declaraciones correspondientes al diseño de la Forma; es generado por Delphi transcribiendo la construcción que hace el usuario en forma visual. No hace falta que el programador vea este archivo ni debe modificar manualmente el texto, Delphi se encarga de su actualización cada vez que visualmente se modifique la apariencia o el contenido de la Forma asociada, ya sea por acciones directas sobre la Forma o modificando propiedades con el Object Inspector .

Para pasar a estudiar este ejemplos es conveniente tener algún conocimiento de Bases de Datos y/o haber leido y practicado la guía Quick Start, incluida en la distribución de Delphi 4 y 5 . 

MiFishfact.dpr
 
program MiFishfact;

uses
  Forms,
  MiFFACTWIN in 'MiFFACTWIN.PAS' {Form1};

{$R *.RES}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

Para proyectos diseñados con formas de interfaz gráfica para usuarios, Delphi genera el archivo  de extensión .dpr. En la sección uses coloca los nombres y las ubicaciones de todas las Units incorporadas al proyecto, además de la referencia a la Delphi-Unit Forms, que contiene la Clase TForm, clase primitiva de todas las formas.

Unit MiFFactwin.pas
Unit construida por el programador.omienzo de bloque de declaracione que contienen librerías Delphi utilizadas.
unit MiFFACTWIN;
{ This application shows how to display Paradox style 
  memo and graphic fields in a form. Table1's 
  DatabaseName property should point to the Delphi sample 
  database. Table1's TableName property should be set to 
  the BIOLIFE table.
  Este ejemplo fué modificado por Marta Sananes para 
  mostrar uso de componente de clase TQuery}
interface
uses
  SysUtils, Windows, Messages, Classes, Graphics, 
  Controls, Dialogs, Forms, StdCtrls, DBCtrls, DBGrids, 
  DB, DBTables, Buttons, Grids, ExtCtrls;
type
Unit construida por el programador.

Observe el texto inicial de comentario en estilo Pascal tradicional, encerrado entre {..}

La palabra interface señala el comienzo de bloque de declaraciones, donde se colocan todas las declaraciones o definiciones (tipos, variables, constantes, funciones y procedimientos, labels).

En la instrucción uses Delphi genera la lista de Units utilizadas en la aplicación, a la cual se pueden agregar las que el usuario desee, preferiblemente usando el botón de Agregar Unit en la barra de herramientas del menú principal.
Comienzo de declaraciones de tipos (tipos de datos y clases)

  TForm1 = class(TForm)
    Panel1: TPanel;
    Label1: TLabel;
    BitBtn1: TBitBtn;

    DBImage1: TDBImage;
    DBLabel1: TDBText;
    DBLabel2: TDBText;
    DBMemo1: TDBMemo;
    DBGrid1: TDBGrid;

    Table1: TTable;
    DataSource1: TDataSource;

 

Delphi genera las declaraciones de los controles y componentes colocados por el programador en la forma y registra en el archivo de la forma (MiFFactWin.dfm en este caso) las propiedades asignadas con el ObjectInspector.
Los controles de tipo TPanel sirven para organizar el diseño de la forma.

En las pestañas rotuladas Data Access y Data Controls de la Paleta de Componentes del ambiente Delphi se encuentran los componentes para acceso a bases de datos (en este ejemplo se usan TTable, TQuery (Tabla resultado de consulta SQL) y TDataSource y controles para visualización de sus elementos (en este ejemplo se usan TDBImage, TDBText, TDBMemo y TDBGrid), respectivamente).

El acceso a una Tabla requiere el uso de dos tipos de componentes: uno de clase TTable y otro de clase TDataSource. Lo primero que hay que definir en el componente de clase TTable es la propiedad DatabaseName. En el ObjectInspector esta propiedad se presenta en un cuadro que despliega como opciones las bases de datos definidas en Windows, locales o remotas, si la versión de Delphi lo permite (Ver Instrucciones para crear una Base de Datos local). Una vez definida la Base de datos, al abrir la propiedad TableName se despliegan los nombres de todas las tablas que conforman la BD, se puede entonces seleccionar el nombre de la tabla a la que se desea acceder. 

Los controles para visualización, como TDBGrid se relacionan con la tabla objetivo através del componente asociado de clase TDataSource, que sirve de vía de acceso al contenido de la tabla. Para establecer la asociación de debe seleccionar el nombre del componente de clase TTable (o de clase TQuery) como valor para la propiedad DataSet del TDataSource. Si la propiedad Active del componente TTable (o TQuery) se coloca con el valor True, los contenidos de la tabla accesados vía el TDataSource se hacen visibles, aún en tiempo de desarrollo. Si la Base de Datos tiene protección de acceso se despliega un cuadro de diálogo para definir el nombre de usuario y su password igual que como sucederá al ejecutarse la aplicación.

    Query1: TQuery; //Componente que contiene el comando SQL
    DataSource2: TDataSource; //TDataSource relacionado
    DBGrid2: TDBGrid; //Tabla para mostrar resultado
    Label2: TLabel; //Letrero para mostrar comando SQL
    Button1: TButton; //Botón para ejecutar la consulta
También se puede acceder a la tabla resultante de una consulta SQL, usando el componente de clase TQuery. Lo primero que hay que definir también es la propiedad DatabaseName. El comando SQL se define en la propiedad SQL, lo cual puede hacerse al desarrollar la aplicación o en tiempo de ejecución antes de aplicar el método Open o el ExecSQL para ejecutarlo. Por lo demás, se procede igual que para un componente de clase TTable. En este ejemplo se agregaron un componente TQuery (Ver string de la consulta en el texto generado de la forma), un TDataSource para dar acceso al contenido de la tabla resultante y un control de clase TDBGrid para visualizar el contenido como tabla. Además se agregaron un botón para que el usaurio ordene la ejecución de la consulta y un letrero de información. 
    Table1Common_Name: TStringField; //campos generados
    Table1Graphic: TBlobField;
    Table1Category: TStringField;
    Table1SpeciesName: TStringField;
    Table1Lengthcm: TFloatField;
    Table1Length_In: TFloatField;
    Table1Notes: TMemoField; 
    Query1SpeciesNo: TFloatField; //campos generados
    Query1Category: TStringField;
    Query1Common_Name: TStringField;
    Query1SpeciesName: TStringField;
    Query1Lengthcm: TFloatField;
    Query1Length_In: TFloatField;
    Query1Notes: TMemoField;
    Query1Graphic: TGraphicField;
Para incluir columnas (campos o fields) de la tabla referida al TTable o de la referida a un TQuery, con el componente seleccionado debe pulsar el segundo botón del ratón para desplegar un menú, seleccionar la primera opción (Fields Editor) y una vez abierta la ventana correspondiente con el ratón sobre el área de trabajo, pulsar nuevamente el segundo botón. Aparece entonces otro menú que permite agregar un campo, crear uno nuevo o agregar todos los campos, con lo cual Delphi agrega en la declaración de la forma tantos objetos como columnas agregadas de la clase correspondiente a la definición de cada uno de ellas. Consulte en el Help las propiedades y métodos de cada uno de las clases de columnas que se muestran. En este ejemplo sólo hacía falta incluir Query1Common_Name y Query1Length_In, ya que las demás no se están utilizando para ningún procesamiento.
    procedure HacerQuery(Sender: TObject);
    procedure FormActivate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
Métodos de respuesta a los eventos considerados y fin de la declaración de la forma. Delphi coloca los encabezados private y public por si el usuario necesita  definiciones adicionales.
var
  Form1: TForm1;
implementation
{$R *.DFM}
Delphi coloca la declaración de la variable de referencia a la forma definida como objeto de la clase TForm1.
Comienzo de bloque de implementación de métodos de las clases definidas y de procedimientos y funciones no asociados a ninguna clase. 
procedure TForm1.HacerQuery(Sender: TObject);
var i: integer;
begin
  Height:=542;
  Query1.Open;
  Query1.First;
  DBImage1.DataSource:=DataSource2;
  DBMemo1.DataSource:=DataSource2;
  DBLabel1.DataSource:=DataSource2;
  DBLabel2.DataSource:=DataSource2;
  for i:=1 to Query1.RecordCount do
  begin
    ShowMessage(Query1Common_Name.Value + ' Largo: '
    + FloatToStrF(Query1Length_In.Value,ffFixed,6,2)+' "');
    Query1.Next;
  end;
  Query1.Close;
  DBImage1.DataSource:=DataSource1;
  DBMemo1.DataSource:=DataSource1;
  DBLabel1.DataSource:=DataSource1;
  DBLabel2.DataSource:=DataSource1;
  Height:=394;
end;
Método de respuesta al evento OnClick en el botón.

Primero se cambia la propiedad altura (Height) de la forma para que se haga visible la tabla resultado de la consulta a la BD (DBGrid2).

El método Open del TQuery hace que se ejecute la instrucción SQL definida en la propiedad SQL. El componente DataSource2 asociado al TQuery permite que se le asocie a su vez la tabla de visualización de clase TDBGrid para mostrar la tabla resultante de la consulta SQL.

Se muestra la forma de navegar en objetos de clases descendientes de la clase TDataSet, como lo son TTable y TQuery. En este caso en la tabla resultado de la consulta Query1, de clase TQuery. El método First posiciona el cursor de navegación en el primer registro o tupla de la tabla.

Para que los controles de visualización definidos para la tabla original muestren, mientras ocurre la navegación, los contenidos de la tupla visitada de la tabla resultado Query1, temporalmente se los asocia con el componente DataSource2 que es la vía de acceso definida para Query1. Dentro del ciclo de repetición for con ShowMessage se muestran, mediante el método Value, los valores de dos de los campos de la tupla: Query1Common_Name y Query1Length_In (para lo cual era necesario incluir en la definición de la forma los objetos que accesan directamente la columna correspondiente de la tabla, Ver Help de las clases de las columnas). Para convertir el string devuelto por Value en el campo numérico se usa la función Delphi FloatToStrF, ver su Help.
El método Next hace avanzar la posición del cursor a la siguente tupla o registro de la tabla. La propiedad RecordCount da el valor del número de tuplas existentes en la tabla.

Se restaura la propiedad DataSource al valor original en los controles de visualización y también se restaura el tamaño inicial de la forma.

procedure TForm1.FormActivate(Sender: TObject);
begin
  Height:=394;
end;
Se aprovecha el evento FormActivate para cambiar la altura (Height) de la forma de manera que inicialmente no esté visible la tabla resultado de la consulta a la BD (DBGrid2).
end. Fin de la Unit.

Forma MiFFactwin.dfm vista como texto
 

object Form1: TForm1
  Left = 199
  Top = 88
  ActiveControl = DBImage1
  BorderIcons = [biSystemMenu, biMinimize]
  BorderStyle = bsSingle
  Caption = 'FISH FACTS'
  ClientHeight = 515
  ClientWidth = 500
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clBlack
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = True
  ShowHint = True
  OnActivate = FormActivate
  PixelsPerInch = 96
  TextHeight = 13
  object Label2: TLabel
    Left = 96
    Top = 368
    Width = 306
    Height = 16
    Caption = 'Resultado del Query: Select * from BIOLIFE where Length_In < 17'
    Color = clBtnFace
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clRed
    Font.Height = -13
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold, fsItalic]
    ParentColor = False
    ParentFont = False
  end
  object Panel1: TPanel
    Left = 6
    Top = 8
    Width = 259
    Height = 217
    Hint = 'Scroll grid below to see other fish'
    ParentShowHint = False
    ShowHint = True
    TabOrder = 0
    object DBLabel1: TDBText
      Left = 4
      Top = 183
      Width = 249
      Height = 24
      DataField = 'Common_Name'
      DataSource = DataSource1
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clRed
      Font.Height = -19
      Font.Name = 'MS Serif'
      Font.Style = [fsBold, fsItalic]
      ParentFont = False
    end
    object DBImage1: TDBImage
      Left = 5
      Top = 8
      Width = 248
      Height = 168
      Hint = 'Scroll grid below to see other fish'
      DataField = 'Graphic'
      DataSource = DataSource1
      TabOrder = 0
    end
  end
  object Panel2: TPanel
    Left = 275
    Top = 8
    Width = 223
    Height = 22
    TabOrder = 1
    object Label1: TLabel
      Left = 7
      Top = 4
      Width = 56
      Height = 13
      Caption = 'About the'
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clBlue
      Font.Height = -11
      Font.Name = 'MS Sans Serif'
      Font.Style = [fsBold]
      ParentFont = False
    end
    object DBLabel2: TDBText
      Left = 67
      Top = 4
      Width = 99
      Height = 13
      AutoSize = True
      DataField = 'Common_Name'
      DataSource = DataSource1
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clBlue
      Font.Height = -11
      Font.Name = 'MS Sans Serif'
      Font.Style = [fsBold]
      ParentFont = False
    end
  end
  object Panel3: TPanel
    Left = 276
    Top = 32
    Width = 223
    Height = 193
    BevelOuter = bvLowered
    TabOrder = 2
    object DBMemo1: TDBMemo
      Left = 3
      Top = 2
      Width = 217
      Height = 183
      BorderStyle = bsNone
      Color = clSilver
      Ctl3D = False
      DataField = 'Notes'
      DataSource = DataSource1
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clBlack
      Font.Height = -11
      Font.Name = 'MS Sans Serif'
      Font.Style = []
      ParentCtl3D = False
      ParentFont = False
      ScrollBars = ssVertical
      TabOrder = 0
    end
  end
  object Panel4: TPanel
    Left = 0
    Top = 257
    Width = 500
    Height = 72
    BevelInner = bvRaised
    BorderStyle = bsSingle
    ParentShowHint = False
    ShowHint = True
    TabOrder = 3
    object DBGrid1: TDBGrid
      Left = 12
      Top = 8
      Width = 386
      Height = 53
      Hint = 'Scroll up/down to see other fish!'
      DataSource = DataSource1
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'MS Sans Serif'
      Font.Style = []
      ParentFont = False
      TabOrder = 0
      TitleFont.Charset = DEFAULT_CHARSET
      TitleFont.Color = clBlack
      TitleFont.Height = -11
      TitleFont.Name = 'MS Sans Serif'
      TitleFont.Style = []
    end
    object BitBtn1: TBitBtn
      Left = 424
      Top = 20
      Width = 57
      Height = 29
      Hint = 'Close Fish Facts'
      Caption = 'E&xit'
      TabOrder = 1
      Kind = bkClose
    end
  end
  object DBGrid2: TDBGrid
    Left = 8
    Top = 384
    Width = 473
    Height = 121
    DataSource = DataSource2
    TabOrder = 4
    TitleFont.Charset = DEFAULT_CHARSET
    TitleFont.Color = clBlack
    TitleFont.Height = -11
    TitleFont.Name = 'MS Sans Serif'
   TitleFont.Style = []
  end
  object Button1: TButton
    Left = 200
    Top = 336
    Width = 75
    Height = 25
    Caption = 'Query'
    TabOrder = 5
    OnClick = HacerQuery
  end
  object DataSource1: TDataSource
    DataSet = Table1
    Left = 355
    Top = 225
  end
  object Table1: TTable
    Active = True
    DatabaseName = 'DBDEMOS'
    ReadOnly = True
    TableName = 'BIOLIFE'
    Left = 389
    Top = 225
    object Table1Category: TStringField
      DisplayWidth = 15
      FieldName = 'Category'
      Size = 15
    end
    object Table1SpeciesName: TStringField
      DisplayWidth = 20
      FieldName = 'Species Name'
      Size = 40
    end
    object Table1Lengthcm: TFloatField
      DisplayWidth = 11
      FieldName = 'Length (cm)'
    end
    object Table1Length_In: TFloatField
      DisplayWidth = 10
      FieldName = 'Length_In'
      DisplayFormat = '0.00'
    end
    object Table1Common_Name: TStringField
      DisplayWidth = 30
      FieldName = 'Common_Name'
      Visible = False
      Size = 30
    end
    object Table1Notes: TMemoField
      FieldName = 'Notes'
      BlobType = ftMemo
      Size = 50
    end
    object Table1Graphic: TBlobField
      FieldName = 'Graphic'
      ReadOnly = True
      Visible = False
      BlobType = ftBlob
    end
  end
  object Query1: TQuery
    DatabaseName = 'DBDEMOS'
    SQL.Strings = (
      'select * from biolife where Length_In < 17')
    Left = 424
    Top = 224
    ParamData = <>
    object Query1SpeciesNo: TFloatField
      FieldName = 'Species No'
      Origin = '"BIOLIFE.DB".Species No'
    end
    object Query1Category: TStringField
      FieldName = 'Category'
      Origin = '"BIOLIFE.DB".Category'
      Size = 15
    end
    object Query1Common_Name: TStringField
      FieldName = 'Common_Name'
      Origin = '"BIOLIFE.DB".Common_Name'
      Size = 30
    end
    object Query1SpeciesName: TStringField
      FieldName = 'Species Name'
      Origin = '"BIOLIFE.DB".Species Name'
      Size = 40
    end
    object Query1Lengthcm: TFloatField
      FieldName = 'Length (cm)'
      Origin = '"BIOLIFE.DB".Length (cm)'
    end
    object Query1Length_In: TFloatField
      FieldName = 'Length_In'
      Origin = '"BIOLIFE.DB".Length_In'
    end
    object Query1Notes: TMemoField
      FieldName = 'Notes'
      Origin = '"BIOLIFE.DB".Notes'
      BlobType = ftMemo
      Size = 50
    end
    object Query1Graphic: TGraphicField
      FieldName = 'Graphic'
      Origin = '"BIOLIFE.DB".Graphic'
      BlobType = ftGraphic
    end
  end
  object DataSource2: TDataSource
    DataSet = Query1
    Left = 456
    Top = 224
  end
end