You are on page 1of 47

26/6/2014

Firebird
Saved from http://infoback.com.ar/buhardilla/firebird/firebird.htm
All snapshots from host infoback.com.ar

search

6 Mar 2013 01:55:18

no othe r snapshots from this url

Linked from es.wikipedia.org Firebird


Text

Image

download .zip

re port abuse

PIN THIS PA GE:

othe r

Firebird
Contenido
Firebird................................................................................................................................................... 1
Introduccin............................................................................................................................................ 5
Descripcin y caractersticas generales.................................................................................................... 5
Arquitectura....................................................................................................................................... 7
Servidor........................................................................................................................................ 7
Cliente.......................................................................................................................................... 7
Bloqueos, versiones y generaciones................................................................................................ 7
Operaciones con mltiples tablas.............................................................................................................. 9
Transacciones.................................................................................................................................... 9
Concurrencia 1: niveles de aislamiento de transacciones................................................................. 11
Concurrencia 2: modo de bloqueo de una transaccin..................................................................... 12
Bloqueos pesimistas..................................................................................................................... 14
Mantener el contexto................................................................................................................... 15
Integridad referencial........................................................................................................................ 15
Instalacin y puesta en marcha............................................................................................................... 17
Descarga desde Internet................................................................................................................... 17
Probar la instalacin.......................................................................................................................... 17
ISQL.......................................................................................................................................... 18
Herramientas................................................................................................................................... 19
IBServer..................................................................................................................................... 19
IBGuardian.................................................................................................................................. 19
ISQL.......................................................................................................................................... 19
Gbak........................................................................................................................................... 19
IBConsole................................................................................................................................... 19
Ejecutar sentencias SQL en IBConsole.................................................................................... 21
IBOConsole................................................................................................................................ 22
IB_SQL...................................................................................................................................... 23
SQL..................................................................................................................................................... 24
El lenguaje de consulta...................................................................................................................... 24
SQLSQL son las iniciales de......................................................................................................... 24
Cursores vs conjuntos....................................................................................................................... 24
Seleccin de registros: SELECT........................................................................................................ 25
Orden en la sala........................................................................................................................... 29
Filtrados y bsquedas................................................................................................................... 30
Fechas/Horas en SQL.................................................................................................................. 32
Criterios de seleccin................................................................................................................... 34
Funciones.................................................................................................................................... 38
Funciones de agregacin.............................................................................................................. 38
Subconsultas................................................................................................................................ 41
Comparacin con el resultado de una subconsulta.......................................................................... 43
Uniones....................................................................................................................................... 45
Consulta de varias tablas relacionadas........................................................................................... 45
Creacin, modificacin y borrado de objetos............................................................................................ 52
Lenguaje de Definicin de Datos (DDL)............................................................................................ 52
http://archive.today/yKaUQ

1/47

26/6/2014
Firebird
Lenguaje de Definicin de Datos (DDL)............................................................................................ 52

Bases de Datos........................................................................................................................... 52
Creacin de una base de datos................................................................................................. 52
El tamao no importa (perdn, Godzilla!)................................................................................... 53
Pginas.................................................................................................................................. 53
El juego de caracteres............................................................................................................. 54
Modificacin de una base de datos........................................................................................... 57
Borrado de una base de datos.................................................................................................. 58
Tablas......................................................................................................................................... 58
Creacin de una tabla.............................................................................................................. 58
Nombres de objetos................................................................................................................. 59
Tipos de datos soportados por Firebird...................................................................................... 59
Condiciones para los campos................................................................................................... 60
Campos calculados.................................................................................................................. 61
Restricciones.......................................................................................................................... 62
Modificacin de la estructura de una tabla................................................................................ 63
Borrado de una tabla completa................................................................................................. 65
Dominios..................................................................................................................................... 65
Creacin de dominios.............................................................................................................. 65
Modificacin de dominios......................................................................................................... 66
Borrado de dominios................................................................................................................ 66
Indices........................................................................................................................................ 66
Crear un ndice....................................................................................................................... 66
Modificar un ndice.................................................................................................................. 66
Borrar un ndice...................................................................................................................... 67
Restricciones.................................................................................................................................... 67
PK.............................................................................................................................................. 67
UQ............................................................................................................................................. 67
FK.............................................................................................................................................. 67
Check......................................................................................................................................... 67
Not Null...................................................................................................................................... 67
Generadores..................................................................................................................................... 67
Crear un generador...................................................................................................................... 68
Modificar un generador................................................................................................................ 68
Borrar un generador..................................................................................................................... 69
Excepciones..................................................................................................................................... 69
Definir excepciones..................................................................................................................... 69
Modificar excepciones................................................................................................................. 69
Borrar excepciones...................................................................................................................... 69
Programacin del servidor...................................................................................................................... 70
Scripts............................................................................................................................................. 70
Procedimientos almacenados............................................................................................................. 71
Procedimientos de accin............................................................................................................. 71
Triggers................................................................................................................................................ 72
Funciones del usuario (UDF).................................................................................................................. 73
Libreras estndar de funciones externas............................................................................................ 73
Crear funciones externas en Delphi................................................................................................... 73
Acceso desde Delphi............................................................................................................................. 74
BDE................................................................................................................................................ 74
IBX................................................................................................................................................. 74
DBX................................................................................................................................................ 74
ADO............................................................................................................................................... 74
IBO................................................................................................................................................. 74
http://archive.today/yKaUQ

2/47

26/6/2014

Firebird

UIB................................................................................................................................................. 74
Optimizacin......................................................................................................................................... 75
Plan de ejecucin.............................................................................................................................. 75
Creacin de ndices........................................................................................................................... 75
Selectividad...................................................................................................................................... 75
Restricciones declarativas vs. activas................................................................................................. 75
Restriccin de la cantidad de registros a traer al cliente....................................................................... 75
Futuro................................................................................................................................................... 75

Introduccin
El mundo de las Bases de Datos es ancho y ajeno, parafraseando a un escritor muy conocido. Existen muchos sistemas de stos, con caractersticas que los distinguen unos
de otros. No obstante, todos comparten el mismo ncleo de funcionalidad, su objetivo bsico: sirven para almacenar y procesar datos, a veces cantidades realmente
grandes.
Las diferencias vienen despus. Cmo se almacenan los datos, qu tipos de datos pueden contener, qu tan avanzado es el lenguaje que permite consultar esos datos,
caractersticas avanzadas para optimizar el proceso de grandes cantidades de datos, por nombrar unas pocas. Aqu veremos solamente uno de estos sistemas en realidad
dos, ya que son prcticamente iguales- aunque me referir eventualmente a otros sistemas para hacer algunas comparaciones que nos permitan situarnos mejor en el tema.
El sistema principal que es objetivo del presente se denomina Firebird, literalmente Pjaro de fuego, el Fnix que renace de sus cenizas. No tengo confirmacin oficial,
pero creo que el nombre se eligi por las mltiples vidas que ha tenido el proyecto Interbase, que culminaron en Firebird. Las caractersticas de este gestor de datos son
prcticamente iguales hasta la versin 1.0- a las de Interbase de Borland en su versin 6.0. Y es que Firebird fue creado a partir de los fuentes de Interbase 6.0, liberados
por Borland bajo licencia IPL. Un conjunto de excelentes y voluntariosos programadores se impuso la tarea de llevar adelante el gestor de datos sin costo, agregando y
mejorando caractersticas. En estos momentos (Febrero 2003) ya est disponible la beta 2 de la versin 1.5 de Firebird, que ya se aparta un poco de Interbase proveyendo
caractersticas diferenciales tanto en el lenguaje de consulta como en los procesos internos.
Por su lado, Borland sigue avanzando tambin con Interbase pero ya no en forma gratuita. Se han liberado ya dos versiones ms de Interbase, 6.5 y 7. Las mejoras y
nuevas caractersticas de estas versiones no estn disponibles en Firebird, o tienen otros nombres y sintaxis. Borland ya tom partido en cuanto a Firebird: no se va a hacer
ningn esfuerzo por mantener la compatibilidad, no slo de Interbase sino tampoco en los componentes de acceso de sus herramientas de desarrollo. As, por ejemplo, el
controlador DBExpress de Interbase soporta las caractersticas nuevas de Interbase 7 pero no las de Firebird 1.5. Cuando hablemos de las formas de acceder por programa
al servidor nos ocuparemos de estos problemas y las soluciones que estn apareciendo.

Descripcin y caractersticas generales


Firebird es un Gestor de Bases de Datos Relacionales. Es decir que trabaja con el esquema relacional surgido en los laboratorios de IBM, de la mano de E. F. Codd y Chris
Date. Este esquema ha sido implementado con xito en forma comercial, y de hecho la mayora de las aplicaciones de Bases de Datos se utilizan gestores que trabajan con
[1]
este modelo .
Firebird es pequea una instalacin completa ocupa alrededor de 10 Mb incluyendo libreras, ejemplos de programacin y BD de muestra-, fcil de instalar y ejecutar, y
an as muy poderosa. Puede trabajar muy bien con cantidades de datos que van desde unos pocos hasta varios millones de registros por tabla. Generalmente no es
necesario tomar medidas especiales para optimizar el rendimiento del servidor, aunque tenemos la posibilidad de tocar algunas variables para sacar ms provecho a
situaciones particulares.
Se puede ejecutar en una amplia variedad de sistemas operativos: Windows en todas sus encarnaciones, Linux, Solaris, MacOS y otros

[2]

Por su tamao, rendimiento y poca necesidad de mantenimiento es un gestor ideal para aplicaciones pequeas y medianas, que se puede llevar sin problemas a trabajar en
situaciones ms exigentes y con mayor carga de trabajo y datos.
Fsicamente, Firebird trabaja con uno o varios archivos adonde almacena todos los datos y estructuras: no ms proliferacin de archivos como tenamos con Paradox o
Dbase. Los archivos de Firebird 1.0 al igual que los de Interbase 6.0- pueden tener hasta 2 Gb de tamao cada uno.
Firebird posee la mayora de las caractersticas avanzadas de los gestores modernos:

Transacciones

Posibilidad de definir ndices ascendentes o descendentes, con restriccin de unicidad

Posibilidad de definir restricciones a los datos en la declaracin de las tablas, como ser
o Integridad referencial
o Unicidad
o Controles de validacin (Check)
o Columnas computadas, slo de lectura

Posibilidad de programacin del servidor mediante disparadores triggers- y procedimientos almacenados stored procedures.

Posibilidad de definir procedimientos almacenados que devuelvan tablas virtuales

Posibilidad de definicin de vistas


http://archive.today/yKaUQ

3/47

26/6/2014
Posibilidad de definicin de vistas

Firebird

Generadores de nmeros secuenciales, independientes de las transacciones

Excepciones

Eventos

Funciones definidas por el usuario

Dominios

Un lenguaje SQL amplio y potente, que contempla funciones avanzadas como ser
o Subconsultas
o Uniones
o Funciones de agregacin
o Ordenamiento por columnas calculadas, etc
o Vectores multidimensionales (matrices)

En el apndice <<<??>>> se puede ver un resumen de las caractersticas y lmites tcnicos de Firebird.

Arquitectura
Firebird se compone de dos partes: el servidor propiamente dicho, y el cliente que se comunica con l.

Servidor
El servidor es la parte que hace el trabajo: almacena los datos, los procesa, ejecuta los procedimientos almacenados y aplica las validaciones. Debe existir uno por lo menos
en la red.

Cliente
El cliente es la parte que se encarga de la comunicacin entre las aplicaciones y el servidor. Maneja los protocolos, enva y recibe datos, enva comandos, etc. Es una capa
mnima una librera de enlace dinmico, algunos archivos auxiliares y entradas en el registro de servicios del sistema- pero necesaria para la comunicacin con el servidor.
Debe instalarse en todos los equipos que vayan a acceder al servidor, incluido el equipo adonde resida fsicamente el mismo servidor si se va a usar como terminal.

Bloqueos, versiones y generaciones


La principal caracterstica que distingue a Firebird/Interbase del resto de los gestores comerciales conocidos como Oracle, SQLServer o MySQL es su arquitectura
generacional.
La mayora de los gestores de datos relacionales implementan un mecanismo de transacciones, y Firebird no es la excepcin; la diferencia est en cmo se implementa el
mecanismo. Generalmente se utilizan bloqueos de diferentes niveles registro, pgina, tabla- para impedir que otras transacciones modifiquen datos que se estn
procesando. Esto tiene la desventaja de que esas transacciones quedarn imposibilitadas de trabajar con los datos bloqueados hasta que la transaccin que impuso el
bloqueo termine.
Pensemos en el siguiente ejemplo: una empresa tiene que consolidar los datos de los inventarios de sus sucursales, para lo cual tiene que leer los valores de cada sucursal y
acumularlos. La aplicacin que har la consolidacin comienza una transaccin y va leyendo y sumando los datos de cada sucursal; no modifica nada, por lo que no seran
necesarios los bloqueos termina de sumar todo, almacena o muestra el resultado y termina la transaccin. Todos contentos.
Ahora pensemos qu pasara si en el medio del clculo una sucursal transfiere productos a otra, o simplemente los vende.
Claro que la operacin debe quedar registrada en la base de datos, por lo que cambian los datos que se estn sumando si no tomamos medidas, podemos llegar a sumar
varias veces los mismos productos, o a dejar alguno afuera.
Estas situaciones se controlan mediante los distintos niveles de aislamiento de las transacciones, que indican lo que una transaccin ver de los cambios que produce otra
transaccin que se activa al mismo tiempo. Para que los datos de la transaccin que acumula sean fidedignos, se debe usar el nivel de aislamiento ms alto posible: esta
transaccin no debera ver los cambios hechos por las dems en todo el tiempo que dure. Este nivel se denomina generalmente de lecturas repetibles.
Para lograr este nivel de aislamiento sera necesario bloquear los cambios a todos los registros a considerar, o hacer una copia (una nueva generacin de datos) de los
registros usados para la acumulacin, que entonces podran ser ledos cuantas veces fuera necesario. La mayora de los gestores de bases de datos utilizan el primer
mecanismo; Firebird usa el segundo.
En breve: cada vez que se hace una modificacin a un registro, se crea una nueva versin o generacin del mismo marcndola con un nmero que identifica a la
transaccin que realiz el cambio. Con la ayuda de otra estructura de la que hablaremos enseguida, este mecanismo permite a Firebird lograr el nivel de lecturas repetibles
sin usar bloqueos, as como evitar el uso de archivos de registro de operaciones (log).

Las transacciones existentes en un determinado momento en la base de datos pueden estar en uno de tres estados

Activa

Aceptada (Committed)

http://archive.today/yKaUQ

[3]

4/47

26/6/2014

Firebird

Cancelada (Rolled back)

El estado de todas las transacciones existentes en la BD es mantenido en las Pginas de Inventario de Transacciones o TIP (Transaction Inventory Pages). Es una lista
de todas las transacciones que tienen datos en la base en cada momento, acompaadas de su estado.
Cuando comienza una transaccin, se le asigna un nmero nico que la identifica (llamado UTN, Unique Transaction Number) y se le entrega una lista de todas las
transacciones que tienen datos en la base y sus estados a ese momento: una copia de la TIP.
Los nmeros identificadores de las transacciones (UTNs) son enteros crecientes en el tiempo; es decir, si una transaccin comienza despus de otra es seguro que recibir
un UTN ms grande que la primera. La consecuencia inversa ser muy usada en el mecanismo de versiones: si hay dos versiones de un mismo registro, la que tenga la
UTN ms grande ser posterior a la otra.
Cuando una transaccin tiene que actualizar un registro, busca en su TIP si haba otras transacciones activas al momento de comenzar. Si no hay ninguna otra, entonces
actualiza el registro sin ms. Pero si encuentra al menos una transaccin activa en la TIP, no modifica el registro original: crea una nueva versin almacenando las
diferencias (para ahorrar espacio) y su propio nmero de transaccin, el UTN.
Ahora bien, si una transaccin quiere leer un registro, compara su propio identificador con el de la ltima versin del registro. Si el UTN de la ltima versin es mayor al de
la transaccin en cuestin, se toma la versin anterior del registro. As se recorre la cadena de versiones hasta encontrar una cuyo UTN sea menor que el de la transaccin,
y que adems est marcada como Aceptada en el inventario (TIP). Cualquier otra versin es pasada por alto.
Ejemplo. Supongamos que tenemos la siguiente secuencia temporal:
1. La transaccin 100 modifica un registro. Se crea una versin con UTN=100.
2. Se acepta la transaccin 100 (estado: committed)
3. Comienza la transaccin 103, que modifica el mismo registro. Se crea una nueva versin con UTN=103.
4. Se cancela la transaccin 103 (estado: rolled back)
5. Comienza la transaccin 110, que modifica el registro. Se crea una nueva versin con UTN=110. La transaccin no termina todava (estado: active)
6. Comienza la transaccin 112.
7. Comienza la transaccin 115, que modifica el registro. Se crea una nueva versin con UTN=115.
8. Se acepta la transaccin 115 (estado: commited)
9. La transaccin 112 lee el registro en cuestin. Cul es la versin que recupera?
La versin 115 es posterior a su propio UTN, por lo que no se considera. Busca el anterior.
La versin 110 corresponde a una transaccin que no ha terminado (estado = active) por lo que tambin se ignora.
La versin 103 corresponde a una transaccin cancelada, por lo que tambin se ignora.
Finalmente, la versin 100 es correcta y es la que se recupera.
Con este mecanismo se obtienen dos beneficios directos:

Se trabaja en un nivel de aislamiento de lecturas repetibles sin bloquear las actualizaciones concurrentes a la lectura

No se necesita llevar un registro de las operaciones para recuperar la base de datos de fallos; toda la informacin est incluida en las versiones y la TIP. Lo nico
que necesita hacer el servidor para recuperar una base de datos despus de un fallo de alimentacin por ejemplo, es recorrer la TIP y marcar como canceladas a
todas las transacciones que figuran como activas. De esta manera, los cambios que se haban producido son ignorados en subsecuentes operaciones.

Por supuesto que tambin hay alguna contra: la base de datos va acumulando basura en la forma de versiones que no son utilizables. Esto obliga a ejecutar una accin de
limpieza a intervalos, proceso que se denomina sweep. Este proceso elimina las versiones anteriores de los registros, dejando solamente la ltima valida, pero puede
impactar negativamente en la performance del servidor. Por defecto se ejecuta automticamente cada 20.000 transacciones. Se puede configurar esta cantidad en los
parmetros del servidor, y tambin se puede ejecutar manualmente la limpieza.
[ERC1]
[ERC2]

Operaciones con mltiples tablas


En el modelo relacional tenemos que lidiar con operaciones que involucran varias tablas. Por ejemplo, el tpico caso de un pedido o una factura: tendremos por lo menos dos
tablas, una para los datos que identifican al pedido (fecha, cliente, nro, etc) y la otra con los datos de cada item que compone el pedido (cantidad, codigo, precio unitario,
etc). Cuando se ingresa una factura, tambin generalmente modificaremos datos en otras tablas: stock o inventario, cuenta corriente del cliente, etc. Sera muy problemtico
si por cualquier causa como un corte de conexin- se interrumpe el proceso de actualizacin de algunas tablas despus de terminar con otras: pueden quedar registros
hurfanos, por ejemplo items que no tienen factura, o datos desactualizados como el total de la cuenta corriente del cliente.
Hay varias tcnicas para combatir estos problemas, un par de las cuales veremos ahora: transacciones y restricciones de integridad referencial.

Transacciones
http://archive.today/yKaUQ

5/47

26/6/2014

Firebird

Una transaccin es un conjunto de operaciones que se aceptan (Commit) o rechazan (Rollback) como una sola. Son como parntesis que encierran las operaciones que se
deben realizar o cancelar juntas: todas las operaciones quedan en suspenso hasta que se termina la transaccin. No se podrn ver desde ninguna otra transaccin, lo cual
es una de las mayores sorpresas cuando uno empieza a trabajar de esta manera (si no tenemos esto en cuenta, los cambios realizados en una estacin no se vern desde
otra hasta que se cierre y se vuelva a abrir la aplicacin).
Las transacciones deben tener los siguientes atributos, reconocidos generalmente el acrnimo ACID, por sus iniciales en ingls:

A por Atomicity (Atomicidad). Las operaciones incluidas en una transaccin se manejan como un todo indivisible. Todas las operaciones se aceptan juntas, o
ninguna.

C por Consistency (Consistencia). Las transacciones siempre llevan la base de datos desde un estado consistente a otro; no pueden quedar datos inconsistentes,
por ejemplo dos registros en la misma tabla con el mismo valor en la clave primaria. Si pueden darse inconsistencias durante el desarrollo de una transaccin; pero las
dems transacciones simultneas que existan no vern este estado, y todas las inconsistencias debern resolverse al momento de terminar la transaccin.

I por Isolation (aIslamiento). Cada transaccin se ejecuta como si estuviera sola en la base de datos; los cambios producidos por otras transacciones concurrentes
no deben verse desde las dems.

D por Durability (Durabilidad o persistencia). Una vez que una transaccin se acepta, sus cambios quedan fijos en la base de datos an en caso de una falla del
sistema o cada de la conexin. Como un corolario, tambin se asegura que los cambios no se mantendrn en caso de una cada prematura del sistema, antes que la
transaccin sea aceptada con Commit.

La implementacin de transacciones de Firebird cumple con todas estas propiedades.


Debido al diseo de Firebird, todos los comandos deben ejecutarse en el contexto de una transaccin; si no la controlamos nosotros, se empieza una automticamente antes
de ejecutar cada comando y se termina tambin automticamente al finalizar el comando. Cuando queremos agrupar varias acciones en una sola transaccin, debemos
comenzarla y terminarla explcitamente. La accin de aceptar todos los cambios de la transaccin se denomina en ingls Commit, mientras que el proceso de rechazar los
cambios, volviendo atrs todas las acciones realizadas, se denomina Rollback.
El lenguaje de programacin de Firebird no tiene sentencias de manejo de transacciones; esto es as porque todos los accesos a Interbase deben hacerse dentro del
contexto de una transaccin, y no se aceptan transacciones anidadas. Es decir que todos los procedimientos almacenados o triggers que puedan llegar a ejecutarse lo
harn siempre dentro de la transaccin del cliente que los ejecuta; en otras palabras, la responsabilidad es toda nuestra!
En base a lo discutido, podemos ya entrever algunos problemas comunes en las aplicaciones y sus causas:

Los datos se pierden al cerrar la aplicacin


Se aceptaron los cambios en la aplicacin, pero no se ha aceptado la transaccin. Los datos estn en suspenso en la Base de Datos hasta que se ejecute Commit, de
tal manera que si nuestra aplicacin no lo hace y cierra la conexin, el servidor asumir que se produjo algn problema y har un Rollback automtico; todas las
modificaciones realizadas en esa transaccin se perdern..

Los cambios hechos en una estacin no se reflejan en otras que acceden simultneamente a los mismos datos
Esto es una consecuencia de las propiedades de Consistencia y Aislamiento. Como dijimos antes, las modificaciones realizadas dentro de una transaccin deben ser
aceptadas o canceladas en conjunto. Hasta ese momento, quedan en un limbo informtico y nadie se enterar de su existencia. Incluso despus de terminada
correctamente una transaccin puede haber diferencias en lo que se ve en una y otra estacin de trabajo depende del nivel de aislamiento de las distintas
transacciones concurrentes, un tema que veremos en breve.

Problemas de bloqueos en registros que ya se modificaron


Cuando se trabaja con mltiples usuarios a la vez es importante mantener las transacciones de corta duracin. Por qu? Porque como hemos visto, los otros usuarios
no vern nuestros cambios hasta que cerremos nuestra transaccin; pero adems, los registros modificados son bloqueados para la edicin desde otras terminales
bloqueo que se mantiene mientras dura la transaccin. Imaginemos que desde un puesto de venta se comienza una factura, se actualiza el stock, y antes de terminar la
transaccin el empleado se detiene a tomar un caf no se podrn vender los mismos productos desde otras terminales hasta que vuelva y termine con su
transaccin!
Tambin hay un problema con el recolector de basurade Firebird, pero ese problema es menos urgente que los anteriores (se nota despus de un tiempo). En breve, el
sistema recolector de basura de Firebird se activa despus de N transacciones (un parmetro de configuracin del servidor) y se encarga de eliminar los objetos
auxiliares que crea el servidor mientras procesa los datos. Si dejamos pasar mucho tiempo sin que se active este sistema, se puede ralentizar mucho la operacin del
servidor.

Concurrencia 1: niveles de aislamiento de transacciones

[4]
Cuando se trabaja en modo multiusuario , accediendo desde varias estaciones a la misma Base de Datos, hay que tener especial cuidado con las transacciones
concurrentes de los clientes. El servidor define varios niveles de aislamiento de transacciones concurrentes, que indican cmo se relacionan las transacciones
simultneas entre s.
Como un ejemplo, consideremos la siguiente situacin: un usuario empieza una transaccin y hace algunos cambios. Mientras todava su transaccin est activa, otro usuario
empieza una segunda transaccin. El segundo usuario no ver los cambios que realice el primero, a menos que est en el modo ms bajo de aislamiento (que no existe
en Firebird, ver a continuacin). Este comportamiento puede confundir al ms pintado, ya que posiblemente las dos transacciones se hagan... en la misma mquina!
Entonces sera posible realizar un cambio en una ventana y no verlo desde otra; incluso re-ejecutando la consulta.
Los niveles de aislamiento de transacciones de Firebird son los siguientes:
http://archive.today/yKaUQ

6/47

26/6/2014
Los niveles de aislamiento de transacciones de Firebird son los siguientes:

Firebird

read commited (lectura de lo aceptado): si estamos en una transaccin con este nivel de aislacin, podremos ver los cambios de los dems cuando ellos terminen su
transaccin con commit (nosotros tendremos que repetir la consulta, o sea cerrar y volver a abrir el conjunto de datos). No es necesario que terminemos nuestra
transaccin para ver las modificaciones.
[5]
snapshot (lectura repetible ): se garantiza que el usuario que est en una transaccin de este tipo ver siempre los mismos datos, aunque otros usuarios hagan cambios y
los acepten. No veremos los cambios hasta que cerremos nuestra transaccin y comencemos una nueva. Este nivel de aislamiento es ideal para los reportes, ya que en un
entorno multiusuario puede darse que cambien los datos entre el momento de la vista previa en pantalla y la impresin propiamente dicha.
snapshot table stability (lectura repetible forzada): igual que la anterior, pero adems desde el momento que accedemos a una tabla sta se bloquea para escritura.
Este nivel es propio de Interbase, y no es muy usado porque impone una restriccin muy severa a los otros usuarios, que slo estarn habilitados para leer de todas las
tablas que toquemos mientras estemos en la transaccin.
Hay un nivel ms de aislamiento que es comn en los sistemas de bases de datos locales: el llamado dirty read o de lectura sucia. En este nivel se pueden ver los
cambios de las dems transacciones, inmediatamente. Se pueden producir problemas por leer datos que no han sido todava aceptados; si el usuario que hizo la modificacin
finalmente rechaza los cambios, hemos ledo datos inexistentes se denominan comnmente filas fantasma, phantom rows. Este nivel no cumple con las propiedades de
aislamiento y consistencia, por lo que no se permite en Firebird.

Concurrencia 2: modo de bloqueo de una transaccin

Cuando se modifica un registro desde una transaccin, ste se bloquea para modificaciones desde otra transaccin; el bloqueo impide que se haga una segunda
modificacin sobre los mismos datos mientras todava no se han aceptado o rechazado los primeros.
Hay dos metodologas de bloqueo: optimista y pesimista.

Los servidores que implementan bloqueos pesimistas asumen que es muy probable que dos usuarios accedan simultneamente a los datos para modificarlos;
entonces toman una postura preventiva y cuando un usuario empieza a editar un registro ste queda inmediatamente bloqueado para la edicin desde cualquier otra
terminal. Este modo de trabajo es muy comn en los sistemas de bases de datos de escritorio.

Los servidores SQL asumen en cambio que no es tan probable que se produzcan ediciones simultneas a los mismos registros; basndose en este supuesto,
solamente bloquea un registro cuando se ha realizado realmente una modificacin en el mismo notificando a la base de datos mediante Post, por ejemplo. Note que no
hemos terminado todava la transaccin. Mientras tanto, el mismo registro puede estar siendo modificado en la memoria interna de varias terminales a la vez. La
primera terminal que guarde el registro (post) bloquea los cambios de las dems. Cmo reaccionarn las aplicaciones que se encuentran con el bloqueo, depende
de la configuracin de las correspondientes transacciones como veremos a continuacin.

El parmetro que se indica cmo reaccionar una transaccin al encontrarse un registro bloqueado se denomina nivel de bloqueo, y se configura al momento de comenzar
la transaccin. Firebird tiene las siguientes opciones:

Modo en espera (WAIT): si hay un conflicto con otra transaccin (por ejemplo, las dos tratan de modificar el mismo registro y aceptar los cambios), el ltimo
proceso queda bloqueado hasta que se termina la primera transaccin.
Modo sin espera (NO WAIT): si hay un conflicto con otra transaccin, el proceso recibe un mensaje de error inmediatamente.

Cul es la razn de ser del primer modo? Pues que el conflicto puede ser temporal. Supongamos que un usuario (1) empieza una transaccin en la cual agrega un registro
con un valor A en la clave primaria. Antes que este usuario haga Commit, otro usuario (2) trata de ingresar un registro tambin con el valor A en la clave primaria. Si la
segunda transaccin se hace en modo WAIT, el usuario 2 queda bloqueado hasta que el primero termine su transaccin. Si (1) hace Commit, (2) recibe un mensaje de error
porque la clave primaria estara duplicada; pero si (1) cancela su transaccin con Rollback, (2) puede insertar su registro sin problemas. En el caso que la segunda
transaccin fuera NO WAIT, el usuario (2) recibe el mensaje de error al momento de querer insertar el registro, aunque luego (1) cancele los cambios.
Los distintos modos de aislamiento junto con los niveles de bloqueo se configuran mediante parmetros en la llamada a la API interna del servidor que comienza la
transaccin. Podemos ver algunos ejemplos en la configuracin de los niveles de aislamiento pre-configurados en los componentes Interbase Express (IBX):
Snapshot: no se ven los cambios realizados por las otras transacciones, pero se permite el acceso de las mismas a los datos que estamos mirando o modificando;
igualmente, podemos ver los datos que otra transaccin est trabajando al mismo tiempo, aunque vemos la versin que exista al momento de iniciar nuestra transaccin.
Parmetros por defecto: concurrency, nowait. Ideal para reportes.

Read Commited: los cambios realizados por los otros usuarios se ven despus que acepten sus transacciones. Parmetros por defecto: read_commited, rec_version,
nowait.
El parmetro rec_version hace que slo veamos la ltima versin estable (aceptada) de los registros. La alternativa es no_rec_version, con lo que indicamos al servidor
que solamente se puede ver un registro si no hay versiones pendientes de aceptacin (ms sobre esto luego, cuando tratemos la arquitectura multigeneracional). En el caso
que desde otra transaccin se haya modificado un registro pero todava no se haya realizado commit, el servidor no nos dejara modificar el registro.
Read-Only Table Stability: esta transaccin no puede acceder a datos que hayan sido cambiados desde que empez, ni permite a otras transacciones que accedan a los
datos que sta haya ledo. Parmetros por defecto: read (slo lectura, en este modo no se pueden modificar los datos), consistency (garantiza que los datos vistos por esta
transaccin no cambien, bloqueando los registros para escritura).
http://archive.today/yKaUQ

7/47

26/6/2014

Firebird

Read-Write Table Stability: igual que la anterior, pero ahora la transaccin bloquea los registros tanto para lectura como para escritura. Parmetros por defecto: write,
consistency.
Los modos ms usados son el Snapshot y el ReadCommitted, ya que permiten el acceso concurrente a los mismos datos (sin bloqueos innecesarios).
Por ejemplo supongamos una tabla Mascotas con los siguientes datos:

Mascotas
Nombre

Categoria

Raza

Edad

Id

Lul

Perro

Caniche

89

Tom

Gato

Angora

908

Pinky

Ratn

Estupidis mousiis

346

Supongamos que esta base de datos se accede desde dos terminales a la vez, A y B. Veamos algunos casos tpicos (las acciones se suponen en la secuencia dada). Para el
caso no importa si usamos un componente IBTable, IBQuery con IBUpdateSQL o un IBDataset. Indique despus de cada accin qu datos ve cada usuario:

A inicia una transaccin en modo Snapshot.

B inicia una transaccin en modo ReadCommitted y lee los datos de la tabla de mascotas.

A pide el contenido de la tabla Mascotas. Qu obtiene?


Lo mismo que est arriba

B modifica la tabla de mascotas, arreglando la edad de Tom que no es 3 sino 4. B hace Commit y vuelve a abrir la tabla.
A ve lo mismo. B ve los datos de Tom modificados

A actualiza la vista de los datos cerrando y abriendo la tabla pertinente, pero sin salir de su transaccin.
A: lo mismo (no ve los cambios)

A modifica la edad de Lul, que no es 5 sino 4. Hace Commit y vuelve a abrir la tabla.
A ve ahora el cambio anterior de B. B todava no ve el cambio de A.

B cierra y abre la tabla.


Ahora B puede ver los cambios de A

B emite la instruccin Select * from Mascotas where Edad=4


B obtiene los datos de Lul y Tom.

B agrega un registro a la tabla de Mascotas, con los siguientes valores: Paco, Loro, Aptrida, 10, 79. Hace Commit. A actualiza la vista cerrando y abriendo
la tabla.
A no ve los cambios hasta que no cierre su propia transaccin.

A borra el registro de Tom. Hace Commit.


B tiene que cerrar y abrir la tabla para ver los cambios.

Qu pasa si B modifica el registro que A acaba de borrar?

Bloqueos pesimistas
A partir de Firebird 1.5, se puede usar un modo de bloqueo pesimista, indicando explcitamente en la sentencia SELECT que se desea bloquear los registros resultado de la
consulta. Veremos algunos ejemplos cuando estudiemos la sentencia SELECT ms adelante; por ahora simplemente digamos que este agregado se hizo para simplificar la
solucin de algunos problemas. No es la forma recomendada de trabajar con los datos, y tiene adems varias restricciones. Citando las notas de la versin 1.5:
"No est disponible en subconsultas, ni para joins. No se puede especificar con el operador DISTINCT, la clusula GROUP BY o cualquier otra operacin de agregacin
de registros. No puede utilizarse con o en una vista, ni con tablas externas, ni con los resultados de un procedimiento almacenado llamado desde un SELECT."
http://archive.today/yKaUQ
8/47

26/6/2014
Firebird
de registros. No puede utilizarse con o en una vista, ni con tablas externas, ni con los resultados de un procedimiento almacenado llamado desde un SELECT."

Mantener el contexto
Una caracterstica que a veces es molesta: cuando cerramos una transaccin ya sea con Commit o con Rollback, se cierran todos los controles de datos asociados a la
misma. Firebird libera los recursos de la transaccin, por lo que los componentes de datos se desconectan. Hay que volver a abrir uno por uno todos los componentes de
acceso a datos que trabajen con esa transaccin.
Para evitar el tener que abrir nuevamente todo, podemos indicar a Interbase que termine la transaccin pero que mantenga los recursos internos -el contexto de la
transaccin. De esta manera mantenemos los componentes conectados aunque aceptamos o cancelamos la transaccin. Las operaciones se denominan
CommitRetaining y RollbackRetaining.
Hay un problema con esta manera de proceder: mientras no cerremos totalmente la transaccin, se evita que el Recolector de Basura de Interbase trabaje. El accionar del
servidor se vuelve ms lento por la proliferacin de versiones la mayora ya obsoletas- de registros. Esto no debera ser un problema a menos que la aplicacin se
mantenga funcionando de esa manera durante horas, das, tal vez semanas... en cuyo caso podemos acomodar las cosas haciendo una copia de seguridad (backup) seguida
de una restauracin sobre la misma base (restore). Cuando se hace un Backup se eliminan los datos temporales (la basura) y al recuperar la Base de Datos sta queda
limpia de polvo y paja.

Integridad referencial
La integridad referencial se refiere al estado de las referencias entre tablas. Es importante que las referencias se mantengan, para asegurar que los datos se puedan
acceder correctamente. Por ejemplo, si tenemos en una tabla los datos de una factura, y en otra el detalle de los productos pedidos. En la tabla de detalle seguramente
tendremos solamente una referencia a la factura si hemos normalizado la base de datos. El valor del campo de referencia (por ejemplo, el Nro de factura) se debe
corresponder al valor de algn campo clave en la tabla de facturas, con lo cual podemos recuperar el resto de los datos. Ahora pensemos qu sucedera si se modifica el
valor del campo de enlace en cualquiera de las puntas de la relacin.

Si modificamos el nro de factura en la tabla de detalle, estaremos referenciando a otra factura: esto puede estar bien, de hecho es la nica manera de corregir un
error en la asignacin.

Si modificamos el nro. de factura en la tabla de facturas, pues eso s puede representar un problema, ya que todos los registros de detalle quedaran hurfanos,
sin que sepamos a qu factura corresponden. Esto no se puede permitir, ya que no tendremos forma de restaurar la relacin.

<<<Grfico con la relacin del ejemplo, con un diagrama E/R>>>


Las comprobaciones que impidan estos problemas y mantengan la integridad referencial se pueden llevar a cabo en el cliente o en el servidor; hablaremos ahora de esta
ltima opcin.
Firebird implementa la restriccin denominada clave externa en forma declarativa: se crea la restriccin como una propiedad ms de una tabla, y el servidor se encargar
de hacerla cumplir cuando sea necesario. En contraste, podemos hacer un control activo escribiendo triggers que controlen explcitamente las referencias.
Las restricciones de clave externa (foreign key) se declaran en la tabla detalle de la relacin, en la tabla que referencia a la maestra. En nuestro ejemplo, la tabla de
facturas sera la maestra, y la de detalles
Para declarar una restriccin de clave externa necesitamos lo siguiente:

Un campo o conjunto de campos del mismo tipo en las dos tablas. Los valores de estos campos en la tabla detalle referenciarn los valores de los campos
correspondientes en la tabla maestra (el nro. de factura del detalle, en nuestro ejemplo)

Una restriccin de unicidad sobre los campos de la relacin en la tabla maestra. Puede ser una clave primaria o una restriccin UNIQUE; cualquiera de las dos
posibilidades implica que los campos de la relacin deben ser declarados como no null (no nulables).

NO es necesario un ndice sobre los campos de la tabla detalle; s es conveniente para acelerar las operaciones de seleccin de datos sobre las dos tablas, por lo que
Firebird crea un ndice automticamente sobre estos campos.

Firebird permite especificar la accin a tomar cuando se intenta violar la integridad referencial (por ejemplo cuando borramos un cliente que est referenciado en una
factura), tanto para las operaciones de borrado como de actualizacin. Las opciones son (los nombres son parte de la sintaxis de la instruccin SQL de declaracin):

No action: la operacin se rechaza de plano.

Cascade: la accin se realiza tambin en los registros referenciados, automticamente. Por ejemplo si cambiamos el nro. de un cliente y ste tiene hechas dos
facturas, en las dos facturas se actualizar el nro. de cliente para que la referencia siga siendo vlida. Si borramos el cliente, se borrarn las facturas que lo
referencian sin ningn aviso por parte del servidor, as que cuidado!

Null: el campo de la tabla maestra en el que se referencia al dato modificado o borrado toma el valor NULL, es decir, pierde la referencia.

Default: el campo de la tabla maestra en el que se referencia al dato modificado o borrado toma el valor por defecto declarado para ese campo.

Las ms usadas son las dos primeras. Firebird incluso nos permite indicar una accin para un caso y otra para el restante, por ejemplo una combinacin muy usada es
NoAction en borrados, Cascade en modificaciones. El servidor entonces mantendr las referencias aunque cambiemos el campo en la tabla de detalle, mientras que
impedir que eliminemos registros de detalle que estn siendo referenciados.
Esta forma de mantener la integridad referencial es muy prctica y valiosa, aunque a veces lleva a un comportamiento no ptimo en el que las operaciones llevan ms
tiempo del necesario. Esto es debido a la selectividad de los ndices, tema que trataremos ms adelante. En esos casos en que el comportamiento no sea el adecuado,
tendremos que recurrir a una verificacin activa de las relaciones usando triggers. Lo veremos tambin ms adelante.
http://archive.today/yKaUQ

9/47

26/6/2014
Firebird
tendremos que recurrir a una verificacin activa de las relaciones usando triggers. Lo veremos tambin ms adelante.

En la prctica, las restricciones de integridad referencial se aplican generalmente cuando se va a poner en produccin el sistema, no antes. Por qu? Pues porque el
servidor no nos dejar modificar la estructura de una tabla que forme parte de una restriccin de integridad referencial, y es muy comn que la estructura vare en el
perodo de diseo y programacin del sistema. As, se crean todas las tablas y dems objetos, se trabaja con esta base de datos, y finalmente se agregan las restricciones
para que no haya sorpresas. Es muy fcil generar un archivo script con las instrucciones SQL necesarias para declarar las restricciones a posteriori de la creacin de las
tablas. No obstante, hay que tener en cuenta que las restricciones se comprueban en el momento de su declaracin esto es, si tenemos datos que no cumplan con las
restricciones no se podrn crear estas ltimas.

Instalacin y puesta en marcha


La instalacin y puesta en marcha de Firebird es muy simple. Se incluye un programa instalador al estilo experto que nos guiar paso a paso en la instalacin; slo
tendremos que seleccionar qu partes instalar y adnde.
A continuacin veremos el proceso completo desde la descarga de los archivos de Internet, la instalacin paso por paso y daremos un primer saludo a las herramientas que
se incluyen con el paquete.

Descarga desde Internet


Firebird es de cdigo abierto, y como tal se lo puede encontrar en Internet para su descarga libre y gratuita. No obstante, es un motivo comn de confusin la existencia de
distintas versiones, tanto de Firebird como de Interbase. Aqu tratar de aclarar el lo.
Se puede descargar el cdigo fuente de FB/IB, en cuyo caso ser necesario compilarlo, o bien el paquete de instalacin ya compilado lo que denominaremos formato
binario. El proceso de compilacin de los fuentes quedar para otros escritos; aqu me limitar a hablar del gestor ya compilado.
El primer sitio donde Interbase estuvo disponible en su version Open Source fue, por supuesto, el de Borland. No he podido verificar si sigue disponible, por lo que pienso
que no.
Hay otro sitio relacionado con Interbase desde sus inicios: http://mers.com[ERC3] . Es una compaa canadiense que desarrolla software usando herramientas de Borland. El
primer grupo de soporte a usuarios de Firebird estuvo localizado en sus servidores hasta que el presidente de la compaa, Robert Schiek, fue contratado por Borland donde
se desempaa ahora como administrador de la comunidad de Interbase (http://bdn.borland.com/interbase[ERC4] ). La lista de soporte ahora funciona en Yahoo! Groups, pero
todava hay un ndice de las preguntas y respuestas en Mers, que se puede consultar con un buscador. En el sitio de la compaa se puede encontrar la versin 6.0.2 de
Interbase Open, para Windows y Linux.
Y llegamos a Firebird. El proyecto comenz apenas una semana despus de la liberacin de Interbase, en SourceForge (http://sourceforge.net/projects/firebird) [ERC5] donde todava se lo puede encontrar. El sitio oficial es ahora http://www.firebirdsql.org[ERC6] , un sitio derivado de IBPhoenix (http://www.ibphoenix.com[ERC7] ), de donde se pueden
obtener las distintas versiones de Firebird as como herramientas, artculos, etc. La versin actual (estable) es la 1.0.2.908[ERC8] , y se puede descargar tambin una versin
1.5 Alpha (no para produccin, inestable y sin garantas). Se espera que pronto se ponga en marcha la versin beta de Firebird 1.5.
Entonces, hagamos un resumen:
Versin

URL para descarga

Interbase 6.0.2

http://mers.com

Firebird 1.0.3

http://www.firebirdsql.org

Firebird 1.5.1

http://www.firebirdsql.org

La instalacin es muy sencilla cuando todo funciona :-P. en Windows, corremos el archivo ejecutable; en Linux, instalamos el paquete rpm o bien ejecutamos el script si
descargamos la version no compilada. Las opciones son mnimas y se reducen a seleccionar los componentes a instalar. Cuando hay algun problema, bueno habr que
empezar a preguntar. El mejor lugar para encontrar respuestas es el foro de soporte firebird-support en yahoogroups.com.

Probar la instalacin
ISQL

Con la distribucin estndar de Firebird se incluye una utilidad para ejecutar sentencias SQL contra el servidor, y mostrar sus resultados. Esta utilidad es de lnea de
comandos y se encuentra en el archivo isql.exe.
Se puede usar isql para probar la instalacin del servidor de la siguiente manera:
Abra una ventana de terminal en la carpeta bin de la distribucin de Firebird
Ejecute el programa escribiendo isql
Isql responder con un indicador (prompt) especial 'SQL>' como se ve en la siguiente imagen:
http://archive.today/yKaUQ

10/47

26/6/2014
Firebird
Isql responder con un indicador (prompt) especial 'SQL>' como se ve en la siguiente imagen:

Escriba
Connect "localhost:c:\archivos de programa\firebird\examples\employee.gdb" user "sysdba" password "masterkey";

para conectar con la base de datos de ejemplo. Note que puede cortar la sentencia en dos o ms lneas simplemente presionando <Enter>; isql indicar que una
lnea contina una sentencia anterior cambiando el indicador (prompt) por 'CON>'. Las sentencias se terminan con punto y coma (;).
Si la conexin se puede establecer, isql responder con un mensaje indicando que est ahora conectado a la base de datos. A partir de ese momento se pueden
ejecutar sentencias SQL sobre esa base de datos, o usar algunos comandos especficos de isql como Show Tables. En la parte de herramientas hablaremos ms en
profundidad sobre la utilidad isql.

Herramientas
IBServer

IBGuardian

ISQL

Gbak
http://archive.today/yKaUQ

11/47

26/6/2014

Firebird

IBConsole

IBConsole es un producto realizado utilizando acceso directo a la API de Interbase (con los componentes IB Express, de los que hablaremos luego), por lo que su
rendimiento es muy bueno. Tambin es simple de usar y nos da la posibilidad de realizar las tareas administrativas comunes como ser: creacin y destruccin de bases de
datos; administracin de usuarios y permisos; realizacin de backups; verificacin de integridad de la Base de Datos; ejecucin de sentencias y scripts SQL, etc.
A partir de la versin 1.5 de Firebird esta utilidad no se incluye ms en la distribucin. Se puede encontrar en codecentral.borland.com en sus versiones para Windows y
Linux; no obstante, no se recomienda IBConsole como herramienta de administracin para bases de datos Firebird, en parte porque est compilado con el conjunto de
componentes IBX que no garantizan compatibilidad con las nuevas versiones de Firebird.

Accederemos a una Base de Datos de ejemplo que se incluye en el paquete (si no instal los ejemplos, hgalo ahora; la base de datos de empleados utiliza tcnicas que vale
la pena estudiar). Usaremos la base de datos llamada Employee.gdb o su versin internacional (que contiene caracteres no ingleses) llamada Intlemp.gdb. Cualquiera de
las dos sirve para nuestros ejemplos porque lo nico que cambia es el contenido de las tablas, no su definicin.
Para usar la base de datos, debemos registrarla en IBConsole. Los pasos necesarios son los siguientes:

registrar el servidor local con la opcin correspondiente del men Server

en el men contextual del rbol de objetos de la izquierda seleccionamos Register

en el cuadro de dilogo que aparece a continuacin, completamos la informacin de registro de la base de datos y aceptamos. La nueva Base de Datos debera
aparecer en el rbol de objetos.
Hasta ahora lo nico que hemos hecho es crear un alias para la Base de Datos; es decir, registrar con IBConsole la ubicacin
fsica del archivo y los datos de conexin, as como un nombre ms descriptivo que el nombre del archivo. Para acceder a los
datos debemos conectarnos a la base de datos. Normalmente en el momento del registro IBConsole conecta automticamente
con la base de datos, como podemos observar en el rbol que se abre y el grfico de la BD tiene una marca verde.
De aqu en adelante, podemos conectarnos haciendo simplemente doble Click sobre el nodo en el rbol o seleccionando la
opcin pertinente del men contextual.
El solo hecho de lograr la conexin ya indica que el servidor est funcionando correctamente. Todava se pueden presentar
problemas en el acceso a travs de la red, pero nos ocuparemos de eso a su debido tiempo.

http://archive.today/yKaUQ

12/47

26/6/2014

Firebird

Ejecutar sentencias SQL en IBConsole


Para ejecutar cualquier sentencia SQL utilizamos la herramienta conocida como Interactive SQL. En IBConsole est integrada
al producto, y se accede desde el men Tools o el botn

. La ventana tiene el siguiente aspecto:

Las sentencias SQL se escriben en el editor superior, se ejecutan con CTRL+E o el botn
ejecucin y estadsticas de ejecucin).

, y el resultado se obtiene inmediatamente en la parte inferior (datos, plan de

Por ejemplo, la siguiente imagen muestra el resultado de pedir el contenido de la tabla employee:

IBOConsole

Esta herramienta es como un clon de IBConsole, pero construida con los componentes IB Objects. Es gratuita y se puede descargar de <<<Ver el enlace real en
IBPhoenix>>>, y en general es ms estable que las versiones de IBConsole que he probado. Se maneja de la misma manera, la interfaz es prcticamente igual, y podemos
esperar que sea til con las nuevas versiones de Firebird, ya que los componentes IBO soportan todas las caractersticas de estos servidores.

http://archive.today/yKaUQ

13/47

26/6/2014

Firebird

IB_SQL

SQL
El lenguaje de consulta
Tal vez el problema mayor que se presenta a los programadores viejos, los que usaban sistemas de datos orientados a archivos como Clipper, Dbase o Cobol, sea el de
cambiar la forma de acceder a los datos. Lo que antes requera recorrer toda una tabla buscando coincidencias o armar tablas temporales con datos de distintas tablas
relacionadas, ahora se hace con una sola sentencia de un lenguaje especial diseado para eso: el Lenguaje Estructurado de Consulta o SQL.
Una de las caractersticas que distinguen a este lenguaje es su orientacin a conjuntos de datos. As por ejemplo, en SQL no pedimos recorre todos los registros y cuando
encuentres uno cuyo campo Nombre comience con A, me lo muestras; en su lugar, pedimos una tabla temporal formada por todos los registros que cumplan la condicion:
el campo Nombre empieza con A. Lleva un tiempo acostumbrarse a pensar en conjuntos de datos, pero se logra. Trataremos aqu de dar la mayor cantidad posible de
ejemplos y ejercicios para que esta forma de pensar se haga casi natural.
SQL son las iniciales de Structured Query Language o Lenguaje Estructurado de Consulta. Es un lenguaje no procedural inventado en IBM a principios de los aos 70,
para implementar el modelo relacional de Codd. Inicialmente se le llam SEQUEL (Structured English Query Language), luego pas a ser SEQUEL/2 y finalmente SQL
(esperemos que no siga la tendencia y en unos aos se termine llamando S). Hoy en da es el lenguaje de consulta ms utilizado por los gestores de Bases de Datos de
todos los tamaos, desde Dbase o Paradox pasando por Oracle, Informix o SQL Server, hasta los gestores de datos utilizados en supercomputadoras.
Hay definidos tres estndares oficiales por el Instituto Nacional de Estndares Americano (American National Standards Institute, ANSI): SQL-86, SQL-89 y SQL-92.
La mayora de los gestores de consultas implementan a su manera las recomendaciones del estndar. Estudiaremos los comandos ms comunes, que se aplican a los
motores de consulta ms utilizados, y cuando sea pertinente comentaremos diferencias en distintos servidores.
A continuacin veremos en detalle el lenguaje SQL que implementa Firebird. Los ejemplos utilizan la base de datos de ejemplo que viene con el servidor, llamada
EMPLOYEE.GDB, y se ejecutan en IBConsole o IBOConsole.

Cursores vs conjuntos
Los gestores de datos tipo Dbase o Paradox trabajaban con el concepto de cursor; el lenguaje SQL trabaja con conjuntos.
Los cursores se pueden ver como una cinta sobre la que se encuentran los registros, con un sealador que se mueve adelante y atrs para marcar el registro activo o
actual. Las operaciones sobre ms de un registro se realizan recorriendo el cursor con el sealador y actuando sobre los registros a medida que son sealados.
Veamos dos operaciones tpicas con este modelo:

Seleccin de un subconjunto de registros, que cumplen un criterio determinado, por ejemplo mostrar los productos de un rubro

El sealador se posiciona en el primer registro; comprueba si ese registro cumple con el criterio; si lo cumple se muestra, si no se saltea; el sealador pasa al siguiente
registro, y repite la comparacin hasta que no hay ms registros en el cursor.

Modificacin de un subconjunto de registros, por ejemplo modificar el precio de todos los productos de determinado rubro

La operatoria es prcticamente la misma, slo que en lugar de mostrar los registros que cumplen el criterio se editan, se cambia el precio, y se vuelven a grabar. Hay que
tener en cuenta que si el cursor est ordenado por algn ndice, el cambio puede hacer que los registros se reubiquen y el sealador seguir al registro que modific, por
lo que puede ir a parar al final del cursor, o recomenzar al principio! En el ejemplo de los precios, seguramente el orden ser por rubro por lo que la modificacin de precios
no afectar la posicin de los registros.
Un servidor SQL como Firebird, en cambio, trabajar sobre conjuntos de registros en una sola operacin. As, las mismas operaciones del ejemplo anterior se haran mucho
ms simples:
Seleccin de un subconjunto de registros que cumplen determinado criterio
http://archive.today/yKaUQ

14/47

26/6/2014
Seleccin de un subconjunto de registros que cumplen determinado criterio

Firebird

Simplemente se emite una sentencia SELECT y el servidor generar un cursor compuesto solamente con los registros que cumplen el criterio. Para mostrar estos registros
se hace el mismo bucle anterior, pero solamente se recorren los registros que cumplen el criterio.

Modificacin de un subconjunto de registros que cumplen un criterio

Se emite una sentencia UPDATE que incluye la operacin a realizar y el criterio de seleccin, y el servidor modificar el subconjunto que cumpla el criterio sin ms
intervencin nuestra.

Seleccin de registros: SELECT


La sentencia estrella de SQL es, sin ninguna duda, SELECT. Esta instruccin permite obtener datos de una o varias tablas, con un poder y flexibilidad increbles. Si SQL
no tuviera ms que esta instruccin, igualmente valdra la pena aprenderlo.
La sintaxis bsica de SELECT es como sigue

[6]

SELECT columnas | *
FROM tablas
[WHERE condicin]
[ORDER BY columnas]

Hay muchas variaciones y agregados sobre este esqueleto bsico, pero todo a su tiempo.
En palabras, esta instruccin devolver una tabla virtual compuesta por las columnas especificadas (el asterisco * se reemplaza por todas las columnas de todas las
tablas), con las filas de las tablas dadas que cumplan la condicin (opcional), y todo ordenado por las columnas indicadas (opcional).
Por ejemplo, para obtener los nombres de los empleados podemos escribir:
SELECT FIRST_NAME
FROM EMPLOYEE
Y veremos en la ventana de ISQL:

La sentencia SQL desaparece del editor, que queda listo para escribir otra; pero puede recuperarse con el botn

o la opcin de men Query|Previous.

Algunas preguntas comunes a esta altura:


http://archive.today/yKaUQ

15/47

26/6/2014

Firebird

Importa si las instrucciones se escriben en maysculas o minsculas?


No. Para el servidor es lo mismo SELECT que select. En la parte que s hay que tener cuidado es en los nombres de campos y tablas, ya que hay dialectos SQL
que distinguen entre maysculas y minsculas. En Firebird, con el dialecto 1 de SQL no hay diferencias; con dialecto 3, las hay nicamente cuando se usan los
nombres entre comillas dobles ().
En qu orden se recuperan los registros si no especificamos una clusula ORDER BY?
En orden natural, lo que significa que no podemos asegurar nada. El motor de consultas obtiene los datos en el orden que sea ms eficiente.
Es posible indicar algn formato en el resultado, por ejemplo el ancho de las columnas?
No. El lenguaje SQL es un lenguaje de consulta, no considera la parte de presentacin de los resultados.
Se pueden usar espacios en los nombres de campos y tablas?
Depende del servidor. En Interbase, nicamente podemos usar espacios con Dialecto 3 y si encerramos el nombre entre comillas dobles. Los servidores actuales
tienden a ser consecuentes con esta norma: si est entre comillas, puede contener cualquier caracter. No obstante, recomendamos no utilizar caracteres especiales
ni espacios debido a los potenciales problemas con los diferentes conjuntos de caracteres. En general se reemplazan los espacios por el caracter de subrayado
(underscore, _) como en el campo FIRST_NAME usado en el ejemplo.
Vamos a extender la tabla de resultados para que muestre otras columnas: el apellido (last_name) y el pas de trabajo (job_country). La sentencia queda como sigue
SELECT FIRST_NAME, LAST_NAME, JOB_COUNTRY
FROM EMPLOYEE
Cmo hara para que aparezca primero el apellido y despus el nombre?
Cuando queremos todas las columnas de la tabla en el resultado, en el mismo orden que estn definidas, podemos usar el comodn * (asterisco):
SELECT *
FROM EMPLOYEE
Notemos en el resultado de esta sentencia que hay una columna la ltima- que combina el contenido de los campos First_Name y Last_Name para mostrar el nombre
completo. En el caso de esta tabla, este campo est definido as, como un campo calculado por el servidor. Nosotros podemos lograr el mismo efecto usando operadores
para construir campos nuevos, no existentes en la tabla original.
Por ejemplo, vamos a mostrar una columna con el Nro. de empleado (emp_no), un guin, el nombre y el apellido:
SELECT emp_no || ' ' || first_name || ' ' || last_name
FROM employee

Hemos utilizado aqu el operador de concatenacin || (dos barras verticales), que permite juntar cadenas de caracteres. El resultado es otra cadena. Notemos que
podemos usar tanto nombres de campos como cadenas constantes, con comillas simples.
Un problema comn cuando se utilizan columnas formadas por expresiones es el nombre de estas columnas. Por ejemplo, la columna generada en el ejemplo anterior se
llama F_1. Quin puso este nombre? El servidor. Es posible cambiarlo? Si, asignando un alias al campo por medio de la partcula as:
SELECT emp_no || ' - ' || first_name || ' ' || last_name AS Empleado
FROM employee

http://archive.today/yKaUQ

16/47

26/6/2014

Firebird

Si ejecutan esta sentencia, vern el mismo resultado que antes pero ahora la columna se llama Empleado, lo cual es mucho ms fcil de recordar.
Antes de continuar sumergindonos en las complejidades de SELECT, realice los siguientes ejercicios para afirmar lo anterior.
Ejercicios
1) Obtenga los siguientes datos (y en este orden) de los empleados: Nombre, Apellido, Nro. de empleado, salario y pas de trabajo.
2) Ahora muestre tres columnas llamadas Apellido, Nombre, Salario. En la primera muestre el apellido, en la segunda el nombre, y en la tercera la informacin
siguiente (los ngulos indican que es el nombre de un campo):
<Job_code>, nivel <job_grade> (U$S <salary>)
3) De la tabla de proyectos: una columna llamada Proyecto con el siguiente formato
(<proj_id>) <proj_name>
otra columna con el tipo de producto (product), y una tercera con el Nro. de empleado del lder del proyecto (team_leader)

Orden en la sala
El orden en que el servidor devuelve los datos depende de varios factores; en general, no se puede asumir un orden determinado por lo que hay que indicarlo explcitamente
usando la clusula ORDER BY.
La clusula ORDER BY es muy simple de usar: es seguida por una lista de campos (que deben figurar en la lista de columnas a mostrar) por los que se ordenar.
Por ejemplo, para obtener datos de los empleados ordenados por pas de trabajo, podemos hacer
SELECT *
FROM employee
ORDER BY job_country
Como podrn ver, hay muchos empleados que trabajan en cada pas, que no guardan entre s un orden predecible. As, si tenemos que buscar un empleado por nombre en el
listado anterior suponiendo que sabemos en qu pas trabaja, tendramos que recorrer todos los empleados de ese pas hasta encontrar el que buscamos.
Para simplificar la bsqueda, podemos indicar al servidor que queremos los resultados ordenados, si, por pas; pero ms todava, el conjunto de empleados de cada pas lo
queremos ordenado por apellido y nombre. Pruebe la siguiente sentencia:
SELECT *
FROM employee
ORDER BY job_country, last_name, first_name
Ya se comienza a notar la potencia del lenguaje. Esta instruccin nos devuelve una tabla con todos los empleados organizados por pas, dentro de cada pas por apellido, y si
hay apellidos repetidos, se ordenan por nombre.
Una variacin posible es el sentido de la ordenacin: si es ascendente o descendente. Por defecto Firebird devuelve los datos ordenados en forma ascendente; para indicar
lo contrario agregamos la partcula desc despus del nombre del campo de ordenacin. Por ejemplo,
SELECT *
FROM employee
ORDER BY job_country desc
Nos devolver los empleados ordenados en forma descendente por pas de trabajo.
Este modificador es vlido slo para la columna a la cual sigue; cada una de las columnas de ordenamiento debe tener su indicador de direccin o se tomar el ascendente
por defecto. Tambin se puede explicitar el orden ascendente usando asc.
SELECT *
FROM employee
ORDER BY job_country desc, last_name asc, first_name desc
Devolver un conjunto ordenado por pas en forma descendente, dentro de cada pas los empleados se ordenarn por apellido en forma ascendente, y si hay apellidos
repetidos, se ordenarn por nombre en forma descendente.
NOTA: como veremos en los ejemplos siguientes, la clusula ORDER BY siempre se coloca al final de la instruccin, despus de todas las dems clusulas optativas.

Filtrados y bsquedas

http://archive.today/yKaUQ

17/47

26/6/2014

Firebird

Filtrados y bsquedas
Todos los ejemplos que hemos hecho hasta ahora devuelven el total de los registros de la tabla en cuestin. Como se habrn imaginado, el lenguaje SQL tiene una clusula
que sirve para reducir el conjunto de registros resultado a un subconjunto que cumpla con ciertas condiciones. Para hacer uso de esta opcin solamente tenemos que
agregar a la sentencia SELECTFROM la clusula WHERE <condicin>.
La condicin debe ser una expresin que devuelva un valor booleano: aquellos registros para los cuales la expresin se evale a Verdadero aparecern en el conjunto
resultado, el resto no.
Por ejemplo, si queremos un listado de los empleados que trabajan en Canada solamente, haramos
SELECT *
FROM employee
WHERE job_country = 'Canada'
Podemos ordenar el resultado agregando al final la clusula order by:
SELECT *
FROM employee
WHERE job_country = 'Canada'
ORDER BY last_name, first_name
Esta instruccin nos permitir encontrar rpidamente un empleado de Canad. Pero podemos tambin usar los operadores lgicos para afinar la bsqueda; por ejemplo, si
queremos ver los empleados de Canada de categora 4, haramos
SELECT *
FROM employee
WHERE (job_country = 'Canada') AND (job_grade = 4)
Notemos que el 4 no est rodeado de comillas; es un nmero, no una cadena. Los parntesis no son necesarios en este ejemplo, pero pueden servir para aclarar el orden
de evaluacin.
El orden de evaluacin puede determinar el resultado de una expresin: por ejemplo, no es lo mismo evaluar 1+2*3 de izquierda a derecha (1+2=3, 3*3=9) que asociando
por precedencia como hacemos en matematicas: 1+(2*3) = 7. La siguiente tabla indica el orden de precedencia de los operadores en Firebird. Algn servidor puede diferir
con este orden, pero en general todos lo consideran de la misma manera. La precedencia va de mayor a menor, ledos de arriba hacia abajo (por ejemplo, se evala primero
una concatenacin que una multiplicacin; pero esta ltima se evala antes que una suma).
Tipo

Operador

Comentario

Cadenas

||

Concatenacin

Matemticos

Multiplicacin

Divisin

Suma

Resta

=, ==

Igualdad

<>,[ERC9] !=,
~=, ^=

Desigualdad

Comparacin

>
<
>=

Lgicos

Mayor
Menor
Mayor o igual

<=

Menor o igual

!>, ~>, ^>

No mayor

!<, ~<, ^<

No menor

NOT

Negacin

AND

Conjuncin (Y)

OR

Disjuncin (O)

Es muy importante conocer el orden de precedencia de los operadores, para no cometer errores que pueden ser muy difciles de detectar. Por ejemplo, si el resultado de
una consulta tiene 1000 registros usando el criterio WHERE n > 1+2*3 y 1010 registros usando el criterio WHERE n > (1+2)*3, cul es el correcto? No sera fcil
decidirlo. Y si deciden mal, y le entregan al jefe la lista de los empleados que cumplen la condicin errnea, y stos son despedidos bueno, no digan que no les avis.
http://archive.today/yKaUQ

18/47

26/6/2014

Firebird

Ejercicios
1) Realizar una consulta que devuelva los nombres y apellidos de los empleados que cobran ms de U$S 100.000 (afortunados ellos).
2) Realizar una consulta que devuelva una tabla como la siguiente, con los datos ordenados por Pas, categora, apellido y nombre:
Empleado

Pas

Categora

Salario

<first_name><espacio><last_name>

<job_country>

<job_grade>

<salary>

3) Agregar a la tabla anterior una columna con el cdigo de trabajo (job_code) entre las de Categora y Salario. Llamar a la columna Codigo_trabajo.
4) Listar aquellos empleados que hayan sido contratados en 1990 (hire_date)
El ltimo ejercicio pone el dedo en una llaga: el manejo de fechas.

Fechas/Horas en SQL
Nuevamente, cada servidor tiene sus convenciones con respecto al formato de las fechas. En Firebird tenemos varios tipos de campos para almacenar fechas y horas:
Dialecto 1
DATE: almacena fecha y hora, como dos nmeros enteros de 32 bits. Equivalente al tipo timestamp del dialecto 3
Dialecto 3
DATE: almacena una fecha como un nmero entero que representa la cantidad de das pasados desde el 1 de Enero de 100. Puede almacenar hasta el da 29 de febrero de
32768. Un valor 0 para la fecha indicar el da 17 de Noviembre de 1858.
TIME: almacena una hora como un nmero entero. El rango permitido va desde las 00:00 AM hasta las 23:59.9999 PM, esto es, 23:59:59.5964 PM.
TIMESTAMP: almacena fecha y hora, como dos nmeros enteros de 32 bits; la parte de fecha es igual al tipo DATE, la parte de hora igual a un campo de tipo TIME
Entonces, cmo podemos usar fechas en criterios de seleccin? Ciertamente, no calculando la cantidad de das pasados desde el da cero, 17 de Noviembre de 1858.
Firebird puede convertir un tipo de dato en otro, y particularmente con las fechas hace la conversin automticamente si el formato del texto con la fecha coincide con
alguno de los reconocidos:
CCYY-MM-DD
MM-DD-CCYY MM-DD-YY
MMM-DD-CCYY MMM-DD-YY
DD-MMM-CCYY DD-MMM-YY
CCYY-MM-DD HH:Min:SS:nnnn
MM-DD-CCYY HH:Min:SS:nnnn MM-DD-YY HH:Min:SS:nnnn
MMM-DD-CCYY HH:Min:SS:nnnn MMM-DD-YY HH:Min:SS:nnnn
DD-MMM-CCYY HH:Min:SS:nnnn DD-MMM-YY HH:Min:SS:nnnn

donde
CC= siglo
YY= ao
MM= mes
DD= da
HH= hora
Min= minutos
SS= segundos
nnnn= milisegundos

El separador de las fechas puede ser '-', '/' o '.'. Para las fechas se puede usar el formato americano (MM/DD) o el europeo (DD.MM), reconocindose por el separador: el
punto para el formato europeo, cualquier otro para el americano.
Por ejemplo, para ver todos los empleados contratados en 1990 podemos escribir:
SELECT *
FROM employee
WHERE (hire_date >= '1990-01-01')
AND (hire_date < '1991-01-01')
Se definen en Firebird algunas literales que son reemplazadas por los valores que representan en el momento de la evaluacin:
NOW: fecha y hora actuales
TODAY: fecha actual
http://archive.today/yKaUQ

19/47

26/6/2014
TODAY: fecha actual

Firebird

YESTERDAY: fecha de ayer


TOMORROW: fecha de maana
Estas literales se utilizan encerradas entre comillas simples, como en el siguiente ejemplo:
SELECT *
FROM employee
WHERE hire_date < 'TODAY'
Que nos devolver todos los empleados contratados antes del da de hoy.
Asimismo, cuando trabajamos en Dialecto 3 podemos usar las funciones current_date, current_time y current_datetime (sin comillas) para referirnos a la fecha y hora
actuales en los tres formatos: DATE, TIME y TIMESTAMP respectivamente.
Podemos tener una idea del tratamiento que da Firebird a las fechas creando una tabla con un campo de cada tipo, y probando los distintos valores. Las instrucciones de
creacin e insercin no han sido explicadas an, pero considero importante el ejemplo en este momento.
Vamos a crear una tabla llamada Prueba, con los siguientes campos:
Campo

Tipo de dato

Clave

Integer

Hora

Time

Fecha

Date

Todo

Timestamp

CREATE TABLE prueba (


clave integer not null primary key,
hora time,
fecha date,
todo timestamp)

La sentencia SQL necesaria aparece en el cuadro de la derecha. No nos preocupemos por ahora de esta sentencia; lo nico que tenemos que saber es que crear la tabla
deseada. Ahora emitimos los siguientes comandos, uno por vez, para llenar la tabla con datos:
INSERT INTO prueba VALUES (1,'09:00','TODAY','NOW')
INSERT INTO prueba VALUES (2,'10:00','YESTERDAY','yesterday')
INSERT INTO prueba VALUES (3,'11:00','tomorrow','time')
INSERT INTO prueba VALUES (4,'12:00',current_date,'now')
INSERT INTO prueba VALUES (5,'13:00','2002-05-24','now')
INSERT INTO prueba VALUES (5,'13:00','2002-05-24','2002-05-24 12:35')
Si ahora pedimos los datos introducidos, con un SELECT comn
SELECT *
FROM prueba
veremos cmo interpret Firebird cada uno de los literales y funciones usados, en cada tipo de campo. Tambin podemos probar otras combinaciones para ganar un
entendimiento mayor de las expresiones que son vlidas y las que no.
Ejercicios
En la base de datos donde cre la tabla Pruebas anterior:
1) devuelva los registros donde <fecha> es menor que hoy
2) devuelva los registros donde <todo> es menor que el momento actual
3) devuelva los registros donde <fecha> sea igual a la fecha de ayer
4) devuelva los registros donde <hora> es menor que las 12 del medioda, ordenados por fecha

Criterios de seleccin
Hay una serie de funciones que se pueden usar en las expresiones de criterios de seleccin. Como de costumbre, estas funciones dependen del servidor de bases de datos,
y veremos aqu en detalle las de Firebird.
<campo> LIKE <cadena>: comparacin de cadenas con comodines. Es similar al operador de igualdad (=) pero solamente puede usarse con cadenas y permite
el uso del comodn % para indicar cualquier carcter (cero o ms) y _ para reemplazar un solo carcter que sin embargo debe existir. Se distingue entre
maysculas y minsculas.
Por ejemplo, la siguiente sentencia devolver todos los empleados cuyo nombre empieza con A (mayscula):
http://archive.today/yKaUQ

20/47

26/6/2014

Firebird

SELECT *
FROM employee
WHERE first_name LIKE 'A%'

Mientras que la siguiente sentencia devolver todos los empleados que contengan una a minscula en cualquier posicin de su apellido:
SELECT *
FROM employee
WHERE last_name LIKE '%a%'

Pruebe a cambiar la a de la condicin por una A.


<campo> STARTING WITH <cadena>: devuelve TRUE si la cadena comparada comienza con el valor pasado. Es equivalente a LIKE <cadena%>; pero el
optimizador de consultas puede usar un ndice (si existe) con STARTING WITH, mientras que con LIKE no.
Como ejemplo, veamos el mismo ejemplo que antes: los empleados cuyo nombre comienza con A:
SELECT *
FROM employee
WHERE first_name STARTING WITH 'A'

<campo> CONTAINING <cadena>: devuelve TRUE si la cadena comparada contiene el valor dado. Es equivalente a LIKE <%cadena%>, pero tiene la
ventaja de poder usarse con campos BLOB.
Como ejemplo, veamos el mismo ejemplo que antes: los empleados cuyo apellido contiene una a:
SELECT *
FROM employee
WHERE last_name CONTAINING 'a'

Tambin existe la versin negada, es decir que devuelve TRUE cuando el valor NO contiene la cadena:
SELECT *
FROM employee
WHERE last_name NOT CONTAINING 'a'

<campo> BETWEEN <valor inferior> AND <valor superior>: devuelve TRUE cuando el valor comparado (que puede ser de cualquier tipo salvo
BLOB) se encuentra entre <valor inferior> y <valor superior>, ambos inclusive. Estos lmites deben ser del mismo tipo que el valor a comparar.
Por ejemplo, la siguiente sentencia devolver los datos de los empleados que cobran entre U$S 50.000 y U$S 72.000:
SELECT *
FROM employee
WHERE salary BETWEEN 50000 AND 72000

La siguiente instruccin traer los empleados contratados en 1990 (equivalente a la que vimos en un ejemplo anterior):
SELECT *
FROM employee
WHERE hire_date BETWEEN '1990-01-01' AND '1990-12-31'

Y la siguiente recuperar todos los empleados cuyo nombre empiece con A, B o C:


SELECT *
FROM employee
WHERE first_name BETWEEN 'A' AND 'Cz'

Notemos el uso de Cz para el lmite superior; cualquier cadena que empiece con C y siga con un carcter comn ser menor o igual que esta cadena, por lo que entran
en la seleccin todos los apellidos comenzados en C.
La versin negada devuelve TRUE cuando el valor no est en el rango dado:
SELECT *

http://archive.today/yKaUQ

21/47

26/6/2014

Firebird

SELECT *
FROM employee
WHERE hire_date NOT BETWEEN '1990-01-01' AND '1990-12-31'

Devolver los empleados que no fueron contratados en 1990.


<campo> IN <conjunto>: devuelve TRUE si el valor existe en el conjunto dado. El conjunto puede ser especificado por extensin, como una lista de valores
separados por comas y encerrados entre parntesis, o como una subconsulta que devuelva un solo campo del tipo correcto.
Por ejemplo, para ver aquellos empleados de USA, Canada y Alemania (Germany) podemos hacer:
SELECT *
FROM employee
WHERE job_country IN ('USA', 'Canada', 'Germany')

Mientras que para ver los empleados que son lderes de algn proyecto podramos hacer:
SELECT *
FROM employee
WHERE emp_no IN (
SELECT team_leader
FROM project)

La consulta interior, encerrada entre parntesis, se denomina subconsulta y es una poderosa posibilidad de SQL en la que ahondaremos en breve.
Tambin existe la versin negada, como se habrn imaginado:
SELECT *
FROM employee
WHERE emp_no NOT IN (
SELECT team_leader
FROM project)

Devuelve los empleados que no son lderes de proyectos.


<campo> IS NULL: devuelve TRUE si el valor es nulo; tambin puede usarse la forma <valor> IS NOT NULL, que devolver TRUE en el caso contrario.
Estas instrucciones fueron creadas especialmente para lidiar con los valores nulos, y generalmente no equivalen a comparar simplemente un campo con el valor
NULL aunque tambin depende del servidor. Veamos un par de ejemplos:
SELECT *
FROM employee
WHERE phone_ext IS NULL

Devuelve los empleados cuya extensin de telfono es desconocida. Pruebe a ejecutar la siguiente sentencia, que parece ser equivalente:
SELECT *
FROM employee
WHERE phone_ext = NULL

Este comportamiento es parte de las extravagancias de los nulos, de las que hablaremos muchas veces.
Si queremos ver los que s tienen almacenada una extensin, haremos
SELECT *
FROM employee
WHERE phone_ext IS NOT NULL

(1.5) CASE
A partir de la versin 1.5 de Firebird, se puede generar una consulta condicional cuyas columnas tomarn valor en base al resultado de la evaluacin de una expresin. La
sintaxis es la siguiente:
Se pueden clasificar las sentencias CASE en dos formas:
1) simple: se define la expresin despus de la palabra CASE y los distintos valores se asignan en base a los distintos resultados de la evaluacin de esta expresin
CASE < expresion valor >
<clausula WHEN simple>...
[ <clausula else> ]
END

http://archive.today/yKaUQ

22/47

26/6/2014

END

Firebird

<<<Ejemplo>>>

2) con bsqueda: para cada valor se especifica una expresin


CASE <clausula WHEN buscada>...
[ <clausula else> ]
END

<<<Ejemplo>>>

Funciones
Existen en todos los servidores algunas funciones que toman un parmetro entre parntesis -usualmente el contenido de un campo- y devuelven el valor modificado. Se
pueden usar tanto en la especificacin de las columnas a devolver como en los criterios.
Firebird es bastante parco en cuanto a las funciones predefinidas; tenemos solamente un puado:
UPPER(<cadena>): devuelve la misma cadena con todos los caracteres en maysculas.
CAST(<valor> as <tipo>): convierte el valor al tipo dado si puede.
GEN_ID(<nombre generador>,<incremento>): incrementa el valor del generador en la cantidad pedida y devuelve el resultado. El generador queda incrementado.
SUBSTRING(cadena FROM inicio [FOR n]): devuelve n caracteres de cadena a partir del caracter nro. inicio. Si no se especifica la clusula FOR, se devuelven

todos los caracteres desde inicio hasta el final.


<<<OJO: creo que hay un problema cuando se usan juegos de caracteres de ms de un byte ver los mensajes de los foros de Firebird y probar con fss_unicode y
iso8859_1>>>
En dialecto 3 disponemos de la funcin EXTRACT para obtener una parte de una fecha:
EXTRACT({year | month | day} FROM <campo fecha>)

Por ejemplo, para obtener los empleados que fueron contratados en el mes de enero (de cualquier ao) haramos

SELECT *
FROM employee
WHERE extract(month from hire_date) = 1
EMP_NO
FIRST_NAME
LAST_NAME
PHONE_EXT HIRE_DATE
--------------------------------------------------------------------
11
K. J.
Weston
34
17/01/1990
20
Chris
Papadopoulos
887
01/01/1990
141
Pierre
Osborne
03/01/1994

(1.5) NULLIF(expr1,expr2) devuelve NULLsi expr1es igual a expr2, caso contrario devuelve expr1.
<<<Ejemplos>>>
(1.5) COALESCE(expr1, expr2, expr3, exprN)devuelve el valor de la primera expresin no nula.
<<<Ejemplos>>>

Funciones de agregacin
Las siguientes funciones operan sobre un conjunto de registros (que puede ser la tabla entera), devolviendo un solo valor por cada grupo:
AVG(<campo>): devuelve el valor medio del campo en el grupo de registros considerado.
COUNT(<campo> | *): devuelve la cantidad de registros del grupo. Si usamos la primera versin, con el nombre de un campo entre los parntesis, devolver la cantidad

de filas en que este campo sea no nulo; la segunda versin, con un asterisco, devuelve la cantidad total de registros del grupo. Si no se encuentra ninguna fila que cumpla
con las condiciones, devuelve 0.
COUNT(distinct <campo>): igual que el anterior, pero cuenta slo los registros con valores diferentes en el campo pedido.

http://archive.today/yKaUQ

23/47

26/6/2014

Firebird

MAX(<campo>): devuelve el valor mximo del campo en el grupo.


MIN(<campo>): devuelve el valor mnimo del campo en el grupo.
SUM(<campo>): devuelve la suma de los valores del campo en el grupo. No considera los valores nulos. Si no encuentra nada para sumar (no hay registros o todos son

nulos) no devuelve 0, como uno esperara: simplemente devuelve un nulo.


Por ejemplo, la consulta siguiente devolver el monto total de remuneraciones anuales, sumando el campo SALARYde todos los registros de la tabla EMPLOYEE:
select sum(salary)
from employee
SUM
----------115522468

Pero SQL puede dar mucha ms informacin que esa; por ejemplo, sera bueno conocer el total pagado en sueldos por departamento, es decir que la suma actuara sobre
subconjuntos de registros.
Para especificar los lmites de cada subconjunto de registros usamos la clusula GROUP BYseguida de una expresin sobre campos de la tabla. Los registros se agruparn
segn los valores de esos campos, de manera que todos los integrantes de un grupo tengan el mismo valor en esos campos. Por ejemplo, la consulta indicada antes de
totales pagados en salarios por departamento puede escribirse como sigue:
select sum(salary) as TotalPorDepto
from employee
group by dept_no
TOTALPORDEPTO
-------------266643
155262.5
130442.81
13480000
95779.69
110000

An mejor, podemos mostrar el nro. de departamento junto a cada total:


select dept_no as Depto, sum(salary) as TotalPorDepto
from employee
group by dept_no
DEPTO TOTALPORDEPTO
-------------------000 266643
100 155262.5
110 130442.81
115 13480000
120 95779.69
121 110000

Trate de visualizar mentalmente el resultado de la sentencia anterior sin la clusula ORDER BY. Si Ud. puede, lo felicito; yo no sabra cmo armar las filas, mezclando
nros. de departamento (que se repiten) y totales por cada departamento diferente. El intrprete SQL tampoco lo sabe, y se queja amargamente:
select dept_no as Depto, sum(salary) as TotalPorDepto
from employee
Dynamic SQL Error
SQL error code = -104
invalid column reference

como hicimos antes, debemos especificar que los registros se agruparn por nro. de departamento; entonces si, cada fila de la salida corresponde a un grupo y todos los
registros del grupo tienen el mismo valor en dept_no, por lo que no hay ambigedades.
La regla sintctica es, entonces:
??????

Suponga ahora que queremos ver solamente aquellos departamentos en los cuales se pagan ms de 250.000 dolares al ao en sueldos. En este caso la restriccin no se
puede aplicar con una clusula WHERE, ya que la condicin a cumplir utiliza el total por departamento calculado sobre los subconjuntos. Para aplicar una condicin de
filtrado despus del agrupamiento de los registros, existe la partcula HAVING:

select dept_no as depto, sum(salary) as TotalPorDepto


from employee
group by dept_no

http://archive.today/yKaUQ

24/47

26/6/2014

Firebird

group by dept_no
having sum(salary)>200000
DEPTO TOTALPORDEPTO
-------------------000 266643
115 13480000
123 390500
125 99000000
621 276739.5
623 287758.25
671 219465.19

Esos son todos los departamentos que cumplen con nuestra condicin.
Ahora cambiamos la pregunta: queremos saber cules son los sueldos que se pagan por departamento, pero solamente en USA. Esta condicin s se debe aplicar registro
por registro, ya que puede haber un departamento con empleados en distintos pases. La sentencia resultante es:
select dept_no as depto, sum(salary) as TotalPorDepto
from employee
where job_country='USA'
group by dept_no
DEPTO TOTALPORDEPTO
-------------------000 266643
100 155262.5
110 130442.81
130 189042.94
180 107377.5
600 132900

Y finalmente, juntamos las dos condiciones: queremos ver los departamentos en los que se pagan ms de U$S 200000 en total, contando solamente los empleados que
trabajan en USA:
select dept_no as depto, sum(salary) as TotalPorDepto
from employee
where job_country='USA'
group by dept_no
having sum(salary)>200000
DEPTO TOTALPORDEPTO
-------------------000 266643
621 276739.5
623 287758.25
671 219465.19

Solamente quedan esos departamentos despus de todos los filtros. Observe el orden de las distintas palabras clave en la sentencia: este orden debe respetarse.
Como ejemplo final, veamos esta misma lista pero ordenada de mayor a menor por monto:
select dept_no as depto, sum(salary) as TotalPorDepto
from employee
where job_country='USA'
group by dept_no
having sum(salary)>200000
order by 2 desc

Note que usamos el ndice del campo de agregado. Hasta la versin 1.02 de Firebird sta era la nica manera de hacerlo, ya que no se podan usar expresiones en la
clusula ORDER BY. En Firebird 1.5 esto se ha corregido, por lo que la sentencia anterior puede escribirse (igual que en la mayora de los gestores de Bases de Datos):
select dept_no as depto, sum(salary) as TotalPorDepto
from employee
where job_country='USA'
group by dept_no
having sum(salary)>200000
order by sum(salary) desc

Notemos la potencia del lenguaje; imagnese lo que tendra que hacer para obtener este resultado usando un cursor, recorriendo los registros uno por uno

Subconsultas
Hay casos en los que no nos basta con una consulta de seleccin. Pensemos por ejemplo cmo podramos obtener una tabla con registros en los que figure cierto valor, que
se debe obtener de otra consulta. Un caso tpico se da en las relaciones 'muchos-a-muchos', en las que tenemos dos tablas relacionadas entre s a travs de una tercera.
Por ejemplo, tomemos el caso de las tablas Employee y Project de la base de datos Employee.gdb que hemos trabajado antes. Estas tablas no se referencian entre s
http://archive.today/yKaUQ

25/47

26/6/2014
Firebird
Por ejemplo, tomemos el caso de las tablas Employee y Project de la base de datos Employee.gdb que hemos trabajado antes. Estas tablas no se referencian entre s
directamente: no hay un campo en la tabla de empleados que referencie a un proyecto en particular si este fuera el caso, cada empleado podra estar solamente en un
proyecto a la vez. Lo mismo pasa con los proyectos: si hubiera un campo para almacenar un nmero de empleado, solamente ese empleado podra estar en ese proyecto
La situacin real es ms compleja. Los empleados pueden estar en ms de un proyecto, y los proyectos pueden tener ms de un empleado. Para esto se necesita una
tercera tabla que contenga las relaciones. En Employee.gdb esta tabla se llama Employee_Project.

La tabla Employee_Project tiene la siguiente estructura:


CREATE TABLE EMPLOYEE_PROJECT (
EMP_NO EMPNO NOT NULL,
PROJ_ID PROJNO NOT NULL,
PRIMARY KEY (EMP_NO,PROJ_ID)
);

Como vemos, solamente tiene dos campos: uno referencia a un empleado, el otro a un proyecto. Cada registro de esta tabla relaciona a un empleado con un proyecto, y la
clave primaria es la conjuncin de los dos campos para permitir repeticiones en cualquiera de ellos por separado pero no en los dos juntos (un mismo empleado no se puede
poner en un mismo proyecto dos veces).
Ahora pensemos en la siguiente pregunta: cules son los nombres de los proyectos en los cuales participa Bruce Young? Intente obtener una respuesta con SQL antes de
seguir leyendo.
Podemos ejecutar la siguiente secuencia de acciones:
1) buscar el nro. de empleado de Bruce Young, ya que ste es el campo que existe en la tabla intermedia Employee_Project. Es muy simple:
select emp_no
from employee
where first_name='Bruce'
and last_name='Young'
EMP_NO
----------4

2) buscar los proyectos en que participa este empleado:


select *
from employee_project
where emp_no=4
EMP_NO
PROJ_ID
------------------4
VBASE
4
MAPDB

3) obtener los nombres de los proyectos 'VBASE' y 'MAPDB'


select Proj_id,Proj_Name
from project
where proj_id in ('VBASE','MAPDB')
PROJ_ID PROJ_NAME
----------------------------VBASE Video Database
MAPDB MapBrowser port

Esto fue fcil, dir usted. S. Pero no resulta difcil encontrarse relaciones de este tipo en las que un registro de una tabla se relaciona con cientos o miles de registros de la
otra en ese caso, sera muy engorroso y tal vez imposible de realizar en un tiempo prudencial la escritura de todos los 'ID' de la segunda tabla en el conjunto enviado al
operador IN.
Esta es una de las aplicaciones de las subconsultas, como ya vimos en la seccin de los criterios de seleccin: el argumento para el operador IN puede ser el resultado de
una consulta. En este caso, quedara

select Proj_id,Proj_Name
from project
where proj_id in (select Proj_Id from employee_project where emp_no=4)
PROJ_ID PROJ_NAME
----------------------------VBASE Video Database
MAPDB MapBrowser port

El resultado es el mismo, como era de esperar. Lo que hemos hecho es juntar varios pasos en uno solo.
Y la pregunta de examen: se puede obtener el mismo resultado con una sola sentencia? El resultado es afirmativo. Se pueden ejecutar todas las operaciones de
seleccin en una sola como la siguiente:
select Proj_id,Proj_Name
from project
where proj_id in
(select Proj_Id from employee_project where emp_no=
(select emp_no from employee where first_name='Bruce' and last_name='Young')

http://archive.today/yKaUQ

26/47

26/6/2014

Firebird

(select emp_no from employee where first_name='Bruce' and last_name='Young')


)

Observe especialmente que cada subconsulta va encerrada entre parntesis.


Este no es, claro, el nico caso en que se utilizan las subconsultas. Prcticamente cualquier problema que requiera la ejecucin de sentencias de seleccin intermedias,
cuyos resultados luego se usarn para obtener la respuesta, se puede escribir usando subconsultas.

Comparacin con el resultado de una subconsulta


Los siguientes operadores se pueden usar con subconsultas:
<valor> ALL<subconsulta>: devuelve TRUEsi el valor es igual a todos los devueltos por la subconsulta
<value> ANY | SOME<subconsulta>: devuelve TRUEsi el valor comparado es igual a alguno de los devueltos por la subconsulta.
EXISTS<subconsulta>: devuelve TRUEsi la subconsulta devuelve al menos una fila.

Ejemplo: determinar si hay al menos un proyecto en el que trabaje Leslie Johnson


select 'Si' as Hay_un_proyecto
from project
where exists
(select Proj_Id from employee_project where emp_no=8)
HAY_UN_PROYECTO
---------------Si
Si
Si
Si
Si
Si

Pruebe con un nro de empleado distinto, por ejemplo 1 (no existe) o 2 (no est asignado a ningn proyecto).
La respuesta es un tanto repetitiva el hecho es que se mostrar un 'Si' por cada proyecto existente en la tabla 'Project', dado que la subconsulta no est relacionada con la
consulta exterior. Entonces, por cada registro de la tabla Project se evala la subconsulta y sta siempre es la misma, siempre da el mismo resultado. Veremos dos maneras
de evitar las repeticiones:
1) Usando una tabla con un solo registro en la consulta externa. En Firebird / Interbase existe una tabla as en todas las bases de datos: es la que almacena
caractersticas de la base de datos en s, y por consiguiente slo tiene un registro. Se llama rdb$database. La consulta anterior quedaria de la siguiente manera
select 'Si' as Hay_un_proyecto
from rdb$database
where exists
(select Proj_Id from employee_project where emp_no=8)

Esta consulta devuelve un solo 'Si' si hay al menos un proyecto que contenga al empleado, y NULL en caso que no haya ninguno. Es bastante eficiente ya que la
subconsulta se ejecuta una sola vez.
2) Usando una subconsulta correlacionada. En este caso la subconsulta se relaciona con la consulta exterior a travs de algn campo, con lo que la evaluacin de la
subconsulta en cada registro de la exterior puede arrojar un resultado diferente.
select 'Si' as Hay_un_proyecto
from project
where exists
(select Proj_Id
from employee_project
where emp_no = 8
and employee_project.Proj_Id = project.Proj_id)
HAY_UN_PROYECTO
---------------Si
Si
Si

El resultado puede tener varias lneas, una por cada proyecto al que est asignado el empleado. Esta consulta es ms lenta que la anterior pero da una informacin
extra: la cantidad de proyectos a los que est asignado el empleado.
SINGULAR<subconsulta>: devuelve TRUEsi la subconsulta devuelve exactamente una fila.

Uniones

http://archive.today/yKaUQ

27/47

26/6/2014

Firebird

Uniones

Firebird permite la unin de varias consultas en una sola, usando la palabra clave UNIONentre las consultas. El resultado de la operacin es una sola tabla, entonces qu
campos tendr esta tabla? Si en todas las consultas unidas hay campos diferentes, cules de ellos se incluirn en el resultado? Bueno, para no complicar las cosas el
estndar SQL define que todas las consultas incluidas en una unin deben tener los mismos campos. O sea:

la misma cantidad de campos,

que se llamen igual,

estn en el mismo orden y

sean del mismo tipo.

Suena un poco restrictivo, pero siguen siendo muy tiles. Veamos algunos ejemplos.
<<<Ejemplos de uniones>>>

Consulta de varias tablas relacionadas


Hasta ahora hemos trabajado siempre con una sola tabla. Pero si seguimos las reglas de normalizacin tendremos que dividir muchas veces los datos en varias tablas; por
ejemplo, en la tabla de proyectos (projects) de la base de datos que estamos usando existe un campo llamado team_leader, numrico. Numrico? Quiere decir que los
lderes de proyecto se reconocen por un nmero nicamente, no por el nombre y apellido como todo el mundo? Bueno, justamente: ese nmero es el nmero de empleado
de un registro de la tabla employee. Despus de todo, hasta los lderes de proyecto son empleados!
<<<grfico de los datos en forma de arbol, a la derecha>>>
Veamos de otra manera la normalizacin de tablas: como un rbol. En este rbol el tronco es nuestra tabla principal, y cada nueva rama es un registro de otra tabla con un
enlace hacia el tronco. En el caso menos botnico de las bases de datos relacionales el enlace viene dado por uno o ms campos que tendrn los mismos valores en las dos
tablas. Para acceder a todos los datos completos de un registro de la tabla principal (el tronco), debemos mostrar tambin los datos de todas las ramas que cuelgan de l.
Algo as como hachar el rbol y poner todas las ramas una al lado de la otra.
Este esquema no sera funcional sin un lenguaje de consulta que permita obtener datos de tablas relacionadas a la vez; esto es lo que hace SELECT con las relaciones o
encuentros (Joins).
Hay varias maneras de recuperar informacin de tablas relacionadas. Por ejemplo, podemos pedir que la BD nos devuelva los datos de todas las compras (tabla de
facturas) de nuestros clientes (cuyos datos estn en otra tabla); pero qu pasar con los datos de los clientes que no han comprado nada todava y por lo tanto no tienen
facturas? Bueno, esto depende del tipo de encuentro que usemos al consultar como veremos en seguida.
En general, las relaciones siempre se hacen entre dos tablas; aunque puede haber varias de estas relaciones de pareja en una sola instruccin SELECT.
Veremos primero la forma ms antigua
WHERE:

[7]

, listando los nombres de todas las tablas intervinientes luego de FROM, separadas por comas, y con las relaciones en la clusula

SELECT columnas | *
FROM tabla1, tabla2, tabla3
[WHERE condicin]
[ORDER BY columnas]

Con un ejemplo se ver ms claro. En la base de datos Employee.gdbtenemos varias tablas relacionadas, por ejemplo las de empleados (datos generales de los
empleados) y la de departamentos (datos de cada departamento de la empresa). En la tabla de departamentos (Apartment) hay un campo que relaciona con la tabla de
empleados: Mngr_No, o nmero de empleado del encargado (Manager). Este nmero se relaciona con el campo Emp_no de la tabla de empleados, de tal manera que cada
departamento que tenga un encargado tendra en el campo Mngr_no su nmero de empleado. Si queremos mostrar el nombre del departamento y el nombre de su
encargado, tendremos que buscar en las dos tablas. La siguiente es una manera de hacerlo en SQL:

SELECT department.department, employee.full_name


FROM employee, department
WHERE department.mngr_no = employee.emp_no
ORDER BY department.department
DEPARTMENT
FULL_NAME
---------------------------------------------------------------Consumer Electronics Div. Cook, Kevin
Corporate Headquarters
Bender, Oliver H.
Customer Services
Williams, Randy
Customer Support
Young, Katherine
Engineering
Nelson, Robert

Esta instruccin nos devuelve la lista de todos los departamentos, y el nombre del encargado, ordenados por departamento.
http://archive.today/yKaUQ

28/47

26/6/2014

Firebird

Un momento! Pidan una lista de los departamentos


ordenados, y comparen por ejemplo, pueden ver en el
primer resultado el departamento Marketing? Este es slo
uno de los que faltan. La razn: el campo Mngr_No de
esos registros tiene un valor nulo, implicando que no hay un
encargado asignado al departamento (o alguien se olvid de
cargarlo en la base de datos).
Moraleja: cuando se utiliza esta forma de relacin entre tablas (listado de las tablas en el FROM, condiciones de enlace en WHERE) nicamente aparecen en el
resultado los registros de las dos tablas en las cuales haya valores de enlace coincidentes. Este tipo de encuentro entre tablas se denomina Encuentro Interno
(INNER JOIN).
Ejercicio
Realice la misma consulta del ejemplo anterior, pero esta vez sin el criterio de seleccin (WHERE). qu obtiene?
La unin interna que acabamos de ver es muy peligrosa; primero porque no muestra todos los registros, y podemos llevarnos un chasco imagnense que le llevan la lista
generada por la primera consulta al jefe y ste busca el departamento de marketing. Y segundo, porque si no especifican la relacin entre las tablas como un criterio de
seleccin (como en el ejercicio) entonces obtendrn lo que se denomina una Encuentro Natural o Cartesiano. En esta unin se muestran todas las combinaciones de los
registros de las tablas. Es decir que si una tabla tiene 10 registros y la otra tiene 5, el resultado contendr 50 registros!
El problema de la unin cartesiana se ve fcilmente cuando pedimos la unin de tres o ms tablas y nos olvidamos de alguna relacin. Por ejemplo, si queremos ver el
nombre de los clientes, las ventas que se le han hecho a cada uno, y la moneda que se utiliza en el pas de origen del cliente, necesitamos las tres tablas Customer (clientes),
Country (pases) y Sales (ventas):

SELECT c.customer as Cliente, pais.currency as Moneda, s.order_date as FechaPedido,


s.order_status as Estado, s.paid as Pagado
FROM customer c, country pais, sales s
WHERE c.cust_no = s.cust_no
AND c.country = pais.country
ORDER BY c.customer

Hay varias cosas para notar en la consulta anterior.


No aparecen todos los clientes. Esto ya era de esperar, no? Cules son los que aparecen?
Las relaciones entre las distintas tablas se unen entre s con AND, para indicar que se tienen que cumplir todas las condiciones para que el registro aparezca en el
resultado.
As se pueden agregar ms tablas, simplemente listndolas en el FROM y agregando una condicin al criterio de seleccin con AND. Qu pasar si nos olvidamos de
algn criterio? Pues que el servidor no emitir ningn error, y generar una unin cartesiana con la tabla que dejemos suelta
Hay otras formas de combinacin de tablas. Podemos pedir al servidor que nos muestre todos los registros de una de las tablas, y nicamente los valores de la otra tabla
cuando haya una correspondencia. Se dice que se preserva una tabla, la que se muestra completa.
Algunos servidores implementan estas combinaciones con variaciones de la sintaxis anterior, agregando nuevos operadores a la sentencia where. Firebird en cambio sigue
el estndar ANSI-92 en el que se propone una nueva forma de especificar las combinaciones entre tablas, indicndolas en el FROM. La sintaxis completa sera
FROM <tabla1> {INNER | LEFT | RIGHT | FULL} JOIN <tabla2> ON <expresin con los campos relacionados>

Escribamos algunos de los ejemplos anteriores con la nueva sintaxis:

SELECT department.department, employee.full_name


FROM employee, department

http://archive.today/yKaUQ

29/47

26/6/2014

Firebird

FROM employee, department


WHERE department.mngr_no = employee.emp_no
ORDER BY department.department

Esta instruccin nos devuelve la lista de todos los departamentos, y el nombre del encargado, ordenados por departamento. Con la nueva sintaxis, quedara:

SELECT department.department, employee.full_name


FROM employee INNER JOIN department ON department.mngr_no = employee.emp_no
ORDER BY department.department

O veamos la siguiente, que trae los datos de los pedidos, clientes y pases
SELECT c.customer as Cliente, pais.currency as Moneda, s.order_date as FechaPedido, s.order_status as Estado, s.paid as
Pagado
FROM customer c, country pais, sales s
WHERE c.cust_no = s.cust_no
AND c.country = pais.country
ORDER BY c.customer

Con la nueva sintaxis:


SELECT c.customer as Cliente, pais.currency as Moneda, s.order_date as FechaPedido, s.order_status as Estado, s.paid as
Pagado
FROM customer c
INNER JOIN country pais ON c.country = pais.country
INNER JOIN sales s ON c.cust_no = s.cust_no
ORDER BY c.customer

La nueva sintaxis separa fsicamente los conceptos lgicos de relacin o encuentro y criterios de seleccin.
Volvamos sobre el primer ejemplo, donde traamos cada departamento con el nombre de su encargado. Notamos antes que no se listan todos los departamentos cuando
pedimos una unin interna, ya que hay departamentos que no tienen encargado. Usando las extensiones a la sintaxis podemos pedir que se nos muestren todos los
departamentos, completando el registro con el nombre del encargado cuando ste exista:

SELECT department.department, employee.full_name


FROM employee
RIGHT JOIN department ON department.mngr_no = employee.emp_no
ORDER BY department.department

DEPARTMENT
FULL_NAME
---------------------------------------------------------------Consumer Electronics Div. Cook, Kevin
Corporate Headquarters
Bender, Oliver H.
Customer Services
Williams, Randy
Customer Support
Young, Katherine
Engineering
Nelson, Robert
European Headquarters
Reeves, Roger
Field Office: Canada
Sutherland, Claudia
Field Office: East Coast Weston, K. J.
Field Office: France
Glon, Jacques
Field Office: Italy
Ferrari, Roberto
Field Office: Japan
Yamamoto, Takashi
Field Office: Singapore
Field Office: Switzerland Osborne, Pierre
Finance
Steadman, Walter
Marketing
Pacific Rim Headquarters Baldwin, Janet
Quality Assurance
Forest, Phil
Research and Development Papadopoulos, Chris
Sales and Marketing
MacDonald, Mary S.
Software Development
Software Products Div.

Note los espacios vacos en la columna 'FULL_NAME' del nombre del encargado. Hemos utilizado aqu una unin a derecha, es decir preservando la tabla de la derecha
de la partcula JOIN (en este caso, department).
Podemos reescribir la misma consulta, con el mismo resultado, preservando la tabla izquierda:

SELECT department.department, employee.full_name


FROM department
LEFT JOIN employee ON department.mngr_no = employee.emp_no
ORDER BY department.department

http://archive.today/yKaUQ

30/47

26/6/2014

Firebird

Notemos que el resultado es el mismo, solamente hemos cambiado el orden de las tablas en la clusula FROM.
Por ltimo, podemos preservar las dos tablas al mismo tiempo: se mostrarn todos los registros de ambas tablas, completando con nulos los lugares donde falten datos
relacionados:

SELECT department.department, employee.full_name


FROM department
FULL JOIN employee ON department.mngr_no = employee.emp_no
ORDER BY department.department
DEPARTMENT
FULL_NAME
---------------------------------------------------------------Consumer Electronics Div. Cook, Kevin
Corporate Headquarters
Bender, Oliver H.
Customer Services
Williams, Randy
Customer Support
Young, Katherine
Engineering
Nelson, Robert
European Headquarters
Reeves, Roger
Field Office: Canada
Sutherland, Claudia
Field Office: East Coast Weston, K. J.
Field Office: France
Glon, Jacques
Field Office: Italy
Ferrari, Roberto
Field Office: Japan
Yamamoto, Takashi
Field Office: Singapore
Field Office: Switzerland Osborne, Pierre
Finance
Steadman, Walter
Marketing
Pacific Rim Headquarters Baldwin, Janet
Quality Assurance
Forest, Phil
Research and Development Papadopoulos, Chris
Sales and Marketing
MacDonald, Mary S.
Software Development
Software Products Div.
Green, T.J.
Nordstrom, Carol
Bishop, Dana
Guckenheimer, Mark
Page, Mary
Johnson, Scott
Burbank, Jennifer M.
Brown, Kelly
Johnson, Leslie
Phong, Leslie
Fisher, Pete
Lee, Terri
Parker, Bill
Lambert, Kim
Yanowski, Michael
Stansbury, Willie
Bennet, Ann
Montgomery, John
De Souza, Roger
Young, Bruce
Ramanathan, Ashok
Hall, Stewart
Leung, Luke
O'Brien, Sue Anne
Ichida, Yuki

Ahora tenemos espacios vacos (recordemos que son valores nulos) en ambas columnas. Este tipo de consultas sirve para ubicar rpidamente registros hurfanos, que han
quedado desenlazados de la tabla maestra en una relacin maestro-detalle. Recordemos que se pueden declarar restricciones de clave externa para evitar esto.
<<<Poner algn otro ejemplo de las uniones externas>>>

Creacin, modificacin y borrado de objetos


Lenguaje de Definicin de Datos (DDL)

El Lenguaje de Definicin de Datos es un subconjunto de SQL con instrucciones para crear, modificar y borrar los distintos objetos que componen la Base de Datos como
ser tablas, ndices, dominios, etc. Incluso permiten la definicin de Bases de Datos completas.

Bases de Datos
http://archive.today/yKaUQ

31/47

26/6/2014

Firebird

Creacin de una base de datos


Para crear una base de datos se utiliza la sentencia CREATE DATABASE. La sintaxis es la siguiente:
CREATE {DATABASE | SCHEMA} 'filespec'
[USER 'username' [PASSWORD 'password']]
[PAGE_SIZE [=] int]
[LENGTH [=] int [PAGE[S]]]
[DEFAULT CHARACTER SET charset]
[<secondary_file>];

SCHEMA = equivalente a DATABASE


<secondary_file> = FILE 'filespec' [<fileinfo>] [<secondary_file>]
<fileinfo> = [LENGTH [=] int [PAGE[S]] | STARTING [AT [PAGE]] int }
[<fileinfo>]

Veremos las distintas opciones de la sentencia anterior a travs de ejemplos.

1. CREATE DATABASE C:\EMPLEADOS.GDB USER SYSDBA PASSWORD masterkey;

Esta es la instruccin ms comn: crea un archivo con el nombre dado como primer parmetro, conectando al servidor con el nombre de usuario y clave dados (el usuario
usado debe tener permisos para creacin de bases de datos utilizaremos casi siempre el nombre del administrador del servidor, que por defecto es SYSDBA con clave
masterkey).
Si ya existe un archivo con el nombre pedido se cancela la operacin.
No es obligatoria la extensin .GDB

[8]

en el archivo; el motor de datos no considera la extensin sino el contenido.

El tamao no importa (perdn, Godzilla!)


El tamao de las bases de datos Firebird es dinmico; el servidor va agregando pginas (a continuacin) al archivo a medida que las necesita. Es posible indicar al servidor
un tamao mximo para un archivo de la base de datos, siempre que haya otros archivos a continuacin. Por ejemplo, en la sentencia anterior podramos agregar LENGHT
10000 para indicar al servidor un tamao mximo de 10000 pginas; pero al tratarse del ltimo archivo de la base (de hecho, el nico) el servidor ignorar la indicacin y
considerar al archivo como de tamao dinmico.
En ejemplos posteriores partiremos una base de datos en varios archivos, caso en el que s se respeta el tamao de cada archivo salvo el ltimo.

2. CREATE DATABASE C:\EMPLEADOS.GDB USER SYSDBA PASSWORD masterkey PAGE_SIZE 4096;

Crea la misma base de datos que el ejemplo anterior, pero instruye al servidor para que utilice pginas de 4096 bytes en lugar de 1024, que es el valor por defecto. Con esta
configuracin se alcanza un mejor rendimiento, como se explica a continuacin.

Pginas
Los registros dentro de las tablas se organizan en conjuntos llamados pginas. Las pginas son la unidad de intercambio de datos entre el archivo en disco y la memoria;
cuando el servidor necesita datos tiene que cargar una pgina entera a la memoria. Estas pginas se mantienen en la memoria por un tiempo, de manera que estn
rpidamente disponibles si se solicitan nuevamente. La divisin en pginas es vlida tanto para datos como para los ndices.
El tamao por defecto de 1024 bytes es muy conservador de memoria; en los sistemas actuales, se alcanza un rendimiento mucho mayor usando pginas de 4096 bytes o
ms (Interbase soporta hasta pginas de 8192 bytes; Firebird, 16384 bytes). Mientras ms grandes las pginas, ms memoria se usar en el servidor pero sern necesarias
menos lecturas de disco. El punto ptimo es un compromiso entre los recursos usados y el rendimiento necesario para la aplicacin en consideracin.

3. CREATE DATABASE C:\EMPLEADOS.GDB USER SYSDBA PASSWORD masterkey PAGE_SIZE 4096 FILE c:\EMPLEADOS2.GDB STARTING AT
PAGE 10001;

Esta instruccin crea una base de datos dividida en dos archivos: el principal, c:\empleados.gdb, de hasta 40.960.000 bytes (4096*10000, unos 40 Mb) y otro
secundario llamado c:\empleados2.gdb que almacenar las pginas a partir de la 10001.
Una forma equivalente de definir la misma base de datos sera la siguiente:
CREATE DATABASE C:\EMPLEADOS.GDB USER SYSDBA PASSWORD masterkey PAGE_SIZE=4096 LENGHT=10000 PAGES FILE
c:\EMPLEADOS2.GDB;

Note tambin que los signos = (igual), as como la palabra PAGES, son opcionales.
Cuando se especifican varios archivos, es importante tener en cuenta que en los archivos secundarios no se pueden incluir nombres de nodos de red; por lo tanto, si se crea
http://archive.today/yKaUQ
32/47

26/6/2014
Firebird
Cuando se especifican varios archivos, es importante tener en cuenta que en los archivos secundarios no se pueden incluir nombres de nodos de red; por lo tanto, si se crea
la base de datos de forma remota, todos los archivos secundarios se crearn en el mismo nodo.

4. CREATE DATABASE C:\EMPLEADOS.GDB USER SYSDBA PASSWORD masterkey DEFAULT CHARACTER SET 'ISO8859_1';

Esta ltima sentencia especifica un juego de caracteres por defecto para la Base de Datos.

El juego de caracteres
El juego de caracteres de una base de datos determina los caracteres a usar en las columnas de tipo CHAR, VARCHAR o BLOB subtipo 1. Ligado al juego de caracteres
estar tambin el tamao de almacenamiento, ya que por ejemplo el juego UNICODE_FSS tiene caracteres que ocupan 1 byte y otros que ocupan hasta 3 bytes.
Tambin acta en el ordenamiento (collation order) y determina las transformaciones que se pueden hacer entre distintos juegos de caracteres (transliteration). Para ver
los distintos juegos de caracteres y las especificaciones de ordenamiento (collation orders) disponibles, podemos interrogar a las tablas de sistema:

SELECT RDB$CHARACTER_SET_NAME, RDB$CHARACTER_SET_ID


FROM RDB$CHARACTER_SETS
ORDER BY RDB$CHARACTER_SET_NAME;
SELECT RDB$COLLATION_NAME, RDB$CHARACTER_SET_ID
FROM RDB$COLLATIONS
ORDER BY RDB$COLLATION_NAME;

En el ejemplo anterior (4) se especifica el juego de caracteres ISO8859_1 para ser usado por defecto; no obstante, se puede cambiar en forma individual para cada
campo alfanumrico de una tabla.
Si no se especifica el juego de caracteres por defecto, se tomar como NONE; esto significa que no se har ninguna conversin al almacenar caracteres en los campos
alfanumricos. Pero mucho cuidado: no se podrn copiar cadenas entre campos definidos con NONE y otros definidos con un juego de caracteres diferente. Esto
restringe la utilizacin futura de distintos juegos de caracteres en campos especficos de una tabla.
Los clientes pueden especificar tambin el juego de caracteres con el que trabajarn, emitiendo una sentencia SET NAMES <juego de caracteres>antes de trabajar
con los campos alfanumricos. Esto le indica al servidor las transformaciones que debe efectuar en los caracteres que se pasan entre el servidor y el cliente, en ambos
sentidos.
Si no especificamos un juego de caracteres para el cliente, se tomar NONE por defecto. La restriccin que comentamos antes de no poder convertir caracteres
extendidos entre NONE y cualquier otro se mantiene, por lo que el servidor rechazar cualquier intento de introducir caracteres extendidos en una tabla.
Podemos enunciarlo como
Regla Prctica: al acceder a una BD con un juego de caracteres distinto de NONE, el cliente tambin debera indicar un juego de caracteres distinto de NONE,
preferentemente el mismo que la BD.
Es muy comn encontrarse con el siguiente problema: a pesar de haber definido el juego de caracteres iso8859_1 por defecto para la base de datos, cuando se quiere
ingresar una cadena con ees o vocales acentuadas el servidor se queja y rechaza el ingreso. Como podr imaginarse si ha ledo lo anterior con atencin, falta definir el
juego de caracteres en la conexin del cliente. Si est ejecutando un script SQL, agregue la sentencia SET NAMES iso8859_1; al principio. Si es un programa, defina el
juego de caracteres de la conexin segn lo requiera su lenguaje de programacin.
Un juego de caracteres puede soportar varias especificaciones de ordenamiento (collation orders). Por ejemplo, el juego de caracteres ISO8859_1usado para los
caracteres europeos puede ser ordenado segn especificaciones francesas (COLLATE FR_CA) o espaolas (COLLATE ES_ES). Las distintas opciones se obtienen de las
tablas de sistema como se indic antes. Este es el resultado en un servidor Firebird 1.0 mediante la siguiente sentencia (una mezcla de las dos anteriores):
<<<Determinar que diferencia hay entre los ordenamientos fr_ca y es_es, con un ejemplo>>>

SELECT cs.RDB$CHARACTER_SET_NAME, co.RDB$COLLATION_NAME


FROM RDB$CHARACTER_SETS cs
left join RDB$COLLATIONS co on cs.RDB$CHARACTER_SET_ID=co.RDB$CHARACTER_SET_ID
ORDER BY cs.RDB$CHARACTER_SET_NAME;
RDB$CHARACTER_SET_NAME

RDB$COLLATION_NAME

ASCII

ASCII

BIG_5

BIG_5

CYRL

DB_RUS
PDOX_CYRL
CYRL

DOS437

DB_UK437
DB_US437
DB_FRA437
DB_ITA437
DB_NLD437

http://archive.today/yKaUQ

DB_SVE437

33/47

26/6/2014

Firebird
DB_SVE437
DB_FIN437
DB_ESP437
DB_DEU437
PDOX_ASCII
PDOX_INTL
PDOX_SWEDFIN
DOS437

DOS850

DB_UK850
DB_US850
DB_FRA850
DB_ITA850
DB_PTB850
DB_FRC850
DB_NLD850
DB_SVE850
DB_ESP850
DB_DEU850
DOS850

DOS852

DB_PLK
DB_SLO
DB_CSY
PDOX_CSY
PDOX_HUN
PDOX_PLK
PDOX_SLO
DOS852

DOS857

DB_TRK
DOS857

DOS860

DB_PTG860
DOS860

DOS861

PDOX_ISL
DOS861

DOS863

DB_FRC863
DOS863

DOS865

DB_DAN865
DB_NOR865
PDOX_NORDAN4
DOS865

EUCJ_0208

EUCJ_0208

GB_2312

GB_2312

ISO8859_1

DA_DA
DE_DE
FI_FI
EN_UK
EN_US
NO_NO
FR_CA
FR_FR
ES_ES
IS_IS
ISO8859_1
IT_IT
PT_PT
DU_NL

http://archive.today/yKaUQ

34/47

26/6/2014

Firebird
SV_SV

ISO8859_2

CS_CZ
ISO8859_2

KSC_5601

KSC_5601
KSC_DICTIONARY

NEXT

NEXT
NXT_DEU
NXT_FRA
NXT_ESP
NXT_US
NXT_ITA

NONE

NONE

OCTETS

OCTETS

SJIS_0208

SJIS_0208

UNICODE_FSS

UNICODE_FSS

WIN1250

WIN1250
PXW_PLK
PXW_SLOV
PXW_CSY
PXW_HUN
PXW_HUNDC

WIN1251

WIN1251
PXW_CYRL

WIN1252

WIN1252
PXW_INTL
PXW_INTL850
PXW_NORDAN4
PXW_SPAN
PXW_SWEDFIN

WIN1253

WIN1253
PXW_GREEK

WIN1254

WIN1254
PXW_TURK

Se pueden agregar especificaciones de ordenamiento, lo que se denomina secuencias de ordenamiento o collations. Las secuencias de ordenamiento se implementan en
Firebird como funciones en libreras externas (.dll en Windows, .so en Linux). En el sitio web www.ibcollations.com se puede encontrar una referencia y una librera de
ejemplo que implementa varias secuencias.

Modificacin de una base de datos


Para modificar una base de datos existente se utiliza la sentencia ALTER DATABASE:
ALTER {DATABASE | SCHEMA}
ADD <add_clause>;
<add_clause> = FILE 'filespec' [<fileinfo>] [<add_clause>]
<fileinfo> = LENGTH [=] int [PAGE[S]]
| STARTING [AT [PAGE]] int [<fileinfo>]

Como vemos, la nica posibilidad de modificacin es la adicin de nuevos archivos a la base de datos.
Con esta instruccin no se puede dividir una base de datos; nicamente agregar archivos a continuacin de los existentes. Para partir una base de datos, haga un respaldo
al restaurarlo puede especificar los nuevos tamaos de los archivos.
Un ejemplo:
ALTER DATABASE
ADD FILE 'empleados2.gdb'
STARTING AT PAGE 10001 LENGTH 10000
ADD FILE 'empleados3.gdb';

http://archive.today/yKaUQ

35/47

26/6/2014

Firebird

La sentencia del ejemplo agregar un archivo llamado empleados2.gdb, que comenzar a partir de la pgina 10001 (si ya haba ms pginas que esas, comenzar a
continuacin de la ltima existente) y despus de 10000 pginas seguir colocando datos en un tercer archivo llamado empleados3.gdb.

Borrado de una base de datos


Para borrar una base de datos (eliminando el archivo fsico) se utiliza DROP DATABASE sin parmetros:
DROP DATABASE;

Hay que estar conectado a la base de datos antes de borrarla.

Tablas
Las tablas son las estructuras bsicas que tienen que estar presentes en nuestra base de datos. Qu es una base de datos sin datos? Entonces, veamos las posibilidades
que nos brinda Interbase para la definicin de tablas, y cmo plasmarlas en SQL.

Creacin de una tabla


La sentencia CREATE TABLEse utiliza para definir la estructura de una tabla. La sintaxis general es la siguiente:
CREATE TABLE table [EXTERNAL [FILE] 'filespec']
(<col_def> [, <col_def> | <tconstraint> ]);

En esencia, lo que espera esta sentencia es el nombre de la tabla que debe ser nico entre las tablas y procedimientos de la base de datos- y una lista de columnas o
restricciones a nivel de tabla, entre parntesis y separadas por comas. Opcionalmente se puede especificar que los datos de la tabla se guarden en un archivo externo.
Veamos, como antes, los distintos elementos de la sintaxis con ejemplos progresivos:

1. CREATE TABLE EJEMPLO1 (CAMPO1 integer);

Esta sentencia crea una tabla llamada EJEMPLO1 con un solo campo de tipo entero llamado CAMPO1. Hay algunas cosas para notar aqu:

Nombres de objetos
Los nombres de los objetos de la Base de Datos deben seguir ciertas normas:
Deben ser nicos en su tipo por ejemplo, no puede haber dos tablas que se llamen igual- en la misma base de datos.
Deben empezar con una letra
En dialecto 3, se pueden usar caracteres no ingleses como la , y tambin espacios; pero entonces, en todas las sentencias SQL que referencien al objeto (includa la
de creacin de la tabla) hay que encerrar este nombre entre comillas dobles ( ).
No se diferencian minsculas de maysculas, salvo que estemos en Dialecto 3 y encerremos el nombre entre comillas dobles ( ). En otro caso, los nombres sern
convertidos a maysculas y en las sentencias SQL se pueden escribir de cualquier forma.

Tipos de datos soportados por Firebird


Las columnas de una tabla almacenan datos de un solo tipo, que debe ser especificado en la declaracin de la tabla. Los tipos de datos soportados por el servidor Firebird
1.0 son los siguientes:
<datatype> =
{SMALLINT | INTEGER | FLOAT | DOUBLE PRECISION}[<array_dim>]
| (DATE | TIME | TIMESTAMP}[<array_dim>]
| {DECIMAL | NUMERIC} [(precision [, scale])] [<array_dim>]
| {CHAR | CHARACTER | CHARACTER VARYING | VARCHAR} [(int)]
[<array_dim>] [CHARACTER SET charname]
| {NCHAR | NATIONAL CHARACTER | NATIONAL CHAR}
[VARYING] [(int)] [<array_dim>]
| BLOB [SUB_TYPE {int | subtype_name}] [SEGMENT SIZE int]
[CHARACTER SET charname]
| BLOB [(seglen [, subtype])]

http://archive.today/yKaUQ

36/47

26/6/2014

Firebird

| BLOB [(seglen [, subtype])]


<array_dim> = [[x:]y [, [x:]y ]]

Nombre

Tipo

Tamao real

Rango

SMALLINT

Nmero entero

2 bytes

-32768..32767

INTEGER

Nmero entero

4 bytes

-216..216-1

INT64 o BIGINT

Nmero entero

8 bytes

-232..232-1

FLOAT

Nmero real

DOUBLE PRECISION

Nmero real

DECIMAL(n,p)[EC10]

Nmero real: n dgitos, p


decimales

NUMERIC(n,p)

Nmero real: n dgitos, p


decimales

En dialecto 3, n <= 18. Si


n>15, se almacena como un
INT64 que se escala
multiplicando y dividiendo
por 10^p

DATE

Fecha

4 bytes (double word)

TIME

Hora

4 bytes (double word)

TIMESTAMP

Fecha y hora

8 bytes

CHAR(n)

Caracteres, tamao fijo.


Mximo n caracteres

N bytes

VARCHAR(n)

Caracteres, tamao
variable. Mximo n
caracteres

N+2 bytes. Los dos


primeros bytes almacenan
el tamao

BLOB sub_type 0

Datos binarios arbitrarios

BLOB sub_type 1

Caracteres, sin lmite de


tamao (Memo)

Condiciones para los campos


[9]
Veamos un ejemplo real, obtenido de la base de datos de ejemplo employee.gdb que se instala con Firebird :
CREATE TABLE CUSTOMER (
CUST_NO INTEGER NOT NULL,
CUSTOMER VARCHAR(25) NOT NULL,
CONTACT_FIRST VARCHAR(15),
CONTACT_LAST VARCHAR(20),
PHONE_NO VARCHAR(20),
ADDRESS_LINE1 VARCHAR(30),
ADDRESS_LINE2 VARCHAR(30),
CITY VARCHAR(25),
STATE_PROVINCE VARCHAR(15),
COUNTRY VARCHAR(15),
POSTAL_CODE VARCHAR(12),
ON_HOLD CHAR(1) DEFAULT NULL,
PRIMARY KEY (CUST_NO)
);

Se han declarado aqu algunas condiciones sobre los campos: por ejemplo, se indica que el campo CUST_NO no puede quedar vaco o que el campo ON_HOLD tomar
un valor por defecto nulo. Estas condiciones son controladas por el servidor, por lo que la aplicacin cliente no debe hacer nada para forzarlas.
La sintaxis completa de la definicin de un campo es la siguiente:
<col_def> = col {<datatype> | COMPUTED [BY] (<expr>) | domain}
[DEFAULT {literal | NULL | USER}]
[NOT NULL]
[<col_constraint>]
http://archive.today/yKaUQ

37/47

26/6/2014

Firebird

[COLLATE collation]
NOT NULL: el registro no se introducir en la tabla si este campo no tiene algn valor.
DEFAULT: el campo tomar el valor por defecto especificado si no se indica ninguno. El valor puede ser una constante, la palabra 'NULL' (se asigna valor nulo), o la
palabra 'USER' (se asigna el nombre del usuario autenticado actualmente). Tambin se puede usar la palabra 'TODAY' para asignar la fecha actual, si el campo es de
tipo DATE.
COLLATE: vlida para campos de caracteres, indica que se usar la secuencia de ordenamiento especificada.
COMPUTED BY: el valor del campo se calcular aplicando una frmula, como se explica en la siguiente seccin.

Campos calculados
Se pueden declarar campos calculados en el servidor, indicando la frmula de clculo en funcin de otros campos de la tabla. Por ejemplo, la siguiente definicin es
vlida:

CREATE TABLE CLIENTES (


ID_CLIENTE INTEGER NOT NULL PRIMARY KEY,
NOMBRE VARCHAR(30) NOT NULL,
APELLIDO VARCHAR(30) NOT NULL,
NOMBRECOMPLETO COMPUTED BY (APELLIDO || ', ' || NOMBRE)
);

Se pueden usar funciones estndar de SQL y/o funciones externas (UDF), encerrando la expresin completa entre parntesis. El tipo de datos de la columna calculada se
asigna automticamente, en base a la expresin de clculo.
Veamos otros ejemplos:
Columna de subtotal para una factura
CREATE TABLE ITEMS (
ID_ITEM INTEGER NOT NULL PRIMARY KEY,
ID_FACTURA INTEGER NOT NULL REFERENCES FACTURAS(ID_FACTURA),
CANTIDAD INTEGER DEFAULT 1 NOT NULL,
DESCRIPCION VARCHAR(50) NOT NULL,
PRECIO_UNIT NUMERIC(18,4) DEFAULT 0 NOT NULL,
SUBTOTAL COMPUTED BY (CANTIDAD*PRECIO_UNIT)
);

Columna que calcula la fecha de cumpleaos del ao actual en base a la fecha de nacimiento
CREATE TABLE FECHAS
(
ID INTEGER,
FECHANAC DATE,
FECHACUMPLE COMPUTED BY (extract(year from current_date) || '-' ||
extract(month from FechaNac) || '-' ||
extract(day from FechaNac))
);

En este ltimo ejemplo habra que tener cuidado con los aos bisiestos: si la fecha de nacimiento cae un 29 de febrero, en todos los aos que no fueran bisiestos se generara
un error. Esto es as porque la columna FECHACUMPLE se considera como de tipo DATE, por el formato especial que le dimos. Podemos evitar el problema usando cast:
CREATE TABLE FECHAS2
(
ID INTEGER,
FECHANAC DATE,
FECHACUMPLE COMPUTED BY (cast(extract(year from current_date) || '-' ||
extract(month from FechaNac) || '-' ||
extract(day from FechaNac) as char(10)))
);

Restricciones
Adems de las condiciones, Firebird acepta que se declaren restricciones a nivel de columna o de tabla.
La sintaxis para las restricciones de tabla es la siguiente:
<restriccion_de_tabla> = [CONSTRAINT constraint]
{{PRIMARY KEY | UNIQUE} (col [, col ])
| FOREIGN KEY (col [, col ]) REFERENCES otra_tabla
[ON DELETE {NO ACTION|CASCADE|SET DEFAULT|SET NULL}]
[ON UPDATE {NO ACTION|CASCADE|SET DEFAULT|SET NULL}]
| CHECK (<condicion>)}

http://archive.today/yKaUQ

38/47

26/6/2014

| CHECK (<condicion>)}

Firebird

Mientras que las restricciones a nivel de columna siguen la sintaxis


<col_constraint> = [CONSTRAINT constraint]
{ UNIQUE
| PRIMARY KEY
| REFERENCES other_table [(other_col [, other_col ])]
[ON DELETE {NO ACTION|CASCADE|SET DEFAULT|SET NULL}]
[ON UPDATE {NO ACTION|CASCADE|SET DEFAULT|SET NULL}]
| CHECK (<search_condition>)}

Como vemos, son casi iguales; de hecho, lo nico que vara es la sintaxis, las restricciones son las mismas. Actualmente se soportan los siguientes cuatro tipos:

PRIMARY KEY (campo1, campo2, ...): clave primaria. Define los campos que formarn la clave primaria de la tabla.

UNIQUE (campo1, campo2, ...): unicidad. Indica que la combinacin de los valores de los campos listados no puede repetirse en la tabla.

FOREIGN KEY (campo1, campo2, ...) REFERENCES tabla2 (campo3, campo4, ...): clave externa o fornea. Los campos (1, 2, ...) listados referencian a los
campos (3, 4, ...) de la segunda tabla. Los valores de los campos de la segunda tabla deben identificar unvocamente a un registro para que la referencia sea vlida; en la
prctica, debe existir una clave primaria o una restriccin de unicidad sobre esos campos.
Opcionalmente se puede especificar qu debe hacer el servidor cuando no se cumple la restriccin, incluso con el detalle de las dos operaciones que pueden hacer que
esto suceda: el borrado (ON DELETE) y la modificacin de datos (ON UPDATE) de la tabla referenciada (tabla2). Las posibilidades son las siguientes:

NO ACTION: el servidor rechazar la operacin

CASCADE: el servidor aplicar la misma operacin en los registros de la tabla detalle (donde se define la restriccin) para que la regla siga siendo vlida

SET DEFAULT: los campos de la tabla de detalle toman los valores por defecto (se pierde la referencia)

SET NULL: los campos de la tabla de detalle toman el valor NULL (se pierde la referencia)

CHECK (condicin): validacin. nicamente se permitir el ingreso del registro en la base de datos si la condicin se cumple.

Un ejemplo de restricciones de columna:


CREATE TABLE CLIENTES (
NROCLIENTE INTEGER NOT NULL PRIMARY KEY,
NOMBRE VARCHAR(50) NOT NULL,
IDPOBLACION INTEGER REFERENCES POBLACIONES(IDPOBLACION)
);

Notemos que en el campo IDPOBLACION no fue necesario siquiera especificar que se trataba de una clave externa (foreign key).

Matrices
La utilizacin del modificador <array_dim> a continuacin del tipo de datos indica que el campo contendr una matriz de valores del tipo indicado. Por ejemplo, si definimos
un campo como
Campo1 INTEGER[4,3]
estamos declarando una matriz de 4 x 3 enteros, que se accedern con el nombre del campo seguido de los correspondientes ndices entre corchetes.
Las matrices pueden ser multidimensionales: simplemente escriba todas las dimensiones separadas con comas, entre los corchetes.

Modificacin de la estructura de una tabla


Se puede modificar la estructura de una tabla ya creada -dentro de ciertos lmites- usando la instruccin Alter table. La sintaxis completa es la siguiente:
ALTER TABLE tabla <operacin> [, <operacin> ];

donde <operacin> es una construccin de la siguiente forma:


<operacin> = {ADD <definicin_de_columna>
| ADD <restriccin_de_tabla>
| ALTER [COLUMN] nombre_columna <clusula_de_columna_alternativa>
| DROP columna
| DROP CONSTRAINT restriccin}
<clusula_de_columna_alternativa > = {TO nuevo_nombre_columna
| TYPE nuevo_tipo_de_datos
| POSITION nueva_posicin}

http://archive.today/yKaUQ

39/47

26/6/2014

Firebird

veremos las distintas opciones por separado para no confundirnos.


Por ejemplo, si tenemos la tabla de clientes que vimos antes
CREATE TABLE CLIENTES (
NROCLIENTE INTEGER NOT NULL PRIMARY KEY,
NOMBRE VARCHAR(50) NOT NULL
);

y queremos agregar las columnas 'direccion' y 'telefono', podemos hacer


ALTER TABLE CLIENTES
ADD DIRECCION VARCHAR(100),
ADD TELEFONO VARCHAR(50);

Ahora, notamos que la columna NOMBRE es muy corta para los datos que debemos introducir; podemos cambiarla haciendo
ALTER TABLE CLIENTES
ALTER COLUMN NOMBRE TYPE varchar(100);

Igualmente, si queremos cambiarle el nombre a una columna


ALTER TABLE CLIENTES
ALTER COLUMN NROCLIENTE TO NRO_CLIENTE;

Lo mismo con la posicin de las columnas. En realidad al servidor le importa muy poco la posicin que tenga una columna dentro de una tabla, por lo que es ms bien una
cuestin esttica.
ALTER TABLE CLIENTES
DROP NOMBRE,
ADD NOMBRE VARCHAR(100) NOT NULL;

Para cambiar los atributos de una columna muchas veces es necesario borrar dicha columna y crearla de nuevo con los atributos deseados. Esta accin por supuesto que
conlleva la eliminacin de los datos de la columna original! La prctica comn en estos casos es la siguiente:
crear una columna temporal con los nuevos atributos
copiar los datos de la columna anterior a la temporal
borrar la columna anterior
crear la columna nueva con los atributos nuevos
copiar los datos de la columna temporal a la nueva
borrar la columna temporal
Los programas de administracin de bases de datos generalmente realizan estas operaciones automticamente.
<<<Ejemplo>>>
Hay que tener presente tambin que las tablas no son, en general, independientes una de otra; las relaciones que forman el modelo de datos pueden impedir que se realice
un cambio en la estructura de una tabla. Piense por ejemplo en qu pasara si tenemos una tabla A que referencia a una tabla B por medio de una columna (clave externa)
y queremos modificar el tipo de datos de esa columna. La referencia a la tabla B ya no sera vlida -los tipos de datos deben ser iguales en los dos lados de la referencia.
Para evitar este problema, el servidor rechazar cualquier cambio que afecte a una columna que forma parte de una restriccin. En estos casos, tendremos que eliminar
primero la restriccin, realizar el cambio, y volver a crear la restriccin.

Borrado de una tabla completa


Se puede eliminar una tabla completa usando la sentencia Drop Table. La sintaxis es muy simple:
DROP TABLE Nombre_Tabla

Esta operacin borrar todos los datos de la tabla; selo con mucho cuidado!

Dominios
http://archive.today/yKaUQ

40/47

26/6/2014

Firebird

Es muy comn que en una base de datos haya varias columnas del mismo tipo (por ejemplo: nombres de empleados, de clientes, de proveedores...). En casos como este,
conviene definir nuevos 'tipos' de datos con las caractersticas comunes a todos (por ejemplo, Varchar(40)) y darle un nombre propio (por ejemplo, NombresDePersonas).
Estos nuevos tipos se denominan Dominios. Los dominios se utilizan como si fueran tipos de datos normales, por ejemplo en las sentencias Create Table y Alter Table.

Creacin de dominios
<<<Sintaxis de Create Domain>>>
CREATE DOMAIN NOMBRESDEPERSONAS AS VARCHAR(40);

Tambin se pueden incluir restricciones en los dominios:


CREATE DOMAIN NOMBRESDEPERSONAS AS VARCHAR(40) NOT NULL;
CREATE DOMAIN IMPORTES AS NUMERIC(18,2) DEFAULT 0 NOT NULL;
CREATE DOMAIN MES INTEGER CHECK(VALUE > 0 AND VALUE <= 12);

Estas restricciones se aplicarn en todas las columnas definidas con este dominio.

Modificacin de dominios
??? hay alguna instruccion para esto?

Borrado de dominios
Para eliminar directamente un dominio, Firebird implementa la sentencia Drop Domain
DROP DOMAIN Nombre_Dominio

<<<Ver que pasa cuando el dominio est en uso>>>


Esta sentencia hizo su aparicin con Firebird 1.0; en Interbase, por lo menos hasta la versin 6 haba que trabajar directamente con las tablas del sistema. <<<confirmar>>>

Indices
Los ndices son estructuras auxiliares que utiliza el servidor para optimizar las consultas. Se construyen con los datos de un subconjunto de las columnas de la tabla a la que
sirven, pero internamente en el servidor estos datos se almacenan de manera diferente para optimizar las bsquedas. As, cuando se emite una instruccin SQL que debe
buscar algn valor en una tabla, si esta tabla no tiene definido un ndice sobre la columna en la que se busca entonces el servidor debe realizar una bsqueda secuencial es
decir, recorrer todos los registros hasta que encuentra el valor buscado. En cambio, si hay un ndice sobre la columna buscada, el servidor automticamente lo utiliza y
recorre la estructura del ndice para encontrar el valor. La estructura del ndice es tal que esta bsqueda slo lleva unas pocas lecturas.
Como veremos en la seccin de optimizacin de consultas, una de las principales armas del programador para acelerar el proceso de los datos son los ndices y la forma en
que se puede indicar al servidor que los utilice.

Crear un ndice
CREATE INDEX

Modificar un ndice
ALTER INDEX

Borrar un ndice
DROP INDEX

Restricciones
http://archive.today/yKaUQ

41/47

26/6/2014

Restricciones

Firebird

Las restricciones en el servidor sirven para mantener la integridad de los datos y tambin para implementar reglas de negocio. Estas restricciones se aplicarn siempre, no
importa de dnde vengan los datos ya sea desde la aplicacin especfica del programador o desde una herramienta de administracin. En este aspecto son convenientes
por la seguridad de los datos. Tambin convienen al programador en el sentido que es ms fcil mantener las reglas de negocio en el servidor, centralizadas, antes que
hacerlo en todos los programas cliente que puedan estar en uso.
La mayor inconveniencia de la implementacin de reglas de negocio en el servidor es la creacin de dependencias entre las estructuras por ejemplo, si se indica que una
columna no puede tener valores repetidos, generalmente se har por medio de una restriccin UNIQUE; mientras esta restriccin exista, no se podr modificar el tipo o
nombre de la columna. Para cambiar su tipo, por ejemplo para aadir ms caracteres porque se nos ha quedado corta una columna, habr que eliminar primero la
restriccin, hacer el cambio a la columna, y luego recrear la restriccin. La situacin empeora cuando se implementan tambin triggers y procedimientos almacenados.
No obstante las dificultades para alterar las estructuras, siempre es conveniente

PK

UQ

FK

Check

Not Null

Generadores
Los generadores son como 'variables' globales mantenidas en el servidor. Almacenan un nmero entero de 64 bits (BIGINT) que no es afectado por las transacciones. Esto
significa que cuando un generador cambia de valor, todas las transacciones actualmente activas pueden ver ese valor inmediatamente. Esto significa que se puede usar un
generador para obtener el valor de una secuencia numrica sin peligro de que dos clientes obtengan el mismo valor. Por esto es muy comn usarlos en la generacin de
claves primarias.
Para acceder a un generador hay que usar una funcin predefinida: gen_id. La funcin espera dos parmetros:
Gen_id(nombre_generador, incremento): bigint
Nombre_generadores el nombre del generador

Incremento es un nmero entero que se sumar al valor actual antes de devolver el resultado.
Esta funcin se utiliza mucho en triggers para generar automticamente el valor de una columna de clave primaria, por ejemplo:

Sin embargo, hay que tener cuidado: al no estar afectado un generador por las transacciones, una vez que se incrementa su valor ya no vuelven atrs a no ser por una
orden especfica de un cliente. Esto implica que pueden quedar 'huecos' en la secuencia. Supongamos que el cliente A pide el valor de un generador (digamos 9), y lo
incrementa en 1 quedando con valor 10. Almacena este valor en una columna de una tabla, y luego por cualquier motivo cancela la transaccin (rollback). La modificacin
de la tabla se vuelve atrs pero no as el generador. Si luego otro cliente hace lo mismo, obtendr el valor 10 y el generador quedar en 11. Esta vez si se acepta la
transaccin, por lo que en la tabla queda el valor 10 pero no el 9. Por lo tanto:
No utilice los generadores para secuencias numricas donde no pueda haber 'huecos' (secuencias auditables, como los nmeros de facturas).

Crear un generador
La sentencia para crear un generador es muy simple:
CREATE GENERATOR nombre_generador;

El generador se crea con valor 0 (cero).


http://archive.today/yKaUQ

42/47

26/6/2014
El generador se crea con valor 0 (cero).

Firebird

Modificar un generador
Se puede modificar el valor de un generador, para que comience a generar nmeros a partir de ah:
SET GENERATOR <Nombre_generador> TO <Nuevo_valor>

Borrar un generador
Drop generator (FB)

Excepciones
Definir excepciones
Create exception

Modificar excepciones
???

Borrar excepciones
Drop exception
(1.5) En la versin 1.5 de Firebird se agrega la posibilidad de cambiar el mensaje de la excepcin al momento de lanzarla. Veremos esta caracterstica cuando hablemos
luego sobre Procedimientos Almacenados y Triggers.

Programacin del servidor


Firebird permite escribir bloques de cdigo que se almacenan en la base de datos. Se programan en un lenguaje especial que se denomina Procedure SQL o PSQL, que
consta de las sentencias SQL estndar ms algunas instrucciones especiales para estos procedimientos.
La ventaja es que se puede centralizar el proceso de los datos en el mismo servidor, lo que garantiza mejor rendimiento y ms facilidad para actualizar el cdigo, ya que slo
se hace en un lugar y todos los clientes se benefician inmediatamente. La desventaja es que el lenguaje no tiene la riqueza de un lenguaje comn de alto nivel como Pascal o
C.
Hay dos clases de objetos que se pueden programar en Firebird: Procedimientos Almacenados y Triggers. La principal diferencia entre los dos es la forma de ejecutarlos.
Los Procedimientos Almacenados se ejecutan por demanda, es decir, el usuario tiene que activarlos explcitamente; los Triggers se ejecutan automticamente cuando se
realiza alguna accin sobre los datos (insert, update, delete).

Scripts
El servidor Firebird permite ejecutar una serie de instrucciones seguidas, obtenidas de un archivo de texto simple. Esta secuencia de instrucciones se denomina script.
Cada instruccin del script debe terminar en un smbolo especial llamado terminador. Por defecto este smbolo es el punto y coma (;) pero puede cambiarse con la
instruccin SET TERM. Por ejemplo, si un script contiene la lnea
SET TERM !;

Indica que a partir de esa lnea y hasta el final del script se considerar como terminador el smbolo (!). Notemos que esta misma lnea termina en punto y coma, ya que es
una instruccin del script. Para volver al terminador por defecto tenemos que emitir la instruccin
SET TERM ;!

Para ejecutar un script en isql hacemos


INPUT <nombre_del_archivo>;

http://archive.today/yKaUQ

43/47

26/6/2014

Firebird

INPUT <nombre_del_archivo>;

Veremos algunos ejemplos a continuacin, cuando escribamos Triggers y Procedimientos Almacenados. Pero antes, repasemos algunas otras instrucciones de mucho uso
en scripts:
SET SQL DIALECT 3;
Indica al compilador que la conexin se har utilizando el dialecto 3 de SQL. Debe emitirse antes de abrir la conexin. <<<Confirmar>>>
SET NAMES <juego_de_caracteres>;
Indica al compilador que la conexin se har utilizando por defecto el juego de caracteres dado. Debe emitirse antes de abrir la conexin.
CONNECT '<cadena_de_conexin>' USER '<nombre_usuario>' PASSWORD '<clave_de_conexin>';
Abre la conexin a la base de datos dada por la cadena de conexin, con el usuario y la clave indicadas.
COMMIT WORK;
Acepta los cambios realizados en la base de datos hasta esa lnea.

Procedimientos almacenados
Para crear un procedimiento almacenado se usa la sentencia CREATE PROCEDURE:
CREATE PROCEDURE nombre
[(parametro <tipo_de_datos> [, parametro <tipo_de_datos> ])]
[RETURNS <tipo_de_datos> [, parametro <tipo_de_datos> ])]
AS <cuerpo_del_procedimiento> [terminador]
<cuerpo_del_procedimiento> =
[<lista_de_declaracion_de_variables>]
<bloque>
< lista_de_declaracion_de_variables> =
DECLARE VARIABLE nombre_variable <tipo_de_datos>;
[DECLARE VARIABLE nombre_variable <tipo_de_datos>; ]
<bloque> =
BEGIN
<sentencia_compuesta>
[<sentencia_compuesta> ]
END
<sentencia_compuesta> = {<bloque> | sentencia;}

Bien, veamos algunos ejemplos para entender esta sintaxis. Dividir a los procedimientos en dos tipos generales: procedimientos de accin y procedimientos de seleccin.
No s si esta es la denominacin 'oficial', pero nos servir para estudiarlos.

Procedimientos de accin
Los procedimientos de accin son aquellos que no devuelven un cursor, solamente ejecutan algunas acciones sobre los datos. Por ejemplo, podemos hacer un procedimiento
que actualice una tabla de auditora:
SET SQL DIALECT 3;
CONNECT 'localhost:c:\archivos de programa\firebird15\examples\employee.fdb' USER 'sysdba' PASSWORD 'masterkey';
SET TERM !;
CREATE PROCEDURE SP_AUDITORIA
AS
BEGIN
INSERT INTO AUDITORIA (ID,FECHA,USUARIO)
VALUES (GEN_ID(GENAUDITORIA,1),CURRENT_DATE,CURRENT_USER);
END!
COMMIT WORK!

http://archive.today/yKaUQ

44/47

26/6/2014

Firebird

SET TERM ;!

Vemos como es necesario cambiar el terminador antes del cuerpo del procedimiento. Esto es as porque el procedimiento completo se interpreta como una sola
instruccin (y por lo tanto tiene que terminar con el smbolo terminador del script); mientras que las instrucciones internas del procedimiento tienen que terminar con
punto y coma. Si no cambiamos el terminador por defecto del script, se tomar el primer punto y coma del procedimiento como final del mismo, obtenindose una
instruccin invlida. En el ejemplo anterior, si eliminamos la lnea SET TERM !; entonces el servidor interpretar lo siguiente como una orden:
CREATE PROCEDURE SP_AUDITORIA
AS
BEGIN
INSERT INTO AUDITORIA (ID,FECHA,USUARIO)
VALUES (GEN_ID(GENAUDITORIA,1),CURRENT_DATE,CURRENT_USER);

Es decir, tenemos el comienzo de un procedimiento almacenado pero no su final (la palabra END). Esto provoca un error de compilacin. Por lo tanto, es
imprescindible cambiar de smbolo terminador antes de la definicin del procedimiento.
Otro detalle a considerar es la utilizacin de la funcin gen_id para obtener el siguiente valor del generador GenAuditoria. Esto es muy comn en la programacin
de procedimientos almacenados.
La variable Current_Datecontiene la fecha actual (de tipo DATE), disponible nicamente en dialecto 3.
La variable Current_Usercontiene el usuario autenticado en el servidor (dialecto 3).
En los procedimientos se pueden usar las sentencias SQL comunes, adems de algunas extensiones especiales.

Triggers
Los triggers o disparadores son procedimientos que se programan en el servidor, en el lenguaje especial del servidor. Estos procedimientos se ejecutan automticamente
cuando se cumple una accin determinada. Hay seis posibilidades:
Before Insert: de produce antes de insertar un registro
After Insert: despus de insertar un registro
Before / After Update: antes / despus de actualizar un registro
Before / After Delete: antes / despus de borrar un registro
Firebird acepta ms de un trigger para cada evento; al crearlos se les asigna un nmero de orden que se seguir al momento de ejecutarlos. Adems, en Firebird 1.5 se
agrega la posibilidad de definir triggers polivalentes, para ms de un evento. Hablaremos de ellos ms adelante.

Funciones del usuario (UDF)


Libreras estndar de funciones externas
Crear funciones externas en Delphi

Acceso desde Delphi


BDE
IBX
DBX
ADO
IBO
UIB
http://archive.today/yKaUQ

45/47

26/6/2014

UIB

Firebird

Optimizacin
Plan de ejecucin
Creacin de ndices
Selectividad
Restricciones declarativas vs. activas
Restriccin de la cantidad de registros a traer al cliente

Futuro

[1]

Actualmente se estn haciendo pruebas con nuevos modelos optimizados para otras tareas como es el caso de las BD distribuidas de Internet o las especficamente diseadas para
trabajar con audio y video- o para otras estructuras de datos, como ser los objetos.
[2]

A partir de la versin 1.5 se ha reducido el espectro de sistemas operativos en los que corre Firebird; se sigue activamente el desarrollo en las plataformas ms utilizadas, como Windows y
Linux, pero el grueso de los programadores no trabaja en las dems. Su disponibilidad depende del trabajo de voluntarios para cada plataforma.
[3]

En realidad hay otro estado, el limbo. Es un estado que solamente surge en transacciones que involucran mas de una base de datos, por lo que no lo consideraremos en la discusin. Las
transacciones en limbo pueden ser eliminadas cuando se hace un backup.

[4]
[5]
[6]
[7]

Por supuesto, una transaccin puede ver cualquier cambio hecho en la misma.
En otros sistemas (y en la BDE) se denomina Repeatable Read a este nivel de aislamiento.

Al final se incluye una referencia de los smbolos especiales usados en los esquemas de sintaxis
El estndar ANSI-92 propone una nueva sintaxis para los encuentros entre tablas, con ms posibilidades. No obstante, la forma inicial se mantiene en uso.

[8]

GDB son las iniciales de la empresa que cre Interbase: Groton Database Systems. Groton se llama el pueblo natal de Jim Starkey, su creador original. Es tambin la causa detrs de la g
inicial de los nombres de las utilidades.
[9]

En la definicin real de esta tabla (de la base de datos employee.gdb) se usan en realidad dominios para la mayora de los campos; he escrito los equivalentes ms simples (sin
comprobaciones ni restricciones) hasta que estudiemos el tema.

http://archive.today/yKaUQ

46/47

26/6/2014

http://archive.today/yKaUQ

Firebird

47/47

You might also like