<-- Capítulo

Indice del tutor de Delphi
© Copyright 1998
por David Martínez.

Todos los derechos reservados

Capítulo -->

Capítulo 5. Acceso a Bases de Datos en Delphi

En este capítulo veremos como Delphi maneja el acceso a bases de datos, incluyendo las librerías requeridas y los componentes que Delphi utiliza. Se asume que usted sabe lo que es una tabla y ha usado sistemas de base de datos básicos, como dBase. No se asume experiencia previa con SQL, pero ayudaría :-) En este curso estaré utilizando SQL local en general. Si hay algo para lo cual necesito utilizar una base de datos grande (porque SQL local no soporte esa función o que no funcione como debe ser para efectos de los ejemplos), utilizaré formato generico SQL-92 exclusivamente (pero si deveras quiere saber exactamente lo que uso, estoy utilizando InterBase, que viene con Delphi 3 Profesional y Cliente/Servidor).

Estructura de Acceso de Datos en Delphi

Desde los inicios de Delphi, Borland decidió crear una estructura de acceso de datos abierta. Una buena parte de la librería de clases VCL esta dedicada a trabajar con acceso de datos de una manera abierta y flexible. Delphi y C++ Builder tienen métodos de acceso a bases de datos únicos en la industria por su flexibilidad y facilidad de uso.

Nota: Si usted tiene C++ Builder (BCB), la estructura de acceso de datos es idéntica a la de Delphi, gracias a que comparten la librería de clases VCL. La version 1 de BCB tiene el VCL de Delphi 2, y la version 3 de BCB tiene el VCL de Delphi 3 (mas unas cuantas cosas que están en el nuevo C++ y que Delphi seguramente tendrá).

Gracias al hecho de que todo en Delphi es un objeto, los creadores de Delphi crearon, entre otros, un componente abstracto llamado "TDataset". Como su nombre lo indica, un dataset es un "set de datos". Como podra ver, el set de datos abstracto no especifica el origen de la base de datos, modo de conexión o marca del producto que está en el servidor. Ni siquiera especifica si nuestro set de datos es una tabla física, un query de SQL o un archivo de texto! De esta manera se generaron los componentes que heredan de TDataset bajo una base común.

Los componentes TTable y TQuery son los componentes mas comúnmente usados para acceso básico a bases de datos (pero no los únicos). Estos componentes representan una tabla y un query de SQL, respectivamente. Para mantener el acceso de datos compatible con los diferentes productos de Borland, se desarrolló una serie de librerías redistribuibles llamada "Borland Database Engine" (BDE). Esta librería debe ser instalada en la máquina del cliente para que TTable y TQuery funcionen correctamente.

El Borland Database Engine es primordialmente una librería para manejar cursores de SQL. Muchos lenguajes son capaces de operar con un sólo "renglón" de datos de la tabla a la vez, por lo cual el manejo de los cursores de SQL no es muy satisfactorio. Pero Delphi utiliza el Database Engine como una "traducción" de cursores de SQL en el formato de Queries y Tablas interno de Delphi. Ademas, el Database Engine nos permite accesar el origen de los datos (la base de datos para la cual estamos escribiendo) a través de "drivers" intercambiables de acceso directo, o si asi deseamos, utilizar ODBC para accesar estos datos.

Un cursor es un concepto de SQL que se refiere a un set de renglones, un orden en que se encuentran esos renglones, y un "renglon actual" dentro de ese orden. Por ejemplo, cualquier "set de resultados" de un enunciado SELECT de SQL, si no devuelve un error, devolvera un cursor (vacío o con información).

Para soportar las muchas maneras en que Delphi puede accesar datos, y para facilitar enormemente al programador preocupaciones acerca de cambios en la base de datos que utilizan tus programas (por ejemplo: "Chin, soy programador de Sybase y ahora la compañía cambio a Oracle... Oracle y Sybase utilizan DLL's de acceso muy diferentes... AAAARRRRGHHH!"), Borland ha creado un muy elaborado set de BDE (Borland Database Engine), drivers para BDE y componentes en el VCL. Como resultado, usted puede programar de una manera muy parecida (casi idéntica!), ya sea que usted utilice tablas de dBase (a traves de una parte del BDE conocido como Local SQL) o bases de datos grandes como Oracle, Sybase o Interbase.

El siguiente diagrama muestra las maneras en que Delphi y la base de datos pueden conectarse (está un poco simplificado, ya que hay algunos componentes intermedios - para mayor información consulte la documentación de Delphi):

¿Complicado? No se preocupe, esta imagen cubre todas las posibilidades de acceso de datos, incluyendo la nueva tecnología MIDAS, asi que no lo tiene que entender en su totalidad. Usualmente usted solo seleccionará uno de los métodos de acceso a bases de datos (dependiendo en su software existente y necesidades de conexión), y se olvidará de todos los demás. Cuando siga las secciones prácticas en los siguientes capítulos, refiérase a este diagrama para "descubrir" qué modo de acceso de datos estamos utilizando en cada sesión práctica. Esta estructura pone todo el poder de acceso a bases de datos de muy diferentes tipos en sus manos, en forma de simples componentes que usted puede poner en sus formas. Al mismo tiempo, le proporciona suficiente poder para escribir su propia estructura de base de datos si eso es lo que usted quiere, sin cambiar los componentes en el lado del cliente.

¿Porqué SQL?

Muchos programadores de Clipper, dBase y FoxBase me preguntan "qué onda con SQL, y por qué es tan importante aprenderlo?". La respuesta es sencilla: COMPATIBILIDAD. Si bien es cierto que muchas compañías tienen su propio "tipo" de SQL, la especificación SQL-92 es soportada por todos y cada uno de los lenguajes de bases de datos grandes. Ademas, Microsoft y Borland han añadido soporte SQL para todos sus lenguajes. El resultado de esto es que, si usted aprende SQL-92, usted puede programar básicamente para cualquier base de datos sin importar su tamaño y complejidad. Claro está, despues de aprender SQL, se puede especializar en cualquier "sabor" de SQL en particular. Pero recuerde, cualquier cosa que programe en Delphi para un específico "tipo" de SQL funcionará, pero le hara mas dificil moverse a otro tipo de servidor en el futuro. Dependerá de usted hacer este tipo de decisiones.

Un buen libro de SQL es "SQL for Dummies", por Allen G. Taylor. Ademas de ser un libro de SQL en general muy facil de entender, el autor utiliza las herramientas de Delphi! El libro explica SQL en general sin especificar una versión de base de datos en particular (Yo sospecho que, ya que esta usando las herramientas de Delphi, esta programando en Interbase). Si usted cree que le pueda interesar migrar a una base de datos SQL en el futuro y utiliza Delphi o C++ Builder, programe en Delphi como si ya tuviera una, utilizando los drivers de SQL local de Paradox, dBase o MSAccess. Despues le será mas facil migrar su base de datos.

Configuración del BDE - Aliases

Un Driver de BDE es un componente de software que actua como intermediario entre la librería de cursores del BDE y los datos Físicos. Delphi viene con drivers para dBase, Paradox e Interbase, además de un driver para ODBC, que le permite accesar cualquiera de las bases de datos que ODBC soporta. En ediciones cliente/servidor, Delphi cuenta con drivers "nativos" de SyBase, Oracle y MS-SQL Server.

ODBC es un producto de Microsoft que es utilizado para accesar datos con Office, Visual Basic y otras aplicaciones de Microsoft y de terceros. Es analogo al BDE en el sentido de que tiene drivers que actuan como intermediarios entre los datos y conexiones físicas y el software de acceso, pero es diferente porque ODBC se limita a traducir llamadas SQL a la conexion fisica, sin libreria de cursores que traduzca los resultados.

Esta estructura requiere de un concepto llamado "Alias". Un alias de BDE es un conjunto de especificaciones que describen el metodo que el BDE utilizará para accesar el servidor, incluyendo driver físico, mapa de caracteres internacionales, etc.

Los Aliases le permiten especificar todos aquellos parámetros que hacen a su aplicación depender de un servidor en particular afuera de su ejecutable, en un archivo de configuración en la maquina del cliente. El programa de instalacion InstallShield que viene con Delphi Professional y Client Server (no estoy seguro si viene con Delphi Standard) le permite instalar el BDE con su aplicación y especificar los aliases necesarios, respetando las configuraciones ya existentes.

Componentes No Visuales de Acceso a Datos

Del lado del cliente en Delphi, la paleta de componentes llamada "Data Access" contiene todos los componentes no visuales que usted puede poner en su aplicación para conectarse a una base de datos. Los componentes más importantes incluyen:

TSession

Un alias se conecta a una "sesión", representada por el componente TSession. Esta sesión es una conexión Física a la base de datos. Los programas de Borland pueden compartir sesiones globalmente, y cada programa puede tener cualquier número de sesiones simultáneas. De este modo, usted puede compartir una sola conexión (sesión) a la base de datos para economizar licencias, sin importar cuantos ejecutables este utilizando para accesar los datos, o si las licencias por conexion no son limitadas en su base de datos, puede utilizar varias sesiones en una sola aplicacion para programar sus queries con multitarea.

Incluso si usted no pone un componente TSession en su aplicación, Delphi define uno por cada aplicación, representado por la variable de objeto global "Session".

TDatabase

TDatabase es la representación de una base de datos. Tal como en su servidor de SQL usted puede crear más de un "contenedor de base de datos", Delphi puede compartir una conexión (TSession) entre varios contenedores de bases de datos (TDatabase). Tal como en la sesión, si usted no pone un TDatabase en su aplicación Delphi especifica uno en la variable de objeto global "Database".

Programadores de dBase/Clipper: Una base de datos, en el sentido de SQL, es una colección de tablas, vistas, procedimientos SQL y tipos de datos. En los viejos tiempos de dBase, muchos programadores "entendían" que una base de datos era un archivo DBF, y el concepto de Tablas no existía. Ahora, si usted utiliza DBF o Paradox, Delphi entenderá por base de datos el directorio donde se encuentran los DBFs en cuestión, y las Tablas serán cada uno de los DBFs. Esto quiere decir que si usted está acostumbrado a poner sus DBFs en diferentes subdirectorios (que es algo que yo acostumbraba a hacer en Clipper/dBase), cada directorio representará un TDatabase diferente. En Delphi un TDatabase para tablas locales no especifica el tipo de tabla, así que usted puede mezclar tablas Paradox y dBase en el mismo directorio sin problemas.

TTable

TTable es la representación de una tabla, y es a lo que están acostumbrados los programadores en Clipper. TTable representa una tabla entera en Delphi. TTable contiene información acerca del tipo de tabla (que solo se usa en tablas locales - paradox, dbase, etc) y del nombre del índice, así como filtros. TTable tiene entre sus métodos, First, Next, Last, etc.

Programadores dBase/Clipper/Paradox: Es MUY IMPORTANTE aprender que, mientras ustedes estarán más inclinados en un principio a usar TTable que su "primo" TQuery, TTable representa la tabla COMPLETA. Esto puede parecer trivial para los usuarios de bases de datos locales, pero en SQL es muy importante. El abrir un TTable por sí mismo (sin filtro) contra un servidor SQL hara que Delphi ejecute un SELECT * FROM LATABLAQUESEA, lo cual, en un ambiente de producción, ¡puede querer decir traerse dos o tres millones de renglones por el cable! En general TTable no es muy usado en un ambiente Cliente/Servidor (aunque tiene sus usos). ¡Tenga cuidado!

TQuery

TQuery es la representación de cualquier comando de SQL que regresa un cursor de SQL (ya sea de tipo SELECT o un "Stored Procedure" - vea TStoredProc). Este cursor de SQL se comporta como una tabla. Los programadores con experiencia en SQL encontrarán a TQuery muy útil, ya que se comporta como un TTable (en el sentido de que tiene First, Next, Last, etc), pero al mismo tiempo es un comando de SQL. El programador de SQL no tiene que hacer "Fetch". Además, cuando el usuario edita campos asociados a un TQuery, Delphi se encarga de generar los comandos "UPDATE" y "DELETE" si el resultado del Query es Read/Write (vea TUpdateSQL).

Programadores dBase/Clipper/Paradox: Probablemente una de las mejores cosas que Delphi tiene para los usuarios de tablas locales es que Delphi tiene un pequeño SQL a traves de los drivers de tablas locales. Esto quiere decir que usted puede programar TQuery como si su tabla DBF tuviera un "servidor SQL". De esta manera, usted puede mantener (si programa con atención a los detalles particulares de cada version de SQL) una sola base de código para tablas locales y bases de datos gigantescas.

TDataSource

El Datasource es, como su nombre lo indica, una representación del "origen de los datos". DataSource no requiere el BDE, pero es el componente que "mapea" los componentes visuales de base de datos con los no visuales. El hacer un componente intermedio es importante porque de este modo podemos tener varias representaciones de los mismos datos sin tener que "atar" la representación de los datos en pantalla a la representación "física" de los datos. Un DataSource se conecta a su vez a cualquier componente tipo Dataset, como TQuery, TTable, TClientDataset, ¡o el que usted haya creado! DataSource nos permite ser consistentes en la representación de nuestros datos en pantalla sin preocuparnos de donde vengan los mismos (Tablas, queries, o nuestros propios metodos).

TUpdateSQL

En SQL-92, existe una limitación en cuanto a los enunciados "Select". Existen muchas circunstancias en las cuales SQL regresará un cursor de solo lectura, en vez de el cursor de Lectura/Escritura que nos gustaría obtener. Por ejemplo, si el enunciado SQL especifica una unión de tablas, SQL nos devolverá un cursor que podemos representar como el resultado de un Query en Delphi, pero no podremos editar el resultado. Obviamente esta limitación es muy severa si queremos hacer ciertas "maravillas" con nuestra aplicación (queries editables con referencias en texto es una de estas cosas).

Aqui es donde UpdateSQL hace su magia. Todos los queries tienen un Edit, Insert y Delete. UpdateSQL puede ser encadenado a un query cuyo resultado será de lectura unicamente para decirle a Delphi qué vamos a hacer cuando el usuario edite, inserte y borre un registro. En el Edit, podemos poner un SQL UPDATE, en Insert podemos poner un SQL INSERT, etcétera. De este modo nos "brincamos" la limitación de SQL utilizando sentencias específicas, pero lo mantenemos automatizado gracias a Delphi.

TStoredProc

Aunque TQuery puede ejecutar un stored procedure que devuelva un valor (y tenemos que usar un TQuery si queremos recuperar ese valor), a veces el stored procedure no devuelve nada. TQuery espera un valor de regreso, y nos devolvera un error si el servidor no devuelve un valor. Por este motivo, para esos procedimientos necesitamos un objeto que nos permita ejecutar un comando SQL sin esperar ninguna respuesta. TStoredProc es ese comando.

En SQL, un "Stored Procedure" es un procedimiento escrito en lenguaje SQL. Puede ser tan sencillo como un Select con variables y un "join" de tablas, o tan complicado como un procedimiento Batch que calcula los salarios de todos los empleados y los pone en la tabla de nómina.

Existen más componentes no visuales de acceso a datos, pero estos son suficientes para hacer muchas aplicaciones cliente servidor sin problemas. Cuando veamos "Multi-Tier" y Objetos de Negocios (Business Objects), que es una nueva capacidad de Delphi Cliente/Servidor, veremos otros modos de acceso de bases de datos un poco más "indirectos".

Componentes Visuales de Acceso a Datos

Los componentes visuales de base de datos son los que ponemos directamente en la forma para desplegar información y permitir al usuario editarla. Todos los componentes de este tipo son llamados "Data-aware", y tienen el prefijo "DB". De este modo, un componente de edición "Edit" en su versión "Data Aware" es llamado "DBEdit". ComboBox se convierte en "DBComboBox". Muchos de los componentes visuales (Incluyendo el Grid) tienen una versión "Data Aware". Además, usted puede crear sus propios componentes data aware.

Ademas, existe un componente llamado "DBNavigator", que es una serie de botones "mapeados" a los comandos Next, Prior, Last, Edit, Delete, etc., de cualquier DataSource.

Todo esto le permite a usted poner unos cuantos componentes data aware en su forma (junto con un DBNavigator), conectarlos a un DataSource (que se encontraria conectado a un Dataset abierto), y correr su programa, y asi de fácil tendria usted una aplicacion básica con acceso a base de datos, ¡sin tener que escribir una sola línea de codigo! Lo cual nos lleva a nuestro próximo capitulo, donde haremos una aplicación de base de datos casi sin tener que usar código!

Capitulo -->