You are on page 1of 239

Desarrollo de software

El texto está diseñado


para programadores,
analistas o técnicos de
sistemas que deseen
conocer la mecánica de
trabajo de las bases de
datos a través del uso de
una de ellas en concreto:
Microsoft SQL Server
2000.
Aspectos que se revisan:

1- Conceptos teóricos
sobre Bases de Datos.
2- Diseño y modelización
de datos tomando como
base el modelo
Entidad/Relación
3- Generalidades de SQL
Server 2000
4- Lenguaje SQL a través
de la implementación del
mismo en SQL Server
2000 (Transact SQL)
5- Ejemplos de diseño
utilizando una
herramienta CASE: Power
Designor

Se requiere como mínimo


tener conocimientos del
sistema operativo
Windows a nivel de
usuario. No es
imprescindible, aunque si
recomendable, conocer
fundamentos de
programación.

BASES DE DATOS CON SQL


SERVER 2000. TRANSACT SQL
JORGE MORATALLA
ADVERTENCIA LEGAL
Todos los derechos de esta obra están reservados a Grupo EIDOS Consultoría y Documentación Informática,
S.L.

El editor prohíbe cualquier tipo de fijación, reproducción, transformación, distribución, ya sea mediante venta
y/o alquiler y/o préstamo y/o cualquier otra forma de cesión de uso, y/o comunicación pública de la misma, total
o parcialmente, por cualquier sistema o en cualquier soporte, ya sea por fotocopia, medio mecánico o
electrónico, incluido el tratamiento informático de la misma, en cualquier lugar del universo.

El almacenamiento o archivo de esta obra en un ordenador diferente al inicial está expresamente prohibido, así
como cualquier otra forma de descarga (downloading), transmisión o puesta a disposición (aún en sistema
streaming).

La vulneración de cualesquiera de estos derechos podrá ser considerada como una actividad penal tipificada en
los artículos 270 y siguientes del Código Penal.

La protección de esta obra se extiende al universo, de acuerdo con las leyes y convenios internacionales.

Esta obra está destinada exclusivamente para el uso particular del usuario, quedando expresamente prohibido su
uso profesional en empresas, centros docentes o cualquier otro, incluyendo a sus empleados de cualquier tipo,
colaboradores y/o alumnos.

Si Vd. desea autorización para el uso profesional, puede obtenerla enviando un e-mail fmarin@eidos.es o al fax
(34)-91-5017824.

Si piensa o tiene alguna duda sobre la legalidad de la autorización de la obra, o que la misma ha llegado hasta
Vd. vulnerando lo anterior, le agradeceremos que nos lo comunique al e-mail fmarin@eidos.es o al fax (34)-91-
5012824). Esta comunicación será absolutamente confidencial.

Colabore contra el fraude. Si usted piensa que esta obra le ha sido de utilidad, pero no se han abonado los
derechos correspondientes, no podremos hacer más obras como ésta.

© Jorge Moratalla, 2001


© Grupo EIDOS Consultaría y Documentación Informática, S.L., 2000

ISBN 84-88457-24-3

Bases de datos con SQL Server 2000. Transact SQL


Jorge Moratalla

Responsable editorial Coordinación de la edición


Paco Marín (fmarin@eidos.es) Antonio Quirós (aquiros@eidos.es)
Autoedición
Magdalena Marín (mmarin@eidos.es)
Jorge Moratalla (jmoratalla@eidos.es)
Grupo EIDOS
C/ Téllez 30 Oficina 2
28007-Madrid (España)
Tel: 91 5013234 Fax: 91 (34) 5017824
www.grupoeidos.com/www.eidos.es
www.LaLibreriaDigital.com
Índice

ÍNDICE................................................................................................................................................... 5
INTRODUCCIÓN ................................................................................................................................. 9
DEFINICIÓN DE BASE DE DATOS ........................................................................................................... 9
CONCEPTOS BÁSICOS ......................................................................................................................... 10
DEL ENFOQUE TRADICIONAL A LOS SISTEMAS DE BASES DE DATOS ................................................. 10
ARQUITECTURA ANSI/X3/SPARC ................................................................................................... 12
EL MODELO RELACIONAL .................................................................................................................. 12
VISIÓN GENERAL SOBRE EL DISEÑO DE BASES DE DATOS.............................................. 15
FASES DEL DISEÑO ............................................................................................................................. 15
DISEÑO CONCEPTUAL ........................................................................................................................ 17
DISEÑO LÓGICO.................................................................................................................................. 17
DISEÑO FÍSICO.................................................................................................................................... 21
DISEÑO CONCEPTUAL ................................................................................................................... 23
INTRODUCCIÓN .................................................................................................................................. 23
ETAPAS DEL DISEÑO CONCEPTUAL .................................................................................................... 24
EL MODELO ENTIDAD / RELACIÓN ..................................................................................................... 24
EJEMPLOS PRÁCTICOS DE DISEÑO CONCEPTUAL................................................................................ 29
DISEÑO LÓGICO............................................................................................................................... 35
INTRODUCCIÓN .................................................................................................................................. 35
PASO DEL ESQUEMA CONCEPTUAL AL ESQUEMA LÓGICO ESTÁNDAR ............................................... 36
ETAPAS EN EL DISEÑO LÓGICO........................................................................................................... 37
PARTICIONAMIENTO HORIZONTAL DE RELACIONES .......................................................................... 38
PARTICIONAMIENTO VERTICAL DE RELACIONES ............................................................................... 41
PARTICIONAMIENTO MIXTO ............................................................................................................... 44
TEORÍA DE LA NORMALIZACIÓN ........................................................................................................ 45
EJEMPLOS PRÁCTICOS DE NORMALIZACIÓN ...................................................................................... 49
PROCESO DE DESNORMALIZACIÓN .................................................................................................... 55
DISEÑO FÍSICO ................................................................................................................................. 57
INTRODUCCIÓN .................................................................................................................................. 57
ESTRATEGIAS EN EL DISEÑO FÍSICO ................................................................................................... 58
CONCEPTOS BÁSICOS SOBRE GESTIÓN DE FICHEROS ......................................................................... 58
ORGANIZACIÓN DE FICHEROS ............................................................................................................ 59
TÉCNICAS PARA EL AUMENTO DE EFICIENCIA ................................................................................... 59
INTRODUCCIÓN A SQL SERVER ................................................................................................. 63
¿QUÉ ES SQL SERVER?...................................................................................................................... 63
ORÍGENES........................................................................................................................................... 64
SQL SERVER E INTERNET .................................................................................................................. 64
LO NUEVO EN SQL-SERVER 2000 ................................................................................................ 65
INTRODUCCIÓN .................................................................................................................................. 65
NUEVAS CARACTERÍSTICAS ............................................................................................................... 65
SOPORTE PARA XML ......................................................................................................................... 66
PARTICIONAMIENTO HORIZONTAL DE RELACIONES Y GESTIÓN DE VISTAS DISTRIBUIDAS ............... 67
SOPORTE PARA VIRTUAL INTERFACE ARCHITECTURE (VIA) ........................................................... 67
FUNCIONES DE USUARIO .................................................................................................................... 67
INDEXACIÓN DE VISTAS ..................................................................................................................... 67
NUEVOS TIPOS DE DATOS ................................................................................................................... 67
NUEVOS TRIGGERS ............................................................................................................................. 68
REGLAS DE INTEGRIDAD REFERENCIAL EN CASCADA ....................................................................... 68
NUEVAS CARACTERÍSTICAS DE INDEXACIÓN .................................................................................... 68
SOPORTE PARA CONSULTAS DISTRIBUIDAS ....................................................................................... 68
CARACTERÍSTICAS DE SEGURIDAD Y CIFRADO DE DATOS ................................................................. 68
INSTALACIÓN DE SQL SERVER 2000 ......................................................................................... 69
EL MODELO E/R EN SQL-SERVER 2000 ..................................................................................... 75
INTRODUCCIÓN .................................................................................................................................. 75
CREAR UN NUEVO DIAGRAMA ........................................................................................................... 77
RESTRICCIONES E INTEGRIDAD REFERENCIAL ................................................................................... 79
MODIFICACIÓN DEL ESQUEMA ........................................................................................................... 81
CREAR UNA NUEVA RELACIÓN .......................................................................................................... 82
EL ANALIZADOR DE CONSULTAS.............................................................................................. 85
INTRODUCCIÓN .................................................................................................................................. 85
LAS OPCIONES DE MENÚ .................................................................................................................... 85
LA BARRA DE HERRAMIENTAS ........................................................................................................... 91
EJECUTANDO UNA CONSULTA ........................................................................................................... 92
EL LENGUAJE DE DEFINICIÓN DE DATOS (DDL) .................................................................. 97
INTRODUCCIÓN .................................................................................................................................. 97
TIPOS DE DATOS ................................................................................................................................. 97
CREACIÓN DE TABLAS ....................................................................................................................... 99
MODIFICACIÓN DE TABLAS .............................................................................................................. 100
BORRADO DE TABLAS ...................................................................................................................... 101
CREACIÓN Y BORRADO DE ÍNDICES ................................................................................................. 101
EJEMPLOS PRÁCTICOS DE USO DEL DDL............................................................................. 103
INTRODUCCIÓN ................................................................................................................................ 103
LA SENTENCIA CREATE TABLE ................................................................................................... 103
LA SENTENCIA ALTER TABLE ...................................................................................................... 107
LA SENTENCIA DROP TABLE ........................................................................................................ 111
LA SENTENCIA CREATE INDEX.................................................................................................... 112
LA SENTENCIA DROP INDEX......................................................................................................... 112
EL LENGUAJE DE MANIPULACIÓN DE DATOS (DML) ....................................................... 115
INTRODUCCIÓN ................................................................................................................................ 115
LA SENTENCIA SELECT .................................................................................................................... 115
LA CLÁUSULA WHERE ..................................................................................................................... 117
LA CLÁUSULA GROUP BY ................................................................................................................ 118
LA CLÁUSULA HAVING .................................................................................................................... 119
LA CLÁUSULA ORDER BY ................................................................................................................ 119
FUNCIONES ESCALARES PARA SELECT ............................................................................................ 119
LA SENTENCIA INSERT ..................................................................................................................... 122
LA SENTENCIA UPDATE ................................................................................................................... 123
LA SENTENCIA DELETE .................................................................................................................... 123
OPERADORES BÁSICOS Y CONSIDERACIONES DEL LENGUAJE ................................... 125
INTRODUCCIÓN ................................................................................................................................ 125
OPERADOR PROYECCIÓN ................................................................................................................. 125
OPERADOR UNION ........................................................................................................................... 127
OPERADOR JOIN ............................................................................................................................... 128
OPERADORES PROPIOS DE TRANSACT SQL ..................................................................................... 132
VARIABLES GLOBALES..................................................................................................................... 135
SENTENCIAS CONDICIONALES.......................................................................................................... 137
SENTENCIAS ITERATIVAS ................................................................................................................. 138
LA SENTENCIA INSERT................................................................................................................ 139
INTRODUCCIÓN ................................................................................................................................ 139
SINTAXIS .......................................................................................................................................... 139
EJEMPLOS......................................................................................................................................... 140
CARGA DE LA BASE DE DATOS DE EJEMPLO ..................................................................................... 143
LA SENTENCIA SELECT............................................................................................................... 147
INTRODUCCIÓN ................................................................................................................................ 147
LA CLAÚSULA WHERE ................................................................................................................... 148
EL OPERADOR JOIN .......................................................................................................................... 149
LAS FUNCIONES DE AGREGADO ....................................................................................................... 151
LA CLAÚSULA GROUP BY ............................................................................................................. 154
LA SENTENCIA UPDATE .............................................................................................................. 157
INTRODUCCIÓN ................................................................................................................................ 157
EJEMPLOS......................................................................................................................................... 157
LA SENTENCIA DELETE .............................................................................................................. 163
INTRODUCCIÓN ................................................................................................................................ 163
LA INTEGRIDAD REFERENCIAL......................................................................................................... 164
LA SENTENCIA TRUNCATE TABLE.............................................................................................. 165
EJEMPLOS......................................................................................................................................... 166
PROCEDIMIENTOS ALMACENADOS Y TRIGGERS ............................................................. 169
INTRODUCCIÓN ................................................................................................................................ 169

7
PARÁMETROS POR REFERENCIA ....................................................................................................... 170
PROCEDIMIENTOS ALMACENADOS DE SISTEMA............................................................................... 172
EXTENDED STORED PROCEDURES .................................................................................................... 173
TRIGGERS ......................................................................................................................................... 174
EJEMPLOS PRÁCTICOS DE USO DE PROCEDIMIENTOS ALMACENADOS .................. 177
INTRODUCCIÓN ................................................................................................................................ 177
LA SENTENCIA IF ... ELSE............................................................................................................... 177
LA SENTENCIA CASE ...................................................................................................................... 179
EJECUCIÓN DINÁMICA DE SENTENCIAS: LA INSTRUCCIÓN EXEC ................................................... 180
CONVERSIÓN DE TIPOS..................................................................................................................... 181
LA SENTENCIA WHILE.................................................................................................................... 182
TRIGGERS EN SQL-SERVER 2000 .............................................................................................. 183
INTRODUCCIÓN ................................................................................................................................ 183
LAS TABLAS DELETED E INSERTED .................................................................................................. 184
TIPOS DE DESENCADENADORES ....................................................................................................... 184
LIMITACIONES DE LOS TRIGGERS ..................................................................................................... 184
RESOLUCIÓN DIFERIDA DE NOMBRES .............................................................................................. 185
EJEMPLOS......................................................................................................................................... 185
SEGURIDAD ..................................................................................................................................... 189
INTRODUCCIÓN ................................................................................................................................ 189
CONCESIÓN DE PRIVILEGIOS ............................................................................................................ 189
REVOCACIÓN DE PRIVILEGIOS ......................................................................................................... 191
DENEGACIÓN DE PERMISOS ............................................................................................................. 193
MANTENIMIENTO DE VISTAS ........................................................................................................... 193
RECOMENDACIONES ........................................................................................................................ 194
EJEMPLO PRÁCTICO DE IMPLEMENTACIÓN...................................................................... 195
INTRODUCCIÓN ................................................................................................................................ 195
LENGUAJE DE DEFINICIÓN DE DATOS............................................................................................... 196
LENGUAJE DE MANIPULACIÓN DE DATOS ........................................................................................ 198
PRESENTE Y FUTURO DE LAS BASES DE DATOS ................................................................ 203
DISEÑO CONCEPTUAL CON POWER DESIGNOR................................................................. 207
INTRODUCCIÓN ................................................................................................................................ 207
CREACIÓN DE UNA ENTIDAD ............................................................................................................ 208
CREACIÓN DE RELACIONES .............................................................................................................. 213
LA RELACIÓN DE HERENCIA............................................................................................................. 215
DISEÑO FÍSICO CON POWER DESIGNOR ............................................................................... 217
PASO DEL ESQUEMA CONCEPTUAL AL ESQUEMA FÍSICO ................................................................. 217
MODIFICACIÓN DE LAS TABLAS ....................................................................................................... 218
COLUMNAS ...................................................................................................................................... 219
INDICES ............................................................................................................................................ 219
ATRIBUTOS EXTENDIDOS ................................................................................................................. 221
TRIGGERS ......................................................................................................................................... 221
RESTRICCIONES................................................................................................................................ 222
CREACIÓN DE VISTAS ....................................................................................................................... 222
EJEMPLO DE DISEÑO CON POWER DESIGNOR................................................................... 225
Introducción

Definición de base de datos


La primera pregunta que surge a la hora de comenzar este curso es la siguiente: ¿Qué es una Base de
Datos?. Existen varias definiciones para responder a esta pregunta:

• "Colección de datos interrelacionados almacenados en conjunto sin redundancias perjudiciales


o innecesarias; su finalidad es servir a una aplicación o más, de la mejor manera posible; los
datos se almacenan de modo que resulten independientes de los programas que los usan; se
emplean métodos bien determinados para incluir nuevos datos y para modificar o extraer los
datos almacenados". (Martin, 1975).

• "Colección o depósito de datos, donde los datos están lógicamente relacionados entre sí,
tienen una definición y descripción comunes y están estructurados de una forma particular.
Una base de datos es también un modelo del mundo real y, como tal, debe poder servir para
toda una gama de usos y aplicaciones". (Conference des Statisticiens Européens, 1977).

• "Conjunto de datos de la empresa memorizado en un ordenador, que es utilizado por


numerosas personas y cuya organización está regida por un modelo de datos". (Flory, 1982).

• "Conjunto estructurado de datos registrados sobre soportes accesibles por ordenador para
satisfacer simultáneamente a varios usuarios de forma selectiva y en tiempo oportuno".
(Delobel, 1982).

• "Colección no redundante de datos que son compartidos por diferentes sistemas de


aplicación". (Howe, 1983).
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

• "Colección integrada y generalizada de datos, estructurada atendiendo a las relaciones


naturales de modo que suministre todos los caminos de acceso necesarios a cada unidad de
datos con objeto de poder atender todas las necesidades de los diferentes usuarios". (Deen,
1985).

• "Conjunto de ficheros maestros, organizados y administrados de una manera flexible de modo


que los ficheros puedan ser fácilmente adaptados a nuevas tareas imprevisibles". (Frank,
1988).

• "Colección de datos interrelacionados". (Elsmari y Navathe, 1989).

Como se ha visto, el concepto de base de datos ha ido cambiando a lo largo del tiempo. En la
actualidad podemos establecer la definición de base de datos como sigue.

"Colección o depósito de datos integrados, almacenados en soporte secundario (no volátil) y con
redundancia controlada. Los datos, que han de ser compartidos por diferentes usuarios y aplicaciones,
deben mantenerse independientes de ellos, y su definición (estructura de la base de datos) única y
almacenada junto con los datos, se ha de apoyar en un modelo de datos, el cual ha de permitir captar
las interrelaciones y restricciones existentes en el mundo real. Los procedimientos de actualización y
recuperación, comunes y bien determinados, facilitarán la seguridad del conjunto de los datos".

Conceptos básicos
• Sistema de Gestión de Base de Datos (SGBD): Conjunto de programas que permiten la
implantación, acceso y mantenimiento de la base de datos. El SGBD, junto con la base de
datos y con los usuarios, constituyen el Sistema de Base de Datos.

• Modelo de datos: Conjunto de conceptos que permiten describir, a distintos niveles de


abstracción, la estructura de una base de datos, a la cual denominamos esquema.

• Sistema de Información: Colección de personas, procedimientos y equipos diseñados,


construidos, operados y mantenidos para recoger, registrar, procesar, almacenar y recuperar
esa información.

• Esquema de una Base de Datos: Estructura de la Base de Datos.

• Ocurrencia del esquema: Conjunto de datos que se encuentran almacenados en el esquema en


un momento determinado. El esquema no varía mientras no varíe el mundo real que éste
describe, mientras que una ocurrencia del esquema es distinta en el transcurso del tiempo.

Del enfoque tradicional a los sistemas de bases de datos


Para comprender mejor las diferencias entre los sistemas tradicionales basados en ficheros y los
sistemas de bases de datos, pongamos un ejemplo. Supóngase que disponemos de un archivo maestro
de clientes con la siguiente información: nombre, dirección, ciudad, provincia y teléfono. Si además de
esto, añadimos dos ficheros, uno para la emisión de facturas, y otro para la emisión de informes,
podemos encontrarnos con los siguientes problemas:

• Producción de inconsistencias o incoherencias, debido a la replica de información (la misma


información puede estar almacenada en distintos ficheros).

10
© Grupo EIDOS 1. Introducción.

• Malgasto de memoria secundaria (por el mismo motivo).

• Si en este momento se quiere añadir en número de fax, se hace necesario una completa
reestructuración de dicho fichero, sin mencionar el rediseño del código de la aplicación, para
dar cabida a este cambio.

En cambio, en un sistema de gestión de bases de datos, estos problemas no tienen cabida, ya que el
control de la información es inherente al propio sistema.

Algunas de las ventajas que ofrece utilizar un Sistema de Bases de Datos son las siguientes:

1. Independencia entre datos y tratamientos. El cambio en los programas no influye en la


disponibilidad de los datos, así como la modificación de éstos no afecta a la reprogramación
de las aplicaciones que los usan.

2. Coherencia de resultados: Debido a que los datos son almacenados una sola vez, se evitan los
problemas que puede ocasionar la redundancia. Más adelante veremos cómo se permite una
cierta duplicidad de datos, con el fin de conseguir una mayor eficiencia, controlada por el
sistema y que no afecta a la redundancia lógica.

3. Mejor disponibilidad de datos para los usuarios: Los datos son compartidos por un conjunto de
usuarios, que accede a ellos de forma concurrente, siempre que estén autorizados a ello.

4. Mayor valor informativo: El conjunto de los datos almacenados en la BD ofrece un mayor


valor informativo, que la suma de ellos independientemente.

5. Mayor eficiencia en la recogida, validación e introducción de los datos en el sistema: Al no


existir redundancia, los datos se recogen y validan una sola vez, aumentando así la eficiencia.

6. Reducción del espacio de almacenamiento: La desaparición (o disminución) de redundancias,


unido a las técnicas de compactación, implica una menor ocupación de almacenamiento
secundario.

A pesar de todas estas ventajas, los Sistemas de Bases Datos no están exentos de inconvenientes. Aquí
se detallan los más importantes:

1. Instalación costosa: La implantación de un sistema de base de datos puede implicar un coste


elevado, tanto en el equipo físico (adquisición de nuevas instalaciones, o ampliaciones de las
existentes) como en el lógico (sistemas operativos, programas, compiladores, etc.), así como
el coste de adquisición o mantenimiento del SGBD.

2. Implantación larga y difícil: Debido a las causas mencionadas anteriormente, la implantación


de un sistema de base de datos puede convertirse en una tarea larga y complicada.

3. Falta de rentabilidad a corto plazo: Los amplios costes que conlleva la implantación, implica
una rentabilidad no a corto, sino a medio, o incluso largo plazo.

4. Escasa estandarización: Esto supone una dificultad añadida a los usuarios de la base de datos.

5. Desfase entre teoría y práctica: Los constantes avances teóricos en al ámbito de las bases de
datos, que muchas veces no se ven traducidos en la práctica, hacen llevarse a engaño a muchos
usuarios, creyendo que constituyen ya una realidad, cuando no han sido todavía plasmados.

11
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Arquitectura ANSI/X3/SPARC
ANSI/X3/SPARC es un grupo de estudio del Standard Planning and Requirements Commitee
(SPARC) del ANSI (American National Standars Institute), dentro del Comité X3 que se ocupa de
ordenadores e informática. En sus estudios acerca de los SGBD, propugnaron una arquitectura basada
en tres niveles de abstracción:

1. Nivel Externo: Es el nivel más cercano a los usuarios, y en el se definen los datos tal y como
los va a ver este. Cada usuario puede tener su propio modelo externo, con aquellos datos e
interrelaciones que dicho usuario necesite. En este nivel, también deberán definirse las
restricciones de uso, como por ejemplo el derecho a insertar o borrar determinados datos, o
poder acceder a ellos.

2. Nivel Conceptual: Proporciona una descripción global del esquema independiente de la


estructura física de la base de datos, es decir, cuales son los datos, como están organizados, las
relaciones entre ellos y las restricciones de integridad y confidencialidad. El modelo
conceptual, que es único, establece el modelo teórico sobre el que están asentados los modelos
externos.

3. Nivel Interno: Nivel más bajo en la abstracción. Describe la estructura almacenamiento físico
de los datos, las estrategias de acceso a los datos, etc. Así mismo especifica todos los aspectos
relacionados con el hardware, como por ejemplo dispositivos de memoria a usar (tamaño de
páginas, número de éstas, tamaño de los buffers, etc.), técnicas de compresión de datos,
criptografiado, etc. El modelo interno, que es único, corresponde a la implementación del
modelo conceptual.

El modelo relacional
El modelo más usado, y por lo tanto el que se estudiará en este curso, es el modelo relacional. El
motivo de que sea éste el modelo más extendido, radica en la facilidad y en su amplia base
matemática, lo que permitirá, como ya se verá más adelante, el poder estructurar o reestructurar las
relaciones, para evitar cierto tipo de anomalías, o acelerar las consultas / actualizaciones. Dicho
modelo se basa en la representación de la información por medio de estructuras tipo tabla,
denominadas relaciones, y que almacenan información para una determinada entidad. Cada una de
estas relaciones representa en sus columnas los valores significativos, es decir, de los que interesa
conocer su valor, para cada entidad. Dichas columnas se denominan atributos, y para cada uno de ellos
existirá un valor (cabe la posibilidad de que existan atributos en los que no aparezca ningún valor).
Cada fila representa la información para cada ocurrencia de una determinada entidad. La información
se descompondrá, como ya se ha dicho, en dar valores para cada uno de los atributos de la entidad. A
dichas filas también se las denomina tuplas. Cada atributo o conjunto de atributos que identifica
unívocamente a cada tupla de la relación se denomina clave. Las claves se representan subrayando el /
los atributo/s que forman parte de ella.

El siguiente ejemplo (Figura 1) representa una relación denominada empleado, que almacena
información sobre los empleados de una empresa. La información que se desea saber de cada
empleado es su código, su nombre y apellidos, su sueldo y su categoría. Por lo tanto, los atributos son
cod_empleado, nombre, apellidos, sueldo y categoría. Además, el atributo cod_empleado es clave de
la relación, ya que si se sabe el valor de dicho atributo, se puede saber a que empleado nos estamos
refiriendo.

12
© Grupo EIDOS 1. Introducción.

Figura 1

13
Visión general sobre el diseño de bases
de datos

Fases del diseño


El diseño de una base de datos suele descomponerse en tres grandes fases (diseño conceptual, lógico y
físico), lo que permite reducir la complejidad que entraña el diseño, a la vez que ayuda a alcanzar los
dos principales objetivos que tienen las bases de datos:

• Ser una representación fidedigna del mundo real,

• Ser un servidor operacional y eficiente de los datos.

El diseño conceptual parte de la especificación de requerimientos, y produce como resultado el


esquema conceptual de la base de datos. Un esquema conceptual es una descripción a alto nivel de la
estructura de la base de datos, independientemente de la elección del equipamiento y del Sistema
Gestor de Base de Datos (en adelante referido como SGBD) que se usen para la implementación de la
base de datos.

El diseño lógico parte del esquema conceptual y genera el esquema lógico. Un esquema lógico es la
descripción de la estructura de la base de datos que puede procesarse por un SGBD. Una vez elegido
el modelo lógico, pueden existir un conjunto de esquemas lógicos equivalentes al mismo esquema
conceptual. La meta del diseño lógico es producir el esquema lógico más eficiente con respecto a las
operaciones de consulta y actualización.
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

El diseño físico toma como punto de partida el esquema lógico y como resultado produce el esquema
físico. Un esquema físico es una descripción de la implementación de la base de datos en memoria
secundaria; describe las estructuras de almacenamiento y los métodos de acceso para acceder a los
datos de una manera eficiente. Por ello, el diseño físico se genera para un SGBD y un entorno físico
determinado.

Figura 2. Diseño de una base de datos

En la Figura 2 se resumen las tres grandes fases del diseño de una base de datos: primero se diseña el
esquema conceptual (que se realiza con un modelo conceptual de datos), esquema que proporciona
una descripción estable de la base de datos (independiente del SGBD) que se vaya a utilizar;
posteriormente se pasa del esquema conceptual al modelo de datos propio de SGBD elegido (diseño
lógico); por último se eligen las estructuras de almacenamiento, los caminos de acceso (índices), y
todos los aspectos relacionados con el diseño físico.

Figura 3. Correspondencia entre el diseño y la arquitectura ANSI/X3/SPARC

16
© Grupo EIDOS 2. Visión general sobre el diseño de bases de datos.

La Figura 3 muestra la correspondencia existente entre las fases de diseño y los niveles de la
arquitectura ANSI/X3/SPARC. El diseño conceptual es una etapa previa al diseño lógico. A su vez, el
diseño lógico se corresponde con los niveles externo (donde se definen las vistas de usuario, es decir,
conjunto de información que puede ser accedida por un usuario) y lógico (estructura de tablas y
restricciones) de la arquitectura ANSI/X3/SPARC. El diseño físico se corresponde con el nivel físico
de dicha arquitectura.

Diseño conceptual
El objetivo del diseño conceptual, también denominado modelo conceptual, y que constituye la
primera fase de diseño, es obtener una buena representación de los recursos de información de la
empresa, con independencia de usuario o aplicaciones en particular y fuera de consideraciones sobre
eficiencia del ordenador. Consta de dos fases:

• Análisis de requisitos: Es en esta etapa donde se debe responder a la pregunta: ¿qué


representar?. Se pretende en esta etapa elaborar un esquema descriptivo del mundo real,
mediante distintas técnicas, aunque la más usada es la de entrevistas a los usuarios, lo que
implica una descripción de los datos mediante el uso del lenguaje natural. Los problemas que
presenta esta primera especificación, se irán refinando hasta obtener el esquema conceptual.

• Conceptualización: En esta etapa se intenta responder a la pregunta: ¿cómo representar?.


Consiste en ir refinando sucesivamente el primer esquema descriptivo, para conseguir pasar
del mundo real al esquema descriptivo y de éste al esquema conceptual, que deberá ser
expresado sin tener en consideración cuestiones de implementación, es decir, debe ser
independiente del SGBD a usar.

Diseño lógico
El objetivo del diseño lógico es transformar el esquema conceptual obtenido en la fase anterior,
adaptándolo al modelo de datos en el que se apoya el SGBD que se va a utilizar.

El modelo relacional es el único modelo que ha permitido abordar la fase de diseño lógico aplicando
una teoría formal: el proceso de normalización.

Sin embargo, la normalización no cubre toda esta fase, mostrándose insuficiente para alcanzar todos
los objetivos de la misma. En la práctica a veces es preciso proceder a una reestructuración de las
relaciones.

La Figura 4, resume la fase de diseño lógico, en la que una vez estructurado el esquema origen,
analizando diferentes factores como las distintas dependencias o la posibilidad de existencia de valores
nulos, se obtiene un esquema relacional, al que se añaden las claves ajenas y otras restricciones de
integridad. Ahora bien, si se tiene en cuenta el segundo de los objetivos mencionados anteriormente, el
de que la base de datos ha de ser un servidor operacional y eficiente de los datos, se hace necesaria una
reestructuración de relaciones, con el fin de mejorar la eficiencia de la base de datos.

Esta reestructuración toma como entrada el esquema relacional estructurado obtenido anteriormente,
así como el análisis de los requisitos de determinadas vistas o aplicaciones críticas, obteniendo de esta
manera un esquema relacional resultante, en el que priman las consideraciones de eficiencia.

En la Figura 4, se detallan las dos etapas en las que se divide la fase de diseño lógico. La primera,
consistente en la estructuración de las relaciones atendiendo a consideraciones de tipo lógico, incluye

17
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

la normalización, así como el particionamiento horizontal de las mismas cuando sea necesario,
mientras que en la segunda se reestructuran las relaciones teniendo en cuenta consideraciones de tipo
físico que pueden llevar a la desnormalización, o al particionamiento horizontal, vertical o mixto. La
razón de esta etapa de reestructuración se encuentra en la falta de flexibilidad de la estructura interna
de los actuales SGBD, los cuales no ofrecen los adecuados instrumentos de diseño físico, obligando a
trasladar a la fase de diseño lógico consideraciones de eficiencia que deberían ser ajenas a dicha fase.

Figura 4. Estructuración y reestructuración de relaciones

El objetivo de la estructuración de relaciones es obtener un esquema relacional estructurado, tomando


como entrada un esquema relacional origen con todas sus dependencias, valores inaplicables, etc.

En esta etapa de estructuración se conseguirá, por razones lógicas, un esquema normalizado, en el cual
se han eliminado los valores nulos (inaplicables) mediante un particionamiento horizontal basado en la
selección, seguido de la proyección.

Las herramientas para llevar a cabo este objetivo son dos:

18
© Grupo EIDOS 2. Visión general sobre el diseño de bases de datos.

• El proceso de normalización

• El particionamiento horizontal de relaciones

El proceso de normalización consiste en sustituir una relación por un conjunto de esquemas


equivalentes, que representan la misma información que la relación origen, pero que no presentan
cierto tipo de anomalías a la hora de realizar operaciones sobre ella, como se muestra en la Figura 5,
en la que una relación origen ha sido sustituida por otras dos, mediante un proceso de normalización.

Figura 5. Normalización de relaciones

El particionamiento horizontal de relaciones, permite eliminar valores nulos inaplicables que pueden
aparecer en las relaciones mediante un proceso de selección, seguido de proyecciones sobre las
relaciones resultantes. El resultado de este particionamiento horizontal será la división de una relación
en la que existen o pueden existir valores nulos, en varias relaciones en las que los valores nulos
inaplicables no tienen cabida.

Figura 6. Particionamiento horizontal de relaciones

El objetivo de la reestructuración es el de mejorar la eficiencia de la base de datos. En la primera etapa


de estructuración de relaciones, se ha propugnado por razones lógicas, normalizar el esquema, así
como eliminar los valores nulos mediante un proceso de particionamiento horizontal. Sin embargo,
esto no quiere decir que las relaciones que se vayan a almacenar en la base de datos sean las
resultantes de estos procesos, ya que se ha logrado el primero de los objetivos de las bases de datos
(ser una representación fidedigna del mundo real), pero puede que no el segundo: el de que la base de

19
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

datos ha de ser un servidor operacional y eficiente de los datos, por lo que se hace necesaria esta
segunda etapa en el diseño lógico. Para lograr este objetivo existen diversos métodos o formas de
organizar los datos, considerando esta idea de mejora de la eficiencia, que son:

• El proceso de desnormalización

• El particionamiento de relaciones

El proceso de desnormalización es justamente el proceso inverso al de normalización. La Figura 7,


muestra un ejemplo en el que dos tablas previamente normalizadas, dan origen a una tabla más grande
(que es justamente la tabla que se tenía antes de realizar la normalización), mediante un proceso de
desnormalización.

Figura 7. Desnormalización de relaciones

El particionamiento de relaciones es otra forma de conseguir una mayor eficiencia en la base de datos.
El objetivo de este proceso es dada una relación, dividirla en otras relaciones de forma horizontal, o
vertical, o mixta (incluye ambas). A cada una de estas formas de particionamiento se la denomina,
respectivamente, particionamiento horizontal, particionamiento vertical y particionamiento mixto.

El particionamiento horizontal de relaciones consiste en la división de las tuplas de una relación en


subconjuntos. Esto es muy útil cuando existen consultas que acceden sólo a determinada parte de la
información dependiendo del valor de algún atributo, o en bases de datos distribuidas, ya que cada
subconjunto puede ubicarse en distintos nodos de la red, acercándose al lugar de su tratamiento.

En el particionamiento vertical, los atributos de una relación R son distribuidos en grupos no


solapados y la relación R se proyecta en relaciones fragmentarias de acuerdo a estos grupos de
atributos. Estos fragmentos se colocan en diferentes localizaciones de la base de datos distribuida. Por
ello, el objetivo del particionamiento vertical es crear fragmentos verticales de una relación de manera
que minimice el coste de acceso a los elementos de datos durante el procesamiento de la transacción.
Si los fragmentos se ajustan bien a los requisitos del conjunto de transacciones facilitado, entonces el
coste de proceso de las transacciones podría ser minimizado. El particionamiento vertical también
puede usarse en la partición de tablas individuales en bases de datos centralizadas, y en la división de
datos entre diferentes niveles de jerarquías de memoria, etc. En el caso de bases de datos distribuidas,
el coste de proceso de transacciones se minimiza incrementando el proceso local de las transacciones
(en un "nodo") así como reduciendo el número de accesos a objetos de datos que no son locales.

20
© Grupo EIDOS 2. Visión general sobre el diseño de bases de datos.

Como su propio nombre indica, el particionamiento mixto engloba a ambos tipos de


particionamiento (horizontal y vertical). Consiste en aplicar un particionamiento vertical a uno o más
de los fragmentos obtenidos mediante un particionamiento horizontal, o viceversa.

Diseño físico
El objetivo del diseño físico, que es la última fase del proceso de diseño, es conseguir una
instrumentación lo más eficiente posible del esquema lógico. Aquí se tienen en cuenta aspectos del
hardware, requisitos de procesos, características del SGBD, del SO y en general, cualquier factor
cercano a la "maquina". Con ello se persigue:

• disminuir los tiempos de respuesta

• minimizar espacio de almacenamiento

• evitar las reorganizaciones

• proporcionar la máxima seguridad

• optimizar el consumo de recursos

El principal problema que se plantea en la fase de diseño físico es el debido a la poca flexibilidad de
los actuales SGBD, los cuales obligan a trasladar a la fase de diseño lógico, aspectos de carácter físico,
que deberían ser ajenos a dicha fase. Esto obliga a iterar desde la fase de diseño físico a la de diseño
lógico, y viceversa, hasta obtener conseguir los objetivos anteriormente expuestos, lo que explica la
obligación de la etapa de reestructuración en el diseño lógico.

Como resultado del diseño físico se genera un esquema físico, que es una descripción de la
implementación de la base de datos en memoria secundaria; describe las estructuras de
almacenamiento y los métodos de acceso para acceder a los datos de una manera eficiente. Por ello el
diseño físico se genera para un SGBD y un entorno físico determinado.

21
Diseño conceptual

Introducción
Como ya se ha visto en el tema anterior, el diseño conceptual, que constituye la primera etapa en el
diseño de una base de datos, consiste en obtener una buena representación de los recursos de
información de la empresa, con independencia de usuario o aplicaciones en particular y fuera de
consideraciones sobre eficiencia del ordenador. Puesto que no se corresponde con ningún nivel de la
arquitectura ANSI/X3/SPARC, sino que es un paso previo, tiende a ser no tenido en cuenta a la hora
de proceder al diseño de una base de datos. Esto no es aconsejable, ya que el diseño lógico parte del
esquema conceptual y, si éste no es correcto, o no representa fielmente la información del mundo real,
el esquema de la base de datos no será estable, viéndonos obligados a reajustarlo constantemente
debido a las deficiencias arrastradas desde esta etapa de diseño. De ahí la importancia de realizar un
buen esquema conceptual, que represente fielmente las características del mundo real.

Otro error que se suele cometer en esta etapa de diseño es el de considerar aspectos tales como la
eficiencia del equipo hardware en el que se vaya a montar la base de datos, o SGBD's concretos. Como
ya se ha dicho, el esquema conceptual debe representar la información fuera de consideraciones sobre
hardware y sobre el SGBD sobre el que se implementará. Por lo tanto, se pueden establecer las
siguientes características que debe cumplir un buen esquema conceptual:

Debe representar fielmente la información del mundo real

• Es independiente del SGBD

• Es independiente del Hardware


Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Conviene no olvidar, por lo tanto, que un buen diseño del esquema conceptual, influirá positivamente
en el resto de etapas.

Etapas del diseño conceptual


La fase de diseño conceptual, puede subdividirse a su vez en dos etapas:

1. Etapa de análisis de requisitos: En esta etapa se debe responder a la pregunta "¿Qué


representar?". El objetivo es elaborar un esquema descriptivo de la realidad, en el que se
provean detalles de los datos a representar. Dicho esquema se obtiene mediante el estudio u
observación del mundo real (estudio de las reglas de la empresa, entrevista a los usuarios,
etc.). Aunque existen muchas respuestas sobre el modo de recoger dicha información, la más
utilizada es el lenguaje natural que, aunque carece del formalismo que pueden infligir
otros métodos, permite una mejor y más fácil comprensión de la información por parte del
usuario, y le permite especificar los requisitos sin la intervención de formalismos. Este primer
esquema percibido bruto (como lo llaman Benci y Rolland), se ira refinando sucesivamente,
hasta llegar al esquema conceptual.

2. Etapa de conceptualización: En esta etapa se debe responder a la pregunta "¿Cómo


representar?". En ella se transforma el esquema obtenido en la primera, mediante
refinaciones sucesivas. Se deberá obtener el esquema conceptual mediante una
representación normalizada, que se apoye en un modelo de datos que cumpla determinadas
propiedades (según Piattini y De Miguel): coherencia, plenitud, no redundancia, simplicidad,
fidelidad, etc. El modelo que se estudiará es el Modelo Entidad / relación (en adelante referido
como ME/R o modelo E/R), que es el más utilizado hoy en día.

El modelo entidad / relación


El modelo E/R fue propuesto por Peter P. Chen en dos artículos que publicó en los años 1976 y 1977.
En ellos define dicho modelo como una vista unificada de los datos, centrándose en la estructura
lógica y abstracta de los datos, como representación del mundo real, con independencia de
consideraciones de tipo físico. Posteriormente se fueron proponiendo nuevas aportaciones al modelo,
lo cual explica que no exista uno sólo, sino distintos modelos según los autores.

Los objetivos que debe cumplir un esquema conceptual son los siguientes (Piattini y De Miguel):

1. Captar y almacenar el universo del discurso mediante una descripción rigurosa.

2. Aislar la representación de la información de los requisitos de máquina y exigencias de cada


usuario en particular

3. Independizar la definición de la información de los SGBD en concreto.

A continuación se describirá el proceso de creación de un esquema conceptual, siguiendo el modelo


E/R. Éste se basa en una representación gráfica de una serie de entidades relacionadas entre sí. Al
utilizar una representación de este tipo, el modelo E/R permite distinguir fácilmente y a simple vista,
las relaciones existentes entre las distintas entidades. Existen muchas formas de representarlo, como
ya se ha comentado; la que se utilizará aquí no es, por supuesto, la única forma de hacerlo. Los
elementos de los que se componen son los siguientes:

24
© Grupo EIDOS 3. Diseño conceptual

1. Entidades: Una entidad es "una persona, lugar, cosa, concepto o suceso, real o abstracto,
de interés para la empresa" (ANSI 1977). En el modelo E/R, se representa por un
rectángulo, con el nombre de dicha entidad escrito en la parte superior. Por ejemplo, la
Figura 8 representa la entidad automóvil.

Figura 8

2. Atributos: Un atributo es cualquier característica que describe a una entidad. Los atributos
de una entidad se colocan dentro del rectángulo que representa dicha entidad, justo debajo
del nombre de ésta. Por ejemplo, se puede decir que un automóvil tiene las siguientes
características: nº de matricula, marca, modelo y color, lo cual se muestra en la Figura 9.

Figura 9

3. Clave: La clave de una entidad es un atributo o conjunto de atributos de dicha entidad, que
son capaces de identificar unívocamente una ocurrencia de una entidad. Es decir, si
conocemos el valor de dichos atributos, seremos capaces de conocer a que ocurrencia de
entidad, entre todas las posibles, hace referencia. Esto implica que los valores de los
atributos clave no se pueden repetir para dos ocurrencias de la misma entidad. En nuestro
ejemplo, seremos capaces de identificar de que automóvil estamos hablando, con sólo
conocer el valor del atributo matrícula, ya que no existe una misma matrícula para dos
automóviles distintos. Los atributos marca, modelo o color no identifican unívocamente
una ocurrencia de la entidad, ya que pueden existir dos automóviles distintos de la misma
marca, modelo o color. En el modelo E/R, un atributo clave se representa subrayando
dicho atributo.

Figura 10

4. Relación: Una relación representa, como su propio nombre indica, una correspondencia
entre dos entidades. Si tenemos dos entidades automóvil y persona, podemos tener una
relación entre ellas. Dicha relación se puede establecer en ambos sentidos:

una persona posee un automóvil, y

Un automóvil pertenece a una persona.

25
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

5. Cardinalidad de una relación: La cardinalidad de una relación representa el número de


ocurrencias que se pueden dar de una relación. Puede ser de tres tipos:

Cardinalidad 1-1: cada ocurrencia de una entidad se relaciona con una ocurrencia de
otra entidad. Ej.: una persona posee un automóvil. Se representa como indica la Figura
11.

Figura 11

Cardinalidad 1-N: también llamada uno a muchos. Cada ocurrencia de una entidad
puede relacionarse con varias ocurrencias de otra entidad. Ej.: una persona posee
varios automóviles. Se representa como muestra la Figura 12.

Figura 12

Cardinalidad N-M: también llamada muchos a muchos. Cada ocurrencia de una


entidad puede relacionarse con varias ocurrencias de otra entidad y viceversa. Ej.: una
persona posee varios automóviles y un automóvil puede pertenecer a varias personas.
Se representa como aparece en la Figura 13.

Figura 13

6. Cardinalidad máxima de una relación: representa el número máximo de ocurrencias de


una entidad con las que se puede relacionarse otra entidad. Ej.: una persona puede tener
como máximo tres automóviles.

7. Cardinalidad mínima de una relación: representa el número mínimo de ocurrencias de una


entidad con las que se puede relacionarse otra entidad. Ej.: un automóvil debe pertenecer
como mínimo a una persona.

8. Entidad débil: se dice que una entidad es débil, o es dependiente de otra, cuando no somos
capaces de conocer a que ocurrencia de entidad nos estamos refiriendo, ni siquiera
conociendo su clave, sino que debemos conocer el valor de algún otro atributo de otra

26
© Grupo EIDOS 3. Diseño conceptual

entidad. Por ejemplo, si tenemos las entidades edificio (con el atributo clave
codigo_edificio) y planta (con el atributo codigo_planta), ésta última es una entidad débil,
ya que no somos capaces de identificar una planta con sólo conocer el código de la planta,
sino que además se necesita conocer el código del edificio al que se hace referencia, para
determinar la planta dentro del edificio.

Figura 14

En general, en una relación se suele representar conjuntamente las cardinalidades máxima y mínima.
En los anteriores casos no se han considerado las cardinalidades mínimas. Éstas vienen a representar la
opcionalidad de la ocurrencia de una entidad en una relación, es decir, si dicha ocurrencia se debe dar
obligatoriamente, o si por el contrario se puede obviar. Los tipos de cardinalidades son los que
aparecen en la Figura 15, (nos fijaremos sólo en un sentido de la relación, el de la izquierda).

Cardinalidad máxima 1, cardinalidad mínima 1.

Cardinalidad máxima 1, cardinalidad mínima 1.

Cardinalidad máxima N, cardinalidad mínima 0.

Cardinalidad máxima N, cardinalidad mínima 1.

Figura 15

Veamos a continuación unos ejemplos para comprender mejor las cardinalidades máxima y mínima.
Como se podrá comprobar, las cardinalidades de una relación se ponen en la última relación a la que
se hace referencia, por ejemplo, si se tienen las entidades alumno y asignatura, la cardinalidad de la
relación un alumno cursa asignaturas, se pondrá al lado de la entidad asignatura.

En el siguiente ejemplo(Figura 16), se tiene una relación 1-1 en la que un automóvil pertenece a una
única persona (cardinalidad máxima 1), sin la posibilidad de que exista un automóvil que no tenga
dueño (cardinalidad mínima 1). Esto significa que en el modelo no interesa tener información de
aquellas personas que no tengan automóvil.

Figura 16

En la Figura 17, se tiene una relación 1-1 en la que una persona puede tener un automóvil como
mucho (cardinalidad máxima 1), o puede no tener ninguno (cardinalidad mínima 0). Esto significa que
el modelo interesa tener información de todas las personas, aunque no tengan automóvil.

27
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Figura 17

En el siguiente ejemplo (Figura 18), se tiene una relación 1-N, en la que un profesor puede dar clase a
muchos alumnos (cardinalidad máxima N), pero como mínimo debe hacerlo a uno (cardinalidad
mínima 1). Esto significa que en el modelo no interesa tener información de aquellos profesores que
no dan clase.

Figura 18

En el siguiente ejemplo, se tiene una relación N-N, en la que una persona puede tener varios
automóviles (cardinalidad máxima N), pero puede que no tenga ninguno (cardinalidad mínima 0). Esto
significa que en el modelo interesa tener información de todas las personas, aunque no tengan
automóvil.

Figura 19

Para concluir esta sección se verá un ejemplo completo que representará todos los conceptos vistos
hasta ahora. Supongamos que se desea establecer un modelo conceptual para la gestión de una
biblioteca. Se desean tener almacenados todos los libros que la componen.

Para cada libro interesa conocer el ISBN, el título, el autor o autores, la editorial, el año de publicación
y la materia. De cada autor se quiere conocer su nombre, apellidos y nacionalidad.

Un autor podrá haber escrito varios libros, de la misma forma que en un libro pueden participar varios
autores. De la editorial se desea conocer el nombre y la ciudad.

A dicha biblioteca podrán estar suscritos varios usuarios. De ellos se quiere saber su DNI, número de
socio, nombre, apellidos, dirección y teléfono. Por cuestiones directivas, se limita el número de
ejemplares prestados a cada usuario a uno.

Se dispone, a su vez, de un único ejemplar de cada libro, por lo que un libro prestado a un usuario, no
podrá ser prestado a otro hasta que se devuelva. Deberá quedar constancia de la fecha de préstamo de
cada ejemplar.

28
© Grupo EIDOS 3. Diseño conceptual

Figura 20

Lo más destacable del anterior ejemplo es la entidad préstamo. Es una entidad débil que depende de
libro y de socio, ya que para diferenciar un préstamo de otro, se necesita saber no sólo el libro, sino el
socio al cual se ha prestado. También se pueden observar que las cardinalidades mínimas son 1. Esto
quiere decir que sólo se guardará información de las entidades cuando exista, al menos, una ocurrencia
de la entidad. Las únicas relaciones que tienen cardinalidad opcional, son las que tienen como origen o
destino a la entidad préstamo, lo cual es lógico, ya que tendremos información de todas las entidades,
aunque todavía no se haya realizado ningún préstamo.

Ejemplos prácticos de diseño conceptual


A continuación resolveremos unos problemas de diseño conceptual, para ir familiarizando al lector
con los conceptos vistos hasta ahora. Para realizarlos se utilizará la S-Designor, que es una
herramienta CASE que abarca gran parte del ciclo de vida de las aplicaciones, incluyendo el diseño de
esquemas conceptuales. No se preocupe si no conoce la herramienta, ya que se verá en detalle en
próximos temas, simplemente quédese con la idea general de la construcción del esquema.

El problema que nos planteamos es el siguiente. Supóngase que se desea informatizar una tienda de
discos. Para ello se desean tener almacenados los nombres de todos los discos disponibles, además de
sus cantantes y canciones. Así mismo se desean almacenar los clientes que han comprado en dicha
tienda. Pues bien, empezaremos identificando las entidades, entendiendo por entidad un grupo de
características que tienen entidad propia. Como primera entidad, podemos establecer los discos que se
venden, ya que se desea conocer información de ellos, como puede ser un código que lo identifique
dentro de la estantería. Por otro lado se desea almacenar todos los artistas que intervienen en los discos
de nuestra tienda, y para cada uno de ellos se desea conocer su nombre y apellidos, por lo tanto ya
tenemos identificada una segunda entidad. Además, se desea conocer todas las canciones que están
disponibles en los discos, identificada cada una de ellas por un código de canción, y que además
tendrán sus propias letras. Pues ya tenemos la tercera entidad. La cuarta estará formada por los
clientes, de los cuales se desea almacenar su nombre, apellidos, dirección y teléfono, y que podrán
estar identificados internamente por un código de cliente.

Figura 21

29
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Una vez establecidas las entidades, sólo nos queda relacionarlas. Podemos observar las siguientes
relaciones:

1. Entre disco y canción: en un disco pueden aparecer varias canciones, y cada canción puede
estar en varios discos (N-M).

2. Entre cantante y canción: un cantante puede componer varias canciones, y una canción puede
estar compuesta por varios cantantes (N-M).

3. Entre cliente y disco: un cliente puede comprar varios discos, pero un disco sólo puede ser
comprado por un cliente 1-N.

Por lo tanto, el esquema conceptual es que muestra la Figura 22

Figura 22

Vamos a plantearnos otro problema. Supongamos que se desea tener almacenados todos los datos de
los profesores de una empresa dedicada a impartir cursos, así como una breve descripción de éstos, y
los alumnos a los cuales se les ha impartido. Empezamos identificando entidades.

De un profesor se desea conocer su nombre y apellidos, dirección y despacho, por lo tanto establece
una entidad. Otra entidad podría ser el alumno, del cual se desea conocer su nombre, apellidos,
dirección y teléfono.

Ni que decir tiene que el curso describe otra entidad, de la cual se desea conocer su descripción. Sin
embargo, podemos recurrir a un procedimiento muy usual, denominado tipificación de estados, muy
usado en el diseño conceptual, y que consiste en tener una entidad que tipifique los posibles estados
que puede tomar un atributo.

La principal ventaja de este procedimiento radica en que muchas veces supone un ahorro de espacio de
almacenamiento (por ejemplo al identificar nombres de ciudades largas con un solo número) además
de una estandarización de los datos almacenados (el estado sólo se almacena una vez).

Por ejemplo podemos tipificar las ciudades, para lo cual creamos una nueva entidad ciudad, donde se
almacenará un código y la descripción de la ciudad. Cuando almacenemos la ciudad de un alumno,
sólo deberemos especificar el código de la ciudad.

30
© Grupo EIDOS 3. Diseño conceptual

Figura 23

Una vez establecidas las entidades, vamos a definir las relaciones entre ellas.

1. Profesor y Curso: un profesor puede impartir varios cursos, pero un curso sólo puede ser
impartido por un profesor (1-N).

2. Alumno y Curso: un alumno puede asistir a varios cursos, y a un curso pueden asistir varios
alumnos (N-M).

3. Alumno y Ciudad: un alumno vive en una ciudad, y una ciudad puede tener varios alumnos
(1-N).

Por lo tanto, el esquema conceptual es el mostrado en la Figura 24.

Figura 24

Cabe destacar que el atributo calificación se da como consecuencia de la relación entre las entidades
curso y alumno. Por lo que podrá ser introducido en la entidad intermedia que surja cuando se haga el
paso a tablas (véase siguiente capítulo).

31
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Vamos a ver un último ejemplo. Supóngase un banco que desea almacenar todos sus clientes, además
de los productos que puede ofrecer a éstos. Cada cliente podrá escoger entre todos estos productos el o
los que más le plazcan (créditos, fondos de inversión, libretas de ahorro, etc.).

De la misma forma, dicho banco tiene intereses en otras empresas, por lo que desea conocer en todo
momento la situación de dichas empresas, para poder mejorar su política de inversiones.

Puesto que dicho banco esta constituido como sociedad anónima, desea almacenar todos los
componentes de su consejo de administración (actuales y ex-miembros) así como todas las actas de las
reuniones ordinarias y extraordinarias.

Las decisiones de inversión en estas empresas saldrán como resultado de dichas reuniones, así como la
oferta de nuevos productos.

Como habrá podido observar, este ejemplo es un poco más complejo, pero no desespere, el proceso es
similar al de los demás ejemplos. Empezaremos definiendo entidades y las veremos representadas en
la Figura 25.

1. Cliente: se desea conocer su nombre, apellidos, dirección y NIF, y estará identificado por un
código interno cod_cliente.

2. Producto: del cual queremos saber su descripción y estará identificado por un código interno
cod_producto.

3. Empresa: identifica las empresas en las cuales el banco ha invertido. De ellas se desea conocer
su código, nombre y CIF.

4. Consejo: establece los componentes del consejo de administración. Para ello se almacenará el
nombre, apellidos y código de cargo de cada uno de sus componentes, y si el cargo es vigente
o no. Podremos utilizar una nueva entidad que tipifique los tipos de cargo.

5. Tipo_cargo: describe los posibles cargos que puede tomar una persona en el consejo de
administración, y esta compuesto por un código de tipo de cargo, y una descripción del mismo
(secretario, presidente, etc.).

6. Reunión: entidad encargada de describir la información de las actas de las reuniones. Sus
atributos son cod_reunión, fecha, extraordinaria, que especifica si la reunión ha sido ordinaria
o extraordinaria y una descripción.

Figura 25

32
© Grupo EIDOS 3. Diseño conceptual

Identifiquemos ahora las relaciones. Su representación gráfica aparece en la Figura 23.

1. Cliente y producto: cada cliente puede escoger varios productos, y cada producto puede ser
ofrecido a varios clientes.

2. Consejo y cargo: un miembro del consejo sólo tiene un cargo, y cada cargo puede pertenecer a
más de un miembro.

3. Reunión y consejo: a cada reunión pueden asistir varios miembros del consejo de
administración, y cada miembro puede asistir a más de una reunión.

4. Reunión y producto: de cada reunión puede salir la oferta de mas de un nuevo producto pero
cada producto nuevo sólo puede salir de una reunión.

5. Reunión y empresa: de cada reunión pueden salir decisiones de invertir en más de una
empresa, y cada decisión de inversión sólo sale de una reunión.

33
Diseño lógico

Introducción
Como ya se ha señalado, el diseño lógico de una base de datos consta de dos etapas: el diseño lógico
estándar y el diseño lógico específico. En el diseño lógico estándar, se toma el esquema conceptual
resultante de la fase de diseño conceptual, y teniendo en cuenta los requisitos de proceso, de construye
un esquema lógico estándar (ELS), que se apoya en un modelo lógico estándar (MLS), que será el
mismo modelo de datos soportado por el SGBD a utilizar (relacional, jerárquico, etc.), pero sin las
restricciones de ningún producto comercial en concreto. En nuestro caso se utilizará el MLS
relacional. Una buena forma de describir el ELS es utilizando el lenguaje estándar del MLS (por
ejemplo SQL).

Una vez obtenido el ELS, y considerando el modelo lógico específico (MLE) propio del SGBD a usar
(ORACLE, INFORMIX, SQL-SERVER, etc.), se elabora el esquema lógico específico (ELE). Al
igual que en el caso anterior, una buena forma de describirlo es utilizando el lenguaje de definición de
datos (LDD) del producto especifico utilizado (en el caso de SQL-SERVER, se usará el TRANSACT
SQL). El diseño lógico específico está muy ligado a la fase de diseño físico, ya que ambos dependen
mucho del SGBD que se utilice.

En la fase de diseño lógico, además de las herramientas ya descritas (MLS, MLE, lenguajes SQL), se
disponen de otras que permiten establecer un buen diseño lógico, como por ejemplo la normalización,
la desnormalización, etc., que ya se verán mas adelante en este tema.
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Paso del esquema conceptual al esquema lógico estándar


Lo primero que hay que realizar en la fase de diseño lógico, es obtener el esquema lógico estándar, a
partir del esquema conceptual obtenido en la primera fase. Las reglas que permiten pasar del modelo
E/R al esquema lógico, son las que a continuación se explican:

• Cada entidad se transforma en una relación: esto es, cada entidad genera una tabla, con sus
mismos atributos, incluyendo las claves.

• Cada relación N-M genera una tabla: las relaciones entre entidades con cardinalidad N-M
generan una tabla, con los atributos clave de ambas entidades.

• Cada relación 1-N importa las claves de la entidad con las que se relaciona: cada relación con
cardinalidad 1-N importa los atributos clave que contiene la entidad con cardinalidad N.

• Cada relación dependiente, importa la clave de la otra entidad, como clave.

Para entender mejor el funcionamiento de este método, veamos el paso a tablas del ejemplo visto en el
tema anterior acerca de la gestión de una biblioteca. La entidad libro está relacionada con la entidad
editorial con cardinalidad 1-N, por lo tanto importa la clave de la entidad con cardinalidad 1. A su vez,
esta relacionada con la entidad con la entidad autor, pero en este caso, la cardinalidad es N-M, lo que
implica que se generará una tabla intermedia, en la que se almacenarán las claves de ambas entidades.
Esta tabla, a la que denominaremos Libro_autor mantiene la información de los códigos de libros junto
con los códigos de autores. Posteriormente, si se desea extraer más información, tanto del libro como
del autor, se deberá acceder a sendas tablas. Por último se dispone de la entidad Préstamo, que es
dependiente tanto de la entidad Libro como de la entidad Usuario, lo que quiere decir que se generará
una tabla, con los atributos de la entidad Préstamo además de las claves de las entidades de las que es
dependiente, es decir, ISBN y Num_socio, que entrarán como claves en dicha tabla. Esta última
relación obtenida, mantiene información de qué libros han sido prestados a qué usuarios y en qué
fecha. El esquema de las tablas resultantes es el que se muestra en la Figura 26

Figura 26

Veamos ahora el paso a tabla de otro ejemplo visto en el tema anterior, cuyo esquema conceptual es el
que muestra la Figura 27.

Empezaremos identificando las relaciones, y concretando las tablas que generarán:

1. Cliente-Disco: puesto que es una relación 1-N, la entidad disco generará una tabla con sus
atributos, e importará el atributo clave de la entidad con cardinalidad 1, es decir, cod_cliente.
A su vez, la entidad cliente generará su propia tabla, con sus propios atributos, es decir,
cod_cliente, nombre, apellidos y telefono.

36
© Grupo EIDOS 4. Diseño lógico

2. Disco-Canción: es una relación 1-N, a si que, siguiendo el mismo razonamiento anterior, la


tabla canción generada importará el cod_disco de la entidad disco.

3. Canción-Cantante: en este caso se tiene una relación N-M, es decir, se generará una tabla
intermedia, con los atributos claves de las entidades que relaciona, es decir, cod_canción y
cod_cantante.

4. Disco_Cantante: siguiendo el mismo razonamiento, al ser una relación N-M, se generará una
tabla intermedia, con los atributos cod_cantante y cod_disco.

Figura 27

Con todo esto, el esquema lógico resultante del esquema conceptual anterior, queda como aparece en
la Figura 28.

Figura 28

Etapas en el diseño lógico


Como ya se ha comentado, la fase de diseño lógico de una base de datos consiste en dos etapas:

• Etapa de estructuración: donde el objetivo primordial es encontrar un esquema que sea una
representación fidedigna del mundo real. La forma de lograrlo es mediante el particionamiento
horizontal, para evitar valores nulos, y el proceso de normalización.

• Etapa de reestructuración: donde se tienen en cuenta aspectos más ligados con el nivel físico,
y que consiste el modificar el esquema obtenido en la fase anterior para adaptarlo a las
consideraciones de eficiencia. Esta etapa, que debería ser ajena al diseño lógico, se considera
aquí debido a la falta de flexibilidad de los SGBD, obligando a trasladar a esta etapa aspectos

37
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

mas relacionados con el nivel físico. La forma de lograrlo es mediante la desnormalización, y


el particionamiento, bien sea horizontal, vertical o mixto.

Comenzaremos por estudiar el particionamiento horizontal de relaciones, usado tanto en la etapa de


estructuración como en la de reestructuración, para dar paso posteriormente al proceso de
normalización, dejando para el final el particionamiento vertical, mixto y la desnormalización.

Particionamiento horizontal de relaciones


Como su propio nombre indica, el particionamiento horizontal consiste en dividir longitudinalmente
las filas que forman una tabla, esto es, separar las filas que conforman una relación, para llevarlas a
otra. Para entenderlo mejor, supóngase el siguiente ejemplo en el que se tiene la tabla publicación, con
los siguientes campos: cod_publicación, título, autor, editorial.

En un momento dado, la información que tenemos en la tabla es la mostrada en la Tabla 1.

Cod_publicación Título Autor Editorial

Miguel de
123BB3-3 El Quijote Ibérica
Cervantes

El impacto de las
113ZD3-0 Francisco Hierves
TI

Rimas y
2322-DD G. A. Becquer Alcalá
Leyendas

Tabla 1

Tenemos información sobre dos libros, con su autor y su editorial correspondiente, y un artículo (El
impacto de las TI) que, como es obvio, no tiene editorial. En este caso, podría ser conveniente "partir"
dicha tabla horizontalmente en otras dos, es decir llevar parte de la información a una tabla, y parte a
otra.

Aquí la diferenciación se establece entre aquellas filas que tienen editorial, es decir, libros, y aquellas
que no tienen editorial, o artículos. Por lo tanto, se crean dos tablas: una para albergar los libros y otra
para ubicar los artículos.

La Tabla 2 posee la tabla de libros, mientras que la Tabla 3 contiene los artículos.

Cod_publicación Título Autor Editorial

123BB3-3 El Quijote Miguel de Cervantes Ibérica

2322-DD Rimas y Leyendas G. A. Becquer Alcalá

Tabla 2

38
© Grupo EIDOS 4. Diseño lógico

Cod_publicación Título Autor

113ZD3-0 El impacto de las TI Fco. Hierves

Tabla 3

Con esto, lo que hemos conseguido es eliminar la existencia de valores nulos no aplicables. Un valor
nulo es aquel que representa información desconocida, inexistente o no válida (en nuestro caso el valor
del atributo editorial en el artículo). Los valores nulos pueden ser aplicables o no aplicables. Mientras
los no aplicables no cambian, es decir, permanecen nulos, los aplicables pueden dejar de serlo en
algún momento.

Esto que acabamos de realizar, es el primer paso que se debe seguir en el proceso de estructuración de
relaciones. Sin embargo, el particionamiento horizontal no sólo se utiliza aquí, sino que también puede
usarse en la fase de reestructuración para conseguir una mayor eficiencia. Por ejemplo, si se dispone
de una base distribuida (para entendernos, una base de datos con distintos nodos, situados en distintas
localizaciones, con determinada información en cada uno) con información acerca de clientes, y
suponiendo que se dispone de dos nodos, uno en Madrid y otro en Barcelona, lo lógico sería pensar en
situar la información de aquellos clientes que residen en Barcelona en dicho nodo, y ubicar
únicamente la información de los clientes que viven en Madrid en dicho nodo. Los motivos son los
siguientes:

• Si se sitúa toda la información en un único nodo, el coste del acceso remoto aumenta (si toda
la información está en Madrid, una consulta de un cliente que vive en Barcelona se debería
realizar al nodo de Madrid, con el coste que ello supone).

• Si se sitúa toda la información en ambos nodos, el coste de almacenamiento aumenta al tener


toda la información duplicada.

En este caso, pues, lo que se deberá realizar en un particionamiento horizontal, para situar aquellas
filas que correspondan a clientes de Madrid, en el nodo de Madrid, y aquellas filas que correspondan a
clientes de Barcelona, en el nodo de Barcelona.

Supongamos, por ejemplo, que tenemos el siguiente esquema lógico, correspondiente a una base de
datos para gestionar los alumnos de una empresa de educación a distancia.

Figura 29

Sobre el esquema de la Figura 29, nos podemos plantear varias cuestiones:

1. Se dispone de dos tablas, alumno y profesor. La tabla alumno guarda sus datos personales, y
las calificaciones obtenidas en cada una de las asignaturas, mientras que la tabla profesor

39
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

almacena, además de sus datos personales, las aulas donde dicho profesor imparte cada una de
las clases.

2. La base de datos se encuentra distribuida, es decir, se dispone de un nodo en cada una de las
provincias, donde se almacena la información relevante a ésta.

3. Los alumnos pueden optar por dos ramas, ciencias o letras, y para cada una de ellas se
imparten dos asignaturas, arte y latín en letras, y matemáticas y ciencias en la rama de
ciencias.

Nos planteamos, entonces, aumentar la eficiencia de la base de datos, para adecuarla a las necesidades
de cada una de las provincias donde se encuentra ubicada la base de datos.

Puesto que en cada nodo sólo precisa información relevante a éste, podemos optar por tres opciones:

Opción 1: colocar la base de datos en un sólo nodo (centralizado), al que accederán los demás.

Opción 2: colocar la parte de información relevante a cada nodo en cada uno de ellos.

Opción 3: colocar una copia de toda la base de datos en cada nodo.

En la Tabla 4 se analizan las ventajas e inconvenientes de cada una de la anteriores opciones.

Ventajas inconvenientes

Se disminuye el espacio de
El resto de las provincias deberá acceder a
almacenamiento (una sola copia de la
la provincia donde se encuentre la base de
Opción 1 información), y en la provincia donde se
datos, con el tráfico de red y aumento de
encuentre la base de datos se disminuirá
tiempo de acceso que esto supone.
el tiempo de acceso

Cada provincia tendrá la parte de


información que le interesa en su propio Si se precisa acceder a otras provincias
Opción 2 nodo, lo que aumenta la eficiencia en las distintas, se aumenta el tiempo de acceso
consultas / actualizaciones, al evitar el (tráfico de red)
acceso por red a otras provincias.

Cada provincia tendrá toda la


Se aumenta el espacio de almacenamiento,
información de todas las provincias en su
Opción 3 de forma directamente proporcional al
propio nodo, disminuyendo el tiempo de
número de provincias.
acceso.

Tabla 4

Analizando la anterior tabla, y teniendo la premisa expuesta de que cada provincia trabajará de manera
aislada, la opción que más nos interesa es ubicar cada parte de información relevante a cada una de
éstas, en su nodo local. La pregunta que surge ahora es ¿cómo se puede realizar?; pues bien, la
respuesta es bastante simple: mediante el particionamiento horizontal. Para ello se deben seguir los
siguientes pasos:

Paso 1: Realizar una consulta para separar las filas correspondientes a cada provincia, en cada una de
las tablas.

40
© Grupo EIDOS 4. Diseño lógico

Paso 2: Ubicar la información obtenida en cada uno de los nodos correspondientes a dichas provincias.

Como ejemplo, supóngase que se desean ubicar las filas de las tablas alumno y profesor en el nodo
provincial de Madrid. Para ello se realizará una "criba" en ambas tablas donde el campo provincia sea
Madrid. La sentencia SQL que realiza se ve en el Código fuente 1.

SELECT * FROM alumno WHERE provincia = "Madrid"


SELECT * FROM profesor WHERE provincia = "Madrid"

Código fuente 1

No se preocupe demasiado si no entiende las anteriores sentencias, ya que se verán en detalle más
adelante. Quédese simplemente con la idea de su funcionamiento, que es el de obtener de ambas tablas
solamente aquellas filas que corresponden a la provincia de Madrid. De esta manera es preciso
proceder para el resto de las provincias.

Otra de las cuestiones que hemos planteado es la referente a las ramas por las que puede optar un
alumno: letras o ciencias. Podemos observar como en la tabla alumno, se encuentran atributos que
hacen referencia a las calificaciones obtenidas en ambas ramas, lo que supone que siempre se darán, al
menos, dos valores nulos inaplicables en cada fila de la tabla, ya que un alumno puede optar por una
de las dos ramas, pero no por ambas. Llegados a este punto, podremos decidir separar las filas de
dicha tabla entre otras dos, denominadas alumno_ciencias y alumno_letras, cada una de ellas
almacenando los atributos correspondientes a cada una de estas ramas, respectivamente. De esta
manera, en la tabla alumno_letras, estarían solamente las filas o tuplas correspondientes a alumnos que
han escogido la rama de letras, y en la tabla alumno_ciencias, aquellos que han optado por la rama de
ciencias. La forma de proceder es, nuevamente, mediante un particionamiento horizontal, con el
objetivo de eliminar estos valores nulos no aplicables. Las tablas quedarían entonces como muestra la
Figura 30.

Figura 30

Particionamiento vertical de relaciones


El particionamiento vertical de relaciones consiste, al contrario que en el caso del particionamiento
horizontal, en dividir las tablas de forma transversal, es decir, crear nuevas tablas con la información
correspondiente a un subconjunto de los atributos de las mismas, pero manteniendo intacta la
información correspondiente a las filas. Veamos un ejemplo para comprenderlo mejor. Supóngase que
tenemos la tabla reparto con la información de todos los repartos realizados por los proveedores a los
clientes. La información que tenemos de dicha tabla (Tabla 5) es: cod_proveedor, cod_cliente,
cod_material, nombre_proveedor, nombre_cliente, ciudad_proveedor, ciudad_cliente y cantidad.

41
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

cod_ cod_ cod_ nombre_ nombre_ ciudad_ ciudad_


cantidad
proveedor cliente material proveedor cliente proveedor cliente

123 113 112 Pepe Juan Sevilla Sevilla 10

128 114 118 Luis Paco Madrid Cuenca 29

837 998 128 Antonio Ángel Barcelona Manresa 12

Tabla 5

Dada la Tabla 5, podría interesarnos tener varias tablas: una que contenga la información del
proveedor, con los atributos nombre_proveedor y ciudad proveedor, otra con la información del
cliente con los atributos nombre_cliente y ciudad_cliente y otra con la información de los repartos con
los atributos cod_proveedor, cod_cliente, cod_material y cantidad. Para ello realizamos un
particionamiento vertical, sobre estos atributos.

nombre_proveedor ciudad_proveedor

Pepe Sevilla

Luis Madrid

Antonio Barcelona

Tabla 6

nombre_cliente ciudad_cliente

Juan Sevilla

Paco Cuenca

Ángel Manresa

Tabla 7

cod_proveedor cod_cliente cod_material cantidad

123 113 112 10

128 114 118 29

837 998 128 12

Tabla 8

42
© Grupo EIDOS 4. Diseño lógico

El resultado es que tenemos el mismo número de filas en todas las tablas, pero más tablas con menos
atributos. Este proceso se realiza en la reestructuración, ya que las ventajas que ofrece están
relacionadas con la eficiencia. Entre ellas destacan:

• Aumento de la concurrencia: cada vez que un usuario accede a una fila de la tabla, ésta se
bloquea, es decir, no puede ser accedida por otro usuario. Al dividir un tabla en más, la
concurrencia aumenta, es decir, si un usuario accede a una fila de una tabla, otro podrá acceder
a la misma fila en otra tabla.

• Aumento de la velocidad de consulta / actualización: al ser las tablas más pequeñas, una
consulta o actualización podrá realizarse en un menor tiempo, ya que se necesitarán menos
accesos a disco para completar la acción.

• Disminución de tiempos de consulta de información irrelevante: si se quiere consultar un solo


atributo de una tabla, se deberá acceder a toda la fila, con lo que ello supone. En cambio, al
reducir el tamaño de las filas, la información a la que accedemos tendrá más probabilidad de
ser utilizada.

Por contra, la principal desventaja que tiene este método es el aumento del tiempo de consulta /
actualización si se desea acceder a dos o más tablas. Es por ello por lo que hay que realizar un estudio
pormenorizado de la probabilidad de consultas que se va a realizar. Para ello existen varios algoritmos,
por ejemplo el de Navathe y Ra, en los que no entraremos, ya que escapan del objetivo del presente
curso.

Por ejemplo, supóngase que se dispone un esquema lógico con una sola tabla, en la que se almacenan
los datos personales de los empleados de una empresa.

Figura 30

Si nos damos cuenta, existen muchos atributos, a los que deberemos acceder en cada consulta, aunque
no nos interese su valor. Esto es debido a que, normalmente, el acceso (o bloqueo de tupla) se realiza
al nivel de fila o tupla, es decir, se accede a toda la fila de la tabla. Puede que esto no nos sea útil, por
ejemplo, sin únicamente deseamos obtener el sueldo de un empleado, ya que deberemos obtener toda
la fila correspondiente a ese empleado, para extraer un solo atributo con todos los inconvenientes que
esto supone, como por ejemplo una disminución de la concurrencia (otro usuario no podrá acceder
simultáneamente a esa fila, ni siquiera para consultar el valor de otro atributo), un aumento del tiempo
de proceso (debemos procesar toda la fila para extraer un solo atributo), un mayor consumo de
memoria (por el mismo motivo), un aumento del número de operaciones de Entrada / salida (puede
que la fila entera no quepa en el buffer de memoria, y debamos realizar más accesos a la base de
datos), etc.

Nos plantemos entonces un particionamiento vertical. Puesto que la única transacción (consulta) que
se va a realizar (de momento) es la consulta del sueldo de un empleado, se puede separar esta tabla en

43
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

otras dos: una con el atributo sueldo, y otra con el resto. De esta manera solventamos los anteriores
inconvenientes que se presentaban.

Para identificar unívocamente cada una de estas filas, y asociarlas a las filas de la tabla homóloga, se
pueden usar dos métodos:

1- Utilizar un identificador de fila, igual para cada fila en ambas tablas, o

2- Utilizar un atributo clave, similar para filas iguales en ambas tablas.

En esta caso optamos por la segunda opción, utilizando el DNI, como campo unión entre ambas tablas,
quedando el esquema lógico particionado verticalmente de la como indica la Figura 31.

Figura 31

Sin embargo, ¿que pasaría si ahora se necesita saber no sólo el sueldo, sino también la categoría de un
empleado?. Pues bien, el esquema obtenido no nos valdría (bueno, de hecho si valdría, pero no sería
demasiado eficiente), ya que ahora se necesitaría realizar una operación de join o unión entre ambas
tablas, para obtener ambos valores. Destacar que la operación de join es bastante costosa en tiempo de
ejecución. La solución, en este caso, pasaría por añadir el campo categoría a la tabla anteriormente
extraída.

Figura 32

Particionamiento mixto
El particionamiento mixto consiste en un híbrido entre ambos tipos de particionamiento. O bien se
aplica un particionamiento vertical a una tabla previamente particionada horizontalmente, o bien se
aplica un particionamiento horizontal a una tabla particionada verticalmente. Por lo tanto, existen dos
opciones:

• Realizar primero un particionamiento horizontal, por ejemplo para ubicar las distintas filas de
una tabla en distintos nodos de una base distribuida (como el ejemplo visto anteriormente), y

44
© Grupo EIDOS 4. Diseño lógico

posteriormente realizar un particionamiento vertical sobre las tablas obtenidas, para conseguir
un mayor ajuste de los tiempos de acceso a datos (evitar acceder a datos irrelevantes).

• Realizar primero un particionamiento vertical, para conseguir disminuir los tiempos de acceso
y posteriormente realizar un particionamiento horizontal sobre dichas tablas.

El particionamiento mixto se usa en la etapa de reestructuración, ya que se tiene en cuenta aspectos


relacionados con el nivel físico (eficiencia). La forma de representar el particionamiento mixto se
denomina árbol de particionamiento, e indica los distintos tipos de particionamiento por los que va
atravesando una determinada relación. La Figura 33 nos muestra como la relación original R se ha
particionado de forma horizontal en otras dos R2 y R1, y a su vez, ésta última, se ha particionado
verticalmente en otras dos R3 y R4.

Figura 33

Teoría de la normalización
El proceso de normalización consiste en la aplicación de un conjunto de reglas, con el objeto de
verificar que el esquema relacional obtenido en esta fase cumple un cierto conjunto de reglas. La
normalización se podría considerar prácticamente como el grueso de la fase de diseño lógico, ya que
es el encargado de modificar el esquema conceptual obtenido en la fase anterior, para que cumpla el
primero de los objetivos de las bases de datos, el de que ha de representar fielmente la realidad. Por lo
tanto es el segundo paso a realizar dentro de la fase de diseño lógico, después de la eliminación de
valores nulos no aplicables (particionamiento horizontal), y se corresponde con la etapa de
estructuración.

La normalización se puede definir como el proceso de sustituir una relación o tabla, por un conjunto
de esquemas equivalentes que representen la misma información, pero que no presenten cierto tipo de
anomalías a la hora de realizar operaciones sobre ella. Las anomalías que puede presentar una relación
son de tres tipos:

• Anomalías de inserción: son producidas por la pérdida de información, al no poder insertar


filas en una relación, ya que no se conoce el valor de algún atributo no principal (que no es
clave). Por ejemplo, supóngase que se dispone de la siguiente relación, correspondiente a los
repartos realizados por distintos proveedores.

Cod_proveedor Cod_material Ciudad Categoría Cantidad

1 A234 Madrid 2 122

1 B298 Madrid 2 100

45
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

2 G344 Sevilla 3 200

2 G392 Sevilla 3 310

3 F893 Valencia 1 400

Tabla 9

Si en este momento se desea añadir un nuevo proveedor, no se puede reflejar en la relación, ya que
dicho proveedor todavía no ha realizado ningún reparto.
• Anomalías de borrado: vienen determinadas por la perdida de información que no se desea, al
eliminar una fila de una relación. Por ejemplo, supóngase el caso anterior. Si se desea borrar el
reparto realizado por el proveedor 3, al existir únicamente una fila con dicho proveedor,
perderemos toda la información relacionada con él, es decir, su ciudad y su categoría.

• Anomalías de modificación o actualización: vienen impuestas por la necesidad de propagar


actualizaciones, es decir, se debe modificar el mismo atributo en más de un sitio. Son debidas
a un diseño redundante. Sigamos con el ejemplo anterior. Si se desea modificar la ciudad de
un proveedor, no bastará con hacerlo en un sitio, sino que se deberán recorrer todas las filas
correspondientes a todos los repartos de dicho proveedor, y modificar el valor de atributo
ciudad en todas ellas. Evidentemente esto es muy peligroso, ya que si nos olvidamos de
actualizar dicho valor en una fila, la base de datos quedará inconsistente, es decir, existirán
dos valores distintos de ciudad para un mismo proveedor, y eso sin contar el tiempo que se
pierde en realizar dicha actualización. Por estos motivos, se pueden establecer dos
conclusiones: el diseño es redundante y el esquema no está normalizado.

Por lo tanto, lo que se busca con el proceso de normalización es eliminar estos tres tipos de anomalías.
Consiste en conseguir, mediante varios pasos, distintas formas normales. Se dice que un esquema de
relación esta en una determinada forma normal si satisface un determinado conjunto de restricciones.
Dichas formas normales son la primera forma normal (1FN), la segunda forma normal (2FN) y la
tercera (3FN), definidas por Codd, la forma normal de Boyce-Codd (FNBC), definida por Boyce y
Codd, y la cuarta y quinta forma normal (4FN y 5FN), definidas por Fagin. La principal característica
que cumple cada una de estas formas normales es que la de nivel superior incluye a la de nivel
inferior, es decir, una relación que esté en 2FN estará en 1FN, una que este en 3FN estará en 1FN y
2FN, como muestra la Figura 34.

Figura 34

Una esquema relacional estará normalizado cuando esté, al menos, en 3FN.

46
© Grupo EIDOS 4. Diseño lógico

Para comprender mejor el proceso de normalización y la obtención de las formas normales, veamos el
concepto de dependencia funcional. Sea el esquema de relación R definido sobre el conjunto de
atributos A y sean X e Y subconjuntos de A llamados descriptores. Se dice que Y depende
funcionalmente de X, o que X determina o implica a Y si, y sólo si, cada valor de X tiene asociado en
todo momento un único valor de Y, y se representa X ---> Y.

Por ejemplo, si se tiene la relación Empleado, compuesta por los atributos DNI, nombre, salario, etc.,
se puede asegurar que DNI ---> Nombre , ya que por cada DNI tenemos un nombre, es decir, para un
mismo DNI no pueden existir más de un nombre.

De la misma forma, se puede concluir que entre Salario y Nombre no existe dependencia funcional, ya
que para un mismo salario pueden existir varios nombres de empleados, (varios empleados pueden
cobrar lo mismo).

La dependencia funcional plena o completa es un caso particular de dependencia funcional. Sea X un


descriptor compuesto por X1 y X2 (X1 y X2 atributos de X), se dice que Y tiene dependencia
funcional plena o completa de X si depende funcionalmente de X pero no depende de ningún
subconjunto del mismo, veamos la Tabla 10.

X -------> Y (Y depende funcionalmente de X)

X1 --/--> Y (Y no depende funcionalmente de X1)

X2 --/--> Y (Y no depende funcionalmente de X2)

Tabla 10

Por ejemplo, si se tiene la relación Libro con los atributos ISBN, Cod_socio y Fecha_préstamo, se
tiene:

ISBN, Cod_socio ------------> Fecha_préstamo (1)

ISBN ----/------> Fecha_préstamo (2)

Cod_socio -----/---------> Fecha_préstamo (3)

Tabla 11

ya que para un libro y un socio sólo existe una fecha de préstamo (1), mientras que el mismo libro se
puede prestar varios días (2) y un mismo socio puede tomar prestado uno o varios libros más de un día
(3). Por estos motivos, se puede concluir que Fecha_préstamo tiene dependencia funcional completa
de ISBN y socio.

Otro caso particular de dependencia funcional es el de dependencia funcional transitiva. Sea la


relación R compuesta por los atributos X, Y, Z, en la que se tiene:

X --------> Y
Y --------> Z
Y ----/---> X

47
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

se dice, entonces, que Z tiene una dependencia transitiva respecto de X a través de Y, y se representa

X ---- ----> Z.

Por ejemplo, si se tiene la relación Empleado, con los atributos Nombre, Dirección y Cod_postal, se
tiene:

Nombre ----------> Dirección (1)


Dirección --------> Cod_postal (2)
Dirección ---/----> Nombre (3)

cada empleado sólo tiene una dirección (1), y cada dirección sólo tiene un código postal (2), mientras
que varios empleados pueden vivir en una misma dirección (3). Por lo tanto Nombre --- --->
Cod_postal.

Veamos a continuación las distintas formas normales.

Primera forma normal (1FN): Una relación está en 1FN si cada atributo de dicha relación, tiene un
sólo valor en cada fila. La siguiente relación, por ejemplo, no está en 1FN, ya que la primera fila tiene
dos valores para el atributo asignatura.

Cod_alumno Nombre Asignatura

10 L. Fernández Matemáticas

Lenguaje

20 P. Alonso Ciencias

Tabla 12

La forma de transformar esta relación a otra que sea 1FN sin pérdida de información, es crear una fila
por cada valor del atributo repetido, de la forma que indica la Tabla 13.

Cod_alumno Nombre Asignatura

10 L. Fernández Matemáticas

10 L. Fernández Lenguaje

20 P. Alonso Ciencias

Tabla 13

Segunda forma normal (2FN): Una relación está en 2FN cuando, además de estar en 1FN, todos los
atributos que no forman parte de ninguna clave candidata suministran información acerca de la clave
completa, no de una parte de la clave. O lo que es lo mismo, cada atributo no principal (que no forma
parte de la clave) tiene dependencia funcional completa respecto de cada una de las claves. Por
ejemplo, si se tiene la relación Libro con los atributos ISBN, Cod_socio y Editorial, de los cuales los
atributos clave son ISBN y Cod_socio, y se tiene la dependencia funcional que sigue:

48
© Grupo EIDOS 4. Diseño lógico

ISBN ---------------> Editorial (1)

dicha relación no esta en 2FN, ya que el atributo no principal editorial, depende funcionalmente de una
parte de la clave, no de toda ella. Para transformarla a otro esquema equivalente, que esté en 2FN, se
descompone dicha relación en otras dos:

R1 = {ISBN, Cod_socio}
R2 = {ISBN, Editorial}

Este es un esquema equivalente al anterior, es decir, representa la misma información, pero


cumpliendo la segunda forma normal, ya que ahora la dependencia (1) es completa. Nótese que la
relación original se ha descompuesto en otras dos, para satisfacer este requisito.

Tercera forma normal (3FN): Una relación esta en 3FN cuando, además de estar en 2FN, no existe
ningún atributo no principal que dependa transitivamente de alguna de las claves de la relación. Por
ejemplo, si tenemos la relación Empleado, con los atributos Nombre, Dirección y Cod_postal, cuya
clave es el atributo nombre, con las siguientes dependencias funcionales:

Nombre ----------> Dirección (1)


Dirección --------> Cod_postal (2)

dicha relación no se encuentra en 3FN, al tener que el atributo no principal cod_postal depende
transitivamente de la clave nombre. Para transformarla a 3FN, se descompone dicha relación en otras
dos equivalentes, que cumplan la tercera forma normal:

R1 = {Nombre, Dirección}
R2 = {Dirección, Cod_postal}

Ahora las nuevas dependencias que tenemos son (1) en R1 y (2) en R2, por lo que se ha eliminado la
transitividad, es decir, dicho esquema se encuentra en 3FN.

Las formas normales que se verán ahora no son muy utilizadas, ya que supone que el esquema este
muy fuertemente normalizado, cosa que puede no interesar en la mayoría de los casos, así que
simplemente se mencionarán.

Se dice que una relación esta en forma normal de Boyce-Codd cuando se tiene que para toda
dependencia funcional se tiene que el implicante (la parte derecha de la dependencia) es clave. La
cuarta y quinta forma normal dependen de un tipo especial de dependencias, denominadas
multivaluadas y de unión respectivamente.

Ejemplos prácticos de normalización


Para comprender mejor el proceso más importante en la fase de diseño lógico de una base de datos,
veremos algún ejemplo sobre cómo normalizar un esquema lógico dado. Por ejemplo, supongamos
que tenemos la instancia que aparece en la Tabla 14 de un esquema lógico, ya visto anteriormente,
referente a los repartos realizados por varios proveedores en una empresa.

Cod_proveedor Cod_material Ciudad Categoría Cantidad

1 A234 Madrid 2 122

1 B298 Madrid 2 100

49
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

2 A234 Sevilla 3 200

2 G392 Sevilla 3 310

3 F893 Valencia 1 400

Tabla 14

Lo primero que cabe preguntarse es ¿está normalizado?. La respuesta es no, ya que se producen
anomalías:

• Inserción: no podemos almacenar un proveedor, hasta que no haya realizado algún reparto.

• Borrado: si borramos el reparto del proveedor 3, perdemos la información referente a dicho


proveedor.

• Actualización: si actualizamos la ciudad del proveedor 1, debemos propagar esta modificación


a dos filas, con la posibilidad de la consiguiente inconsistencia del esquema.

En la Tabla 15 iremos modificando el anterior esquema, hasta lograr que este normalizado, con el
objeto de eliminar las anteriores anomalías. Lo primero es identificar las dependencias del esquema:

Para cada valor del atributo cod_proveedor, tenemos un único valor


del atributo ciudad, como podemos comprobar en las dos primeras
filas, en las que el valor 1 para el código del proveedor implica la
cod_proveedor ciudad ciudad Madrid, o para las dos siguientes en que el valor 2 para el
atributo cod_proveedor implica la ciudad Sevilla. Es decir,
conociendo el valor del código del proveedor, estamos en
disposición de asegurar la ciudad del mismo.

El atributo ciudad implica el atributo categoría. Para cada valor del


ciudad categoría atributo ciudad, tenemos un valor distinto del atributo categoría.
Conociendo la ciudad, conocemos la categoría

Para cada valor distinto del conjunto de atributos cod_proveedor y


cod_proveedor, cod_material cod_material, tenemos un valor distinto para el atributo cantidad.
cantidad Conociendo el código del proveedor y del material, podemos saber
la cantidad abastecida.

Tabla 15

Lo siguiente es encontrar una clave para la tabla, es decir, un atributo o conjunto de atributos que
identifiquen unívocamente cada tupla de la relación. En nuestro caso, estaría formada por los atributos
cod_proveedor y cod_material, ya que la combinación de estos valores no se repiten para más de una
fila en la tabla.

• 1FN: el esquema está en 1FN, ya que en cada fila tenemos un único valor para cada atributo.
Un esquema lógico, normalmente, está por defecto en 1FN, al menos.

• 2FN: el esquema no está en 2FN, ya que, aunque está en 1FN, nos encontramos con la
siguiente dependencia:

50
© Grupo EIDOS 4. Diseño lógico

cod_proveedor --------> ciudad

Puesto que la clave de la relación esta formada por los atributos cod_proveedor y
cod_material, tenemos que hay un atributo no principal (ciudad), que depende funcionalmente
de una parte de la clave (cod_proveedor), no de toda ella. Por lo tanto, deberemos
descomponer dicha relación en otras dos, de tal forma que el atributo ciudad dependa de toda
la clave.

Una posible forma, puede ser llevar el atributo ciudad junto con la parte de clave de la que
depende (cod_proveedor) a otra relación, junto con las dependencias funcionales que le
afectan. Otra forma de proceder es dejar en una relación aquellos atributos que forman parte
de la dependencia, y llevar los demás a otra relación. Por lo tanto, nos quedan las relaciones
que muestra la Tabla 16.

Atributos Dependencias Clave

cod_proveedor,
Cod_proveedor,cod_material
Relación 1 cod_maerial cod_proveedor,cod_material
cantidad
cantidad

Cod_proveedor
cod_proveedor ciudad
Relación 2 ciudad cod_proveedor
ciudad categoría
categoría

Tabla 16

De esta manera, ahora la dependencia anterior ya es completa con respecto la clave, ya que en
la segunda relación la clave es ahora cod_proveedor, por lo que el atributo ciudad depende de
toda la clave.

• 3FN: Hasta aquí el esquema está en 1FN y 2FN, pero no en 3FN, ya que el atributo categoría
en la relación 2 depende transitivamente de la clave de dicha relación, que es cod_proveedor,
es decir,

cod_proveedor ciudad
ciudad categoría

Como cod_proveedor no depende funcionalmente de ciudad, ya que en una ciudad puede


haber varios proveedores, esto es, para cada valor de ciudad, puede haber distintos valores de
cod_proveedor:

ciudad --/ cod_proveedor

tenemos que categoría depende transitivamente de la clave cod_proveedor:

cod_proveedor categoría

Por lo tanto deberemos descomponer la relación 2 en otras dos, de manera tal que se evite la
dependencia funcional transitiva entre ambos atributos.

Esto se puede conseguir llevándonos cada dependencia a una relación distinta.

51
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Atributos Dependencias Clave


cod_proveedor
cod_proveedor,cod_material
Relación 1 cod_material cod_proveedor
cantidad
cantidad
Cod_proveedor
Relación 2 cod_proveedor ciudad cod_material
ciudad
ciudad
Relación 3 Ciudad categoría Ciudad
categoría

Tabla 17

De esta manera se ha eliminado la dependencia transitiva, ya que al existir una sola


dependencia, es imposible que esta dependa de otra.

Por lo tanto hemos conseguido obtener un esquema normalizado en 3FN, mediante la descomposición
de una relación inicial en otras tres. De este modo hemos conseguido eliminar las dependencias que se
nos planteaban en la relación original:

• Inserción: si queremos insertar un nuevo proveedor, no hace falta que haga ningún reparto, ya
que bastará con insertarlo en la relación 2.

• Borrado: si borramos un reparto, no perdemos la información referente al proveedor, ya que


ésta se almacena en la relación 2

• Actualización: si cambiamos la categoría de una ciudad, no hace falta cambiarla en todas las
filas, sino sólo una vez en la relación 3.

Veamos ahora otro ejemplo de normalización. Supongamos esta vez que tenemos el esquema lógico
de la Tabla 18, que representa los cursos impartidos por un profesor, junto con su fecha, y domicilio
de éste.

Cod_post
Profesor Fecha Curso Precio Domicilio
al

Juan 01/02/99 Windows 95 10.000 C/ Alcala, 389 28027

Pedro 03/02/99 Visual Basic 20.000 C/Caimán, 28 28190

Juan 03/02/99 Windows 95 10.000 C/Alcala, 389 28027

Luis 01/02/99 Delphi 25.000 C/Remanso,34 28007

Pedro 03/03/99 Windows 98 15.000 C/Caimán, 28 28190

Tabla 18

Este esquema no está normalizado, ya que se producen las siguientes anomalías:

• Inserción: No podemos insertar los datos de un profesor hasta que éste no haya impartido un
curso.

52
© Grupo EIDOS 4. Diseño lógico

• Borrado: Si borramos la impartición del curso de Delphi, perdemos los datos de dicho curso, y
del profesor que lo imparte.

• Actualización: Si modificamos la dirección del profesor Juan, debemos hacerlo en dos filas y
si modificamos el precio de un curso o el código postal de un domicilio, también.

Procedemos de igual forma que en el ejemplo anterior. Lo primero es identificar la clave, que en
nuestro caso está compuesta por los atributos profesor, fecha y curso, ya que el conjunto de estos tres
atributos, identifica de manera unívoca cada fila de la relación. El siguiente paso es identificar las
dependencias funcionales.

Para cada valor diferente del atributo curso, podemos existe un valor
Curso precio diferente para el atributo precio, es decir, el atributo curso identifica el
atributo precio.

Cada profesor vive en su domicilio. El atributo profesor identifica


Profesor domicilio
unívocamente el atributo domicilio.

El atributo domicilio identifica el atributo cod_postal, cada domicilio


Domicilio cod_postal
tiene un código postal.

Tabla 19

Ahora debemos comprobar si dicha relación cumple las reglas de cada una de las formas normales:

• 1FN: Puesto que para cada fila existe un solo valor para cada atributo, la relación se encuentra
en 1FN.

• 2FN: Dicha relación no se encuentra en 2FN, ya que tenemos la siguiente dependencia:

curso -----> precio

es decir, el atributo precio no tiene dependencia funcional completa con respecto a la clave,
sino sólo a una parte. Por lo tanto, desglosamos esta relación en otras dos, dejando en una
dicha dependencia junto con sus atributos, y en la otra las demás.

Atributos Dependencias Clave


Profesor
Fecha
Profesor domicilio Profesor, fecha,
Relación 1 Curso
domicilio cod_postal curso
Domicilio
Cod_postal
Curso
Relación 2 Curso precio curso
Precio

Tabla 20

Ya hemos eliminado la dependencia no completa de la clave para la anterior dependencia


funcional. Pero todavía tenemos un atributo que depende de parte de la clave en la
relación 1:

53
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

profesor domicilio

Por lo tanto, desglosamos la relación 1 en otras dos, una que contenga los atributos
referentes a dicha dependencia y otra con los demás.

Atributos Dependencias Clave

Profesor
profesor domicilio
Relación 1 Domicilio profesor
domicilio cod_postal
Cod_postal

Curso
Relación 2 curso precio curso
Precio

Profesor
Profesor, fecha
Relación 3 Fecha
curso
Curso

Tabla 21

Esta relación ya se encuentra en 2FN, ya que, además de estar en 1FN, no tiene dependencias
no completas de ningún atributo no principal con respecto de la clave.

• 3FN: El anterior esquema no se encuentra en 3FN, ya que la relación 1 tiene una dependencia
transitiva con respecto de la clave:

profesor domicilio
domicilio cod_postal

Como domicilio no depende de profesor, ya que en un mismo domicilio pueden vivir varios
profesores, tenemos una dependencia transitiva del atributo cod_postal con respecto de la
clave:

profesor cod_postal

Por lo tanto, para romper esta dependencia, podemos llevar cada una de ellas a una nueva
relación, con lo que nos queda lo que indica la Tabla 22.

Ahora podemos asegurar que el esquema se encuentra normalizado hasta la tercera forma
normal.

Atributos Dependencias Clave

Profesor
Relación 1 profesor domicilio profesor
Domicilio

Curso
Relación 2 curso precio curso
Precio

54
© Grupo EIDOS 4. Diseño lógico

Profesor
Profesor,
Relación 3 Fecha
fecha curso
Curso

Domicilio
Relación 4 Domicilio cod_postal domicilio
Cod_postal

Tabla 22

Lo que hemos conseguido es sustituir un esquema en el que sólo existía una relación, en otro con
cuatro, que mantiene la misma información, pero que no presenta las anomalías que se daban en el
original:

• Inserción: si queremos dar de alta un nuevo curso lo haremos en la relación 2 y si queremos


insertar un nuevo profesor, lo haremos en la relación 1.

• Borrado: si borramos la impartición de un curso, no perdemos la información de dicho curso,


o del profesor que lo imparte.

• Actualización: si cambiamos el precio de un curso, o el domicilio de un profesor, sólo se hará


una vez, en la relación correspondiente.

Un último detalle a tener en cuenta es el de la descomposición sin perdida de dependencias, esto es,
que no se queden dependencias en el camino, para que el esquema original y el normalizado tengan la
misma información.

Proceso de desnormalización
El proceso de desnormalización hace referencia justo al proceso inverso de normalización que se
acaba de ver. En estos momentos, el lector puede preguntarse que para qué se procede a normalizar un
esquema, cuando posteriormente se va a desnormalizar, es decir, a dejarlo como estaba. La respuesta
es simple; primero se procede a estructurar el esquema, y una parte de esta estructuración es la
normalización de relaciones. Posteriormente, y debido a aspectos de eficiencia, se puede proceder a
realizar una reestructuración del esquema, parte de la cual supone la desnormalización del mismo.
Esto supone que puede que el esquema resultante de la normalización sea lo suficientemente eficiente
como para que no sea preciso reestructurarlo, o que simplemente no nos interese que el esquema sea
eficiente. Además, puede que normalicemos hasta un cierto nivel, y que solo interese desnormalizar
hasta otro determinado nivel. En definitiva, el proceso de desnormalización supone la unión de varias
relaciones en un número menor de ellas, es decir, a medida que disminuya el nivel de normalización,
es frecuente que el número de relaciones disminuya.

Destacar, por último, que interesa tener un nivel fuerte de normalización cuando el número de
actualizaciones sea alto con relación al de consultas, ya que se evitarán las anomalías expuestas. Sin
embargo, si el número de consultas es alto con relación al de actualizaciones, interesará que el nivel de
normalización sea bajo, ya que el diseño será redundante, lo cual implica que se tardará menos en
buscar la información. Como norma general, se procurará que el esquema esté siempre normalizado al
nivel de 3FN.

Por ejemplo, supóngase el ejemplo de los cursos visto en el apartado anterior. Si tenemos que no se
van a realizar prácticamente actualizaciones, si no que se van a realizar consultas sobre los atributos
profesor, domicilio y cod_postal, nos encontramos que para realizarla necesitamos acceder a dos

55
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

tablas (relación 1 y relación 4), es decir, se deberá realizar un join, con el aumento de tiempo de
proceso que ello supone. Por lo tanto, puede interesar en este caso desnormalizar dicho esquema un
nivel, hasta 2FN, donde para acceder a dicha información, simplemente se precisa consultar la relación
1.

Atributos Dependencias Clave

Profesor
profesor domicilio
Relación 1 Domicilio profesor
domicilio cod_postal
Cod_postal

Curso
Relación 2 curso precio curso
Precio

Profesor
Profesor, fecha
Relación 3 Fecha
curso
Curso

Tabla 23

56
Diseño físico

Introducción
El diseño físico busca conseguir una instrumentación lo más eficiente posible del esquema lógico,
considerando los aspectos más cercanos al hardware, es decir, los requisitos de procesos,
características del SGBD, del Sistema Operativo y del hardware, pretendiendo los siguientes objetivos:

• Disminuir los tiempos de respuesta

• Minimizar espacio de almacenamiento

• Evitar las reorganizaciones

• Proporcionar la máxima seguridad

• Optimizar el consumo de recursos

Como ya se ha comentado, debido a la falta de flexibilidad de los actuales SGBD, es preciso llevar a
cabo a cabo en muchas ocasiones un proceso de reestructuración de relaciones para conseguir una
mayor eficiencia, lo que significa que se debe iterar desde el diseño lógico específico al físico y
viceversa, hasta obtener un esquema aceptable, que optimice el ratio coste / beneficios.

El diseño físico es fuertemente dependiente del producto comercial que se vaya a usar, debido a la
carencia de un modelo formal, equivalente al relacional que permita una definición formal de esa fase
de diseño. Sin embargo, existen características que son comunes a la mayoría de los productos, y que
pueden ser utilizadas para definir un esquema físico.
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Se podría considerar el diseño físico como una caja negra, en la que se toman como entradas los
recursos de la máquina, los recursos lógicos (SO, etc.), el esquema lógico obtenido en la fase anterior,
información sobre las aplicaciones que se ejecutarán en la máquina así como los objetivos que se
plantean en esta fase, y se obtienen como salidas una estructura interna, que representa la
implementación del esquema lógico en un hardware específico, junto con unas normas de seguridad y
unas especificaciones para el ajuste, es decir, la forma de iterar entre la etapa de diseño lógico
específico y la fase de diseño físico.

Estrategias en el diseño físico


Existen tres tipos de estrategias que los fabricantes de SGBD imponen en sus productos comerciales:

1. Inflexibilidad. El SGBD impone una estructura interna, impidiendo y dejando al administrador


pocas opciones de cambiarlo. La principal ventaja de esta estrategia es la independencia físico
/ lógica del esquema, aunque por contra, el esquema interno resultará más ineficiente.

2. Flexibilidad. Es el contrapunto al anterior caso. Implica que el administrador de la base de


datos pueda diseñar la estructura interna, lo cual supone un aumento de la eficiencia, aunque
también de la dependencia físico / lógica.

3. Híbrido entre ambos. El SGBD proporciona una estructura interna opcional que el diseñador
puede cambiar con el fin de mejorar la eficiencia. Entre las ventajas que supone utilizar esta
técnica estriba la de que la BD puede empezar a funcionar de inmediato al disponer del
esquema interno opcional, con la posibilidad de ir mejorando sucesivamente la eficiencia al ir
realizando ajustes, a la par que se mantiene la independencia. Destacar que esta es la estrategia
más utilizada en los actuales SGBD.

Conceptos básicos sobre gestión de ficheros


La unidad básica de las estructuras físicas (ficheros) es el registro físico, también denominado página
o bloque, que es la unidad mínima que puede tratarse en una operación de Entrada / salida. Las tuplas
(en el caso del modelo relacional) se almacenan en dichos registros, pudiendo almacenar cada uno de
éstos varias de aquellas. De aquí podemos definir el factor de bloqueo para un fichero como el número
de registros lógicos (o tuplas) por bloque para dicho fichero. Del mismo modo, si los datos son muy
grandes, un registro lógico puede estar almacenado en varios registros físicos. El tamaño de los
bloques depende del producto comercial y del sistema operativo, oscilando éste entre 2 y 4 Kbytes.

Los bloques, que se encuentran almacenados en los sectores del disco, deben ser accedidos por el
SGBD utilizando los mecanismos de gestión de ficheros que provee el sistema operativo. El tiempo en
acceder a un sector del disco, que es bastante elevado, está compuesto por varios factores:

• Tiempo de arranque: tiempo que tarda el disco en empezar a mover las cabezas.

• Tiempo de seek: tiempo necesario para mover las cabezas al cilindro (conjunto de pistas del
mismo diámetro) requerido.

• Tiempo de latencia: tiempo que debe esperar hasta que el sector para por debajo de las
cabezas.

• Tiempo de transferencia: tiempo necesario para transferir la información, por el bus de datos,
a memoria principal.

58
© Grupo EIDOS 5. Diseño físico

Para acelerar este proceso, se suele usar un dispositivo de almacenamiento intermedio, denominado
caché o buffer, cuyo cometido es el de almacenar los datos más usados, aprovechando de este modo
la ley de proximidad temporal, es decir, los datos que han sido usados más recientemente, tienen una
alta probabilidad de que sean usados en un futuro cercano, evitando de este modo accesos extra a
disco. Este dispositivo es gestionado por el sistema operativo, utilizando diversas políticas, entre la
que la más usada es la LRU (Least Recently Used), es decir, los bloques que se han usado hace más
tiempo, son candidatos a desalojar la caché para albergar otros bloques. Otra política es aprovechar la
ley de proximidad referencial, es decir, los datos próximos tienen mayor probabilidad de ser
referenciados.

Algunos SGBD permiten especificar las características de los registros físicos. Se pueden agrupar
determinado número de bloques contiguos en unidades llamadas extensiones. Los parámetros que se
pueden especificar son:

• El porcentaje de espacio libre que se deja en cada bloque para albergar posteriores
actualizaciones de los registros lógicos. Al modificar un valor de un atributo, puede que éste
no quepa en el espacio reservado. De esta forma se evita la concatenación de bloques, que
incide en un menor tiempo de respuesta.

• Número de bloques que se asignan a las extensiones.

• Porcentaje de utilización de cada bloque.

Organización de ficheros
Existen varias formas de organizar los ficheros, de forma que el acceso a los mismos se realice de una
y otra forma:

• Secuencial: El método de acceso es secuencial, es decir, un registro detrás de otro. Es


conveniente usar esta forma de organización cuando existe una carga masiva de datos, las
tablas son pequeñas o cuando se accede a casi todas las filas, es decir, un índice (ya se verá
más adelante lo que es) estorbaría, ya que de todas maneras se necesita acceder a todas las
filas.

• Hash: Es una forma de organizar los ficheros teniendo como base una tabla indexada que
apunta a la información. Es útil cuando las filas se recuperan por el valor de la clave, que en
este caso actúa como función para determinar la posición donde se encuentra la información.

• ISAM: Es una opción más amplia que la anterior, ya que soporta búsquedas por valores de
clave, además de por parte de ella o usando patrones de búsqueda.

• Árbol B+: Es una estructura que soporta búsquedas dicotómicas (el número de búsquedas es
menor que log2 n). La ventaja con respecto al caso anterior es que crece de forma dinámica.

Técnicas para el aumento de eficiencia


Existen varias técnicas para aumentar la eficiencia del esquema:

• Índices: Se puede definir un índice como una estructura que sirve para mejorar la eficiencia de
las consultas a una base de datos. Un índice se define sobre uno o varios atributos. A la hora
de acceder a dichos atributos, el tiempo de acceso será instantáneo. Un índice se puede

59
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

comparar con el índice de un libro; si disponemos de dicho índice, podemos acceder a la


página del libro de forma inmediata, mientras que si no lo tenemos, deberemos ir mirando
hoja por hoja hasta encontrar la página deseada. Por ejemplo, supóngase que tenemos la
relación que muestra la Tabla 24.

Cod_jugador Nombre Apellido Equipo

10 Adrián Illie Valencia

20 Fernando Redondo R. Madrid

25 José Guardiola Barcelona

30 Claudio López Valencia

49 Fernando Hierro R. Madrid

80 Rafael Alkorta At. Bilbao

90 Rafael M. Vázquez Deportivo

Tabla 24

Si en este momento se desea hacer una consulta sobre todos los jugadores que se llamen
Fernando, se deberá acceder a todas las filas, encontrándose dos jugadores que cumplen este
requisito, es decir, se han realizado siete accesos. Sin embargo, si se dispone de un índice por
el atributo Nombre, los accesos serían inmediatos a las dos únicas filas que cumplen este
requisito, reduciéndose en este caso el número de accesos a dos. Si ahora se desea buscar
todas las filas con el nombre de Rafael, y que pertenezcan al Deportivo, se realizarían siete
accesos (toda la tabla). Si tuviésemos un índice por el atributo Nombre, se encontraría una
única fila, pero se debería acceder a dos, es decir, las filas cuyo nombre es Rafael. Sin
embargo si tuviésemos un índice combinado para los atributos Nombre y Equipo, solo se
realizaría un acceso, la de nombre Rafael y equipo Deportivo.

Ya se ha visto entonces la ventaja de usar este tipo de estructuras para acceder rápidamente a
la información. Sin embargo no todo son ventajas, ya que cuanto mayor sea esta estructura,
mayor espacio de almacenamiento será necesario, sin contar el tiempo que se pierde en
actualizar el índice cuando se modifica algún valor de los atributos que forman parte de él. Por
este motivo, se suele indexar la clave primaria (mediante un índice único, es decir, que no
permita valores repetidos), o aquellos atributos que no vayan a ser modificados. La siguiente
lista resume una serie de consejos a la hora de indexar campos:

• Indexar la clave primaria con un índice único

• Indexar las claves ajenas, es decir los atributos de una tabla que son clave que otras tablas

• Indexar aquellos atributos que se van a consultar con más frecuencia, y que no van a ser
alterados

• No indexar tablas pequeñas

• No indexar tablas que se van a recorrer secuencialmente

60
© Grupo EIDOS 5. Diseño físico

• No indexar atributos de tipo carácter muy largos

• Agrupamiento o "clustering": Se entiende por "clustering" de tablas la agrupación de tablas


cuyas filas comparten un grupo de atributos llamado clave de agrupamiento. Esta técnica
supone una desnormalización física de las tablas, que se encuentran físicamente agrupadas,
pero que lógicamente siguen siendo dos tablas independientes, por lo que el agrupamiento será
transparente al usuario. La Figura 35 muestra un agrupamiento de dos relaciones Empleado y
Departamento.

Figura 35

Con este método se consigue mejorar la eficiencia en la consulta simultanea de ambas tablas, pero
empeora cuando se recorren de forma separada.
• Compresión de datos: Por un lado, la compresión de datos permite reducir el espacio
requerido para almacenar la información, lo que radica en un menor número de operaciones de
Entrada / salida. Sin embargo, se requiere un mayor tiempo de proceso debido a la necesidad
de descomprimir los datos que se recuperan.

La técnica de compresión más utilizada es la de compresión diferencial, que consiste en


almacenar la diferencia entre el valor de un atributo y el que le precede.

• Redundancia de datos: La redundancia de datos consiste en duplicar el valor de ciertos


atributos de una tabla en otra, con el fin de evitar accesos a tablas consultadas frecuentemente.
Sin embargo, esta redundancia debe ser controlada, es decir, se debe garantizar la consistencia
de la base de datos. La forma más segura de controlarlo es mediante disparadores o triggers,
que cambien el valor de todos los atributos duplicados, cuando cambia uno de éstos.

61
Introducción a SQL Server

¿Qué es SQL Server?


SQL Server es un Sistema de Gestión de Bases de Datos Relacionales (SGBDR), desarrollado por
Microsoft, que permite, como su propio nombre indica, la gestión de un entorno de bases de datos
relacional. SQL Server abarca, tanto el área de diseño, como la de administración, proporcionando un
interfaz bastante amigable con el usuario.

¿Por qué se llama SQL Server?. Pues bien, se llama SQL porque utiliza este lenguaje para la
definición y manejo de los datos, y se llama Server porque dispone de una parte servidora que se
encarga de atender a los procesos clientes, que son los que realizan las peticiones a éste; es decir, sigue
una arquitectura cliente/servidor.

SQL Server utiliza una extensión al SQL estándar, que se denomina Transact SQL. Esto quiere decir
que soporta el SQL de ANSI, pero además se le han añadido ciertas funciones adicionales, no
contempladas en el estándar, y que son específicas para este producto, es decir, si ejecutamos una
sentencia del conjunto adicional (Transact SQL) en otro SGBRD, éste no la entendería.

El Transact SQL, soporta la definición, modificación y eliminación de bases de datos, tablas, atributos,
índices, etc., es decir, el lenguaje de definición de datos (DDL), así como la consulta, actualización y
borrado de tuplas de tablas, es decir, el lenguaje de manipulación de datos (DML).
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Orígenes
Como podemos comprobar, el mercado de la informática ha ido cambiando sorprendentemente desde
hace unos pocos años. Cuando surgió aquella maquina que hoy denominamos PC, nadie podía
imaginar que iba a desbancar de su puesto a las grandes plataformas como el Sistema 36 de IBM o el
VAX de Digital.

Por aquel entonces, principios de los ochenta, empezaban a implantarse las bases de datos
relacionales, sobre todo con ORACLE, pero ni por asomo podían ser utilizadas en los PCs. ORACLE
fue el nombre que se le dio a un proyecto, destinado a investigar el modelo relacional, por aquel
entonces algo utópico. Sin embargo, ante la falta de resultados positivos, se decidió cancelar el
proyecto, y venderlo a Relational Software Inc. (RSI). En 1979, RSI lanzó al mercado la versión 2 de
ORACLE, que fue la primera base de datos relacional en utilizar el lenguaje SQL. Fue un poco más
tarde cuando RSI decidió cambiar su nombre por el de su producto estrella, ORACLE. Sin embargo, la
aparición de dBase, de Ashton-Tate, supuso una revolución en el mundo de las bases de datos para PC,
originando una batalla para ganar posiciones en este mercado.

En el año 1988, ante el boom del PC, Ashton-Tate, IBM, Microsoft y Sybase, deciden aliarse para
sacar un nuevo producto al mercado: una base de datos relacional, para PC. Este hecho supuso el
nacimiento de SQL-Server. A su vez, IBM y Microsoft se comprometieron a desarrollar un nuevo
entorno, dirigido a las bases de datos, capaz de soportar SQL-Server, y le dieron el nombre de OS/2.

A su vez, SQL Server fue avanzando, adaptándose a las nuevas tendencias del mercado. Fue entonces
cuando la aparición de Windows NT reemplazó a OS/2 como soporte para SQL Server. Desde
entonces y hasta hoy, los SGBD relacionales más vendidos resultan ser ORACLE y SQL Server.

SQL Server e Internet


El impacto que, sobre todo durante estos últimos años, ha venido sufriendo el uso de Internet, obliga a
pensar si SQL Server puede ser útil para manejar y/o obtener datos de la red de redes. La verdad es
que las interfaces de acceso a bases de datos, también han ido experimentado un largo y constante
cambio, a la vez que han ido apareciendo otros nuevos, con el fin de adecuarse a las necesidades
cambiantes del mercado.

El interfaz de acceso a bases de datos por excelencia, ha sido siempre ODBC, que significa Open
Database Connection (Conexión abierta a Bases de Datos), y que supone la abstracción por parte del
usuario que quiere acceder a la base de datos, que no tiene por qué saber las características de ésta.
ODBC ofrece una serie de métodos encapsulados, los cuales hacen todo el trabajo de traducción.

La aparición de Internet, supuso el nacimiento de un nuevo interfaz, adecuado al lenguaje Java,


llamado JDBC. Su cometido es el mismo que ODBC, pero en este caso se ofrecen una serie de
funcionalidades especiales para adaptarlo al lenguaje Java.

Sin embargo, otra forma de acceder a una base de datos desde Internet es la ofrecida por un producto
llamado Microsoft Internet Information Server (IIS). La combinación de éste con SQL Server, ofrece
una potente forma de unir SQL e Internet. Mediante esta forma, se pueden mostrar datos en un
navegador de Internet, obtenidos de una base de datos SQL, por ejemplo.

64
Lo nuevo en SQL-Server 2000

Introducción
Como decíamos, SQL-Server ha ido evolucionando a lo largo de los últimos años. La apuesta de
Microsoft por este SGBD ha sido (y es) bastante fuerte, lo cual ha hecho posible la mejora y
adaptación del mismo, sobre todo al entorno remoto y distribuido. La Figura 36 muestra la
arquitectura general de este SGBD.

Veremos en este capítulo las mejoras que ha sufrido esta nueva versión, con respecto a las anteriores,
mejoras que pasamos a detallar a continuación.

Nuevas características
Entre las nuevas características que ofrece SQL-Server 2000, cabe destacar las siguientes:

• Soporte para XML.

• Particionamiento horizontal de relaciones y gestión de vistas distribuidas.

• Soporte para Virtual Interface Architecture (VIA).

• Funciones de usuario.

• Indexación de vistas.
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

• Nuevos tipos de datos.

• Nuevos triggers.

• Reglas de integridad referencial en cascada.

• Nuevas características de indexación.

• Soporte para consultas distribuidas.

• Características de seguridad y cifrado de datos.

Figura 36

Soporte para XML


El Extensible Markup Language, más conocido como XML es un metalenguaje, es decir, un lenguaje
utilizado para definir lenguajes, y que se usa sobre todo para el intercambio de datos.

Su sintaxis es similar a la que nos ofrece el HTML, es decir, un conjunto de etiquetas que definen la
estructura de los datos. El Código fuente 2 define un posible formato de intercambio.

<cliente>
<nombre>Pepe</nombre>
<apellidos>Lopez</apellidos>
<telefono>912345678</telefono>
</cliente>

Código fuente 2

66
© Grupo EIDOS 7. Lo nuevo de SQL - Server 2000

SQL-Server 2000 ofrece la posibilidad de devolver un conjunto de resultados utilizando para ello este
tipo de formato, facilitando así el intercambio de datos.

Particionamiento horizontal de relaciones y gestión de


vistas distribuidas
Otra de la características nuevas que nos ofrece SQL-Server 2000 es la posibilidad de particionar
horizontalmente los datos de una relación. Ya se ha comentado lo útil que es este tipo de
reestructuración de relaciones, sobre todo en el ambiente distribuido, en el cual se pueden colocar las
tuplas en los servidores que se supongan más posibilidades tengan de consultarlas en forma local.

Del mismo modo, se pueden definir vistas distribuidas que accedan a estos datos, en cada uno de los
servidores que nos interese, de manera que la ejecución de la misma dé la impresión de estar
interactuando sobre un conjunto completo de resultados.

Soporte para Virtual Interface Architecture (VIA)


SQL-Server 2000 introduce nuevas librerías de red, que permiten definir un entorno distribuido de
forma eficiente, posibilitando una gran conectividad, tanto de servidores como de aplicaciones, en este
tipo de entornos.

Funciones de usuario
Una funcionalidad nueva que aparece en esta versión del SGBD es la de permitir al usuario definir sus
propias funciones. De esta forma se pueden definir funciones que oculten parte de la complejidad que
puede entrañar una consulta, no sólo para la posterior reutilización de la misma, sino también teniendo
en cuenta la abstracción para otros programadores que puedan precisar su uso.

Indexación de vistas
Esta funcionalidad permite optimizar la ejecución de vistas que actúan sobre la base de datos, creando
índices sobre los resultados de ejecución de la misma, que son almacenados en la base de datos. El
usuario no debe preocuparse de la actualización de los datos, sino que éstos son indexados
automáticamente cada vez que se actualicen.

Nuevos tipos de datos


SQL-Server 2000 soporta tres nuevos tipos de datos con respecto a la anterior versión, la 7, que son el
bigint o entero de 8 bytes, sql_variant, que soporta el almacenamiento de valores de distintos tipos, y
table, que permite el almacenamiento temporal de resultados para su uso posterior.

67
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Nuevos triggers
Un trigger o desencadenador es un código especial que se ejecuta cuando se cumple una determinada
condición, como por ejemplo al modificar o borrar datos (se verá en detalle en un capítulo posterior).

SQL-Server 2000 soporta dos nuevos tipos de triggers, que son INSTEAD OF y que sustituye el
comportamiento de ciertos comandos, como por ejemplo insert, update o delete, y AFTER, que se
ejecuta una vez concluida la acción que lo ha desencadenado.

Reglas de integridad referencial en cascada


Las reglas de integridad referencial son la base del mantenimiento de la consistencia en la base de
datos, y hacen referencia a información que esta relacionada entre si, como por ejemplo el
departamento de un empleado cuyo código se especifica. La forma más usual de mantenerlo es usando
claves foráneas, y especificando el comportamiento de las inserciones, borrados y actualizaciones de
este tipo de datos.

Nuevas características de indexación


Las nuevas características de indexación permiten crear índices sobre campos calculados (no existen
como tal en la base de datos, sino que se calculan a partir de otros valores), así como especificar si se
desea construir estos índices de manera paralela, lo que aumenta la velocidad de procesado.

Soporte para consultas distribuidas


El optimizador de consultas ofrece la funcionalidad de ubicar datos en servidores distribuidos,
dependiendo de valores tales como el nivel de carga, el tráfico de red, etc., de manera que las consultas
pueden acceder a distintos servidores para obtener el resultado final.

Características de seguridad y cifrado de datos


SQL-Server 2000 utiliza Kerberos como servidor de autenticación, para acreditar el acceso al servidor
que se realiza desde el cliente, así como diversas técnicas de seguridad.

68
Instalación de SQL Server 2000

En este capítulo, veremos como instalar SQL Server 2000, y las distintas opciones que plantea. Para
empezar, introduzca el CD-ROM que contiene el programa. Si no arranca automáticamente, utilice el
explorador para ejecutar el fichero autorun contenido en el CD-ROM. Tenemos dos opciones, la
standard o la personal. La primera de ellas realiza una instalación completa, incluyendo los
componentes servidor, mientras que la segunda es útil en el caso de que no dispongamos de un
servidor. La primera pantalla que aparece es la que se muestra en la Figura 37.

Figura 37
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

En nuestro caso instalaremos la opción standard (si no disponemos de un servidor, únicamente se


instalarán los componentes cliente).

En principio, el único requisito que se necesita es disponer de un equipo con al menos 64 Mb de


memoria RAM (recomendable 128 Mb) y sistema operativo Windows 98/NT/2000, en el cual se haya
instalado la versión 5.5 del navegador WEB Microsoft Internet Explorer.

Para proseguir la instalación, pulsamos la opción SQL Server 2000 Components, apareciéndonos la
pantalla que muestra la Figura 38.

Figura 38

Pulsamos el botón Next, visualizándose la pantalla que se muestra en la Figura 39.

Figura 39

70
© Grupo EIDOS 8. Instalación de SQL - Server 2000

En este caso, puesto que queremos instalar los componentes cliente en nuestro equipo local, sólo nos
permite la selección de esta opción. Si pulsamos el botón Next, visualizaremos la siguiente pantalla
que muestra la Figura 40

Figura 40

Nuevamente, al estar instalando la versión standard en un equipo con Windows 98, sólo se nos
permite seleccionar la opción de crear una nueva instancia de SQL Server. Pulsando el botón Next,
obtendremos la pantalla que se muestra en la Figura 41, donde se nos insta a poner nuestro
nombre y compañía.

Figura 41

71
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Si pulsamos nuevamente el botón Next, podremos visualizar la pantalla que se muestra en la Figura 42,
cuyo cometido es el de mostrarnos las condiciones de uso de la licencia; pulsamos Yes para pasar a la
siguiente pantalla que se indica en la Figura 43.

Figura 42

Figura 43

Seleccionando la opción de instalación de las herramientas cliente y pulsando el botón Next,


accederemos a la pantalla de la Figura 44, en la que podemos seleccionar los componentes y
subcomponentes a instalar.

72
© Grupo EIDOS 8. Instalación de SQL - Server 2000

Figura 44

Dejamos marcados los que vienen por defecto y pulsamos el botón Next, para acceder a la página de la
Figura 45, tras la cual el sistema empezará a instalar los componentes seleccionados y, tras unos
minutos, mostrará la pantalla final en la cual se nos informa de la conclusión del proceso de
instalación, como muestra la Figura 46.

Figura 45

73
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Figura 46

74
El modelo E/R en SQL-SERVER 2000

Introducción
SQL-Server nos ofrece una herramienta para realizar diseños relacionales, pero no a nivel conceptual,
sino a nivel lógico, es decir, tal y como se plasmarían las relaciones en tablas, pudiendo además
especificar cuestiones como la integridad referencial, las restricciones, etc.

Para acceder a esta herramienta, deberemos acceder a la opción del Administrador corporativo o
Enterprise manager.

Una vez dentro, daremos de alta el registro de servidor (si no se encuentra ya hecho), y accederemos a
la opción Diagramas (Diagrams) de la base de datos deseada dentro del grupo Bases de datos
(Databases), como muestra la Figura 47.

En la parte derecha podremos observar como aparecen todos los diagramas disponibles para la base de
datos seleccionada.

Para acceder a uno de ellos, bastará con hacer doble click con el ratón sobre el, mientras que para crear
uno nuevo, seleccionaremos la opción New Database Diagram del menú contextual que aparece al
hacer click con el botón derecho del ratón sobre esta pantalla, como muestra la Figura 48.
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Figura 47

Figura 48

76
© Grupo EIDOS 9. El modelo E/R en Sql-Server 2000

Crear un nuevo diagrama


Vamos a crear ahora un nuevo diagrama, para lo cual actuamos como se acaba de comentar. Nos
aparecerá entonces una ventana, como la de la Figura 49, que no es más que la primera página de un
asistente que nos guiará durante el resto del proceso de creación del diagrama. Pulsamos el botón
Siguiente para avanzar al siguiente paso, que se muestra en la Figura 50.

Figura 49

Figura 50

77
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

En la parte izquierda nos aparecen todas las tablas disponibles, mientras que en la derecha tenemos las
tablas que nosotros seleccionaremos para pasar a formar parte de nuestro diagrama. La forma de
añadir una tabla al diagrama es seleccionándola y pulsando el botón Add, mientras que para eliminarla
del mismo, como el lector ya habrá podido adivinar, habremos de pulsar el botón Remove.

La caja de selección que aparece en la parte inferior bajo el nombre Add related tables automatically
permite añadir todas las tablas relacionadas con las seleccionadas de manera automática, pudiendo
además especificar el número de niveles que se incluirán, es decir, tablas relacionadas de tablas
relacionadas. Esta opción es muy útil para chequear restricciones de una tabla que no sabemos con
cuales se relaciona.

Una vez seleccionadas todas la tablas que deseamos pasen a formar parte del diagrama (en nuestro
caso escogemos las tablas authors, titleauthor y titles), pulsamos el botón Siguiente para avanzar al
próximo paso, que se muestra en la Figura 51.

Figura 51

Este es el último paso, en el que se nos muestran las tablas que hemos seleccionado. Pulsamos el botón
Finalizar, y ya tenemos nuestro diagrama, que tendrá un aspecto similar al mostrado en la Figura 52.

En el podemos observar las tablas que hemos seleccionado, junto con el nombre de sus atributos, las
claves (que aparecen con un icono en forma de llave), y las relaciones entre ellas. Estas relaciones
muestran las dependencias existentes entre ellas.

Vamos a guardar nuestro diagrama, para trabajar posteriormente con el, pulsando el icono en forma de
disco de la barra de herramientas, y dándole un nombre coherente.

78
© Grupo EIDOS 9. El modelo E/R en Sql-Server 2000

Figura 52

Restricciones e integridad referencial


Una de las principales utilidades que nos ofrece esta herramienta es la de establecer las restricciones y
las reglas de integridad referencial de una manera fácil y visual.

Para visualizar este tipo de características, pulsamos con el botón derecho del ratón en la opción
Propiedades (Properties) del menú contextual, dentro de la tabla o relación deseada, apareciéndonos
una pantalla similar a la de la Figura 53.

Dentro de la pestaña Relationship se pueden especificar restricciones y características tales como la


integridad referencial. Para ello debemos indicar el atributo que actúa como clave primaria dentro de
la tabla origen, y el atributo que actúa como clave ajena dentro de la tabla destino y le damos un
nombre a dicha restricción.

Sin embargo, para establecer este tipo de reglas, existe otra manera mucho más cómoda, que es
seleccionar con el ratón el atributo que es clave ajena dentro de una tabla y, sin soltarlo, arrastrarlo
hasta la tabla que contiene la clave primaria con la cual se relaciona.

En la pestaña Indexes/Keys es donde se especifican aspectos referentes a los índices que van a hacer
referencia a los atributos de la tabla, y cuyo aspecto es el mostrado en la Figura 54.

79
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Figura 53

Figura 54

80
© Grupo EIDOS 9. El modelo E/R en Sql-Server 2000

En esta pantalla podemos crear o borrar índices, definidos sobre uno o varios atributos, de tipo
ascendente o descendente (se refiere a la ordenación). El índice primario hará referencia a la clave
primaria de la relación, aunque también podemos especificar otro tipo de índices, como de tipo único,
cluster, etc.

Dentro de la pestaña Check Constraints podemos indicar las restricciones sobre los atributos de la
tabla. Por ejemplo, en la Figura 55 se especifica una restricción sobre el atributo clave de la tabla,
especificando mediante una expresión regular que dicho atributo deberá ser rellenado con 9 dígitos, y
que se aplicará en las replicaciones, inserciones y actualizaciones.

Figura 55

Modificación del esquema


Aparte de definir restricciones, la herramienta de diagramas también nos da la posibilidad de realizar
modificaciones del esquema, esto es, añadir o borrar tablas o atributos del diagrama (existentes o
nuevas), cambiar el tipo o el nombre de los mismos, crear nuevas relaciones, etc.

Para ello, nuevamente habrá que escoger la opción correspondiente haciendo click con el botón
derecho del ratón, como muestra la Figura 56.

81
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Figura 56

Otra de las formas de modificar, por ejemplo, el nombre de un atributo, es pulsando sobre el y
escribiendo directamente el nuevo sobre la tabla, o cambiar el tipo haciendo click derecho en el
atributo y escogiendo la opción de propiedades, y escoger la pestaña Columns.

Crear una nueva relación


Una vez vistos los principales conceptos en la creación de diagramas, vamos ahora a crear una nueva
relación con una tabla existente, para practicar lo aprendido hasta ahora. Lo primero es seleccionar la
opción Add Table del menú contextual y seleccionar la tabla existente en el esquema que deseamos
añadir al diagrama, como muestra la Figura 57.

Una vez que aparezca la tabla seleccionada en el diagrama, vamos a añadir la relación con una
existente. Para ello pulsamos con el ratón el atributo stor_id en la tabla authors y, sin soltarlo, nos
movemos a la tabla stores. Ya tenemos la relación entre ambas tablas, sólo tendremos que confirmarlo
ante la pantalla que nos aparece en la Figura 58. El diagrama resultante es el mostrado en la Figura 59.
Si hacemos click derecho y escogemos la opción propiedades sobre la nueva relación creada, podemos
observar las restricciones y las reglas de integridad aplicables a la misma, mostradas en la Figura 60

Figura 57

82
© Grupo EIDOS 9. El modelo E/R en Sql-Server 2000

Figura 58

Figura 59

83
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Figura 60

84
El analizador de consultas

Introducción
El analizador de consultas (o query analizer) es la herramienta que permite editar y ejecutar sentencias
de T-SQL. Su apariencia es la que muestra la Figura 61.

Podemos observar en ella un editor, que sirve para ejecutar las sentencias, una barra de menú, con las
opciones disponibles, y una barra de herramientas con iconos de acceso rápido a ciertas utilidades.

Las opciones de menú


Entre las opciones que ofrece el menú File, podemos encontrar las siguientes:

• Connect: Abre una nueva conexión a una base de datos.

• Disconnect: Cierra la conexión a la base de datos en uso.

• Disconnect all: Idem que el anterior, pero para todas las conexiones abiertas

• New: Abre una nueva ventana dentro del editor.

• Open: Abre un archivo de SQL existente.

• Save: Guarda a un archivo la ventana del editor en uso.


Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

• Save as: Idem que el anterior, pero con la posibilidad de indicar un nombre de archivo.

• Save all queries: Idem que el anterior, pero para todas las ventanas abiertas en el editor.

• Print: Imprime la ventana en uso del editor.

• Recent file list: Muestra una lista con los archivos más recientemente usados.

• Exit: Cierra el analizador de consultas.

Figura 61

Figura 62

En el menú Edit podemos encontrar las siguientes opciones:

86
© Grupo EIDOS 10. El analizador de consultas

• Undo: Deshace el último cambio realizado en el texto de la ventana en uso del editor.

• Cut: Corta el texto seleccionado al portapapeles.

• Copy: Copia el texto seleccionado al portapapeles.

• Paste: Pega el contenido del portapapeles a la ventana en uso del editor.

• Select all: Selecciona todo el texto de la ventana en uso del editor.

• Clear window: Borra todo el contenido de la ventana en uso del editor.

• Find: Busca un texto determinado dentro de la ventana en uso del editor.

• Repeat last find: Idem que el anterior, pero para buscar varias coincidencias.

• Replace: Reemplaza un texto por otro, dentro de la ventana en uso del editor.

• Go to line: Mueve el cursor a una línea determinada, dentro de la ventana en uso del editor.

• Bookmarks: Permite manejar los bookmarks, o marcas dentro del texto de las sentencias a
ejecutar, para su mejor identificación.

• Insert template: permite añadir una plantilla de una sentencias, muy util para sentencias
repetitivas. Además SQL-Server nos ofrece plantillas predeterminadas, para cada uno de los
casos más representativos (creación de vistas, procedimientos almacenados, etc.), ahorrando al
programador la mayor parte del trabajo.

• Replace template parameters: Permite al usuario cambiar los parámetros dentro de una
plantilla, es dccir, rellenarla con las tablas, campos, etc. que se ajusten a sus necesidades.

• Advanced: Opciones avanzadas de edición.

Figura 63

87
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Dentro del menú Query nos encontramos con las opciones disponibles, relacionadas con la edición y
ejecución de consultas:

• Change Database: Permite cambiar la actual conexión a una base de datos por otra.

• Parse: Compila la consulta del editor, verificando su sintaxis, y mostrando errores si no


cumple con ésta.

• Execute: Ejecuta la consulta del editor.

• Cancel executing query: En el caso de que se esté ejecutando una consulta, permite
detenerla.

• Display estimated execution plan: Muestra el plan previsto, desglosando en pasos cómo se
ejecutará la consulta. La Figura 65 indica un posible plan de ejecución para una consulta
concreta.

• Index tunning wizard: Permite realizar el ajuste o “tunning” (cuyo concepto ya ha sido visto
en los primeros capítulos) de los índices de una base de datos concreta. En particular, esta
opción arranca un asistente para realizarlo.

• Results in text: Si está marcada esta opción, los resultados de la consulta serán mostrados en
formato textual.

• Results in grid: Si está marcada esta opción, los resultados de la consulta serán mostrados en
una rejilla o grid, separados por filas y columnas.

• Results to file: Si está marcada esta opción, los resultados de la consultas serán enviados a un
archivo.

• Show execution plan: Si esta opción esta marcada, se muestra el plan de ejecución de la
consulta, una vez realizada. Si la opción display estimated execution plan nos enseñaba el plan
estimado, esta opción muestra, junto con los resultados, el plan real de ejecución de ésta.

• Show server trace: Si esta opción está marcada, se muestra información acerca de la traza de
ejecución de la consulta en el servidor, es decir, pasos de la ejecución, consumo de
procesador, número de lecturas/escrituras, etc. La Figura 66 muestra una posible traza de
ejecución en el servidor de una sentencia select de ejemplo.

• Show client statistics: Si esta opción está marcada, se muestran estadísticas de ejecución de la
consulta, vista desde la parte cliente. Una posible estadística es la mostrada en la Figura 67.

• Current connection properties: Muestra información acerca de la actual conexión a la base


de datos.

Por su parte, la opción de menú Tools muestra opciones referentes a herramientas que se pueden usar
para configurar diversas opciones referentes al editor o ejecución de consultas.

La opción Window permite manejar las ventanas que se encuentran dentro del editor, para colocarlas
en cascada, en mosaico, navegar entre ellas, etc.

Por último la opción Help ofrece una completa ayuda tanto del editor, como cuestiones diversas sobre
T-SQL.

88
© Grupo EIDOS 10. El analizador de consultas

Figura 64

Figura 65

89
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Figura 66

Figura 67

90
© Grupo EIDOS 10. El analizador de consultas

La barra de herramientas
Crea un nueva consulta, pudiendo utilizar para ello una plantilla.

Abre una consulta existente en un archivo

Guarda la consulta del editor en un archivo

Introduce una plantilla de consulta en el editor

Corta el texto seleccionado al portapapeles

Copia el texto seleccionado al portapapeles

Pega el texto almacenado en el portapapeles

Borra el contenido de la ventana del editor

Busca un texto determinado en la consulta del editor

Deshace el último cambio realizado en la consulta del editor

Permite seleccionar la forma en que se mostrarán los resultados (en texto,

rejilla o archivo) y la información adicional (plan de ejecución, trazas de

servidor y estadísticas de cliente).

Compila la consulta para verificar su sintaxis.

Ejecuta la consulta.

Detiene la ejecución de una consulta.

Permite seleccionar la base de datos.

Muestra el plan estimado de ejecución de la consulta

Muestra una lista de los objetos del sistema

Permite realizar una búsqueda de los objetos del sistema

Muestra información acerca de la actual conexión

Muestra el panel de resultados de la ejecución de la consulta

91
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Ejecutando una consulta


Pongamos ahora en práctica los conceptos aprendidos ejecutando una consulta sencilla (no debe
preocuparse si todavía no entiende nada de código, ya que entraremos en detalle en posteriores
capítulos). Para ello accederemos al analizador de consultas, tecleando el servidor (si no se pone nada
se accederá al servidor local) y el login y password, como muestra la Figura 68.

Figura 68

Una vez hecho esto, ya tenemos acceso a todas las bases de datos existentes en el servidor. Escogemos
una de ellas, por ejemplo pubs, y dentro del editor tecleamos el Código fuente 3, cuyo cometido es
mostrar todos los valores de todos los atributos de la tabla titles.

SELECT * FROM titles

Código fuente 3

A continuación ejecutamos la sentencia, haciendo click en el botón en forma de flecha verde de la


barra de herramientas, escogiendo la opción Execute del menú Query, o tecleando F5.

Lo que nos aparecerá será una ventana como la de la Figura 69.

En ella podemos apreciar como se nos ha dividido el editor en dos partes. La de arriba contiene la
sentencia a ejecutar, mientras que la de abajo muestra los resultados de la ejecución de la misma.

Probemos ahora a mostrar los resultados en forma de tabla. Para ello seleccionamos la opción Results
in grid del menú Query. Ejecutamos nuevamente, y lo que nos aparece ahora es una ventana como la
que muestra la Figura 70.

92
© Grupo EIDOS 10. El analizador de consultas

Figura 69

Figura 70

En ella podemos observar como lo que antes nos aparecía en forma de texto, ahora nos aparece en un
grid, con una salvedad, el mensaje que indicaba el número de registros devueltos aparece ahora en otra
pestaña en la parte inferior, nombrada como Messages. Esta pestaña no sólo sirve para visualizar el

93
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

número de registros seleccionados, sino muestra otro tipo de mensajes, como por ejemplo los de error,
tal como se puede observar en la Figura 71.

Figura 71

Por último, guardaremos nuestra pequeña consulta en un archivo, para lo cual seleccionaremos la
opción Save as del menú File, y escogiendo un nombre para el mismo, como muestra la Figura 72.

Figura 72

94
© Grupo EIDOS 10. El analizador de consultas

Otra de las posibilidades que nos ofrece SQL-Server es la de exportar los datos que hayamos obtenido
en una consulta. Para ello, y estando en el modo de Results in grid, seleccionamos con el ratón el
rango de resultados que deseemos exportar y hacemos clic con el botón derecho del ratón para
seleccionar la opción Save as. Nos aparecerá una ventana como la de la Figura 73, en la que
deberemos dar un nombre al archivo, y la forma de exportación y separación de campos.

Figura 73

95
El lenguaje de definición de datos (DDL)

Introducción
Como ya se vio en la anterior parte acerca del diseño de esquemas relacionales, existen dos tipos de
sentencias, con diferente cometido, que permiten mantener dicho esquema:

• Lenguaje de Manipulación de Datos (DML): permite manipular los datos del esquema
relacional, es decir, consultar, actualizar, o borrar información.

• Lenguaje de Definición de Datos (DDL): permite establecer y/o modificar el esquema


relacional, es decir, añadir, borrar o actualizar atributos, tablas, índices, etc.

En este capítulo se verá este último, dejando el primero para otro posterior. Si el lector encuentra
alguna terminología un tanto desconocida, no se preocupe, ya que en un próximo capítulo se
describirán con detalle los operadores básicos que ofrece Transact SQL, así como algunas
consideraciones acerca del lenguaje.

Tipos de datos
Existe una amplia variedad de tipos de datos que podemos utilizar en Transact SQL. Estos tipos de
datos serán utilizados a la hora de definir los atributos de una tabla. La Tabla 25 muestra una
descripción de éstos.
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Identificador Descripción Rango de valores Tamaño


en SQL Server

Int Entero Desde -2.147.483.648 hasta 4 bytes


+2.147.483.647

bigint Entero largo 8 bytes

Smallint Entero corto Desde -32.768 hasta 32.767 2 bytes

Tinyint Entero minúsculo (sin Desde 0 hasta 255 1 byte


signo)

numeric(p,s) decimal exacto sin Enteros y decimales desde - de 2 a 17 bytes


decimal(p,s) redondeo 1.79E308 hasta +1.79E308 dependiendo de la
en donde p es el número de precisión
dígitos de la parte entera especificada
(precisión) y s es el de la
parte decimal (escala)

float(n) numérico de coma Redondeos de números 8 bytes


flotante con redondeo, desde -1.79E308 hasta
donde n está +1.79E308. Precisión
comprendido entre 8 y positiva: desde 2.23E-308
15. Doble precisión. hasta 1.79E308
Precisión negativa: desde -
2.23E-308 hasta -1.79E308

real numérico de coma Redondeos de números 4 bytes


flotante con redondeo, desde -3.40E38 hasta
donde n está +3.40E38. Precisión
comprendido entre 1 y positiva: desde 1.18E-38
7. Simple precisión. hasta 3.40E38
Precisión negativa: desde -
1.18E-38 hasta -3.40E38

char(n) Alfanumérico de Declarable hasta un máximo 1 byte por carácter


longitud fija de 255 caracteres declarado. Espacio
consumido fijo.

varchar(n) Alfanumérico de Declarable hasta un máximo 1 byte por carácter


longitud variable de 255 caracteres usado. Espacio
consumido variable

money Moneda. Números con 8 bytes


una precisión de
cuatro decimales.

smallmoney Moneda. Números con Desde - 4 bytes


una precisión de 922.337.203.685.447,5508
cuatro decimales. hasta
922.337.203.685.447,5507

98
© Grupo EIDOS 11. El lenguaje de definición de datos (DDL)

datetime Fecha y hora para Desde 1-enero-1753 hasta 8 bytes


fechas históricas 31-diciembre-9999. El dato
horario se guarda como
número de milisegundos
desde la medianoche del día
en cuestión

smalldatetime Fecha y hora para uso Desde 1-enero-1900 hasta 4 bytes


corriente 06-junio-2079. El dato
horario se guarda como
número de milisegundos
desde la medianoche del día
en cuestión

binary(n) Campo binario de Máximo de 255 bytes de n bytes, sean usados


longitud fija longitud todos o no

varbinary(n) Campo binario de Máximo de 255 bytes de n bytes como


longitud variable longitud máximo

text Campo para texto Máximo de 2 Gigabytes de Máximo 2 GB


largo de tipo Memo. longitud

image Campo para guardar Máximo de 2 Gigabytes de Máximo 2 GB


imágenes de hasta 2 longitud
Gigas

Sql_variant Almacena datos de


distintos tipos

table Almacena datos


temporales

bit Tipo bit 0ó1 Desde 1 bit mínimo


reutilizado a partir
del espacio de otra
columna hasta 1
byte máximo si la
columna fuera
única.

Tabla 25

Creación de tablas
Una de las principales sentencias de definición de datos es la de creación de una tabla. Su sintaxis es la
siguiente:

CREATE TABLE tabla (atributo tipo)

La ejecución de esta sentencia, genera como resultado una nueva tabla, en la base de datos en la que
estemos conectados. El nombre de la tabla debe ir después de la palabra TABLE. El nombre de los

99
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

atributos deberá ir entre paréntesis, especificando el tipo. Si existe más de un atributo, se deberán
separar por comas.

Otra opción nos permite cargar un número de filas de otra tabla, cargando su estructura. La sentencia
encargada de esto la vemos en el Código fuente 4.

SELECT * INTO tabla1 FROM tabla2

Código fuente 4

La anterior sentencia, lo que haría sería volcar el contenido de la tabla tabla2 en la tabla tabla1. Sin
embargo, para poder utilizar esta opción, es necesario modificar un parámetro de SQL Server. Para
ello, deberemos ejecutar el Código fuente 5.

sp_dboption base_datos, 'select into/bulkcopy', true

Código fuente 5

Modificación de tablas
Entendemos por modificar una tabla, cambiar su estructura, es decir, añadir atributos, borrarlos, o
cambiar la definición. La sentencia que permite modificar una tabla es la que muestra el Código fuente
6.

ALTER TABLE tabla ADD atrib tipo NULL

Código fuente 6

Nótese que el nuevo atributo añadido debe ser de tipo NULL, ya que si no se permiten valores nulos,
se produciría un error, al crearse los campos de la tabla con este valor.

Por ejemplo, si queremos añadir un atributo atributo1 de tipo varchar(30), a la tabla tabla1, deberíamos
ejecutar el Código fuente 7.

ALTER TABLE tabla1 ADD atributo1 varchar(30) NULL

Código fuente 7

Sólo pueden modificar las tablas el administrador, el propietario de la base de datos, y el propietario
de la tabla.

100
© Grupo EIDOS 11. El lenguaje de definición de datos (DDL)

Borrado de tablas
La sentencia que borra una tabla aparece en el Código fuente 8.

DROP TABLE tabla

Código fuente 8

El nombre de la tabla que se borra, debe ir a continuación de la palabra reservada TABLE.

Para poder borrar una tabla, ésta no debe estar siendo usada. En este caso deberemos hacer un
SELECT de otra tabla para liberarla. Además sólo podrá borrar una tabla el administrador, o el
propietario de la misma.

Creación y borrado de índices


La creación de índices en SQL Server, así como en la mayoría de los SGBDR existentes, se debe
realizar junto con la creación de la estructura de las tablas. De este modo se evitan posibles colisiones
que pueden surgir al crear índices cuando la tabla ya tiene datos. Por ejemplo, si creamos un índice
único por un campo, esto es no puede admitir duplicados, y se encuentran valores no únicos, la
generación del índice daría un error. Sin embargo, SQL Server permite la creación de índices, aunque
la base de datos esté cargada.

ALTER TABLE tabla ADD CONSTRAINT K1 PRIMARY KEY (cod1, cod2)

Código fuente 9

Esta sentencia permite añadir una clave primaria en tabla, por los campos cod1 y cod2.

Para crear un índice en la tabla todos, denominado Código, por el campo cod_cliente, se debe
especificar el Código fuente 10.

CREATE INDEX codigo ON todos (cod_cliente)

Código fuente 10

Sí además queremos que el índice no admita valores nulos, se debe ejecutar el Código fuente 11.

CREATE UNIQUE INDEX codigo ON todos (cod) WITH IGNORE_DUP_KEY

Código fuente 11

101
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

La sentencia que se encarga de borrar un índice, se muestra en el Código fuente 12. Esta sentencia se
encarga de borrar el índice código creado anteriormente.

DROP INDEX codigo

Código fuente 12

102
Ejemplos prácticos de uso del DDL

Introducción
Se verán en este capítulo una serie de ejemplos para poner en práctica los conceptos aprendidos en el
anterior, para afianzar al lector en el uso del lenguaje de definición de datos, plasmado en el
analizador de consultas de SQL-Server 2000. Además, la definición de estos esquemas nos servirá
como base para utilizar el lenguaje de manipulación de datos en próximos capítulos.

La sentencia CREATE TABLE


Esta sentencia es la que permite la creación de nuevas tablas dentro de una base de datos. Recordamos
su sintaxis en el Código fuente 13.

CREATE TABLE tabla (atributo tipo)

Código fuente 13

Por ejemplo, se procederá a continuación a crear una tabla destinada a contener información acerca de
las ofertas disponibles en una agencia inmobiliaria. Interesará almacenar por cada una de las ofertas la
siguiente información: un código de identificación, la provincia y el domicilio donde se encuentra, el
tipo de bien inmueble al que pertenece, si se encuentra en venta o alquiler y el precio del mismo. La
sentencia SQL que nos permite crear esta tabla se muestra en el Código fuente 14:
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

CREATE TABLE [dbo].[Oferta] (


[OF_ID] [int] NOT NULL PRIMARY KEY ,
[OF_Provincia] [varchar] (50) NOT NULL ,
[OF_Direccion] [varchar] (50) NOT NULL ,
[OF_Tipo] [varchar] (50) NOT NULL ,
[OF_Transaccion] [varchar] (50) NOT NULL ,
[OF_Precio] [int] NOT NULL
) ON [PRIMARY]

Código fuente 14

Sin embargo, la tabla que hemos creado más arriba puede dar problemas, ya que no esta normalizada;
por ejemplo, no podremos crear un tipo de bien inmueble nuevo hasta que no dispongamos de un bien
con esas características. Por lo tanto procederemos a crear una tabla para los tipos de bienes y otra
para las provincias (que a su vez se relacionará con una tabla de comunidades autónomas). Para ello
primero borramos el esquema creado anteriormente, utilizando la sentencia drop table (aprenderemos
como modificar un esquema en el siguiente epígrafe). El diagrama de la Figura 74 mostraría el
esquema resultante, y el Código fuente 15 las sentencias a ejecutar para conseguirlo.

Figura 74

DROP TABLE Oferta


GO
CREATE TABLE [dbo].[ComunidadAutonoma] (
[CA_ID] [int] NOT NULL PRIMARY KEY,
[CA_Nombre] [varchar] (50) NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Oferta] (

104
© Grupo EIDOS 12. Ejemplos prácticos de uso del DLL

[OF_ID] [int] NOT NULL PRIMARY KEY,


[Prv_ID] [int] NOT NULL ,
[OF_Direccion] [varchar] (50) NOT NULL ,
[TB_ID] [int] NOT NULL ,
[OF_Transaccion] [varchar] (50) NOT NULL ,
[OF_Precio] [int] NOT NULL
)
GO

CREATE TABLE [dbo].[Provincia] (


[Prv_ID] [int] NOT NULL PRIMARY KEY,
[CA_ID] [int] NOT NULL ,
[Prv_Nombre] [varchar] (50) NOT NULL
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[TipoBien] (


[TB_ID] [int] NOT NULL PRIMARY KEY,
[TB_Nombre] [varchar] (50) NOT NULL
) ON [PRIMARY]
GO

Código fuente 15

Supongamos ahora que se desea tener constancia de los datos personales de los comerciales que
trabajan en dicha agencia, necesitando almacenar, para cada uno de ellos, la siguiente información:
NIF (que de momento hará las veces de clave primaria de la tabla), nombre y apellidos, dirección,
código postal, provincia, teléfono y categoría, como muestra el Código fuente 16 .

CREATE TABLE [dbo].[Comercial] (


[Com_NIF] [char] (10) NOT NULL PRIMARY KEY,
[Com_Nombre] [varchar] (50) NOT NULL ,
[Com_Apellidos] [varchar] (50) NOT NULL ,
[Com_Direccion] [varchar] (50) NOT NULL ,
[Com_CodPostal] [char] (5) NOT NULL ,
[Prv_ID] [int] NOT NULL ,
[Com_Telefono] [char] (9) NOT NULL ,
[Com_Categoria] [varchar] (10) NOT NULL
) ON [PRIMARY]
GO

Código fuente 16

Al igual que para los comerciales, se necesitará también conocer los datos personales de los clientes
que están suscritos a nuestra agencia, conociendo por cada uno de ellos su NIF, nombre y apellidos,
dirección, provincia, código postal, teléfono y sus datos bancarios (nos bastará con el CCC de la
cuenta bancaria), siendo en NIF la clave primaria de la tabla, como muestra el Código fuente 17.

CREATE TABLE [dbo].[Cliente] (


[Cli_NIF] [char] (10) NOT NULL PRIMARY KEY,
[Cli_Nombre] [varchar] (50) NOT NULL ,
[Cli_Apellidos] [varchar] (50) NOT NULL ,
[Cli_Direccion] [varchar] (50) NOT NULL ,
[Cli_CodPostal] [char] (5) NOT NULL ,
[Prv_ID] [int] NOT NULL ,
[Cli_Telefono] [char] (9) NOT NULL ,
[Cli_CCC] [varchar] (30) NOT NULL

105
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

) ON [PRIMARY]
GO

Código fuente 17

Hasta el momento, el diagrama de la Figura 75 muestra la situación actual en la que se encuentra


nuestro esquema relacional:

Figura 75

Sin embargo, podemos darnos cuenta de que falta una cosa bastante importante para ubicar el
inmueble, y que son los transportes públicos más cercanos de los cuales dispone. Nos podemos
plantear esta información como dos tablas: una de tipos de transporte (por ejemplo metro y cercanías
RENFE) y otra de transportes en sí, que almacenará las estaciones o paradas para cada tipo de los
mencionados (por ejemplo Legazpi y Pacífico para metro y Fanjul y Móstoles para cercanías), como
muestra el diagrama de la Figura 76 y el Código fuente 18.

CREATE TABLE [dbo].[TipoTransporte] (


[TT_ID] [int] NOT NULL PRIMARY KEY,
[TT_Nombre] [varchar] (30) NOT NULL )
ON [PRIMARY]
GO
CREATE TABLE [dbo].[Transporte] (
[Tr_ID] [int] NOT NULL PRIMARY KEY,
[Tr_Nombre] [varchar] (30) NOT NULL,
[TT_ID] [int] NOT NULL
) ON [PRIMARY]
GO

Código fuente 18

106
© Grupo EIDOS 12. Ejemplos prácticos de uso del DLL

Figura 76

En un momento dado nos puede interesar la posibilidad de tener almacenados en la base de datos
todos los códigos postales, para posibles clasificaciones de inmuebles o futuras estadísticas, así que
daremos también de alta esta tabla, necesitando los siguientes atributos: el código postal (que actuará
como clave primaria de la tabla) y la provincia (ya que una misma provincia dispondrá de distintos
códigos postales, es una relación 1-N, e importa la clave de esta última tabla), como nos indica el
Código fuente 19

CREATE TABLE [dbo].[CodigosPostales] (


[Prv_ID] [int] NOT NULL,
[CP_Codigo] [char] (5) NOT NULL PRIMARY KEY
) ON [PRIMARY]
GO

Código fuente 19

La sentencia ALTER TABLE


Como ya se explicó, esta sentencia permite la modificación del esquema o la estructura de una tabla ya
creada. Su sintaxis es la descrita en el Código fuente 20:

ALTER TABLE tabla ADD atrib tipo NULL

Código fuente 20

107
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Volviendo sobre el ejemplo de la agencia desarrollado en el anterior epígrafe, podemos darnos cuenta
de varios aspectos del esquema que no son del todo correctos, y que se podrían mejorar.

Así, por ejemplo, los comerciales aparecen desconectados de las ofertas de bienes, por lo que no
mucho sentido, a no ser que sólo nos interesen dichos datos a título informativo. Pero ya que tenemos
esa tabla y, puesto que el modelo relacional es eso, la relación entre tablas, podremos conseguir
información de valor añadido si conectamos la tabla de ofertas a la de comerciales, para de este modo
conocer qué comerciales han intervenido en la compra/alquiler de qué inmuebles. Esto puede ser muy
útil a la hora de calcular comisiones o prever promociones, etc. Para conseguir esta característica
adicional en nuestro esquema, será necesario añadir un atributo más a la tabla de ofertas que la
relacione con el comercial. Esto es así debido a la relación 1-N que existe entre ambas tablas (un
comercial interviene en la transacción de muchos inmuebles, pero un inmueble sólo puede ser
gestionado por un comercial), lo que hace que se importe el atributo clave de la tabla de comerciales
como muestra el diagrama de la Figura 77.

Figura 77

Sin embargo esto nos obliga a modificar el esquema, con objeto de añadir este nuevo atributo a la
tabla de ofertas existente como muestra el Código fuente 21.

ALTER TABLE [dbo].[Oferta] ADD [Com_NIF] [char] (10)


GO

Código fuente 21

108
© Grupo EIDOS 12. Ejemplos prácticos de uso del DLL

Sin embargo nos encontramos con un problema, y es que no podemos añadir un nuevo atributo con la
propiedad not null, así que deberemos ejecutar una segunda sentencia, que modifique el atributo
añadido para que no pueda tomar valores nulos (ya que es una clave ajena):

ALTER TABLE [dbo].[Oferta] alter column [Com_NIF] [char] (10) not null
GO

Código fuente 22

Igual que para los comerciales, nos interesaría saber qué clientes han comprado/alquilado qué
inmuebles, para controlar los pagos, enviarles facturas, etc. La conexión entre ambas tablas es similar
al caso anterior. Y al igual que en el anterior caso también, se necesita modificar el esquema de la base
de datos, así que se utilizará, de un modo similar, la sentencia alter table (véase el Código fuente 23).

ALTER TABLE [dbo].[Oferta] ADD [Cli_NIF] [char] (10)


GO
ALTER TABLE [dbo].[Oferta] alter column [Cli_NIF] [char] (10) not null
GO

Código fuente 23

Siguiendo el mismo razonamiento, haremos lo mismo con la tabla de códigos postales. El caso de la
tabla de transportes es algo especial, ya que para un mismo inmueble pueden existir más de una
estación de metro cercana, que a su vez puede estar próxima a otros inmuebles; es un claro ejemplo de
relación N-M. Si recordamos lo que ocurría con este tipo de relaciones, se creaba una tabla intermedia
que importaba las claves de ambas. El Código fuente 24 muestra la forma de hacerlo:

CREATE TABLE [dbo].[OfertaTransporte] (


[Of_ID] [int] NOT NULL ,
[Tr_ID] [int] NOT NULL
) ON [PRIMARY]
GO

Código fuente 24

Sin embargo esta tabla dispone de una clave primaria compuesta, formada por ambos atributos, así que
se deberá ejecutar el Código fuente 25 para modificar el esquema de forma que se añada una
restricción en forma de clave primaria a dicha tabla:

ALTER TABLE [dbo].[OfertaTransporte] WITH NOCHECK ADD


CONSTRAINT [PK_OfertaTransporte] PRIMARY KEY NONCLUSTERED
(
[Of_ID],
[Tr_ID]
) ON [PRIMARY]
GO

Código fuente 25

109
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Sin embargo no debemos olvidarnos de un aspecto muy importante, que es el de las claves ajenas y las
restricciones. Deberemos relacionar todas las tablas de manera que se establezca una relación entre las
claves ajenas que unen las relaciones, para no tener problemas de borrar una tupla de una tabla que sea
clave ajena en otra relación, o insertar tipos que no estén dados de alta en las tablas maestras que los
tipifican.

Ejecutando el Código fuente 26 podremos estar seguro de esto:

ALTER TABLE [dbo].[Oferta] ADD


CONSTRAINT [FK_Oferta_Cliente] FOREIGN KEY
(
[Cli_NIF]
) REFERENCES [dbo].[Cliente] (
[Cli_NIF]
),
CONSTRAINT [FK_Oferta_Comercial] FOREIGN KEY
(
[Com_NIF]
) REFERENCES [dbo].[Comercial] (
[Com_NIF]
),
CONSTRAINT [FK_Oferta_Provincia] FOREIGN KEY
(
[Prv_ID]
) REFERENCES [dbo].[Provincia] (
[Prv_ID]
),
CONSTRAINT [FK_Oferta_TipoBien] FOREIGN KEY
(
[TB_ID]
) REFERENCES [dbo].[TipoBien] (
[TB_ID]
)
GO

ALTER TABLE [dbo].[OfertaTransporte] ADD


CONSTRAINT [FK_OfertaTransporte_Oferta] FOREIGN KEY
(
[Of_ID]
) REFERENCES [dbo].[Oferta] (
[OF_ID]
),
CONSTRAINT [FK_OfertaTransporte_Transporte] FOREIGN KEY
(
[Tr_ID]
) REFERENCES [dbo].[Transporte] (
[Tr_ID]
)
GO

ALTER TABLE [dbo].[Provincia] ADD


CONSTRAINT [FK_Provincia_ComunidadAutonoma] FOREIGN KEY
(
[CA_ID]
) REFERENCES [dbo].[ComunidadAutonoma] (
[CA_ID]
)
GO

ALTER TABLE [dbo].[Transporte] ADD


CONSTRAINT [FK_Transporte_TipoTransporte] FOREIGN KEY
(
[TT_ID]

110
© Grupo EIDOS 12. Ejemplos prácticos de uso del DLL

) REFERENCES [dbo].[TipoTransporte] (
[TT_ID]
)
GO

Código fuente 26

Como podemos ver, la forma de introducir claves ajenas en la base de datos es mediante restricciones,
poniendo el nombre de la tabla donde se encuentra el atributo que es clave ajena, seguido de las
palabras foreign key y a continuación las referencias a los atributos que son clave en sus relaciones.

Con todo esto, obtenemos el esquema relacional que se muestra en el diagrama de la Figura 78:

Figura 78

La sentencia DROP TABLE


Permite el borrado de una tabla existente en la base de datos, y su sintaxis es la que se muestra en el
Código fuente 27:

DROP TABLE tabla

Código fuente 27

111
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Retomando el ejemplo que nos lleva en este capítulo, podemos observar que la tabla de código
postales, de momento, no nos aporta nada, ya que la información que se precisa para un inmueble, no
recoge este dato como algo necesario, por contra, puede dificultarnos la gestión de la base de datos, así
que procederemos a su borrado, como muestra el Código fuente 28:

Drop table CodigosPostales

Código fuente 28

La sentencia CREATE INDEX


La sintaxis que permite la creación de índices sobre tablas es la especificada en el Código fuente 29:

CREATE [UNIQUE] INDEX indice ON tabla (atributos)

Código fuente 29

Recordemos cual es el cometido de un índice, que no es otro que el de acelerar las consultas que se
realizan sobre una base de datos. Sin embargo, es una decisión del diseñador el establecer los índices
oportunos para que el rendimiento de la misma no se vea afectado, ya que un índice es una estructura
que si bien acelera las consultas, puede llegar a ralentizar las actualizaciones de datos.

Veamos que índices podemos crear en el ejemplo que nos lleva este capítulo. Por ejemplo, podemos
adivinar que la tabla crítica para realizar consultas será la de ofertas. Es más, podemos intuir que la
mayoría de las consultas de dicha tabla involucrarán a los atributos precio y tipo de transacción
(alquiler o venta).

La siguiente decisión es considerar si crear un único índice con estos dos atributos, o crear dos por
separado. Pues bien, depende de las consultas que se vayan a realizar.

Si suponemos que la mayoría de las consultas se realizarán por ambos criterios, convendría crear un
único índice con ambos atributos. Sin embargo y, como será el caso, la mayoría de las consultas se
realizaran por precio o por tipo de transacción, conviene crearlos por separado de la siguiente forma:

CREATE INDEX oferta1 ON Oferta (Of_Transaccion)


GO
CREATE INDEX oferta2 ON Oferta (Of_Precio)
GO

Código fuente 30

La sentencia DROP INDEX


Permite el borrado de un índice creado para una tabla, y su sintaxis es la que se muestra en el Código
fuente 31.

112
© Grupo EIDOS 12. Ejemplos prácticos de uso del DLL

DROP INDEX codigo

Código fuente 31

Si en nuestro caso deseáramos borrar el índice oferta2 creado anteriormente, deberíamos ejecutar:

drop index Oferta.oferta2

Código fuente 32

La salvedad es que debemos indicar el código del índice de la forma tabla.indice, para evitar
ambigüedades.

113
El lenguaje de manipulación de datos
(DML)

Introducción
Ya se ha visto en un capítulo anterior el lenguaje de definición de datos (DDL), que es el que permite
definir y modificar la estructura de un esquema. Veremos a continuación el otro lenguaje, el de
manipulación de datos, que nos permite, como su propio nombre indica, manejar los datos contenidos
en el esquema.

La sentencia Select
La sentencia Select es una sentencia SQL, que pertenece al conjunto del Lenguaje de Manipulación de
Datos, y que sirve para recuperar registros de una o varias tablas, de una o varias bases de datos. Su
sintaxis es la siguiente:

SELECT <atributos> FROM <tablas>


[WHERE <condicion>]
[GROUP BY <atributos>]
[HAVING <condición>]
[ORDER BY <atributos>]

Donde las mayúsculas representan palabras reservadas, y lo encerrado entre corchetes es opcional,
puede ser omitido. Una vez vista la anterior forma de representación, vamos a detenernos en la sintaxis
de la sentencia Select. Se compone de tres partes:
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

• SELECT <atributos>: permite hacer una proyección de las tablas, es decir, seleccionar los
campos que deseamos recuperar de la base de datos, separados por comas. Si se especifica el
símbolo *, se obtendrán todos los campos de la tabla.

• FROM <tablas>: permite especificar la tabla de la cual se desean obtener los datos. Si se
especifica más de una tabla, éstas irán separadas por comas.

• WHERE <condición>: permite establecer una condición de recuperación de las filas de la/s
tabla/s. Sólo se obtendrán aquellas tuplas que verifiquen dicha condición, que será opcional.
En el caso de que se omita esta parte, se recuperarán todas las filas.

• GROUP BY <atributos>: permite establecer una selección de campos cuando se utilizan


funciones escalares o de conteo (ya se verá más adelante lo que significa.

• HAVING <condición>: establece una condición para los atributos obtenidos como resultado
de la aplicación de funciones escalares.

• ORDER BY <atributos>: permite obtener el resultado de la consulta ordenado por los


atributos especificados.

En el caso de que se especifiquen varias tablas, en la cláusula FROM, será conveniente denotar los
campos de la cláusula SELECT precedidos por el nombre de la tabla donde se encuentra y un punto,
para que, en el caso de que dicho campo exista en más de una tabla, se sepa en cada momento a cual
de ellos nos estamos refiriendo, evitando en este caso el problema de ambigüedad.

Si por ejemplo, deseamos obtener todos los valores de los atributos title y price de la tabla titles,
deberíamos escribir el Código fuente 33.

SELECT title, price FROM titles

Código fuente 33

De esta manera, obtenemos todas las filas, ya que no hemos dado ninguna condición, de la tabla titles
(especificada en la cláusula FROM), de las cuales sólo visualizaremos los valores de los atributos title
y price (especificados en la cláusula SELECT). Si por el contrario, deseamos obtener todos los
atributos de dicha tabla, deberíamos escribir el Código fuente 34.

SELECT * FROM titles

Código fuente 34

Puesto que hemos especificado el literal * dentro de la cláusula SELECT, la anterior sentencia nos
devuelve todos los atributos de todas las filas de la tabla titles, es decir, nos devuelve toda la
información almacenada en ella.

116
© Grupo EIDOS 13. El lenguaje de manipulación de datos (DML)

La cláusula Where
La forma de usar el Transact SQL para realizar consultas realizando una proyección horizontal (es
decir, seleccionando las filas), es mediante la opción WHERE. A continuación de esta palabra
reservada, se debe especificar la condición lógica que se debe evaluar, para obtener aquellas filas que
la cumplen.

Para expresar una expresión lógica se pueden emplear cualquiera de los operadores de Transact SQL
cuyo resultado devuelva un valor lógico, aunque también se pueden utilizar operadores de cadena.
Estos operadores serán vistos en detalle en el siguiente capítulo, pero básicamente son los siguientes:

• : compara si una expresión es mayor que otra

• < : compara si una expresión es menor que otra

• >= : compara si una expresión es mayor o igual que otra

• <= : compara si una expresión es menor o igual que otra

• <>: compara si una expresión es distinta que otra

• LIKE : compara todas las cadenas que verifican un patrón de búsqueda

• NOT LIKE : compara todas las cadenas que no verifican un patrón de búsqueda

• BETWEEN : compara todas las cadenas que están comprendidas en un rango de valores

• IN : compara todas las cadenas que están contenidas en una lista

Por ejemplo, si queremos obtener los títulos cuyos derechos de autor sean mayores del 10 %,
teclearemos el Código fuente 35. De la misma forma, si queremos obtener todos los títulos cuyo precio
no supere los 2$, ejecutaremos el Código fuente 36.

SELECT * FROM titleauthor WHERE royaltyper > 10

Código fuente 35

SELECT * FROM titles WHERE price <= 2

Código fuente 36

Si queremos obtener el nombre de los autores cuya primera letra este comprendida entre la C y la H, y
que a continuación tenga el literal 'urry', ejecutamos el Código fuente 37.

SELECT au_fname FROM authors WHERE au_fname LIKE '[C-H]urry'

Código fuente 37

117
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

O si queremos obtener la ciudad de todos los autores, que se corresponda con San Francisco o con Salt
Lake City, ejecutaremos el Código fuente 38.

SELECT city FROM authors


WHERE city in ('San Francisco','Salt Lake City')

Código fuente 38

Si se desea conocer todos los títulos cuyo precio oscila entre 1 y 2 dólares, ejecutaremos el Código
fuente 39.

SELECT title FROM titles


WHERE price BETWEEN 1 AND 2

Código fuente 39

La cláusula Group by
La cláusula GROUP BY agrupa, como su propio nombre indica, filas que tienen el mismo valor para
un atributo, en grupos distintos. Por ejemplo, si queremos obtener el apellido de todos los autores,
ejecutamos el Código fuente 40.

SELECT au_lname FROM autors

Código fuente 40

Si nos fijamos en el resultado obtenido, tenemos que existen dos autores, cuyo apellido es el mismo,
Ringer. Por lo tanto, se muestran dos filas iguales para este apellido, una por cada autor que se apellida
Ringer. Supongamos ahora, que lo único que nos interesa es obtener todos los apellidos que sean
distintos. Para ello deberemos agrupar los autores cuyo apellido sea el mismo en un único grupo, y a
continuación mostrar los grupos, en lugar de las filas. Con esto garantizamos que sólo se mostrará una
fila por cada apellido distinto, ya que sólo mostramos una fila del grupo, en lugar de todas. Esto que
parece tan complicado, se resume en una sentencia, usando la cláusula GROUP BY.

SELECT au_lname FROM authors GROUP BY au_lname

Código fuente 41

En ella, lo que se hace es simplemente un select, pero no de las filas de la tabla, sino de los grupos
obtenidos a partir de la cláusula GROUP BY. Puesto que deseamos agrupar por el apellido, detrás de
esta cláusula se debe determinar el atributo au_lname, garantizando así que todas las filas cuyo valor
de este atributo sea igual, irán al mismo grupo.

118
© Grupo EIDOS 13. El lenguaje de manipulación de datos (DML)

La cláusula Having
La cláusula HAVING es similar a la cláusula WHERE, salvo que aquella se usa como condición de
búsqueda cuando se especifica la cláusula GROUP BY. Por lo tanto el funcionamiento es similar al ya
visto para WHERE. La única diferencia es que HAVING se aplica a condiciones de grupo. Por
ejemplo, si dada la anterior sentencia de agrupación, deseamos que sólo se muestre el autor cuyo
apellido sea Ringer, ejecutaremos el Código fuente 42.

SELECT au_lname FROM authors GROUP BY au_lname HAVING au_lname = 'Ringer'

Código fuente 42

La cláusula Order by
La cláusula ORDER BY determina el orden de visualización de las filas obtenidas en la sentencia
SELECT. A continuación de dicha palabra reservada, se debe especificar el atributo o los atributos por
los cuales se ordenará el resultado obtenido en la consulta.

Por ejemplo, si queremos mostrar el nombre y apellido de todos los autores de nuestra base de datos
pubs, bastará con ejecutar la sentencia que aparece en el Código fuente 43 donde el atributo
especificado a continuación de la cláusula ORDER BY, es decir, au_lname, determina cómo se
ordenarán las filas que se mostrarán, en este caso alfabéticamente por el apellido.

SELECT au_lname, au_fname FROM authors ORDER BY au_lname

Código fuente 43

Funciones escalares para Select


Entendemos por funciones escalares, todas aquellas que permiten realizar operaciones de conteo de
filas, suma de atributos, obtención de medias, etc. Dichas funciones se especifican a continuación de la
palabra reservada SELECT. Las funciones que soporta la sentencia SELECT en el Transact SQL son
las siguientes:

• SUM: Realiza una suma acumulativa de un atributo para todas las filas accedidas mediante
una consulta SQL.

Por ejemplo, supongamos que tenemos una tabla de pedidos, con los atributos cod_cliente,
cod_material y precio. Si queremos obtener la suma del precio de todos los pedidos
almacenados, bastará con realizar una función de tipo SUM, como la que vemos en el Código
fuente 44.

SELECT sum(precio) FROM pedido

Código fuente 44

119
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

La anterior consulta obtiene la suma del precio para todas las filas de la tabla pedido, ya que
no hemos especificado ninguna condición en la cláusula WHERE.

Si ahora queremos obtener la suma total de todos los pedidos realizados por el cliente cuyo
código es "R12CE", debemos realizar la misma consulta, pero especificando una condición
para obtener únicamente las filas cuyo cod_cliente es "R12CE":

SELECT sum(precio) FROM pedido WHERE cod_cliente = "R12CE"

Código fuente 45

• COUNT: Cuenta todas las filas de las tablas accedidas mediante una consulta SQL.

Por ejemplo, si tenemos una tabla cliente, con todos los clientes de una empresa de servicios,
con los atributos DNI, nombre, apellidos, dirección y población, y queremos saber todos los
clientes que tenemos, deberemos realizar un count, para obtener todas el número de filas de la
tabla ejecutamos el Código fuente 46.

SELECT count(DNI) FROM cliente

Código fuente 46

En el anterior ejemplo, al existir el mismo número de filas, sea cual sea el atributo que
seleccionemos, podríamos haber escogido cualquier otro. En general, se suele escribir el
Código fuente 47.

SELECT count(*) FROM cliente

Código fuente 47

Si ahora queremos saber el número de clientes que viven en Madrid, deberemos realizar un
conteo de todas las filas con la condición de que el atributo población sea Madrid.

SELECT count(*) FROM cliente WHERE poblacion = "Madrid"

Código fuente 48

Si queremos saber cuantos títulos tenemos nuestra base de datos, teclearemos el Código fuente
49.

SELECT count(*) FROM titles

Código fuente 49

120
© Grupo EIDOS 13. El lenguaje de manipulación de datos (DML)

Y si queremos saber cuantos títulos tenemos, cuyo precio es mayor de 20 $, deberemos


realizar lo mismo, pero especificando esta condición en la cláusula WHERE. Al resultado de
la búsqueda le llamaremos caros.

SELECT count(*) caros FROM titles WHERE price > 20

Código fuente 50

• AVG: Realiza una media aritmética de los atributos para todas las filas accedidas mediante la
consulta SQL.

Si por ejemplo tenemos una tabla de materiales, con los atributos cod_material, descripción,
precio y cantidad_pedida, y queremos saber la cantidad media pedida de todos los materiales,
deberemos realizar una media aritmética, teniendo en cuenta todas las filas de la tabla:

SELECT avg(cantidad_pedida) FROM material

Código fuente 51

La anterior sentencia, internamente, realiza primero una suma de todos los valores, y a
continuación la divide por el número total de filas accedidas, es decir, realiza la media
aritmética.

Volviendo a nuestra cultural base de datos pubs, si queremos saber la media del precio de los
títulos que tenemos disponibles, deberemos ejecutar el Código fuente 52.

SELECT avg(price) media FROM titles

Código fuente 52

• MAX: Obtiene el máximo valor del atributo especificado, de entre todas las filas
seleccionadas mediante la sentencia SQL.

Supóngase, por ejemplo, que tenemos la tabla de materiales descrita anteriormente. Si


queremos saber el material mas caro, deberemos realizar un SELECT con la cláusula max, que
obtenga el mayor valor para el atributo precio de todas las filas.

Para nuestro ejemplo, si queremos saber cual es el libro más caro, ejecutaremos el Código
fuente 53.

SELECT max(price) caro FROM titles

Código fuente 53

121
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

• MIN: Obtiene el mínimo valor del atributo especificado, de entre todas las filas seleccionadas
mediante la sentencia SQL. Si queremos saber cual es el libro más barato de nuestra base de
datos, deberemos ejecutar el Código fuente 54.

SELECT min(price) barato FROM titles

Código fuente 54

La sentencia Insert
La otra gran sentencia de manipulación de datos es INSERT. Si SELECT nos permitía recuperar
datos, INSERT nos va a permitir añadirlos al esquema, es decir, con esta sentencia podemos añadir
información a la base de datos. Recordemos que estamos en el modelo relacional, por lo que la
información se añadirá a una tabla en forma de filas. Si sólo queremos insertar un valor para un
atributo, el resto de los de la tabla deberá contener el valor nulo (NULL). Sin embargo, habrá ciertas
ocasiones en que esto no será posible, cuando el atributo esté definido como NO NULO, en cuyo caso
deberemos especificar un valor para éste. La sintaxis de este sentencia es:

INSERT INTO tabla (atributos)


VALUES (valores)

donde tabla especifica la tabla en la cual se añadirá la fila, atributos es una lista de atributos
separados por comas que determinan los atributos para los cuales se darán valores, y valores
especifica los valores que se darán para estos atributos, separados por comas.

Por ejemplo, si queremos añadir un nuevo autor a nuestra base de datos, deberemos ejecutar el Código
fuente 55.

INSERT INTO authors (au_id, au_lname, au_fname)


VALUES ('409-99-9876', 'Pepe', 'Perez')

Código fuente 55

Destacar que si el valor a introducir es alfanumérico, deberá ir encerrado entre comillas, mientras que
si es numérico no. Pues bien, si ejecutamos la anterior sentencia, obtenemos el siguiente error:

Server: Msg 515, Level 16, State 2, Line 1


Cannot insert the value NULL into column 'contract', table
'pubs.dbo.authors'; column does not allow nulls. INSERT fails.
The statement has been terminated.

La razón es que no hemos dado valor al atributo contract, que ha sido definido como no nulo. Por lo
tanto, rectificamos el Código fuente 55, para dar un valor al Código fuente 56.

INSERT INTO authors (au_id, au_fname, au_lname, contract)


VALUES ('409-99-9876', 'Pepe', 'Perez', 1)

Código fuente 56

122
© Grupo EIDOS 13. El lenguaje de manipulación de datos (DML)

El valor que hemos dado al atributo contract es un 1, ya que está definido como tipo binario, es decir,
sólo admite dos valores, 0 para especificar que no está contratado, y 1 para el caso contrario.

Al ejecutar esta sentencia, obtenemos como resultado

(1 row(s) affected)

lo que nos indica que la fila se ha insertado con éxito. Podemos comprobarlo ejecutando un SELECT
sobre dicha fila.

SELECT * FROM authors WHERE au_id = '409-99-9876'

Código fuente 57

La sentencia Update
El objetivo de la sentencia UPDATE es actualizar los valores de una o varias filas de una tabla, sin
necesidad de borrarla e insertarla de nuevo. La sintaxis es la siguiente:

UPDATE tabla SET atributo1 = valor1 , atributo2 = valor2, ...


WHERE condicion

donde tabla especifica la tabla donde se encuentran las filas que queremos actualizar, condición
especifica la condición que se debe cumplir para actualizar las filas, y lo que viene a continuación de
SET especifica la asignación de los nuevos valores a los atributos. Por lo tanto se actualizarán todas
las filas que cumplan la condición especificada. Si queremos cambiar el nombre al autor que hemos
insertado en el anterior apartado, deberemos escribir el Código fuente 58.

UPDATE authors SET au_fname = 'Pepito'


WHERE au_id = '409-99-9876'

Código fuente 58

Lo que hacemos con la anterior sentencia es buscar el autor insertado, por el código (condición
where), y a continuación actualizar el valor del atributo nombre de la fila obtenida a Pepito. Si
ejecutamos la anterior sentencia, obtenemos el resultado: (1 row(s) affected) lo que quiere
decir que la fila ha sido actualizada con éxito. Podemos comprobarlo ejecutando el Código fuente 59.

SELECT * FROM authors WHERE au_id = '409-99-9876'

Código fuente 59

La sentencia Delete
El objeto de la sentencia DELETE es el de borrar filas de una tabla. Para poder borrar filas en una
tabla se deben cumplir las condiciones de seguridad determinadas por el administrador (se verán en un

123
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

próximo capítulo), y deben de cumplirse también las reglas de integridad referencial. La sintaxis es la
siguiente:

DELETE FROM tabla


WHERE condicion

donde tabla especifica la tabla sobre la cual queremos borrar las filas, y condición especifica la
condición que se debe cumplir para que se borren las filas. Si omitimos la condición, se borrarán todas
las filas de la tabla, es decir, la sentencia que aparece en el Código fuente 60 borra todas las filas de la
tabla authors.

DELETE authors

Código fuente 60

Por ejemplo, si queremos borrar la fila que hemos creado en la tabla autores, deberemos ejecutar el
Código fuente 61. obteniendo el siguiente resultado: (1 row(s) affected)

DELETE FROM authors


WHERE au_id = '409-99-9876'

Código fuente 61

lo que viene a decir que la fila se ha borrado. Para comprobarlo, ejecutamos la sentencia que muestra
el Código fuente 62. cuyo resultado es: (0 row(s) affected), lo que quiere decir que la fila
no se encuentra en la tabla, es decir, ha sido borrada.

SELECT * FROM authors WHERE au_id = '409-99-9876'

Código fuente 62

124
Operadores básicos y consideraciones
del lenguaje

Introducción
En este capítulo se describirán con detalle los operadores básicos, así como algunas apreciaciones
acerca del lenguaje que ofrece Transact SQL.

Entendemos por operadores, aquellas palabras reservadas o símbolos delimitadores que nos permiten
aplicar las diversas técnicas del álgebra relacional. Las principales que veremos aquí son:

• Proyección

• Unión

• Join o combinación

No confundir los anteriores operadores propios del álgebra relacional, con los que ofrece SQL Server,
es decir, los que permiten la evaluación de expresiones, unión de cadenas, comparaciones lógicas, etc.

Operador proyección
El operador de proyección es muy usado, sobre todo para acotar la consulta de tablas. Dicho operador
consiste en restringir la cantidad de información que obtenemos de una o varias tablas.
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Aquí veremos la proyección vertical, es decir, en realizar una criba sobre aquellos atributos que nos
interesen para todas las filas de una tabla, aunque también se puede acotar el resultado de ésta,
especificando una condición, para que el resultado se aplique únicamente a las tuplas que la cumplan.

Veamos ahora como realizar una proyección utilizando Transact SQL. Para especificar los atributos de
la tabla o tablas que deseamos que aparezcan en la consulta, se deberán proporcionar éstos a
continuación de la palabra reservada SELECT, y separados por comas.

Para especificar las tablas sobre las cuales se desea realizar la proyección, se deberán especificar
después de la palabra reservada FROM.

Así, el Código fuente 63 realiza una proyección de los atributos campo1 y campo2 de la tabla tabla1:

SELECT campo1, campo2 FROM tabla1

Código fuente 63

El método no varia si queremos realizar la proyección sobre más de una tabla.

SELECT tabla1.campo1, tabla2.campo1 FROM tabla1, tabla2

Código fuente 64

En el anterior ejemplo se ha proyectado sobre dos campos de dos tablas distintas. Para distinguir el
campo1 de tabla1, del campo1 de tabla2, se precede el nombre de la tabla al del campo, seguido por un
punto.

Probemos ahora con el query analyzer. Una vez abierto, nos conectamos a la base de datos pubs,
seleccionándola en la lista desplegable de la parte superior derecha, y tecleamos el Código fuente 65.

SELECT title título, type tipo FROM titles

Código fuente 65

Nótese como después de cada atributo hemos tecleado otro nombre. A este nombre se le denomina
alias y sirve para que el atributo obtenido aparezca con otro nombre.

Así, en nuestro ejemplo, se recuperarán todas las filas de la tabla titles, y realizaremos una proyección
sobre los atributos title y type, pero como podemos observar en el resultado mostrado en la Figura 79,
dichos atributos aparecen bajo los nombre título y tipo, que son los alias que les hemos dado
respectivamente.

126
© Grupo EIDOS 14. Operadores básicos y consideraciones del lenguaje

Figura 79

Operador Union
El operador unión consiste, como su propio nombre indica, en unir campos de más de una tabla. El
resultado obtenido contendrá entonces campos de las tablas especificadas en la cláusula FROM. Este
operador casi nunca se utiliza por separado, sino junto con el de proyección, para obtener el resultado
consultando en varias tablas, y quedarnos luego sólo con la información relevante. El Código fuente
66 constituye un ejemplo de unión de las tablas tabla1 y tabla2:

SELECT * FROM tabla1, tabla2

Código fuente 66

Otra forma de realizar una unión entre el resultado de dos consultas, es utilizar la palabra reservada
UNION. Por ejemplo, si queremos obtener la unión de las dos consultas a dos tablas, escribiremos el
Código fuente 67.

Probemos ahora en el query analizer, tecleando el Código fuente 68.

Pulsamos ahora el botón de ejecución, o F5, y obtenemos el resultado mostrado en la Figura 80, que
no es ni más ni menos, que todas las filas de las tablas titles y titleauthor.

127
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Figura 80

SELECT * FROM tabla1 UNION SELECT * FROM tabla2

Código fuente 67

SELECT * FROM titles, titleauthor

Código fuente 68

Operador join
El operador de join es uno de los más usados en el álgebra relacional. Sirve para combinar dos tablas
entre sí, utilizando un atributo común. Lo que se realiza es una unión de cada fila de una tabla, con
todas las filas de la tabla con la que se hace el join, cuyos atributos comunes coincidan.

La forma de realizarlo en Transact SQL es especificando en la cláusula WHERE los atributos por los
cuales se va a realizar el join entre ambas tablas.

SELECT * FROM tabla1, tabla2 WHERE tabla1.campo1 = tabla2.campo1

Código fuente 69

128
© Grupo EIDOS 14. Operadores básicos y consideraciones del lenguaje

El Código fuente 69 realiza un join entre las tablas tabla1 y tabla2, por el campo1 de ambas tablas.
Veamos un ejemplo de como funciona un join. Supóngase que tenemos las dos siguientes tablas, y
deseamos hacer un join por el atributo campo1 de ambas.

Campo1 Campo2

1 10

2 9

3 4

4 1

Tabla 26

Campo1 Campo2

1 5

1 3

2 8

Tabla 27

Lo primero que se realiza al hacer un join es una unión de ambas tablas, copiando cada fila de la
primera tabla, y para cada fila cuyo campo común sea igual en ambas tablas, copiar las filas de la
segunda tabla.

Por ejemplo, para la primera fila de la Tabla 26, hay dos filas en la Tabla 27 cuyo atributo campo1 es
igual. El join de estas dos tablas queda como muestra la Tabla 28

tabla1.campo2 tabla1.campo1 tabla2.campo1 tabla2.campo2

10 1 1 5

10 1 1 3

9 2 2 8

Tabla 28

Como hemos podido comprobar, la tercera fila de la tabla 1, no aparece en el join. Esto es debido a
que el valor del atributo por el que se hace el join (campo1), cuyo valor es 3, no existe en el atributo
campo1 de la tabla 2. A este tipo de join se le denomina inner join. El otro tipo de join, denominado
outer join, consiste en realizar el join, pero incluyendo todas las filas de ambas tablas, aunque éstas no
tengan correspondencia en su homóloga. Dentro de este tipo de join, existen dos categorías:

129
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

• Left join: incluyen todas las filas de la primera tabla, aunque éstas no tengan correspondencia
en la segunda. Los campos de la segunda tabla se rellenan con interrogantes.

Tabla1.campo2 tabla1.campo1 tabla2.campo1 tabla2.campo2

10 1 1 5

10 1 1 3

9 2 2 8

4 3 ? ?

Tabla 29

En Trasact SQL, la sentencia para realizar este left join se muestra en el Código fuente 70.

SELECT * FROM tabla1


left join tabla2 on tabla1.campo = tabla2.campo2

Código fuente 70

• Rigth join: incluyen todas las filas de la segunda tabla, aunque éstas no tengan
correspondencia en la primera. Los campos de la primera tabla se rellenan con interrogantes.

tabla1.campo2 tabla1.campo1 tabla2.campo1 tabla2.campo2

10 1 1 5

10 1 1 3

9 2 2 8

? ? 4 1

Tabla 30

En Trasact SQL, la sentencia para realizar este rigth join aparece en el Código fuente 71.

SELECT * FROM tabla1


rigth join tabla2 on tabla1.campo = tabla2.campo2

Código fuente 71

También se puede realizar un join por más de un campo. El Código fuente 72 realiza un join entre las
tablas Tabla 26 y Tabla 27, por los campos comunes campo1 y campo2.

130
© Grupo EIDOS 14. Operadores básicos y consideraciones del lenguaje

SELECT * FROM tabla1, tabla2 WHERE tabla1.campo1 = tabla2.campo1 AND tabla1.campo2


= tabla2.campo2

Código fuente 72

En el lenguaje de manipulación de datos, una de las operaciones más usuales es precisamente la de


join de varias tablas. Veamos un ejemplo de implementación de join en Transact SQL. Si se desea
obtener el título de cada obra, junto con el nombre de su autor, deberemos ejecutar el Código fuente
73.

SELECT titles.title, authors.au_lname FROM titles, titleauthor, authors


WHERE titles.title_id = titleauthor.title_id
AND titleauthor.au_id = authors.au_id

Código fuente 73

Analicemos la anterior sentencia. Deberemos acceder a la tabla de títulos, que es donde se encuentra el
título de cada obra.

A continuación, realizamos un join de esta tabla, con la tabla intermedia titleauthor, que es la que
almacena el código de cada título, junto con los autores que lo han escrito (recuérdese que en las
relaciones N-M, se genera una tabla intermedia con la clave de cada tabla).

A partir de esta tabla, podemos acceder a los autores, realizando un join de la tabla titleauthor con la
tabla authors, precisamente por el campo au_id, que es el código del autor. Por lo tanto, la cláusula
WHERE realiza los dos join necesarios para acceder a las tres tablas.

Como se puede observar, en la cláusula FROM se deben especificar todas las tablas que serán
accedidas, aunque de éstas no se muestre ningún atributo.

El resultado es el mostrado en la Figura 81.

En la cláusula WHERE, además de las condiciones de join, podremos especificar otro tipo de
condiciones.

Por ejemplo, si queremos obtener una relación de todos los títulos cuyo precio no supere los 20 $,
junto con sus autores, ejecutaremos la misma sentencia que antes, pero añadiendo ahora una nueva
condición, que es que el atributo price de la tabla titles no supere los 20$.

SELECT titles.title, authors.au_lname, titles.price FROM titles, titleauthor,


authors

WHERE titles.title_id = titleauthor.title_id

AND titleauthor.au_id = authors.au_id


AND titles.price < 20

Código fuente 74

131
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Figura 81

Figura 82

Operadores propios de Transact SQL


Los operadores que nos proporciona SQL Server se dividen en varios grupos:

132
© Grupo EIDOS 14. Operadores básicos y consideraciones del lenguaje

• Aritméticos: realizan operaciones aritméticas. Ej.: suma, multiplicación, división, etc.

• De nivel de bit: realizan operaciones transformando los operandos a bits. Ej.: AND al nivel de
bit, etc.

• Lógicos: realizan operaciones que devuelven un resultado lógico. Ej.: comparaciones, etc.

• De cadena: realizan operaciones que afectan a strings o cadenas de caracteres.


Ej.:concatenación, búsqueda, etc.

La Tabla 31 muestra un resumen de los principales operadores con que nos podemos encontrar en
Transact SQL.

DESCRIPCIÓN EJEMPLO RESULTADO

+ Suma SELECT 2 + 4 6

- Resta SELECT 3 - 1 2
Operadores
Aritméticos * Multiplicación SELECT 3 * 2 6

/ División SELECT 6 / 2 3

Módulo o resto de la
% SELECT 4 % 3 1
división entera

AND binario (1 si los


11 & 10 = 10 -
& bits de ambos SELECT 3 & 2
>2
operandos son 1)

OR binario (1 si el bit
11 | 10 = 11 ->
| de alguno de los dos SELECT 3 | 2
3
operandos es 1)
Operadores nivel de bit
OR exclusivo binario
11 ^ 10 = 01 ->
^ (1 si el bit de los SELECT 3 ^ 2
1
operandos es distinto)

NOT binario (cambia


~ SELECT ~ 2 ~10 = 01 -> 1
el bit)

Operadores lógicos

= Igual SELECT 1 = 2 FALSO

< Menor SELECT 1 < 2 VERDADERO

> Mayor SELECT 1 > 3 FALSO

>= Mayor o igual SELECT 1 >= 1 VERDADERO

<= Menor o igual SELECT 10 <= 1 FALSO

133
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

<> Distinto SELECT 1 <> 2 VERDADERO

!= Distinto SELECT 1 != 1 FALSO

!> No mayor SELECT 1 !> 3 VERDADERO

!< No menor SELECT 1 !<1 VERDADERO

+ Concatenación SELECT 'A' + 'B' AB

Cadenas coincidentes. SELECT * FROM


NOT: negación de la tabla WHERE
[] Curry Hurry
expresión LIKE: atributo1 LIKE '[C-
búsqueda por patrón H]urry'

Cadenas no
SELECT + FROM
coincidentes. NOT:
tabla WHERE
Operadores de Cadena [^] negación de la J,K,L,M
atributo1 NOT LIKE
expresión LIKE:
'[^I-Z]'
búsqueda por patrón

Cadena con ese


carácter coincidente.
SELECT * FROM
NOT: negación de la
_ tabla WHERE Hurry
expresión
atributo2 like '_urry'
LIKE: búsqueda por
patrón

Tabla 31

Otros operadores importantes aplicables a expresiones son los siguientes:

• BETWEEN: Verifica los valores comprendidos dentro del rango especificado. La sintaxis es:

expresion BETWEEN expresion AND expression

Por ejemplo, si queremos obtener todos los títulos cuyo precio oscile entre los 30 y los 50
dólares, escribimos el Código fuente 75.

SELECT * FROM titles


WHERE price BETWEEN 10 AND 50

Código fuente 75

• IN: Verifica si el valor especificado está contenido dentro de una lista de ellos. La sintaxis es:

expresion IN lista

Por ejemplo, si queremos obtener el nombre de todos los autores que vivan en San Francisco o
en Salt Lake City, ejecutamos el Código fuente 76.

134
© Grupo EIDOS 14. Operadores básicos y consideraciones del lenguaje

SELECT au_lname FROM authors


where city in ('San Francisco','Salt Lake City')

Código fuente 76

También se puede especificar como lista, el resultado de otra consulta. Por ejemplo, si
queremos obtener el nombre de los autores, que viven en ciudades pertenecientes al estado de
California (CA), escribimos el Código fuente 77.

SELECT au_lname FROM authors


where city IN (SELECT city FROM authors WHERE state = 'CA')

Código fuente 77

En la anterior consulta, la forma de evaluación es desde dentro hacia fuera, es decir, primero
se evalúa la sentencia que está entre paréntesis, y luego se aplica el valor obtenido para la
evaluación del operador IN.

Variables globales
Existe un conjunto de variables globales, que informan en cada momento del estado del sistema, o del
resultado de una consulta, etc. Esta variables se pueden distinguir porque comienzan por dos arrobas
@@. La Tabla 32 muestra un resumen con las variables globales que nos pueden resultar de utilidad:

@@connections número de conexiones realizadas desde que se ejecutó SQL Server

@@cpu_busy número de ticks (3.33 milisegundos) de ocupación de la CPU ejecutando


instrucciones SQL Server desde que éste fue ejecutado

@@cursor_rows número de filas seleccionadas en la última selección

@@datefirst número del primer día de la semana

@@error número del último error producido en la ejecución de una sentencia, 0 si no


ha habido error

@@fetch_status estado de la preselección (0: preselección satisfactoria, -1: preselección


erronea, -2: filas no disponibles)

@@identity identificador de la última operación realizada

@@idle número de ticks de tiempo ocioso de CPU desde que se ejecutó SQL Server

@@io_busy número de ticks de tiempo empleado en realizar operaciones de


entrada/salida desde que se ejecutó SQL Server

@@LANGID lenguaje local actual seleccionado

135
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

@@language descripción del lenguaje especificado para SQL server

@@lock_timeout tiempo de time-out (tiempo hasta el cual se intenta dar por válida la
transacción) en milisegundos para bloqueo

@@max_connectio número máximo de conexiones simultaneas que permite SQL Server


ns

@@max_precision nivel de precisión usado por los tipos de datos decimal y numeric

@@nestlevel nivel de anidamiento del actual procedimiento almacenado

@@options información sobre las opciones de usuario

@@pack_received número de paquetes recibidos por SQL Server desde que se inicializó

@@pack_sent número de paquetes enviados por SQL Server desde que se inicializó

@@packet_errors número de paquetes erróneos desde que SQL Server se inicializó

@@procid identificador del actual procedimiento almacenado

@@remserver nombre del servidor remoto

@@rowcount número de filas afectadas por una sentencia de selección

@@servername nombre del servidor local

@@servicename nombre de la clave de registro para SQL Server

@@spid identificador del proceso actualmente en ejecución

@@textsize tamaño máximo para los tipos de datos texto e imágenes

@@timeticks número de milisegundos por tick de CPU

@@total_errors número total de errores producidos desde que se inicializó SQL Server

@@total_read número de lecturas de disco desde que se inicializó SQL Server

@@total_write número de escrituras en disco desde que se inicializó SQL Server

@@trancount número de transacciones activas por el usuario en curso

@@version versión, fecha y tipo de procesador actualmente en uso para SQL Server

Tabla 32

136
© Grupo EIDOS 14. Operadores básicos y consideraciones del lenguaje

Sentencias condicionales
Las sentencias condicionales son aquellas que permiten discriminar entre diversas sentencias, según se
cumpla el valor de una expresión lógica. Existen dos tipos de sentencias condicionales. La primera de
ellas tiene la siguiente sintaxis:

IF expresion_logica
sentencia1
[ELSE sentencia2]

La sentencia 1 sólo se ejecutará si el resultado de la evaluación de la expresión lógica es verdadera. En


otro caso, se ejecutará la sentencia 2, correspondiente a la parte ELSE (opcional). Si se desea
especificar un conjunto de sentencias, en lugar de una sola, éstas deberán ir encerradas entre las
palabras reservadas BEGIN y END. Si deseamos obtener los títulos almacenados cuando éstos superen
las 10 unidades, y el número de ellos cuando no lo superen, ejecutaremos el Código fuente 78.

IF (SELECT count(*) FROM titles) > 10


BEGIN
SELECT title FROM titles
END
ELSE
BEGIN
SELECT count(*) FROM titles
END

Código fuente 78

En definitiva, la sentencia SELECT title FROM titles sólo se ejecuta cuando se cumple la condición
(SELECT count(*) FROM titles) > 10. En otro caso, se ejecutará la rama ELSE, que devuelve el
número de títulos almacenados en la tabla titles.

Otra forma de ejecutar sentencias de forma condicional, corresponde a la sentencia CASE. La sintaxis
es la siguiente:

CASE expresion1
WHEN expresion2 THEN resultado1
WHEN expresion3 THEN resultado2
...
[ELSE resultado3]

La anterior sentencia compara la expresión 1, con el resto de expresiones especificadas a continuación


de la palabra reservada WHEN. Si alguna de estas expresiones se cumple, se devolverá el resultado
correspondiente especificado a continuación de la palabra reservada THEN. Si llegados al final, no ha
verificado ninguna de las expresiones, se devolverá el resultado especificado a continuación del ELSE.

Por ejemplo, si queremos saber el nombre de los estados de los autores, en lugar de las iniciales,
podemos ejecutar el Código fuente 79.

SELECT state = CASE state


WHEN 'CA' THEN 'California'
WHEN 'OR' THEN 'Oregon'
ELSE 'Otro'

137
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

END
FROM authors

Código fuente 79

En este caso se comprueba el valor del atributo state, y si este es igual a CA, se devolverá California,
si es OR se devolverá Oregon, y en otro caso se devolverá el literal 'Otro'.

Sentencias iterativas
Una sentencia iterativa es aquella que permite ejecutar una o varias sentencias de manera repetida,
mientras se cumpla una condición lógica. La sentencia que permite realizarlo es WHILE, y su sintaxis

WHILE expresion_logica
sentencia
[BREAK]
[CONTINUE]

La sentencia especificada se ejecuta de forma iterativa, mientras se cumpla la expresión lógica. La


cláusula BREAK, permite romper el bucle, y abandonarlo, aunque se cumpla la expresión lógica,
mientras que CONTINUE permite ejecutar de nuevo las sentencias desde el comienzo del bucle,
ignorando aquellas que vienen a continuación del CONTINUE.

138
La sentencia INSERT

Introducción
La sentencia insert permite la introducción de nuevos registros dentro de un esquema. Su sintaxis, que
ya se ha visto, especifica el nombre de una tabla, los atributos que se van a insertar, y los valores para
dichos atributos. Si insertamos un valor nulo para un atributo que no acepta ese tipo de valores, o si no
especificamos un valor concreto para este tipo de columnas, se producirá un error y la fila no será
insertada.

Sintaxis
La sintaxis de la sentencia insert es la siguiente

INSERT INTO <tabla>


(<atributos>)
VALUES (<valores>)

donde <atributos> es una lista de atributos separados por comas, y <valores> es una lista de valores
separados por comas. Existe una correspondencia unívoca entre los atributos y los valores, es decir, al
atributo especificado en primer lugar se le asignará el valor indicado en primer lugar, y así
sucesivamente. La palabra reservada INTO es opcional y se puede omitir en la sentencia.
Bases de datos con SQL Server2000 – Transact SQL © Grupo EIDOS

Ejemplos
Para comenzar veremos un ejemplo sencillo de inserción de tuplas en la tabla del ejemplo de la
agencia inmobiliaria que venimos manejando. Insertaremos dos Comunidades Autonomas en la tabla
de comunidades, como indica el Código fuente 80.

INSERT INTO ComunidadAutonoma


(CA_ID, CA_Nombre)
VALUES (1, ‘Catalunya’)

INSERT INTO ComunidadAutonoma


(CA_ID, CA_Nombre)
VALUES (2, ‘Madrid’)

Código fuente 80

Figura 83

Para ver si efectivamente se han insertado ambos registros, ejecutamos una sentencia select como
muestra el Código fuente 81 (véase la Figura 83).

SELECT *
FROM ComunidadAutonoma

Código fuente 81

140
© Grupo EIDOS 15. La sentencia INSERT

Como decíamos, si ahora intentamos insertar otra provincia si especificar el atributo CA_ID, que es
clave, se producirá un error, como podemos observar en la Figura 84 al ejecutar el Código fuente 82.

INSERT INTO ComunidadAutonoma


(CA_Nombre)
VALUES (‘Andalucía’)

Código fuente 82

O si por el contrario introducimos un valor duplicado para la clave, también obtendremos el error de la
Figura 85 al ejecutar el Código fuente 83.

INSERT INTO ComunidadAutonoma


(CA_ID, CA_Nombre)
VALUES (1, ‘Andalucía’)

Código fuente 83

Figura 84

Otra forma de introducir filas es no especificando la lista de atributos, en cuyo caso los valores se van
asignando de manera secuencial a los atributos de la tabla. Por ejemplo en el Código fuente 84 se
asigna el valor 3 al atributo CA_ID y ‘Andalucía’ al atributo CA_Nombre.

141
Bases de datos con SQL Server2000 – Transact SQL © Grupo EIDOS

Figura 85

INSERT INTO ComunidadAutonoma


VALUES (3, 'Andalucía')

Código fuente 84

Del mismo modo se pueden especificar valores para los atributos en distinto orden, siempre que se
expresen de manera explícita en la lista de los mismos, como muestra el Código fuente 85, en el que se
asigna el código 1 a la provincia Madrid, que pertenece a la comunidad de Madrid (es decir, código 2).

INSERT INTO Provincia


(Prv_Nombre, Prv_ID, CA_ID)
VALUES ('Madrid’, 1, 2)

Código fuente 85

Así mismo se pueden especificar menos valores que atributos, siempre que para los atributos que no se
especifiquen se puedan insertar valores nulos o los establecidos por defecto. La forma de asignar estos
valores por defecto es como se muestra en el Código fuente 86.

INSERT INTO tabla DEFAULT VALUES

Código fuente 86

142
© Grupo EIDOS 15. La sentencia INSERT

Esto insertaría una nueva fila en la tabla, con los valores establecidos por defecto.

Otra forma de insertar filas es a partir del resultado de una consulta. Por ejemplo, el Código fuente 87
insertaría en la tabla 2, los valores de la tabla 1. Ni que decir tiene que ambos esquemas deben
coincidir. También se puede especificar un filtro en la claúsula where para la consulta.

INSERT INTO tabla2


SELECT *
FROM tabla1

Código fuente 87

Carga de la base de datos de ejemplo


Para concluir este capítulo, se ofrecen las sentencias necesarias para cargar las tablas de la base de
datos del ejemplo de la agencia inmobiliaria que venimos utilizando.

INSERT INTO Provincia


VALUES (2, 1, 'Barcelona')

INSERT INTO TipoBien


VALUES (1, 'Piso')
INSERT INTO TipoBien
VALUES (2, 'Chalet')
INSERT INTO TipoBien
VALUES (3, 'Solar')

INSERT INTO Cliente


VALUES ('11384H', 'Juan Jose', 'Martinez', 'C/Bernardino 2', '28021', 1,
'913382888', '12888271777')
INSERT INTO Cliente
VALUES ('11383K', 'Alfonso', 'Loira', 'C/Apache 34', '28023', 1, '913334888',
'123423471777')
INSERT INTO Cliente
VALUES ('123454L', 'Amadeo', 'Lerra', 'C/Portugal 4', '08021', 2, '933485888',
'1282344777')

INSERT INTO Comercial


VALUES ('113384H', 'Juan Alberto', 'Espado', 'C/Alcala 321', '28038', 1,
'914538288', '1')
INSERT INTO Comercial
VALUES ('11323K', 'Luis', 'Canto', 'C/Esplandiu 4', '28033', 1, '913379888', '2')
INSERT INTO Comercial
VALUES ('22354L', 'Pedro', 'Alcantara', 'C/Portugal 4', '08021', 2, '933485875',
'3')

INSERT INTO Oferta


VALUES (1, 1, 'C/Samba, 4', 1, 'V', 100000, '11323K', '11384H')
INSERT INTO Oferta
VALUES (2, 2, 'C/Salca, 34', 2, 'A', 1000, '113384H', '11383K')
INSERT INTO Oferta
VALUES (3, 1, 'C/Sabueso, 83', 1, 'V', 100000, '11323K', '11383K')
INSERT INTO Oferta
VALUES (4, 2, 'C/Llobregat, 34', 2, 'V', 100000, '11323K', '11384H')
INSERT INTO Oferta
VALUES (5, 1, 'C/Alcala, 197', 1, 'A', 500, '113384H', '11384H')
INSERT INTO Oferta
VALUES (6, 2, 'C/Alquimia, 34', 2, 'V', 100000, '22354L', '123454L')

143
Bases de datos con SQL Server2000 – Transact SQL © Grupo EIDOS

INSERT INTO Oferta


VALUES (7, 1, 'C/Alcosta, 867', 1, 'V', 100000, '11323K', '123454L')
INSERT INTO Oferta
VALUES (8, 1, 'C/Lorca, 33', 1, 'V', 100000, '22354L', '11384H')
INSERT INTO Oferta
VALUES (9, 1, 'C/Alcantara, 256', 1, 'V', 100000, '11323K', '11384H')
INSERT INTO Oferta
VALUES (10, 1, 'C/Arboleda, 32', 1, 'V', 100000, '11323K', '11384H')
INSERT INTO Oferta
VALUES (11, 1, 'C/Simbiosis, 32', 1, 'V', 100000, '11323K', '11384H')

INSERT INTO TipoTransporte


VALUES (1, 'Metro')
INSERT INTO TipoTransporte
VALUES (2, 'Cercanias')
INSERT INTO TipoTransporte
VALUES (3, 'Bus')

INSERT INTO Transporte


VALUES (1, 'Sol', 1)
INSERT INTO Transporte
VALUES (2, 'La Musas', 1)
INSERT INTO Transporte
VALUES (3, 'Alvarado', 1)
INSERT INTO Transporte
VALUES (4, 'Pacífico', 1)
INSERT INTO Transporte
VALUES (5, 'Sants', 1)
INSERT INTO Transporte
VALUES (6, 'Atocha', 2)
INSERT INTO Transporte
VALUES (7, 'Chamartin', 2)
INSERT INTO Transporte
VALUES (8, '12', 3)
INSERT INTO Transporte
VALUES (9, '24', 3)
INSERT INTO Transporte
VALUES (10, '2', 3)
INSERT INTO Transporte
VALUES (11, '123', 3)
INSERT INTO Transporte
VALUES (12, '56', 3)
INSERT INTO Transporte
VALUES (13, '34', 3)
INSERT INTO Transporte
VALUES (14, '5', 3)

INSERT INTO OfertaTransporte


VALUES (1, 1)
INSERT INTO OfertaTransporte
VALUES (1, 2)
INSERT INTO OfertaTransporte
VALUES (1, 3)
INSERT INTO OfertaTransporte
VALUES (3, 1)
INSERT INTO OfertaTransporte
VALUES (4, 4)
INSERT INTO OfertaTransporte
VALUES (4, 5)
INSERT INTO OfertaTransporte
VALUES (6, 1)
INSERT INTO OfertaTransporte
VALUES (6, 2)
INSERT INTO OfertaTransporte
VALUES (6, 6)
INSERT INTO OfertaTransporte
VALUES (8, 8)

144
© Grupo EIDOS 15. La sentencia INSERT

INSERT INTO OfertaTransporte


VALUES (8, 9)
INSERT INTO OfertaTransporte
VALUES (8, 10)
INSERT INTO OfertaTransporte
VALUES (8, 11)
INSERT INTO OfertaTransporte
VALUES (9, 1)
INSERT INTO OfertaTransporte
VALUES (9, 8)
INSERT INTO OfertaTransporte
VALUES (10, 3)
INSERT INTO OfertaTransporte
VALUES (10, 10)
INSERT INTO OfertaTransporte
VALUES (10, 11)
INSERT INTO OfertaTransporte
VALUES (10, 12)
INSERT INTO OfertaTransporte
VALUES (10, 5)

Código fuente 88

145
La sentencia SELECT

Introducción
La sentencia select es la principal manera que tiene el usuario de consultar información de la base de
datos. Veremos aquí algunos ejemplos de utilización, basándonos en los ejemplos que hemos visto en
el capítulo acerca del DDL.

La forma más simple de utilización es especificando una lista de atributos de una tabla. Así el Código
fuente 89 mostraría todos los datos referentes a comerciales

SELECT *
FROM Comercial

Código fuente 89

y el Código fuente 90 mostraría el nombre y apellidos de todos los clientes

SELECT Cli_Nombre, Cli_Apellidos


FROM Cliente

Código fuente 90
Bases de datos con SQL Server2000 – Transact SQL © Grupo EIDOS

La claúsula WHERE
La forma de especificar una condición dentro de una sentencia select es mediante la claúsula WHERE,
que especifica una condición lógica que devolverá únicamente aquellos registros que la cumplan.

Por ejemplo, para obtener todos los inmuebles de la tabla de ofertas que se encuentran en venta,
deberíamos teclear el Código fuente 91.

SELECT *
FROM Oferta
WHERE Oferta.Of_Transaccion = ‘V’

Código fuente 91

O si queremos consultar todos los inmuebles cuyo precio oscile entre 100 y 2.000 euros, deberemos
ejecutar Código fuente 92.

SELECT *
FROM Oferta
WHERE Oferta.Of_Precio >= 100 and Oferta.Of_Precio <= 2000

Código fuente 92

Esta sentencia equivaldría a esta otra:

SELECT *
FROM Oferta
WHERE Oferta.Of_Precio BETWEEN 100 and 2000

Código fuente 93

Si además deseamos especificar un orden, habrá que utilizar la claúsula ORDER BY.

Por ejemplo, el Código fuente 94 muestra el precio de todos los inmuebles de 100 a 2.000 euros,
ordenado de más caro a más barato, como muestra la Figura 86.

SELECT Oferta.Of_Precio
FROM Oferta
WHERE Oferta.Of_Precio BETWEEN 100 and 2000
ORDER BY Oferta.Of_Precio

Código fuente 94

148
© Grupo EIDOS 16. La sentencia SELECT

Figura 86

El operador join
Si la sentencia select es la más utilizada para consulta de información, el operador join es el más usado
para obtener información de tablas relacionadas. Si deseamos obtener datos de dos tablas que están
relacionadas por un atributo, deberemos utilizar este operador para obtener la información contenida
en ambas.

Por ejemplo, para obtener una información detallada de en que provincias se encuentran los
inmuebles, deberemos ejecutar el Código fuente 95.

SELECT Of_Direccion, Prv_Nombre


FROM Oferta
Inner join Provincia on Oferta.Prv_ID = Provincia.Prv_ID

Código fuente 95

De esta manera obtenemos la información de la provincia, que se encuentra en otra tabla distinta de la
de ofertas, y que se encuentra relacionada con ésta mediante la clave ajena Prv_ID.

En el anterior ejemplo se ha utilizado un inner join, pero también existen otros tipos de join, como
pueden ser el left outer y el rigth outer. La diferencia entre ambos ya se ha comentado en un capítulo
anterior, así que no se entrará en detalle. Si por ejemplo deseamos obtener todas las viviendas que no

149
Bases de datos con SQL Server2000 – Transact SQL © Grupo EIDOS

han sido compradas todavía por ningún cliente, o que han sido asignadas a clientes erróneos
deberemos ejecutar el Código fuente 96.

SELECT Of_Direccion, Prv_Nombre, Cliente.Cli_NIF


FROM Oferta
Inner join Provincia on Oferta.Prv_ID = Provincia.Prv_ID
Left outer join Cliente on Oferta.Cli_NIF = Cliente.Cli_NIF
WHERE Cliente.Cli_NIF is null

Código fuente 96

En el anterior ejemplo, primero realizamos un inner join para obtener la provincia (caso de que no
exista no aparecería nada), y a continuación un left outer join con la tabla de clientes para obtener el
cliente que tiene asignado la oferta; si dicho cliente no existe en la base de datos, obtendremos ese
atributo a nulo.

Puesto que se ha utilizado una claúsula where que nos devuelve únicamente los clientes que tienen
dicho atributo a nulo, obtendremos los clientes que no tienen correspondencia con las ofertas.

Supongamos que ahora nos viene un cliente, y nos pregunta por todos los inmuebles, que sean pisos,
que se encuentren en alquiler y que pertenezcan a la provincia de Madrid. Habría que ejecutar el
Código fuente 97.

SELECT *
FROM Oferta
Inner join Provincia on Oferta.Prv_ID = Provincia.Prv_ID
and Provincia.Prv_Nombre = ‘Madrid’
inner join TipoBien on Oferta.TB_ID = TipoBien.TB_ID
and TipoBien.TB_Nombre = ‘Piso’
WHERE Oferta.Of_Transaccion = ‘A’

Código fuente 97

Aunque el anterior código es válido, hubiese sido más cómodo crear una vista como la siguiente:

CREATE VIEW dbo.vInmuebles


SELECT Oferta.Of_Transaccion, Oferta.Of_Direccion,
Provincia.Prv_Nombre, TipoBien.TB_Nombre
FROM Oferta INNER JOIN
Provincia ON
Oferta.Prv_ID = Provincia.Prv_ID INNER JOIN
TipoBien ON Oferta.TB_ID = TipoBien.TB_ID

Código fuente 98

Ya continuación hacer un select de la vista como si de una tabla se tratase:

SELECT *
FROM vInmuebles

150
© Grupo EIDOS 16. La sentencia SELECT

WHERE Of_Transaccion = ‘A’ and TB_Nombre = ‘Piso’ and Prv_Nombre = ‘Madrid’

Código fuente 99

Vamos ahora a por un ejemplo con los transportes. Supóngase que se desea saber cuanto valen todos
los pisos que están próximos a una estación de cercanías o de metro. El código sería el siguiente:

SELECT Of_Precio
FROM Oferta
Inner join OfertaTransporte on Oferta.Of_ID = Transporte.Of_ID
Inner join Transporte on OfertaTransporte.Tr_ID = Transporte.Tr_ID
Inner join TipoTransporte on Transporte.TT_ID = TipoTransporte.TT_ID
And (TipoTransporte.TT_Nombre = ‘Metro’
or TipoTransporte.TT_Nombre = ‘Cercanias’)

Código fuente 100

Incluso podemos seleccionar todos los clientes que no han comprado ningún inmueble:

SELECT Cliente.Cli_Nombre
FROM Cliente
Left outer join Oferta on Oferta.Cli_NIF = Cliente.Cli_NIF
WHERE Oferta.Cli_NIF is null

Código fuente 101

Sin embargo, el anterior código podría haberse simplificado de la siguiente manera:

SELECT Cli_NIF
FROM Cliente
WHERE Cli_NIF not in (SELECT Cli_NIF FROM Oferta)

Código fuente 102

Las funciones de agregado


Imaginemos ahora que deseamos obtener el inmueble más caro de todos. Ordenando por precio de
manera descendente, lo cual se obtiene mediante la claúsula ORDER BY <atributo> DESC, y
cogiendo el primer registro de todos (utilizando la claúsula TOP 1), obtenemos el inmueble cuyo
precio es máximo, como muestra el Código fuente 103 y podemos apreciar en la Figura 87.

SELECT top 1 Of_Direccion, Of_Precio


FROM Oferta
ORDER BY Of_Precio desc

Código fuente 103

151
Bases de datos con SQL Server2000 – Transact SQL © Grupo EIDOS

Figura 87

Sin embargo, T-SQL nos ofrece una forma más sencilla de realizar esta consulta, utilizando una
función de agregado que se denomina max. De esta manera obtenemos el máximo valor para el
atributo que especificamos para dicha función, como muestra el siguiente código equivalente:

SELECT max(Of_Precio)
FROM Oferta

Código fuente 104

Además de este función de agregado, SQL-SERVER nos ofrece otras muchas, que veremos en más
detalle a continuación.

Por ejemplo, y análogamente a max, encontramos la función min, encargada de devolver el registro
cuyo valor es el mínimo, dentro de la consulta especificada. El Código fuente 105 devolvería el
inmueble más barato de la provincia de Madrid.

SELECT min(Of_Precio)
FROM Oferta
Inner join Provincia on Provincia.Prv_ID = Oferta.Prv_ID and
Provincia.Prv_Nombre = ‘Madrid’

Código fuente 105

152
© Grupo EIDOS 16. La sentencia SELECT

Otra función muy usual es la de suma, expresada por sum, y cuyo cometido es devolver como
resultado la suma del atributo especificado entre paréntesis, dentro de la consulta especificada. Si
queremos obtener el dinero gastado por un cliente del que sabemos que su apellido empieza por
“Marti”, bastaría ejecutar el Código fuente 106.

SELECT sum(Of_Precio)
FROM Oferta
inner join Cliente on Oferta.Cli_NIF = Cliente.Cli_NIF
and Cliente.Cli_Apellidos like 'Marti%'

Código fuente 106

En el anterior código nos basamos en utilizar un join con la tabla de clientes utilizando el atributo
común Cli_NIF, restringiendo en ésta última tabla por aquellos clientes cuyo atributo apellidos
comience por Marti (claúsula like).

No menos importante es la función count, cuya misión es contar es numero de filas que devuelve la
consulta. En este caso, aunque se puede especificar un atributo entre paréntesis, lo más usual es poner
el comodín *, ya que el número de filas es similar es para todos los atributos. El Código fuente 107
serviría para contar el número de filas de la tabla Oferta, es decir, el número total de ofertas
almacenadas en la base de datos.

SELECT count(*)
FROM Oferta

Código fuente 107

Y si queremos obtener el número de ofertas existentes en la provincia de Barcelona, volveremos a


utilizar esta sentencia, pero ahora filtrando por el código de provincia que, como no conocemos a
priori, será necesario obtener por medio de un join que contenga dicho nombre, como muestra el
Código fuente 108.

SELECT count(*)
FROM Oferta
Inner join Provincia on Oferta.Prv_ID = Provincia.Prv_ID
And Provincia.Prv_Nombre = ‘Barcelona’

Código fuente 108

Para obtener media aritméticas, SQL-SERVER nos ofrece la función avg, para un atributo
determinado dentro de una consulta. Por ejemplo, el código que nos muestra la media del precio de los
inmuebles de Barcelona, seria equivalente al código que realiza los cálculos por separado.

SELECT avg(Of_Precio) FROM Oferta


Inner join Provincia on Oferta.Prv_ID = Provincia.Prv_ID
And Provincia.Prv_Nombre = ‘Barcelona’

Código fuente 109

153
Bases de datos con SQL Server2000 – Transact SQL © Grupo EIDOS

SELECT sum(Of_Precio) / count(Of_Precio) as media


FROM Oferta
Inner join Provincia on Oferta.Prv_ID = Provincia.Prv_ID
And Provincia.Prv_Nombre = ‘Barcelona’

Código fuente 110

El funcionamiento es similar para las funciones encargadas de calcular la desviación típica (stdev), la
desviación típica de la población (stdevp), la varianza estadística (var) y la varianza de llenado (varp).

La claúsula GROUP BY
Si deseamos obtener agrupaciones dentro de una consulta, deberemos utilizar esta claúsula. Si por
ejemplo deseamos obtener la media del precio de los pisos por provincias, en principio deberíamos
ejecutar el Código fuente 111.

SELECT avg(Of_Precio), Provincia.Prv_Nombre


FROM Oferta
Inner join Provincia on Oferta.Prv_ID = Provincia.Prv_ID

Código fuente 111

Sin embargo, si ejecutamos este código, nos mostraría un error, ya que avg devuelve un registro, y
Prv_Nombre puede que no sea único, por lo que SQL SERVER se hace “un lio”. Para evitar esto,
debemos utilizar es la claúsula group by, para obtener los resultados agrupados; entonces tendremos
un avg por cada grupo que obtengamos. Modificamos el código para utilizar esta cláusula, y
obtenemos algo como la Figura 88.

SELECT avg(Of_Precio), Provincia.Prv_Nombre


FROM Oferta
Inner join Provincia on Oferta.Prv_ID = Provincia.Prv_ID
GROUP BY Provincia.Prv_Nombre

Código fuente 112

Paralelamente al uso de group by se suele utilizar la claúsula having. Para entendernos, es como un
where pero que se aplica a grupos de registros, en lugar de a registros por si solos. Si modificamos la
anterior consulta para que sólo se devuelvan aquellas provincias cuya media de precio supera los
100.000 euros, lo lógico sería ejecutar el código.

SELECT avg(Of_Precio), Provincia.Prv_Nombre


FROM Oferta
Inner join Provincia on Oferta.Prv_ID = Provincia.Prv_ID
GROUP BY Provincia.Prv_Nombre
WHERE avg(Of_Precio) > 100000

Código fuente 113

154
© Grupo EIDOS 16. La sentencia SELECT

Figura 88

Sin embargo esto nos devuelve un error, ya que el where se aplica a registros y, al estar utilizando
group by deberemos especificar una función de agregado. Sustituimos el where por having en el
Código fuente 114.

SELECT avg(Of_Precio), Provincia.Prv_Nombre


FROM Oferta
Inner join Provincia on Oferta.Prv_ID = Provincia.Prv_ID
GROUP BY Provincia.Prv_Nombre
HAVING avg(Of_Precio) > 100000
Código fuente 114

Otra utilidad que ofrece la cláusula group by es la de obtener los valores distintos que aparecen para
uno o varios atributos. Por ejemplo, para obtener cuales son las provincias en las cuales tenemos algún
inmueble, podríamos ejecutar el código.

SELECT Prv_Nombre
FROM Oferta
inner join Provincia on Oferta.Prv_ID = Provincia.Prv_ID

Código fuente 115

155
Bases de datos con SQL Server2000 – Transact SQL © Grupo EIDOS

Sin embargo, esto nos devuelve un registro por cada oferta que se encuentre, con los consiguientes
duplicados. Para evitar esto, podemos utilizar la función dinstinct, como sigue.

SELECT distinct(Prv_Nombre)
FROM Oferta
inner join Provincia on Oferta.Prv_ID = Provincia.Prv_ID

Código fuente 116

Sin embargo esto no es válido si queremos realizar algún tipo de información adicional, por ejemplo
contar el número de inmuebles por provincia, que sí se resolvería utilizando la claúsula group by,
como muestra el Código fuente 117.

SELECT count(Prv_Nombre) Cantidad, Prv_Nombre


FROM Oferta
inner join Provincia on Oferta.Prv_ID = Provincia.Prv_ID
GROUP BY Prv_Nombre

Código fuente 117

156
La sentencia UPDATE

Introducción
Esta sentencia es la que permite la actualización de la información almacenada en la base datos. Si la
sentencia insert se utilizaba para añadir nueva información, la sentencia update se utiliza para
modificar la información existente. Su sintaxis es la siguiente.

UPDATE <tabla>
SET <atributo> = <valor>
FROM <tablas>
WHERE <condicion>

Si se especifica más de una asignación de un valor a un atributo, éstas se deberán separar por comas.

La claúsula FROM se puede omitir, en el caso de sólo se necesite acceder a una tabla, que será la
misma que la que se actualice.

Ejemplos
Para comenzar veremos un ejemplo sencillo, que se muestra en el Código fuente 118 donde se
actualiza la dirección del comercial cuyo NIF es 11323K.

UPDATE Comercial
SET Com_Direccion = 'C/Esplandiu, 5'
Bases de datos con SQL Server2000 – Transact SQL © Grupo EIDOS

WHERE Com_NIF = '11323K'

Código fuente 118

Para comprobar que efectivamente el cambio ha tenido efecto, vamos a consultar los datos de este
comercial, ejecutando el Código fuente 119, obteniendo el resultado de la Figura 89.

SELECT Com_NIF, Com_Direccion


FROM Comercial
WHERE Com_NIF = '11323K'

Código fuente 119

Figura 89

Pero no simplemente se puede actualizar una fila cada vez, sino que se pueden actualizar todas las filas
que coincidan con un criterio de búsqueda. Por ejemplo, se puede hacer subir a la categoría 4 a todos
los comerciales de Madrid, para la cual se deberá ejecutar el Código fuente 120.

UPDATE Comercial
SET Com_Categoria = '4'
FROM Comercial, Provincia
WHERE Comercial.Prv_ID = Provincia.Prv_ID
and Prv_Nombre = 'Madrid'

Código fuente 120

158
© Grupo EIDOS 17. La sentencia UPDATE

En este caso hemos tenido que especifica la claúsula from para acceder a la tabla de provincias,
aunque no sea ésta la que se actualice, ya que necesitábamos conocer el identificador correspondiente
a la provincia de Madrid. Para comprobar si se han actualizado los datos, y sólo los correspondientes a
la provincia de Madrid, ejecutamos el Código fuente 121.

SELECT Com_Categoria, Prv_Nombre


FROM Comercial, Provincia
WHERE Comercial.Prv_ID = Provincia.Prv_ID

Código fuente 121

Figura 90

Hasta ahora sólo hemos actualizado un atributo; pero como hemos dicho, es posible actualizar más de
uno simultáneamente. Por ejemplo, el Código fuente 122 muestra como actualizar la dirección y el
teléfono del cliente Juan Jose Martinez.

UPDATE Cliente
SET Cli_Direccion = 'C/Apache 35', Cli_Telefono = '912237887'
WHERE Cli_Nombre = 'Juan Jose' and Cli_Apellidos = 'Martinez'

Código fuente 122

159
Bases de datos con SQL Server2000 – Transact SQL © Grupo EIDOS

Para comprobar que se ha actualizado correctamente el registro, ejecutamos el Código fuente 123,
obteniendo el resultado de la Figura 91.

SELECT *
FROM Cliente
WHERE Cli_Nombre = 'Juan Jose' and Cli_Apellidos = 'Martinez'

Código fuente 123

Figura 91

Del mismo modo, no hace falta especificar un valor a la hora de actualizar uno o varios atributos, sino
que se puede indicar una expresión. Por ejemplo, podemos subir el precio de todos los inmuebles de
Barcelona un 5%. Primero ejecutaremos el Código fuente 124 para comprobar cual es el precio de
estos inmuebles.

SELECT Of_Precio, Prv_Nombre


FROM Oferta
inner join Provincia on Provincia.Prv_ID = Oferta.Prv_ID
where Prv_Nombre = 'Barcelona'

Código fuente 124

Ahora ejecutamos el Código fuente 125 para actualizar su precio a un 5% más de su valor actual.

160
© Grupo EIDOS 17. La sentencia UPDATE

UPDATE Oferta
SET Of_Precio = Of_Precio + (Of_Precio * 0.05)
FROM Oferta, Provincia
WHERE Provincia.Prv_ID = Oferta.Prv_ID and Prv_Nombre = 'Barcelona'

Código fuente 125

Y para comprobar que efectivamente se han actualizado estos registros, ejecutamos nuevamente el
Código fuente 126.

SELECT Of_Precio, Prv_Nombre


FROM Oferta
inner join Provincia on Provincia.Prv_ID = Oferta.Prv_ID
where Prv_Nombre = 'Barcelona'

Código fuente 126

De la misma forma que para la sentencia select, update nos permite la utilización de las funciones de
agregación, para el cálculo de expresiones. Por ejemplo, actualizaremos la categoría del comercial
dependiendo del número de inmuebles que haya vendido cada uno. Si ha vendido entre 0 y 2, la
categoría a asignar será de 1, entre 3 y 4 será 2, entre 5 y 6 será 3, y así sucesivamente. Para calcular
dicha categoría podemos aplicar la siguiente fórmula:

Categoria = (nº inmuebles vendidos / 2) + (nº inmuebles vendidos módulo 2)

El operador de módulo o resto de la división entera se representa en T-SQL como %.

Vayamos paso a paso; primero veamos cuantos inmuebles ha vendido cada comercial, ejecutando la
sentencia del Código fuente 127.

SELECT count(*) cantidad, Com_Nombre


FROM Comercial
left outer join Oferta on Oferta.Com_NIF = Comercial.Com_NIF
GROUP BY Comercial.Com_Nombre

Código fuente 127

Por lo tanto vemos que la asignación de categorías sería 1 para Juan Alberto y Pedro, y 4 para Luis.
Ejecutemos ahora el Código fuente 128 que nos permite hacer esto.

UPDATE Comercial
SET Com_Categoria =
((SELECT count(*) / 2 FROM
Oferta where Comercial.Com_NIF = Oferta.Com_NIF) +
(SELECT count(*) % 2 FROM
Oferta where Comercial.Com_NIF = Oferta.Com_NIF))

Código fuente 128

161
Bases de datos con SQL Server2000 – Transact SQL © Grupo EIDOS

Lo primero que se ha hecho es para cada comercial calcular el número de ofertas que tiene
relacionado, para dividirlo por 2, calcular su módulo 2 y luego sumarlo y asignarlo al campo categoría.
Si ejecutamos una selección, como la que se muestra en el Código fuente 129 para comprobar que
efectivamente la actualización se ha realizado con éxito, nos encontraríamos con lo siguiente.

SELECT Com_Nombre, Com_Categoria


FROM Comercial

Código fuente 129

162
La sentencia DELETE

Introducción
La sentencia delete es la que nos permite borrar tuplas almacenadas en la base de datos. Su sintaxis es
la siguiente.

DELETE FROM tabla


WHERE condicion

Donde tabla especifica el nombre de la tabla de donde se desean borrar las filas que cumplen la
condición especificada en la claúsula where. Si ésta se omite, se borrarán todas las filas de la tabla
especificada (mucho cuidado con esto).

Si por ejemplo ejecutamos el Código fuente 130, nos encontraremos con que se borrará la oferta cuyo
código es 11 de la tabla de ofertas.

DELETE FROM Oferta


WHERE Of_ID = 11

Código fuente 130

Para comprobar si se ha borrado dicho registro, podemos hacer una select completa de la tabla y
verificar que falta dicho registro aunque, lo más sencillo, y conociendo que el registro que hemos
borrado era el último introducido, podemos obtener el máximo valor para el atributo Of_ID, y
comprobar que no es superior a 10, ejecutando el Código fuente 130.
Bases de datos con SQL Server2000 – Transact SQL © Grupo EIDOS

SELECT max(Of_ID)
FROM Oferta

Código fuente 131

La integridad referencial
Un aspecto a tener en cuenta es el no violar las reglas de integridad referencial que sostienen la base
de datos. Recordemos al lector que estas reglas son las que permiten mantener la información de la
base de datos en un estado coherente, para evitar posibles inconsistencias que pudieran surgir al
eliminar atributos que son clave ajena en otra relación.

Para comprender mejor esto, supongamos que borramos todos los comerciales de la base de datos.
Esto supondría que tendríamos ofertas inconsistentes, es decir, hacen referencia a comerciales que ya
no existen en la base de datos.

Para evitar esto, las reglas de integridad nos permiten olvidarnos a la hora de borrar un registro, si éste
esta relacionado con alguna otra tabla, evitando esta pérdida de información.

Si lo hemos hecho bien, cuando pretendamos borrar una tupla de estas características, el SGBD nos
advertirá de ello y no nos dejará borrarla.

De esta manera, si por ejemplo queremos borrar el comercial Luis Canto, ejecutaremos el Código
fuente 132.

DELETE FROM Comercial


Where Com_Nombre = 'Luis' and Com_Apellidos = 'Canto'

Código fuente 132

que, como cabía esperar, nos da un error. Es decir, primero deberemos borrar todas las ofertas en las
que haya participado dicho comercial, ejecutando el Código fuente 133.

DELETE FROM Oferta


FROM Comercial
Where Oferta.Com_NIF = Comercial.Com_NIF
and Com_Nombre = 'Luis' and Com_Apellidos = 'Canto'

Código fuente 133

Sin embargo, al ejecutar este código nos encontramos en la misma situación, ya que resulta que
existen filas en la tabla que relaciona las ofertas y los transportes, que hacen referencia a dicha oferta.

Por lo tanto, primero deberemos borrar éstas, como muestra el Código fuente 134.

DELETE FROM Oferta


FROM Comercial

164
© Grupo EIDOS 18. La sentencia DELETE

Where Oferta.Com_NIF = Comercial.Com_NIF


and Com_Nombre = 'Luis' and Com_Apellidos = 'Canto'

Código fuente 134

Una vez borradas las filas de OfertaTransporte, volvemos atrás para borrar las filas de Oferta,
ejecutando el Código fuente 135.

DELETE FROM Oferta


FROM Comercial
Where Oferta.Com_NIF = Comercial.Com_NIF
and Com_Nombre = 'Luis' and Com_Apellidos = 'Canto'

Código fuente 135

Y una vez borradas las ofertas de dicho comercial, ya le podemos eliminar de la base de datos, sin
preocuparnos de posibles inconsistencias, con el Código fuente 136.

DELETE FROM Comercial


Where Com_Nombre = 'Luis' and Com_Apellidos = 'Canto'

Código fuente 136

La sentencia TRUNCATE TABLE


Esta sentencia funciona de la misma forma que la instrucción delete sin especificar una cláusula
WHERE: ambas quitan todas las filas de la tabla. Pero TRUNCATE TABLE es más rápida y utiliza
menos recursos de los registros de transacciones y de sistema que delete.

La instrucción DELETE quita una a una las filas y graba una entrada en el registro de transacciones
por cada fila eliminada. TRUNCATE TABLE quita los datos al cancelar la asignación de las páginas
de datos utilizadas para almacenar los datos de la tabla y sólo se graba en el registro de transacciones
la página de asignaciones quitadas.

TRUNCATE TABLE quita todas las filas de una tabla, pero permanece la estructura y sus columnas,
restricciones, índices, etc. El contador utilizado por una identidad para las nuevas filas se restablece al
valor de inicialización de la columna. Si desea conservar el valor del contador, se debe utilizar delete
en su lugar.

Por ejemplo, el Código fuente 137 borraría todos los datos de la tabla Cliente

TRUNCATE TABLE Cliente

Código fuente 137

165
Bases de datos con SQL Server2000 – Transact SQL © Grupo EIDOS

Ejemplos
Veamos ahora algunos ejemplos para afianzar al lector en el uso de esta sentencia. Por ejemplo, y al
igual que hacíamos con la sentencia select, se puede utilizar el resultado de una subconsulta para
borrar un conjunto de registros.

Por ejemplo, si queremos borrar todas las ofertas de la Catalunya, podemos utilizar una subconsulta
que nos devuelva los identificadores de las provincias pertenecientes a dicha comunidad, para a
continuación efectuar el borrado de toda las ofertas que contengan dicho identificador, utilizando para
ello el operador de contenido (in).

Sin embargo, primero habrá que borrar todas las filas de OfertaTransporte que estén relacionadas con
éstas, para lo cual podemos volver a ejecutar una subconsulta en un segundo nivel para obtener dichas
filas. Para ello ejecutamos el Código fuente 138

DELETE FROM OfertaTransporte


WHERE Of_ID in (SELECT Of_ID
FROM Oferta
WHERE Prv_ID in (SELECT Prv_ID
FROM ComunidadAutonoma, Provincia
WHERE ComunidadAutonoma.CA_Nombre = 'Catalunya'
and ComunidadAutonoma.CA_ID = Provincia.CA_ID))

Código fuente 138

De esta manera y, una vez borradas todos los transportes disponibles para la oferta, borraremos las
ofertas como era nuestra pretensión, ejecutando el Código fuente 139.

DELETE FROM Oferta


WHERE Prv_ID in (SELECT Prv_ID
FROM ComunidadAutonoma, Provincia
WHERE ComunidadAutonoma.CA_Nombre = 'Catalunya'
and ComunidadAutonoma.CA_ID = Provincia.CA_ID)

Código fuente 139

Además de especificar una tabla en una sentencia delete, se puede indicar una consulta. Por ejemplo,
el Código fuente 140 mostraría como borrar las dos primeras ofertas.

DELETE Oferta
FROM (SELECT top 2 * FROM Oferta) as t

Código fuente 140

Puesto que esto devuelve un error debido a la integridad referencial, deberemos ejecutar primero el
Código fuente 141que elimine las filas de OfertaTransporte relacionadas.

166
© Grupo EIDOS 18. La sentencia DELETE

DELETE OfertaTransporte
FROM (SELECT top 2 * FROM Oferta) as t
WHERE t.Of_ID = OfertaTransporte.Of_ID

Código fuente 141

En este código, se ha utilizado una subconsulta como tabla, especificando para la misma un alias (t),
que nos servirá para luego hacer referencia a dicha subconsulta en la claúsula where. Aquí, por
ejemplo, se utiliza para hacer un join con la tabla OfertaTransporte, que permita borrar dichas filas.

En este código, se ha utilizado una subconsulta como tabla, especificando para la misma un alias (t),
que nos servirá para luego hacer referencia a dicha subconsulta en la claúsula where. Aquí, por
ejemplo, se utiliza para hacer un join con la tabla OfertaTransporte, que permita borrar dichas filas.

167
Procedimientos almacenados y triggers

Introducción
Los procedimientos almacenados son conjuntos de sentencias en leguaje Transact SQL que pueden
almacenarse en el propio servidor. Los procedimientos almacenados de SQL Server, son más potentes,
porque permiten almacenar funciones y procedimientos compuestos por varias instrucciones,
introducir saltos, bucles, etc. También se pueden compilar procedimiento escritos en lenguaje C, para
ampliar su potencia modularmente.

Por ejemplo, podemos crear un procedimiento para recuperar el nombre de un autor, cuyo código se
pasa por parámetro.

CREATE PROCEDURE ObtenerNombre @au_id varchar(11) AS


SELECT au_name
FROM author
WHERE author.au_id = @au_id

Código fuente 142

Con esta sentencia, se crea un procedimiento almacenado, de nombre ObtenerNombre, al que se le


pasa un parámetro, llamado @au_id, de tipo varchar(11), que realiza una consulta para obtener el
nombre de la tabla author, cuyo código coincida con el parámetro. De esta forma, si queremos obtener
el nombre del autor cuyo código sea '123', deberemos ejecutar el procedimiento pasándole como
argumento este valor:
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Las llamadas a procedimientos almacenados se pueden realizar de las siguientes formas:

• Pasando los argumentos en el mismo orden que en el que se han declarado.

ObtenerNombre '123'

Código fuente 143

• Pasando los argumentos nombrados. En este caso no hace falta que los parámetros vayan en el
mismo orden.

ObtenerNombre @au_id = '123'

Código fuente 144

Parámetros por referencia


Si ejecutamos las anteriores sentencias, obtendremos el resultado directamente en la ventana que
tengamos abierta en SQL Server. Pero ¿que pasa si queremos obtener un parámetro de salida, como
resultado de la ejecución del procedimiento?. La solución para este caso es utilizar la palabra
reservada OUTPUT para los argumentos de salida.

Si por ejemplo, queremos obtener el número de autores y el número de libros que tenemos en la base
de datos, crearemos el procedimiento almacenado que muestra el Código fuente 145.

CREATE PROCEDURE num_autores_libros @autores int OUTPUT, @libros int OUTPUT AS


SELECT * FROM Authors
SELECT @autores = @@ROWCOUNT
SELECT * FROM Titles
SELECT @libros = @@ROWCOUNT
RETURN (0)

Código fuente 145

Vamos a estudiar el anterior ejemplo. Básicamente es similar al anterior. Detrás de la palabra


reservada PROCEDURE damos el nombre del procedimiento almacenado, y a continuación
proporcionamos los parámetros, junto con su tipo (que en este caso es entero), y diremos sin éstos son
de salida, en cuyo caso especificamos la palabra reservada OUTPUT a continuación. Tras la palabra
reservada AS se codifica el cuerpo del procedimiento.

Primero contamos todas las filas de la tabla authors, realizando un SELECT * FROM Authors. A
continuación devolvemos en el parámetro @autores el valor obtenido, utilizando @@ROWCOUNT.
Acto seguido se realiza lo mismo para la tabla titles. Nótese como la forma de asignar un valor a un
atributo es mediante una sentencia SELECT, igualando el parámetro al valor.

La función @@ROWCOUNT devuelve el número de filas que se han seleccionado. Es equivalente a


la sentencia que aparece en el Código fuente 146

170
© Grupo EIDOS 19. Procedimientos almacenados y triggers

SELECT COUNT(*) FROM Authors

Código fuente 146

El Código fuente 146, por lo tanto, se podría sustituir por Código fuente 147.

CREATE PROCEDURE num_autores_libros @autores int OUTPUT, @libros int OUTPUT AS


SELECT @autores = (SELECT COUNT(*) FROM Authors)
SELECT @libros = (SELECT COUNT(*) FROM Authors)
RETURN (0)

Código fuente 147

Para ejecutar el anterior procedimiento, seguiremos los siguientes pasos:

1. Declarar las variables que vamos a utilizar para llamar al procedimiento. La sintaxis para
declarar una variable es utilizar la palabra reservada DECLARE, seguido del nombre de la
variable y el tipo.

DECLARE @num_autores int


DECLARE @num_libros int

Código fuente 148

2. Ejecutar el procedimiento. La sintaxis es utilizar la palabra reservada EXEC, seguida del


nombre del procedimiento, y los parámetros, separados por comas, especificando si son de
retorno.

EXEC num_autores_libros @num_autores OUTPUT, @num_libros OUTPUT

Código fuente 149

3. Mostrar los resultados.

SELECT autores = @num_autores, libros = @num_libros

Código fuente 150

Tras ejecutar las anteriores sentencias, obtendremos como resultado el siguiente listado:

autores libros
--------------- ---------------
23 18
(1 row(s) affected)

171
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Si queremos borrar un procedimiento almacenado, ejecutaremos la sentencia DROP PROCEDURE,


seguido del nombre del procedimiento. Por ejemplo, si queremos borrar el procedimiento almacenado,
creado en el anterior ejemplo, escribiremos el Código fuente 151

DROP PROCEDURE num_autores_libros

Código fuente 151

Procedimientos almacenados de sistema


SQL Server nos ofrece una serie de procedimientos almacenados ya implementados, es decir, listos
para ejecutar, cada uno con su propio objetivo o fin. Por ejemplo, si deseamos saber los usuarios
conectados a nuestro sistema, podemos elaborar una consulta SELECT sobre la tabla de sistema que
contiene los usuarios conectados, o ejecutar el procedimiento almacenado sp_who.

Figura 92

Así, si escribimos sp_who, obtendremos una lista con todos los usuarios conectados, como podemos
observar en la Figura 92.

Si queremos obtener una lista con todas las tablas del sistema, disponemos de otro procedimiento
almacenado denominado sp_tables. Del mismo modo, si deseamos conocer todos los atributos de una
tabla, deberemos ejecutar sp_columns seguido del nombre de la tabla.

172
© Grupo EIDOS 19. Procedimientos almacenados y triggers

Por ejemplo, para listar los atributos de la tabla authors ejecutamos sp_columns authors, y
obtenemos el resultado de la Figura 93

Existe una gran variedad de procedimientos almacenados, como por ejemplo para crear dispositivos,
para comprobar el espacio usado por una tabla, etc. Aquí sólo hemos visto dos ejemplos de aplicación.

Figura 93

Extended stored procedures


Una de las principales ventajas que ofrece SQL Server es que permite la ejecución de procedimientos
almacenados escritos en otro lenguaje de programación, como por ejemplo C, aprovechando de este
modo toda la potencia que ofrece un compilador de este estilo.

De todos es conocida la potencia que ofrece el lenguaje C, ya que es un compilador a bajo nivel. Esto
es, permite interaccionar con el hardware, obtener datos del Sistema Operativo, etc. La técnica que
permite el aprovechamiento de un lenguaje externo a SQL Server, para el diseño de procedimientos
almacenados se denomina Extended Stored Procedures.

Este es un caso un poco más complicado que el manejo de procedimientos almacenados intrínsecos al
propio SQL Server. Los Extended Stored Procedures se implementan como DLLs, que serán
privadas a SQL Server, y cuya gestión del espacio de memoria corresponde a éste. Una DLL
(Dinamic Link Library) es un conjunto de funciones, que se cargan dinámicamente en memoria,
esto es, se cargan en memoria cuando vayan a ser usadas, y se descargan cuando no se necesiten. Si
por ejemplo, uno de estos procedimientos intenta acceder a una dirección que cae fuera del espacio de

173
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

direcciones permitido, SQL Server atrapa la excepción, mata la tarea, y libera los bloqueos,
continuando normalmente con su trabajo.

Para registrar una Extended Stored Procedure, el administrador del sistema deberá ejecutar la
sentencia en Transact SQL que aparece en el Código fuente 152.

sp_addextendedproc nombre_función, nombre_DLL

Código fuente 152

Para ejecutar una de estas funciones en una base de datos distinta de aquella en la que se ha registrado,
se deberá preceder el nombre de la base de datos al nombre de la función.

Hay que destacar que estos procedimientos únicamente podrán ser ejecutados y registrados por el
administrador del sistema. Si éste desea permitir la ejecución a los demás usuarios, deberá ejecutar el
Código fuente 153.

GRANT EXEC ON procedimiento TO PUBLIC

Código fuente 153

Esta sentencia SQL otorga (GRANT) privilegios de ejecución (EXEC) sobre el procedimiento
especificado, a todos los usuarios de la base de datos. Si sólo deseamos otorgar este privilegio a un
usuario, deberemos especificar su identificador de usuario tras TO.

Triggers
Los disparadores de procedimiento, más comúnmente conocidos como triggers, son una especie de
procedimientos almacenados, a diferencia que se ejecutan cuando ocurre un evento sobre alguna tabla.
Entendemos por evento, cualquier acción del tipo:

• Inserción

• Borrado

• Actualización

La sintaxis de la sentencia de creación de triggers es la siguiente:

CREATE TRIGGER nombre ON tabla FOR accion AS codigo

donde acción especifica el evento que debe ocurrir para que se dispare el trigger, y que puede ser:

• UPDATE: actualización.

• INSERT: inserción.

• DELETE: borrado.

174
© Grupo EIDOS 19. Procedimientos almacenados y triggers

Por ejemplo, si queremos crear un trigger llamado modificación_autor, sobre la tabla Authors, que
muestre un mensaje cada vez que se actualiza una fila de la tabla, deberemos escribir el Código fuente
154.

CREATE TRIGGER modificacion_autor ON authors FOR UPDATE AS


print "Han actualizado la tabla de autores"

Código fuente 154

Para comprobar el funcionamiento de este trigger, podemos actualizar cualquier fila de la tabla de
autores, por ejemplo con la sentencia que aparece en el Código fuente 155.

UPDATE authors SET au_fname = 'Miguel' WHERE au_id = '267-41-2394'

Código fuente 155

Con esto conseguimos dos cosas, actualizar el nombre del autor cuyo código es el especificado a
Miguel, y obtener el mensaje que se muestra como ejecución del trigger de actualización.

Sin embargo, los triggers en SQL Server tienen una serie de limitaciones:

1. No se puede disparar un trigger dentro de otro trigger, ya que daría lugar a un bucle infinito

2. Por esta razón, un trigger no puede ejecutar instrucciones DDL (lenguaje de definición de
datos)

3. No se pueden ejecutar sentencias como SELECT INTO o de creación de dispositivos dentro


de un trigger

Del mismo modo, para borrar un trigger, deberemos ejecutar la sentencia DROP TRIGGER trigger.
Por ejemplo, si queremos borrar el trigger anteriormente creado, ejecutaremos el Código
fuente 156

DROP TRIGGER modificacion_autor

Código fuente 156

175
Ejemplos prácticos de uso de
procedimientos almacenados

Introducción
Los procedimientos almacenados es una de las principales funcionalidades que ofrece SQL-Server,
que permite al usuario que los usa abstraerse de la complejidad interna que puede encerrar. Por
ejemplo, pueden ser llamados desde otras aplicaciones, con los parámetros adecuados, siendo el
servidor el encargado de realizar las operaciones, descargando de trabajo al cliente.

Los procedimientos almacenados suelen utilizar sentencias de diverso tipo de T_SQL, como pueden
ser las de control de flujo, las de iteración, etc., que veremos en detalle mediante algunos ejemplos
prácticos.

La sentencia IF ... ELSE


Esta sentencia permite evaluar una expresión y provocar la entrada o ejecución de un bloque u otro,
dependiendo de que la condición sea verdadera o falsa.

El Código fuente 157 muestra un procedimiento almacenado encargado de insertar un nuevo tipo de
transporte si no está dado de alta en la base de datos. Para ello se comprueba que el número de filas
que devuelve el select sea cero, en cuyo caso la condición es verdadera, y se ejecutará el insert.
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

CREATE PROCEDURE sp_Insertar_TipoTransporte


@TT_ID int,
@TT_Nombre varchar(40)
AS
if (select count(*) from TipoTransporte where TT_ID = @TT_ID) = 0
insert into TipoTransporte
values (@TT_ID, @TT_Nombre)

Código fuente 157

Probemos a insertar un tipo de transporte que exista, y otro que no exista, para comprobar como
funciona. Para ello ejecutamos el Código fuente 158.

exec sp_Insertar_TipoTransporte 1, 'Metro'


exec sp_Insertar_TipoTransporte 4, 'Tranvía'

Código fuente 158

Para comprobar lo que ha ocurrido en la tabla de tipos de transporte, ejecutamos el siguiente código.

SELECT *
FROM TipoTransporte

Código fuente 159

Y como podemos comprobar, sólo se ha insertado el último registro. Podemos hacerlo un poco más
elegante, y devolver un parámetro que nos indique si ha habido error o no.

CREATE PROCEDURE sp_Insertar_TipoTransporte


@TT_ID int,
@TT_Nombre varchar(40),
@error char(1) output
AS
if (select count(*) from TipoTransporte where TT_ID = @TT_ID) = 0 begin
set @error = 'N'
insert into TipoTransporte
values (@TT_ID, @TT_Nombre)
end
else set @error = 'S'

Código fuente 160

Podemos observar una novedad, y es que se ha encerrado entre las palabras begin...end el bloque que
deseamos se ejecute cuando se cumple la condición, además del uso de la sentencia set para asignar un
valor a un parámetro o variable. Para ejecutar ahora el procedimiento, necesitamos un parámetro más
de llamada, que devolverá ‘S’ si se ha producido error, y ‘N’ si se ha insertado el registro con éxito,
cuyo tipo debe coincidir con el tipo del parámetro de salida declarado en el procedimiento.

178
© Grupo EIDOS 20. Ejemplos prácticos de uso de procedimientos almacenados

declare @error char(1)


exec sp_Insertar_TipoTransporte 1, 'Metro', @error output
select @error

Código fuente 161

Al ejecutar este código, mostramos el parámetro de salida y vemos como, efectivamente, se devuelve
una ‘S’, lo que indica que se ha producido un error. Sin embargo, si ejecutamos este otro código, se
devolverá una ‘N’, lo que indica que el registro se ha insertado correctamente, al no existir todavía en
la base de datos.

declare @error char(1)


exec sp_Insertar_TipoTransporte 5, 'Aeropuerto', @error output
select @error

Código fuente 162

Otro ejemplo nos muestra como comprobar si existen filas para un parámetro determinado, con el fin
de mostrar un mensaje determinado.

CREATE PROCEDURE sp_Hay_Comerciales


@Prv varchar(40)
AS
if (select count(*)
from Provincia
inner join Comercial on Comercial.Prv_ID = Provincia.Prv_ID
and Provincia.Prv_Nombre = @Prv) > 0
print 'Hay comerciales asociados a la provincia de ' + @Prv
else print 'No hay comerciales asociados a la provincia de ' + @Prv

Código fuente 163

En este código podemos comprobar como se obtiene el número de registros de un inner join, para
obtener el identificador de la provincia que coincide con el nombre que se pasa como parámetro. Si
dicho atributo es nulo, querrá decir, al ser un inner join, que o bien no existe la provincia, o bien no
existe ningún comercial asociado a ella. Ejecutemos el procedimiento para comprobar si existen
comerciales para la provincia de Barcelona.

exec sp_Hay_Comerciales 'Barcelona'

Código fuente 164

La sentencia CASE
Una variante a la instrucción if...else es la sentencia case, muy útil sobre todo cuando tenemos muchos
if anidados. Por ejemplo, el código expuesto antes utilizando if...else, equivaldría al siguiente,
utilizando case.

179
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

CREATE PROCEDURE sp_Hay_Comerciales2


@Prv varchar(40)
AS
select
case (select count(*) from Provincia
inner join Comercial on Comercial.Prv_ID = Provincia.Prv_ID
and Provincia.Prv_Nombre = @Prv)
when 0 then 'No hay comerciales asociados a la provincia de ' + @Prv
else 'Hay comerciales asociados a la provincia de ' + @Prv
end

Código fuente 165

Ejecución dinámica de sentencias: la instrucción EXEC


Como hemos visto, la instrucción exec se utiliza para ejecutar un procedimiento almacenado, pero no
sólo eso, sino que además sirve para evaluar una expresión de tipo carácter. Por ejemplo, el siguiente
código muestra como ejecutar un select de todas las provincias.

Exec (‘select * from Provincia’)

Código fuente 166

Esto puede resultar muy útil para montar sentencias en tiempo de ejecución, cuyos valores no
conocemos a priori, o para los cuales deseamos realizar un tratamiento distinto dependiendo de los
valores que tomen.

El siguiente código mostraría un procedimiento almacenado que se encarga de realizar búsquedas de


clientes. Recibe dos parámetros, uno es la provincia y otro es el código postal. Si se especifica
únicamente la provincia, se realizará una búsqueda de todos los clientes que sean de esta provincia,
mientras que si especifica el código postal, se realizará una búsqueda, además, por este atributo.

CREATE PROCEDURE sp_Clientes


@Prv varchar(40),
@CP varchar(5)
AS
-- La variable condicion almacena la claúsula where y la variable join los
join
declare @condicion varchar(255)
declare @join varchar(255)
set @condicion = ''
set @join = ''

-- Si se ha especificado la variable @Prv, montar la condicion y el join


if not @Prv is null begin
set @condicion = ' Provincia.Prv_Nombre = ' + '''' + @Prv + ''''
set @join = ' inner join Provincia on Provincia.Prv_ID =
Cliente.Prv_ID'
end

-- Si se ha especificado el cod postal, concatenar la condición


if not @CP is null begin
if @condicion <> ''
set @condicion = @condicion + ' and '

180
© Grupo EIDOS 20. Ejemplos prácticos de uso de procedimientos almacenados

set @condicion = @condicion + ' Cli_CodPostal = ' + '''' + @CP + ''''


end
if @condicion <> ‘’
set @condicion = ‘ where ‘ + @condicion
exec ('select * from cliente ' + @join + @condicion)

Código fuente 167

Manejamos dos variables, una almacenará la condición, que se ira concatenando, dependiendo de los
parámetros que se indiquen, y otra almacenará el join que se deberá realizar con la tabla de provincia,
en el caso de que se especifique como parámetro el nombre de la provincia. Una vez montadas estas
cadenas, se ejecuta la sentencia exec, para evaluar la expresión resultante.

Si ejecutamos el anterior procedimiento almacenado, sin especificar ninguno de los parámetros,


obtendremos todos los clientes

exec sp_Clientes null, null

Código fuente 168

Si especificamos el parámetro provincia = Madrid, obtendremos todos los clientes de la provincia de


Madrid

exec sp_Clientes ‘Madrid’, null

Código fuente 169

Si además especificamos el parámetro codigo postal, obtendremos lo siguiente.

exec sp_Clientes 'Madrid', 28023

Código fuente 170

Conversión de tipos
Muchas veces nos encontraremos la necesidad de convertir un valor de un tipo a otro tipo para operar
con él. Es entonces cuando intervienen dos instrucciones que nos permiten realizar esto. Dichas
instrucciones son cast y convert.

La sintaxis de la expresión cast es la siguiente.

Cast (expresion as tipo)

y la de convert.

Convert (tipo, expresion)

181
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Por ejemplo, podemos utilizarlo para convertir un tipo de datos carácter a fecha.

Cast (‘01/01/01’ as datetime)

Código fuente 171

O un carácter a entero

cast (‘3’ as int)

Código fuente 172

La sentencia WHILE
La instrucción while permite iterar un numero de veces que no conocemos a priori, hasta que deje de
cumplirse la condición boleana. Su sintaxis es la siguiente.

WHILE expresion
sentencias
[BREAK]
[CONTINUE]

La claúsula break es optativa y indica al bucle que deje de ejecutarse, mientras que la claúsula
continue, que también es optativa, indica al bucle que se reinicie.

En el siguiente ejemplo, se recorre los comerciales, mientras que la categoría sea distinta de 6, y va
duplicando la misma, hasta que alguno supera el valor de 6.

CREATE PROCEDURE sp_ActualizaComercial


AS
WHILE (SELECT Com_Categoria FROM Comercial) <> '6'
BEGIN
UPDATE Comercial
SET Com_Categoria = cast(Com_Categoria as int) * 2

IF (SELECT MAX(Com_Categoria) FROM Comercial) > 6


BREAK
ELSE
CONTINUE
END

Código fuente 173

182
Triggers en SQL-Server 2000

Introducción
Como ya se ha comentado, los triggers o desencadenadores son una especie de procedimientos
almacenados, que se ejecutan cuando ocurre una acción dentro de la base de datos. Así, si por ejemplo
se ejecuta una inserción, una actualización, o un borrado de una tabla, se ejecutarían las sentencias
definidas para el trigger en concreto de esa tabla específica.

Recordamos cual es su sintaxis:

CREATE TRIGGER nombre


ON tabla
FOR [DELETE | INSERT | UPDATE]
AS
sentencias

Las palabras reservadas DELETE, INSERT y UPDATE corresponden a cada una de las acciones para
las cuales se puede definir un desencadenador dentro de la tabla especificada.

El bloque de sentencias permite prácticamente cualquier tipo de ellas dentro del lenguaje T-SQL, pero
con ciertas limitaciones. Por ejemplo, no se podrá utilizar la sentencia select, ya que un trigger no
puede devolver datos al usuario, sino que simplemente se ejecuta para cambiar o comprobar los datos
que se van a insertar, actualizar o borrar.
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Las tablas deleted e inserted


Dentro de la definición de un trigger, podemos hacer referencia a un par de tablas lógicas, cuya
estructura es similar a la tabla donde se esta ejecutando el trigger; es decir, es una copia de la tabla en
la cual se van a insertar o borrar los datos, y que contiene, precisamente, los datos que van a ser
añadidos o borrados.

La utilidad de estas dos tablas es la de realizar comprobaciones entre los datos antiguos y los nuevos.
Así, por ejemplo, si queremos recuperar los datos de la tabla que estamos borrando, dentro del trigger,
se deberá ejecutar el siguiente código:

SELECT *
FROM deleted

Código fuente 174

Tipos de desencadenadores
SQL-Server permite la definición de varios tipos de triggers, entre los cuales cabe destacar los
siguientes:

• Desencadenadores múltiples: para una misma tabla, se pueden definir distintos triggers para la
misma acción, es decir, si definimos un trigger para insert, y resulta que dicha tabla ya tenía
definido un trigger para esa misma acción, se ejecutarán ambos triggers cuando ocurra dicho
evento sobre la tabla.

• Desencadenadores recursivos: se permite la recursividad entre las llamadas a los triggers, es


decir, un trigger puede llamar a su vez a otro, bien de forma directa, bien de forma indirecta.

• Desencadenadores anidados: si un trigger cambia una tabla en la que se encuentra definido otro
trigger, se provoca la llamada de este último que, si a su vez vuelve a modificar otra tabla, puede
provocar la ejecución de otro trigger, y así sucesivamente. Si se supera el nivel de anidamiento
permitido, se cancelará la ejecución de los triggers.

Limitaciones de los triggers


Aunque ya se han comentado algunas de las limitaciones a la hora de programar triggers, veamos en
detalle las restricciones que implica la definición de triggers:

• Un trigger sólo se puede aplicar a una tabla

• Aunque un trigger se defina dentro una sola base de datos, puede hacer referencia a objetos que se
encuentran fuera de la misma

• La misma acción del desencadenador puede utilizarse para definir más de un trigger sobre la
misma tabla

• La opción SET elegida dentro de la ejecución de un desencadenador, volverá a su estado


previamente definido una vez concluya la ejecución del mismo

184
© Grupo EIDOS 21. Triggers en SQL – Server 2000

• Así mismo, no se permite la utilización de las sentencias del DDL dentro de la definición de un
trigger

• En una vista no se puede utilizar un desencadenador

Resolución diferida de nombres


La resolución diferida de nombres es una utilidad que permite escribir triggers que hagan referencia a
tablas que no existen en el momento de la compilación. Por ejemplo, el siguiente código hace
referencia a una tabla x, que no existe en el momento de escribir el trigger.

CREATE TRIGGER trigger1


on authors
FOR INSERT, UPDATE, DELETE
AS
SELECT a.au_lname, a.au_fname, x.info
FROM authors a INNER JOIN x
ON a.au_id = x.au_id
GO

Código fuente 175

Ejemplos
Veamos a continuación algunos ejemplos que complementen lo visto hasta ahora. El siguiente código,
muestra la forma de enviar un mensaje de correo electrónico a una persona, cuando se añade una
nueva oferta.

CREATE TRIGGER enviar_correo


ON Oferta
FOR INSERT
AS
EXEC master..xp_sendmail 'Pepe',
'Tenemos una nueva oferta en nuestra base de datos.'
GO

Código fuente 176

Sin embargo, si queremos que se envíe el mensaje cada vez que se cambia algo en la tabla de ofertas,
deberemos reescribir el trigger para las acciones update y delete, como se muestra en el siguiente
código.

DROP TRIGGER enviar_correo


GO

CREATE TRIGGER enviar_correo


ON Oferta
FOR INSERT, UPDATE, DELETE
AS
EXEC master..xp_sendmail 'Pepe',

185
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

'La tabla de ofertas ha cambiado'


GO

Código fuente 177

En el Código fuente 178, se muestra como crear un trigger que, utilizando la tabla inserted para
comprobar los valores que se van a añadir o modificar, posibilite la cancelación de la acción, si el
nivel del trabajo no está dentro de los valores permitidos.

CREATE TRIGGER empleado_modificar


ON employee
FOR INSERT, UPDATE
AS

/* Obtener el nivel para el trabajo actual */

DECLARE @min_lvl tinyint,


@max_lvl tinyint,
@emp_lvl tinyint,
@job_id smallint
SELECT @min_lvl = min_lvl,
@max_lvl = max_lvl,
@emp_lvl = i.job_lvl,
@job_id = i.job_id

FROM employee e INNER JOIN inserted i ON e.emp_id = i.emp_id


JOIN jobs j ON j.job_id = i.job_id
IF (@job_id = 1) and (@emp_lvl <> 10)
BEGIN
RAISERROR ('Debe especificar el nivel 10 para el trabajo 1', 16, 1)
ROLLBACK TRANSACTION
END
ELSE
IF NOT (@emp_lvl BETWEEN @min_lvl AND @max_lvl)
BEGIN
RAISERROR ('El nivel para el trabajo:%d debe estar entre %d y %d.',
16, 1, @job_id, @min_lvl, @max_lvl)
ROLLBACK TRANSACTION
END
Código fuente 178

Primero declaramos las variables min_lvl y max_lvl, que almacenarán los valores mínimo y máximo
permitidos para un trabajo, emp_lvl, que almacenará el nivel para el empleado, y job_id que almacena
el identificador del trabajo que se va a actualizar.

A continuación realizamos un join entre la tabla de empleados y la tabla inserted o, lo que es lo


mismo, entre la tabla de empleados tal y como está antes de ejecutar el trigger, y la tabla de empleados
tal y como quedaría después de ejecutarlo (en otras palabras, entre la antigua y la nueva), y a
continuación con la tabla de trabajos. Todo esto sirve para encontrar los valores de la tabla de trabajos
que corresponden al trabajo que vamos a asignar al empleado.

Ahora se comprueba si el trabajo que estamos asignando es el 1, en cuyo caso el valor para el nivel
debería ser 10. Para ello comprobamos esta situación mediante un if y, en caso de que sea verdadero,
se lanza un error con la sentencia RAISERROR, y se cancela la transacción con ROLLBACK
TRANSACTION.

186
© Grupo EIDOS 21. Triggers en SQL – Server 2000

En otro caso se comprueba que el nivel de la tarea esté dentro de los límites permitidos para el
empleado. Si esto no se cumple se volverá a lanzar un error, y se cancelará la transacción.

Para los desconocedores del lenguaje C, quizá la última sentencia RAISERROR no les sea demasiado
clara. Destacar, simplemente, que cada %d que aparece dentro de la cadena de texto será sustituido
respectivamente por el valor de cada una de las tres últimas variables que aparecen dentro de dicha
sentencia.

187
Seguridad

Introducción
El de la seguridad es un tema muy importante, para la protección de la información, sobre todo en
entornos grandes, donde la amenaza de potenciales accesos indebidos es muy grande.

Podemos hablar de seguridad a dos niveles:

• Seguridad física: entendemos por seguridad física aquella que persigue salvaguardar los datos
de agresiones externas, como por ejemplo la destrucción de la base de datos, debido a aspectos
físicos, como por ejemplo un incendio o una inundación.

• Seguridad lógica: la seguridad lógica afecta a la protección de los datos de accesos u


operaciones no deseados, como por ejemplo, una consulta a información no autorizada por
parte de un usuario, el borrado de una tabla, o parte de sus atributos, etc.

En este capítulo nos centraremos en la seguridad lógica, ya que la seguridad física afecta a aspectos de
administración (copias de seguridad, mantenimientos de dispositivos duplicados con mirror, etc.) que
escapan a los objetivos del presente curso.

Concesión de privilegios
SQL Server mantiene un sistema de perfiles, en el que la principal división se establece entre el
administrador del sistema y el resto de usuarios. El administrador del sistema actúa al nivel de
superusuario, y puede realizar "casi" cualquier operación, mientras que un usuario corriente sólo podrá
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

realizar operaciones que afecten a sus objetos, o a los objetos que le permita el administrador u otro
usuario.

Los objetos de SQL Server (tablas, bases de datos, ...) tienen un propietario, que normalmente suele
ser el superusuario, o el usuario que lo haya creado. En principio, si otro usuario desea acceder a dicho
objeto, no podrá hacerlo, a menos que el propietario o el administrador le dé permiso. Los permisos se
pueden establecer en el ámbito de un usuario (conceder un privilegio a un usuario) o en el ámbito de
grupo o público (accesible por todos).

Del mismo modo, los permisos pueden ser propagados en cascada, esto es, un usuario puede dar
permiso a otro usuario, para que éste a su vez pueda dar permiso a otros.

La sentencia que permite otorgar privilegios es la siguiente:

GRANT sentencia TO usuarios

Por ejemplo, si queremos otorgar el permiso de crear bases de datos y tablas al usuario Pepe,
deberemos escribir la sentencia que muestra Código fuente 179

GRANT CREATE DATABASE, CREATE TABLE TO Pepe

Código fuente 179

Si queremos otorgar todos los permisos a todos los usuarios, deberemos escribir la sentencia que
aparece en el Código fuente 180.

GRANT ALL TO PUBLIC

Código fuente 180

Cuidado con esta sentencia ya que es muy peligroso dejar que cualquier usuario haga lo que quiera. De
todas maneras, este control corresponde al administrador del sistema.

Del mismo modo se pueden establecer privilegios sobre los objetos, en lugar de sobre las acciones. En
este caso, la sintaxis es la mostrada

GRANT permisos (columnas) ON tabla TO usuario

La sentencia GRANT permite establecer los permisos deseados (inserción, borrado, actualización)
sobre una serie de atributos de una tabla, a unos determinados usuarios. No sólo se pueden conceder
permisos en el ámbito de tabla, sino también en el ámbito de vista, o procedimientos almacenados.

Por ejemplo, si deseamos que todos los usuarios puedan consultar la tabla de autores, deberemos
escribir lo que indica el Código fuente 181.

GRANT SELECT ON authors TO PUBLIC

Código fuente 181

190
© Grupo EIDOS 22. Seguridad

Con esto lo que hacemos es conceder el permiso SELECT sobre la tabla Authors, a todos los usuarios.
Si queremos restringir el SELECT al campo au_lname, deberemos ejecutar el Código fuente 182.

GRANT SELECT (au_lname) ON authors TO PUBLIC

Código fuente 182

Y si deseamos que además de consultar se pueda actualizar, la sentencia en cuestión es la que muestra
el Código fuente 183.

GRANT SELECT, UPDATE ON authors TO PUBLIC

Código fuente 183

Si queremos propagar los privilegios, debemos adjuntar la opción WITH GRANT OPTION. Por
ejemplo, si queremos conceder el privilegio de ejecución de un procedimiento almacenado a un
usuario, y que éste a su vez pueda conceder este privilegio a otros usuarios, debemos escribir la
sentencia mostrada en el Código fuente 184.

GRANT EXECUTE ON procedure TO usuario WITH GRANT OPTION

Código fuente 184

Revocación de privilegios
La sentencia homóloga a la concesión de privilegios es REVOKE. Con esta sentencia podemos quitar
permisos a los usuarios sobre un objeto, o para ejecutar ciertas sentencias. La sintaxis para quitar
permisos sobre la ejecución de sentencias es la siguiente:

REVOKE sentencia FROM usuarios

donde sentencia especifica aquellas cuyos permisos se revocan, y usuarios establece una lista de
usuarios a los cuales se les aplicará dicha sentencia. Por ejemplo, si ejecutamos el Código fuente 185.

REVOKE CREATE DATABASE FROM alberto

Código fuente 185

Estamos impidiendo al usuario alberto la posibilidad de crear bases de datos.

Para revocar todos los permisos, deberemos especificar ALL como sentencia a aplicar.

191
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Así mismo, para que la sentencia tenga efecto para todos los usuarios de la base de datos, deberemos
establecer public en la lista de usuarios. Por ejemplo, el Código fuente 186 revoca todos los permisos
a todos los usuarios.

REVOKE ALL FROM PUBLIC

Código fuente 186

La sentencia para aplicar revocación de permisos a objetos aparece en el Código fuente 187.

REVOKE [GRANT OPTION FOR] permisos


[(atributos)] ON tabla FROM usuarios [CASCADE]
AS papel

Código fuente 187

La opción GRANT OPTION FOR es opcional, y permite revocar la propagación en cadena de


permisos a usuarios, es decir, éstos conservarán los suyos, pero no podrán autorizar a terceros. La
opción permisos permite especificar los permisos que se revocarán, pudiendo restringirlos a una serie
de atributos o a una o varias tablas. La opción CASCADE es opcional, y permite revocar privilegios
en cascada, es decir, a los usuarios especificados, y a todos los que éstos concedieron permisos. Por
último, la opción papel permite eliminar la ambigüedad que se puede originar cuando un usuario
pertenece a varios grupos, o tiene varios perfiles.

Por ejemplo, si queremos revocar los permisos de inserción de filas en la tabla autores, al usuario
Pepe, escribimos lo que indica el Código fuente 188.

REVOKE INSERT ON authors FROM Pepe

Código fuente 188

Si no queremos que dicho usuario consulte los atributos au_lname y au_fname de dicha tabla, la
sentencia a ejecutar aparece en el Código fuente 189.

REVOKE SELECT (au_lname, au_fname) ON authors FROM Pepe

Código fuente 189

Y si queremos revocar dicho permiso no sólo al usuario Pepe, sino también a todos los usuarios a los
que éste a otorgado dicho permiso, ejecutaremos el Código fuente 190.

REVOKE SELECT (au_lname, au_fname) ON authors FROM Pepe CASCADE

Código fuente 190

192
© Grupo EIDOS 22. Seguridad

Denegación de permisos
Otra opción es la de denegar un permiso a uno o varios usuarios. Lo que permite es que dichos
usuarios no obtengan privilegios, hasta que no se revoque dicha denegación. La sintaxis para denegar
permisos es la siguiente:

DENY sentencia TO usuarios

Y para objetos:

DENY permisos [(atributos)] ON tabla TO usuarios [CASCADE]

El funcionamiento es similar al ya visto en las anteriores sentencias.

Si por ejemplo, tenemos un usuario de la base de datos un tanto conflictivo, y no queremos que cree
bases de datos, bastará con revocarle el privilegio a hacerlo. Pero el problema surge cuando el
administrador del sistema se olvida de este detalle y, por error, le concede dicho permiso. Para evitar
que esto suceda, lo recomendable es denegar el permiso a dicho usuario.

DENY CREATE DATABASE TO conflictivo

Código fuente 191

De esta manera, mientras no se revoque dicha denegación, no se le podrán conceder privilegios para la
creación de bases de datos a dicho usuario. Del mismo modo podemos actuar para denegarle el
permiso de acceder a determinados campos de una tabla, como por ejemplo a los atributos au_lname y
au_fname de la tabla de autores.

DENY SELECT (au_lname, au_fname) ON authors TO conflictivo

Código fuente 192

Mantenimiento de vistas
Otro método para controlar la seguridad y el acceso indebido a los datos almacenados, consiste en
mantener vistas de la base de datos. Una vista es un conjunto de información que es accesible por uno
o varios usuarios. Como ya se vio en la parte anterior sobre diseño de bases de datos, las vistas se
corresponden con el esquema externo de la base de datos, es decir la porción de la base de datos que es
accesible a los usuarios. También se dijo que podía haber más de un esquema externo, lo que nos lleva
a pensar que la base de datos puede mantener varias vistas a la vez.

El lector se preguntará ¿por qué una vista impide realizar accesos indebidos?. Pues bien, la respuesta
es fácil. Puesto que una vista se puede contemplar como una consulta a una parte de la información, si
queremos que un usuario no acceda a determinados datos, le daremos vistas que no consulten dicha
información. Corresponde al administrador en este caso el estudio de las consultas que se pueden
realizar con relación a los usuarios del sistema, y otorgar permisos sobre las vistas a éstos.

La sintaxis del comando para la creación de vistas es la siguiente:

193
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

CREATE VIEW vista [(atributos)] [WITH ENCRYPTION] AS


sentencia [WITH CHECK OPTION]

La opción WITH ENCRYTION permite encriptar, es decir, ocultar, el código de la vista, mientras que
la opción WITH CHECK OPTION permite hacer visibles las modificaciones realizadas tras la
ejecución de la vista.

Por ejemplo, si queremos crear una vista sobre el atributo au_lname de la tabla authors, escribimos el
Código fuente 193.

CREATE VIEW autores (au_lname) AS


SELECT au_lname FROM authors

Código fuente 193

Si un usuario quiere consultar ahora los autores de la base de datos, deberá ejecutar la vista,
escribiendo la sentencia que muestra el Código fuente 194

SELECT * FROM autores

Código fuente 194

Recomendaciones
Por último, existen una serie de recomendaciones, que todo administrador que se precie debe tener en
cuenta a la hora de implementar la seguridad de una base de datos:

• Proporcionar un único identificador a cada usuario, para de esta manera saber en todo
momento quien está haciendo qué.

• Establecer perfiles y grupos de usuarios, de forma jerárquica incluso, ya que permite


establecer más fácilmente los niveles de seguridad.

• Proporcionar a los usuarios procedimientos almacenados para la inserción, actualización y/o


borrado de filas, ya que permite controlar mejor los usos indebidos de estas sentencias.

• Usar triggers para evitar ciertas operaciones no deseadas.

194
Ejemplo práctico de implementación

Introducción
En este capítulo, estudiaremos un ejemplo, para recopilar los conocimientos aprendidos a lo largo del
curso. El problema en sí es mantener una base de datos de ornitología (ciencia que estudia las aves).
Se desea almacenar la información de cada una de las especies del país. De cada especie se quiere
conocer el nombre de la misma, el nombre científico, la clase a la que pertenece y el tipo de árbol en el
que anida, así como si es un ave migratoria o no. De cada clase de árbol, se desea conocer su nombre,
el tipo de hoja, y la región de la cual es autóctono.

Por consiguiente, tenemos las siguientes entidades:

• ave: cod_ave, nombre, nom_cientifico, clase, migratoria, observaciones

• árbol: cod_arbol, nombre, tipo_hoja

• región: cod_region, desc_region

Las relaciones que tenemos son las siguientes:

• ave-árbol: un ave puede anidar en varios tipos de árboles, y en un árbol pueden anidar varias
especies (N-M).

• árbol-región: un árbol puede ser autóctono de varias regiones, y en una región puede haber
distintas clases de árboles (N-M).
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Con la anterior información, podemos obtener el diagrama entidad-relación que vemos en la Figura
94.

Figura 94

Una vez realizado el diseño conceptual, el siguiente paso es realizar el diseño lógico, cuya primera
etapa es el paso a tablas. Cada entidad genera una tabla, con sus atributos, y las relaciones N-M
generan también tabla, con las claves de ambas entidades como atributos. Con esto, nos queda el
esquema lógico que muestra la Figura 95.

Figura 95

El siguiente paso en el diseño es realizar el diseño físico, ya que en nuestro caso no se aplicarán
métodos de normalización o particionamiento. Lo que realizaremos es codificar las instrucciones
necesarias en Transact SQL, para obtener el esquema físico. Destacar que lo que aquí entendemos por
diseño físico, también engloba al diseño lógico específico, al usar un SGBD concreto para la
implementación.

Para implementar el esquema en Transact SQL, utilizaremos el Query Analizer de SQL Server.

Lenguaje de definición de datos


Lo primero que haremos será crear la base de datos, a la que denominaremos ornitología, para lo cual
escribimos el Código fuente 195.

CREATE DATABASE ornitologia

Código fuente 195

Una vez creada la base de datos, nos conectamos a ella, seleccionándola de la lista desplegable que
aparece en la parte superior derecha del Query Analizer.

196
© Grupo EIDOS 23. Ejemplo práctico de implementación

A continuación crearemos las tablas obtenidas en el esquema lógico. Empezaremos por crear la tabla
ave.

CREATE TABLE ave (


cod_ave smallint NOT NULL,
nombre varchar(30) NOT NULL,
nom_cientifico varchar(30),
clase varchar(10),
migratoria bit)

Código fuente 196

En la anterior sentencia cabe destacar que los atributos cod_ave y nombre han sido declarados como
no nulos, es decir, no se podrá insertar filas que no tengan valores nulos para dichos atributos. Para
especificar si un ave es migratoria o no, se utilizará un campo bit, es decir, un 0 para indicar que el ave
no es migratoria, y un 1 si lo es. Análogamente, creamos la tabla arbol.

CREATE TABLE arbol (


cod_arbol smallint NOT NULL,
nombre varchar(30) NOT NULL,
tipo_hoja varchar(10))

Código fuente 197

Seguimos con la tabla de regiones.

CREATE TABLE region (


cod_region smallint NOT NULL,
desc_region varchar(30) NOT NULL)

Código fuente 198

Y por último las tablas que las relacionan, que son ave_arbol, y arbol_region:

CREATE TABLE ave_arbol (


cod_ave smallint NOT NULL,
cod_arbol smallint NOT NULL)
CREATE TABLE arbol_region (
cod_arbol smallint NOT NULL,
cod_region smallint NOT NULL)

Código fuente 199

Una vez creadas las tablas, el siguiente paso es crear los índices para ellas. Empezaremos por crear un
índice único que será la clave de la tabla ave, al que llamaremos clave, y que utilizará el campo
cod_ave.

197
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

ALTER TABLE ave ADD CONSTRAINT clave_av PRIMARY KEY (cod_ave)

Código fuente 200

Análogamente hacemos con las demás tablas, donde los índices de clave única serán por cod_arbol
para la tabla arbol, por cod_región para la tabla región, por cod_arbol y cod_region para la
tabla.arbol_region, y por cod_ave y cod_arbol para la tabla ave_arbol:

ALTER TABLE arbol ADD CONSTRAINT clave_ab PRIMARY KEY (cod_arbol)


ALTER TABLE region ADD CONSTRAINT clave_re PRIMARY KEY (cod_region)
ALTER TABLE ave_arbol ADD CONSTRAINT clave_aa PRIMARY KEY (cod_ave,cod_arbol)
ALTER TABLE arbol_region ADD CONSTRAINT clave_ar PRIMARY KEY (cod_arbol,cod_region)

Código fuente 201

Oh, !vaya!, nos hemos olvidado de definir un atributo para la tabla ave. Pero eso no es problema, ya
que podemos modificar cómodamente el esquema de dicha tabla, mediante la sentencia ALTER, para
introducir un nuevo campo.

ALTER TABLE ave ADD observaciones text NULL

Código fuente 202

Por último, es labor del administrador el decidir a quien y sobre que objetos otorga qué permisos.
Nosotros, de momento, crearemos una vista para consultar todas las aves que son migratorias

CREATE VIEW migratorias AS


SELECT nombre FROM ave WHERE migratoria = 1

Código fuente 203

Lenguaje de manipulación de datos


Hasta ahora hemos estado utilizando el Lenguaje de Definición de Datos, para definir el esquema. A
continuación utilizaremos el Lenguaje de Manipulación de Datos para introducir información en el
esquema, y para realizar algunas consultas. Empezaremos añadiendo los siguientes datos:

• Tabla ave

Cod_ave Nombre Nom_cientifico Clase Migratoria Observaciones

1 Flamenco Zancuda Si Migran en grupo


hacia lugares cálidos

2 Pato salvaje Palmípedo No

198
© Grupo EIDOS 23. Ejemplo práctico de implementación

3 Mirlo Si Emite un sonido muy


Blanco peculiar

4 Golondrina Golondrina Si Famosas por los


común versos de Becquer

Tabla 33

INSERT INTO ave (cod_ave, nombre, clase, migratoria, observaciones)


VALUES (1, 'Flamenco', 'Zancuda', 1, 'Migran en grupo hacia lugares cálidos')
INSERT INTO ave (cod_ave, nombre, clase, migratoria)
VALUES (2, 'Pato salvaje', 'Palmipedo', 0)
INSERT INTO ave (cod_ave, nombre, migratoria, observaciones)
VALUES (3, 'Mirlo Blanco', 1, 'Emite un sonido muy peculiar')
INSERT INTO ave (cod_ave, nombre, nom_cientifico, migratoria, observaciones)
VALUES (4, 'Golondrina', 'Golondrina común', 1, 'Famosas por los versos de
Becquer')

Código fuente 204

• Tabla árbol

Cod_arbol Nombre Tipo_hoja

1 Encina Caduca

2 Roble Perenne

3 Naranjo Caduca

4 Pino Perenne

Tabla 34

INSERT INTO arbol (cod_arbol, nombre, tipo_hoja)


VALUES (1, 'Encina', 'Caduca')
INSERT INTO arbol (cod_arbol, nombre, tipo_hoja)
VALUES (2, 'Roble', 'Perenne')
INSERT INTO arbol (cod_arbol, nombre, tipo_hoja)
VALUES (3, 'Naranjo', 'Caduca')
INSERT INTO arbol (cod_arbol, nombre, tipo_hoja)
VALUES (4, 'Pino', 'Perenne')

Código fuente 205

199
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

• Tabla región

Cod_region Desc_region

1 Centro

2 Sur

3 Nor-noroeste

4 Pirineos

5 Levante

Tabla 35

INSERT INTO region (cod_region, desc_region)


VALUES (1, 'Centro')
INSERT INTO region (cod_region, desc_region)
VALUES (2, 'Sur')
INSERT INTO region (cod_region, desc_region)
VALUES (3, 'Nor-noroeste')
INSERT INTO region (cod_region, desc_region)
VALUES (4, 'Pirineos')
INSERT INTO region (cod_region, desc_region)
VALUES (5, 'Levante')

Código fuente 206

Supongamos ahora que nos dicen que puede haber pinos en las regiones centro, nor-noroeste y
Pirineos, naranjos en la región Levante, encinas en las regiones centro, sur y nor-noroeste y robles en
la región centro. Lo que tenemos que hacer es dar de alta estas filas en la tabla arbol_region, con los
valores correspondientes a cada código de arbol y región.

INSERT INTO arbol_region (cod_arbol, cod_region)


VALUES (4, 1)
INSERT INTO arbol_region (cod_arbol, cod_region)
VALUES (4, 3)
INSERT INTO arbol_region (cod_arbol, cod_region)
VALUES (4, 4)
INSERT INTO arbol_region (cod_arbol, cod_region)
VALUES (3, 5)
INSERT INTO arbol_region (cod_arbol, cod_region)
VALUES (1, 1)
INSERT INTO arbol_region (cod_arbol, cod_region)
VALUES (1, 2)
INSERT INTO arbol_region (cod_arbol, cod_region)
VALUES (1, 3)
INSERT INTO arbol_region (cod_arbol, cod_region)
VALUES (2, 1)

Código fuente 207

200
© Grupo EIDOS 23. Ejemplo práctico de implementación

Supongamos ahora que nos dicen que el mirlo blanco anida en los naranjos y en los pinos, y que los
patos salvajes anidan en los estanques donde preferentemente haya encinas.

Lo que hay que hacer es crear las filas correspondientes a cada uno de los códigos en la tabla
ave_arbol.

INSERT INTO ave_arbol (cod_ave, cod_arbol)


VALUES (3, 3)
INSERT INTO ave_arbol (cod_ave, cod_arbol)
VALUES (3, 4)

INSERT INTO ave_arbol (cod_ave, cod_arbol)


VALUES (2, 1)

Código fuente 208

Puesto que de momento no hemos encontrado ningún mirlo blanco, cambiaremos este ave por el mirlo
común. Para ello debemos actualizar la fila correspondiente, con la sentencia que aparece en el Código
fuente 209.

UPDATE ave SET nombre = 'Mirlo común'


WHERE nombre = 'Mirlo blanco'

Código fuente 209

Supongamos ahora que queremos realizar las siguientes consultas, cuyas sentencias se especifican a
continuación:

• Todos los árboles de la región centro:

SELECT nombre FROM arbol, arbol_region, region


WHERE region.desc_region = 'centro'
AND region.cod_region = arbol_region.cod_region
AND arbol_region.cod_arbol = arbol.cod_arbol

Código fuente 210

Lo que hace la anterior sentencia es obtener el atributo desc_arbol de la tabla arbol. Para ello,
primero se pone la condición de que la región debe ser centro.

Con las filas obtenidas, hacemos un join contra la tabla arbol_region, para obtener el código
de los árboles cuya región es centro. Si ahora queremos obtener la descripción del árbol,
deberemos realizar otro join contra la tabla árbol. El resultado obtenido son los árboles pino,
encina y roble.

• El número de aves que son migratorias. Para ello deberemos contar todas las filas de la tabla
ave, cuyo atributo migratoria tenga el valor true.

201
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

SELECT count(*) FROM ave WHERE migratoria = 1

Código fuente 211

El resultado obtenido es el de 3 aves.

• El nombre de las aves que anidan en árboles de hoja caduca ordenados alfabéticamente. Lo
que debemos hacer es seleccionar primero todas las filas cuyo atributo tipo_hoja para luego
hacer el join de estas filas con la tabla ave_arbol por el campo cod_arbol, para obtener así el
código de las aves que anidan en dichos árboles. Acto seguido, si queremos obtener el nombre
de las aves, deberemos realizar un join de las filas obtenidas, con la tabla ave, por el atributo
cod_ave y proyectar sobre nombre. La anterior explicación se resume en la sentencia mostrada
en el Código fuente 212.

SELECT ave.nombre FROM arbol, ave_arbol, ave


WHERE arbol.tipo_hoja = 'caduca'
AND arbol.cod_arbol = ave_arbol.cod_arbol
AND ave_arbol.cod_ave = ave.cod_ave
ORDER BY ave.nombre

Código fuente 212

Como resultado del Código fuente 212, obtenemos que dichas aves corresponden al mirlo blanco y
al pato salvaje
Si ahora queremos consultar todas las aves que son migratorias, podemos aprovechar la vista anterior,
para hacerlo ejecutamos el Código fuente 213.

SELECT * FROM migratorias

Código fuente 213

202
Presente y futuro de las bases de datos

La evolución de las bases de datos en los últimos años, ha permitido el afianzamiento de un modelo
que se ha tomado como base de la práctica totalidad de los SGBD existentes en la actualidad, el
modelo relacional. Sin embargo, no ha sido sino hasta hace unos pocos años cuando este modelo vio la
luz, como consecuencia de una necesidad de simplificación de los primeros modelos que se usaron
como base.

Como ya se ha comentado, los primeros modelos que surgieron fueron el jerárquico y el modelo en
red. El primero nació como una conceptualización de la forma de entender las relaciones entre los
objetos, es decir, una clasificación natural, que permitía navegar entre ellos para obtener la
información que se necesitaba.

Para que el lector lo comprenda mejor, era una especie de clasificación del modo “pais – comunidad –
provincia – localidad” o “empresa – departamento – empleado”. Las relaciones entre los objetos se
establecían de una manera natural, mediante referencias a los mismos.

El modelo en red nació como una ampliación del modelo jerárquico, en el cual ya no se tienen árboles,
sino grafos, lo cual dificulta ampliamente la definición y el manejo del esquema. Sería algo del estilo
“empresa – empleado – empresa ...”.

Sin embargo, la evolución de estos modelos, dieron lugar a uno nuevo, el relacional, cuya simplicidad
y potencia revolucionaron el mercado de las bases de datos. A pesar de ello, la evolución siguió otra
rama alternativa, dando lugar a las denominadas bases de datos orientadas a objetos. Aunque fueron
muchos los que apostaron por éstas, la realidad es que en la actualidad su uso no supera el 5% de la
cuota de mercado con respecto al modelo relacional.
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Debido a lo anterior, fueron muchos los que pensaron que no sería mala idea unir lo mejor de ambos
modelos: el relacional y el orientado a objetos. Así nace el modelo objeto-relacional. Tomando como
base el relacional, une a éste la funcionalidad que ofrece la orientación a objetos. De esta forma se
tienen relaciones en forma de tablas, cuyos atributos pueden ser a su vez referencias a objetos, además
de incorporar sus propios métodos. Por ejemplo, se puede tener el atributo domicilio que se puede
descomponer en calle, provincia y localidad, que tendría el método alta(), que se ejecutaría cada vez
que se da de alta un nuevo domicilio.

Como el lector ya habrá podido comprobar, en estos modelos ni siquiera se cumple la 1FN, lo cual
desbarata prácticamente todo el proceso de normalización. Además, se necesitará un lenguaje especial
para definir y manejar la información. Surge entonces el SQL:1999 como lenguaje estándar para el
acceso y definición de este tipo de esquemas.

Por otro lado, no paran de surgir nuevos estudios y propuestas de modelos que amplían los ya
existentes. Así por ejemplo, podemos encontrar bases de datos espaciales (para manejo de información
en tres dimensiones), bases de datos fuzzy (o que manejan información imprecisa, como por ejemplo
alto, joven, caro, y que ya disponen de su propio lenguaje), y así un sinfín de posibilidades.

Sin embargo, lo que más expectación esta suscitando actualmente, y que se prevé tenga un mayor
impacto si cabe, en un futuro no muy lejano, es el data warehousing y el data mining.

Por data warehousing se entiende el almacenamiento masivo de los datos que gestiona una empresa,
que debido al avance y mejora de los SGBD actuales, permite una mejor gestión de los mismos. Así
por ejemplo, cabe imaginar, por ejemplo, una empresa que dispone de cantidades ingentes de
información (empleados, clientes, proveedores, ventas, compras), que en un principio es gestionada
desde ámbitos distintos, y puede no tener relación ninguna entre sí (cada departamento manejaría
únicamente la información relevante al mismo). Pues bien, el concepto de data warehousing (en lo
sucesivo DW) se refiere a la posibilidad de integrar toda esta información, que aparece dispersa en el
ámbito del negocio, para su mejor gestión, de una forma más eficaz y eficiente, de tal manera que
dicha información pueda ser utilizada más provechosamente.

De esta forma se puede obtener, mediante herramientas específicas (OLAP, ROLAP, etc.) información
de una manera más útil. Por ejemplo, se pueden utilizar los denominados data marts, que son una
especie de vistas con la información que interesa obtener, con la peculiaridad que el acceso se realiza
en varias dimensiones de una forma más eficaz (por ejemplo las ventas por proveedores en cada
región).

En cambio, este proceso, como puede imaginar el lector, es una tarea ardua, tediosa y difícil, que
implica una carga, filtrado y proceso de los datos, para evitar incoherencias, duplicidades e
información irrelevante, y se resume en la Figura 96.

Una vez que se tiene el DW, se pueden aplicar procesos que permitan una obtención de información
añadida, que no aparece de manera explícita en el mismo. Una de las técnicas más importantes de
extracción de información es la denominada data minning o minería de datos (en lo sucesivo DM).
Como su propio nombre indica, consiste en la navegación a través de los datos para inferir
conocimiento mediante técnicas de Inteligencia Artificial, que no se encuentra de manera explícita.

Esta técnica es muy útil sobre todo en el ámbito del marketing y publicidad, para obtener, por ejemplo,
posibles clientes potenciales para una campaña comercial, o personalizar el tipo de información que un
cliente puede recibir, entre otras.

204
© Grupo EIDOS 24. Presente y futuro de las bases de datos

Figura 96

Ya existen en el mercado varios productos que soportan tanto el DW como el DM, pero que, debido a
su elevado precio, hacen que todavía sea un mercado que no se encuentre al alcance de todo el mundo,
pero que se espera crezca positivamente en un futuro no muy lejano.

Sin embargo, SQL Server 2000 ya nos permite adentrarnos es este mundo, ofreciéndonos diversas
posibilidades de las ya mencionadas, como resume la Figura 97.

Figura 97

205
Diseño conceptual con Power Designor

Introducción
Empezaremos dando respuesta a la pregunta "¿qué es Power Designor?". Pues bien, se puede
decir que Power Designor es una herramienta CASE para el diseño de bases de datos. Una
herramienta CASE es aquella que permite al usuario la realización de unas determinadas tareas de
forma fácil y precisa. En nuestro caso, Power Designor permite al usuario establecer el diseño de un
esquema relacional, de forma clara y sencilla, evitándole tareas engorrosas, como el paso del diseño
conceptual al físico, etc.

Power Designor abarca dos de las tres grandes etapas del diseño de un esquema relacional:

1. El diseño conceptual

2. El diseño físico

El diseño conceptual permite establecer la definición de las tablas, las relaciones entre éstas y su
cardinalidad, los atributos y sus tipos, las claves, etc., mientras que el diseño físico comprende la
definición de índices, la redundancia controlada de datos, y en general todos los aspectos relacionados
con esta fase de diseño. Además nos permite pasar fácilmente del esquema conceptual, al esquema
físico, y realizar ingeniería inversa, es decir, obtener el esquema conceptual de una base de datos, con
sólo conocer su esquema físico. Y no solo esto, sino que también se ofrece la posibilidad de generar un
script (trozo de código) que es capaz de crear el esquema físico para una plataforma y un SGBD
concreto.

Los tipos de archivos manejables por Power Designor son dos:


Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

1. Extensión CDM: contiene la definición del esquema conceptual (Conceptual Data Model)

2. Extensión PDM: contiene la definición del esquema físico (Physical Data Model)

Power Designor se compone de cuatro módulos:

• Data Architect: se encarga de la definición de los esquemas conceptual y físico. Es en el que


nos centraremos.

• MetaWorks: útil para el trabajo en red de varios diseñadores.

• AppModeler: para la modelación del esquema físico.

• ProcessAnalist: para realizar el diseño de procesos, es decir, diagramas de flujo de datos.


Comprende la etapa de diseño del ciclo de vida del software.

Creación de una entidad


Para entrar en la aplicación, ejecutar el módulo DataArchitect. Acto seguido nos sale una pantalla
en blanco. Para crear un nuevo esquema conceptual, acceder al menú File-New. Nos aparecerá una
pantalla en blanco junto con una barra de herramientas, su apariencia se muestra en la Figura 98.

Figura 98

Para crear una nueva entidad, se deberá pulsar el botón de creación de entidades, y hacer click con el
botón izquierdo del ratón en cualquier parte de la pantalla. Una vez que tengamos creada la entidad, se
deberán definir sus propiedades, es decir, su nombre, atributos y tipos, claves de la entidad, etc. Para
ello tenemos dos formas: pulsar el botón de definición de entidades y hacer click izquierdo sobre la
entidad, o hacer doble click sobre dicha entidad. La pantalla que nos aparece se muestra en la Figura
99.

En ella se deberá teclear el nombre que le demos a la entidad, un código que representará de manera
unívoca a la entidad, y se deberá especificar si la entidad generará tabla en el esquema físico. Pulsando
el botón Rules se podrán definir las Bussiness Rules o Reglas de Negocio, es decir, las

208
© Grupo EIDOS Apéndice A. Diseño conceptual con Power Designor

restricciones que determinar el comportamiento de las entidades y/o sus relaciones. "Un cliente no
puede pedir un crédito superior a 1.000 euros" o "un proveedor sólo puede atender a un cliente" son
ejemplos de reglas de negocio. En este apartado también se definen las reglas de integridad
referencial.

Figura 99

Las reglas de negocio pueden ser de los siguientes tipos:

• Validación: Especifican las restricciones que puede tener un valor en el esquema. Ej: el
crédito de un cliente no puede superar el 20% de su compra.

• Hecho: Describen los hechos o forma de funcionar de la empresa. Ej: un cliente puede
realizar uno o más pedidos.

• Definición: Especifican características o propiedades de un objeto en el sistema de


información. Ej: un cliente es una persona identificada por su DNI y por su
nombre.

• Fórmula: Definen los cálculos a realizar en el sistema de información. Ej: la suma total de los
pedidos realizados por un cliente.

La pantalla para la asignación de reglas de negocio a una entidad aparece en la Figura 100

Para añadir una regla, bastará con pulsar el Botón Add... y nos aparecerá una lista con todas las reglas
definidas. Si todavía no se ha introducido ninguna, será preciso pulsar el botón List... para hacerlo. La
pantalla que nos permite definir las reglas de negocio es la que se muestra en la Figura 101.

Si queremos introducir una nueva regla, habrá que pulsar el botón New, especificar el nombre y el
código de la regla, y el tipo de ésta. Pulsando el botón Define se visualizará la siguiente pantalla, en la

209
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

que podremos teclear la descripción de la regla o la formula aplicable, dependiendo del tipo de regla
que hayamos escogido. Además se puede especificar si la expresión a evaluar se desea ejecutar en el
cliente o en el servidor.

Figura 100

Figura 101

La principal ventaja de ejecutar una expresión en el servidor radica en la velocidad de ejecución de la


misma, aunque la mayor desventaja es, sin duda, la probabilidad de cargar al servidor con demasiado
trabajo, lo que implica una ganancia de tiempo no tan drástica.

210
© Grupo EIDOS Apéndice A. Diseño conceptual con Power Designor

Figura 102

Volvemos a la pantalla de definición de entidades para determinar los atributos de la entidad, para lo
cual pulsamos el botón Atributtes. Se mostrará entonces una nueva ventana, cuyo aspecto se muestra
en la siguiente figura, en la que podremos incluir nuevos atributos para dicha entidad. Para ello se
dispone de dos opciones:

1. Pulsar el botón New e introducir el nombre, código y tipo de dato, o

2. Pulsar el botón Add... lo cual permitirá seleccionar un atributo de entre los ya existentes en el
sistema de información.

Figura 103

211
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

De esta pantalla cabe destacar dos cosas. Una es la posibilidad de determinar un atributo como
identificador (identifier), es decir, ese atributo será clave para dicha entidad, o como obligatorio
(mandatory) en cuyo caso dicho campo deberá tener siempre un valor no nulo. Recuérdese que un
valor nulo no es ni el cero ni el espacio en blanco, simplemente es un valor que no tiene valor (valga la
redundancia). La segunda es el tipo de atributo. Power Designor nos permite escoger entre una amplia
gama de tipos de datos, dejando al usuario la posibilidad de especificar su longitud y precisión. Dichos
atributos serán traducidos a los tipos específicos del SGBD con el que se vaya a trabajar (recordar
que en la definición del esquema conceptual no se tiene por qué saber la implementación física que se
va a realizar). Dentro de esta pantalla también se puede especificar el dominio de un atributo, es decir,
el rango de valores que puede tomar. En la lista desplegable etiquetada como Domain se puede
seleccionar el dominio que se va asignar a ese atributo. En el caso de que no tengamos definido ningún
dominio todavía, se podrá acceder a la pantalla que permite hacerlo, pulsando el botón .... Ésta tiene
un aspecto muy parecido al de todas las pantallas de definición vistas hasta ahora.

Figura 104

Para incluir un nuevo dominio, se deberá pulsar el botón New e introducir el nombre, código y tipo de
dato de éste. La definición en si del dominio se establece al pulsar el botón Check en el que se
mostrará una nueva pantalla, como la Figura 105, que permite establecer las principales características
del dominio.

En la carpeta de Standard Parameters es donde se especificará el rango que tomará el atributo. En este
caso se ha introducido un dominio para los números telefónicos, que variará entre 600.000.000 (para
los móviles) y 999.999.999 (para los fijos), también se puede introducir directamente la lista de
valores que puede tomar, introduciéndolos en la lista de la derecha, e introducir otro tipo de
restricciones como son el caso de las mayúsculas o minúsculas en los caracteres, o no permitir la
modificación del atributo.

En la carpeta de Validation Rules (Figura 106), es donde se permite la definición de restricciones mas
especificas. En nuestro caso se ha optado por la expresión ofrecida por defecto.

Se ha visto hasta ahora que en la mayoría de las pantallas aparecen dos botones (o carpetas) con los
nombres Description y Annotation. La utilidad de ambos es la de disponer de un editor que permite la
introducción de textos explicatorios y/o aclaratorios, en las definiciones de atributos, entidades y otros.

212
© Grupo EIDOS Apéndice A. Diseño conceptual con Power Designor

Figura 105

Figura 106

Creación de relaciones
Se hablará en este apartado de las relaciones entendidas como la "unión" o relación entre dos
entidades. Para crear una relación entre dos entidades pulsaremos el botón de relación entre entidades
de la paleta de herramientas. Acto seguido haremos click derecho con el ratón en la entidad origen y,

213
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

sin soltarlo, lo moveremos hasta la entidad destino. La Figura 107 muestra la relación existente entre
las entidades cliente y proveedor.

Figura 107

Una vez definida la relación, el siguiente paso es establecer la cardinalidad de la misma. Nuevamente,
para obtener el cuadro de diálogo de definición de propiedades, haremos doble click sobre la relación,
obteniendo algo parecido a la Figura 108.

Figura 108

Es aquí donde se deberá establecer la cardinalidad máxima y mínima de la relación en ambos sentidos.
Por ejemplo, podemos decir que un proveedor puede distribuir a uno o más clientes. Es decir, cada
ocurrencia de la entidad proveedor puede relacionarse con una (cardinalidad mínima) o varias
(cardinalidad máxima) ocurrencias de la entidad cliente. En el sentido contrario, un cliente sólo puede
abastecerse de un proveedor, lo que implica cardinalidad mínima y máxima uno.

Para establecer la cardinalidad máxima, se dispone de unos botones de selección, bajo el nombre de
Cardinality. Si escogemos la opción One, estamos diciendo que la cardinalidad máxima será uno,
mientras que si se selecciona la opción Many, se estará indicando que la cardinalidad máxima es
muchos (o N). Para determinar la cardinalidad mínima, se dispone de otros botones de selección, bajo

214
© Grupo EIDOS Apéndice A. Diseño conceptual con Power Designor

el nombre Existence. Si indicamos la opción Optional, quiere decir que la cardinalidad mínima es
cero, mientras que si se escoge la opción Mandatory se obliga a que la cardinalidad mínima será uno.

Un tipo especial de relación es la relación de dependencia. Como ya se estudio en anteriores temas,


una relación de este tipo indica que depende de otra relación para su identificación. Si por ejemplo se
tiene la entidad pedido con los pedidos realizados por un cliente, y la entidad linea_pedido, con los
detalles de cada pedido, esta última entidad tiene una relación de dependencia con aquella, ya que no
se sabrá a que línea de pedido nos estamos refiriendo, sin saber a que pedido corresponde. Para indicar
una relación de este tipo, bastará con seleccionar la caja de selección denominada Is dependent.

Nuevamente nos encontramos en esta ventana con el botón Rules, en el cual podremos establecer las
reglas de negocio, además de disponer de otras dos carpetas para introducir cualquier descripción que
se nos ocurra.

La relación de herencia
Otro tipo especial de relación es la relación de herencia. Consiste en la propiedad que tienen algunas
entidades de heredar el comportamiento de otras. Por ejemplo, podemos tener tres entidades:
automóvil con los atributos marca, modelo, precio y num_puertas, la entidad motocicleta con los
atributos marca, modelo, precio y cilindrada y la entidad bicicleta con los atributos marca, modelo,
precio y num_cambios. Pero si nos damos cuenta, las tres relaciones tienen tres atributos en común,
marca, modelo y precio. Podemos aprovechar esta ventaja para definir una relación de herencia,
suponiendo que estas son características básicas de cualquier vehículo. De esta forma se tendrá una
relación vehículo con los atributos marca, modelo y precio, de las que heredarán las entidades
automóvil con atributo num_puertas, motocicleta con atributo cilindrada y bicicleta con atributo
num_cambios. Ni que decir tiene, que estas relaciones, con atributos privados o específicos a cada
una, heredan o importan los atributos de la entidad padre. El ejemplo se representa como indica la
Figura 109.

Figura 109

Para establecer una relación de herencia, se deberá escoger en la paleta el botón relación de herencia,
seleccionar una relación, pinchar en la relación padre, y a continuación pinchar en las demás
relaciones llevándolas hasta el punto de unión.

215
Diseño físico con Power Designor

Paso del esquema conceptual al esquema físico


Una vez realizado el diseño del esquema conceptual, el siguiente paso es obtener el esquema físico.
Cabe destacar que Power Designor no da la posibilidad de realizar la fase intermedia de diseño lógico,
sino que ésta está divida entre las fases de diseño conceptual y diseño físico. Por ejemplo, si queremos
realizar un particionamiento vertical, será preciso generar el esquema físico y cambiarlo según
nuestras pretensiones y/o necesidades.

Para generar el esquema físico a partir del conceptual, se puede seleccionar la opción de menú
Dictionary - Generate Physical Model o pulsar las teclas Ctrl-G. Automáticamente aparece una
pantalla, como la mostrada en la Figura 110.

En la parte superior se especifica el SGBD específico sobre el cual se generará el esquema físico. Esto
es importante, sobre todo, para determinar las restricciones del SGBD, los tipos de datos del mismo,
etc. Justo debajo se nos preguntará por el nombre del fichero en el que se guardará el modelo físico,
con extensión .PDM. En la carpeta Generation se nos sigue preguntando una serie de parámetros. Por
ejemplo, permite especificar el nombre de los índices primarios y ajenos (campos que son clave en
otras entidades) que se generarán para cada tabla. También se puede decir si las reglas de actualización
o de borrado se propagarán a todas las tablas o sólo a la que afecte, etc. En la segunda carpeta se nos
da la opción de preservar ciertos cambios, como por ejemplo los gráficos, las etiquetas, o las reglas de
negocio.

Una vez que estemos seguros de haber dado las opciones correctas, pulsaremos el botón OK y, tras un
breve período de tiempo nos aparecerá un mensaje con el resultado de la generación; si algo ha
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

fallado, se deberá revisar nuevamente el esquema conceptual, en otro caso tendremos el


correspondiente esquema físico.

Figura 110

Modificación de las tablas

Figura 111

218
© Grupo EIDOS Apéndice B. Diseño físico con Power Designor

Una vez generado el esquema físico, podremos adecuarlo a nuestro gusto, teniendo en cuentas las
necesidades del sistema, y las restricciones del SGBD. De esta manera será preciso realizar un estudio
detallado de las consultas que se realizarán a la base de datos, de la velocidad del hardware, del
número de actualizaciones, etc., para de esta forma, conseguir una mayor eficiencia.

En este caso ya podemos hablar de tablas, es decir, de la concreción física de las entidades diseñadas
en el esquema conceptual. Podemos empezar modificando las características de las tablas, para lo que
será necesario hacer doble click sobre una de ellas, apareciéndonos la Figura 111.

En ella podemos especificar varias características, que estudiaremos a continuación en detalle.

Columnas
La edición de columnas consiste en borrar, insertar y/o cambiar la definición uno o más atributos de
las tablas. La forma de hacerlo es similar a la pantalla mostrada en el anterior tema acerca de la
definición de atributos, salvo que en esta se puede determinar un atributo como clave ajena (atributo
que es clave en otra tabla).

Otra funcionalidad que ofrece Power Designor es la definición de atributos extendidos, que permite la
determinación de ciertas características correspondientes a los atributos de una tabla, como pueden ser
la forma de visualización (lista desplegable, editor, etc.), el valor inicial o por defecto del mismo,
etiquetas, cabeceras, comentarios que se mostrarán a la hora de visualizarlos, etc. A esta funcionalidad
se accede pulsando el botón Extended, ante el cual aparece la Figura 112.

Figura 112

Indices
La definición de los índices de una tabla es otra de las características del diseño físico ya estudiadas,
cuyo cometido es el aumento de eficiencia a la hora de realizar las consultas. Recuérdese, sin

219
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

embargo, la desventaja que supone el tener una tabla de índices demasiado extensa, a la hora de
realizar actualizaciones. Por lo tanto, es preciso realizar un estudio detallado de las transacciones que
se darán en la base de datos.

Para acceder a la pantalla de definición de índices, se deberá pulsar el botón Indexes. Dicha pantalla
tiene la apariencia de la Figura 113.

Figura 113

Para definir un nuevo índice, pulsaremos el botón New, teclearemos su nombre, y especificaremos su
tipo, de entre los siguientes:

• Primary key: índice por clave primaria. Es el índice que se seguirá por defecto, y define los
atributos que son clave en la tabla.

• Foreign key: es el índice que hace referencia a campos de la tabla, que son clave en otra tabla.

• Unique: índice único, es decir, sus campos no pueden tener valores duplicados.

• Cluster: índice cluster, usado para recorrer los cluster de una base de datos (se remite al lector
al capítulo de diseño físico).

Para añadir campos a un índice, se pulsará el botón Add y se seleccionarán los atributos que se desean
añadir. Además se puede especificar la ordenación del índice, que puede ser ascendente o descendente.

En el botón Alternate Keys se pueden especificar claves alternativas o secundarias. Este es otro tipo de
claves, además de las primarias, que sirven para identificar una ocurrencia de una entidad en la base de
datos.

220
© Grupo EIDOS Apéndice B. Diseño físico con Power Designor

Atributos extendidos
Como ya se ha visto, la funcionalidad que ofrece Power Designor sobre atributos extendidos, permite
la modificación de ciertas características de éstos.

Sin embargo, pulsando el botón Extended, nos podemos encontrar con otra pantalla, totalmente
distinta a la mostrada anteriormente, pero cuya finalidad es la misma: modificar el aspecto de
visualización de estos atributos, y cuyo aspecto es el mostrado en la Figura 114.

Figura 114

Como se puede observar, en ella no se pueden definir formas de visualización de los atributos, ni
valores iniciales, ni nada por el estilo, pero nos permite establecer las fuentes (tipo de letra, tamaño,
estilo, etc.) con las cuales se mostrarán las tablas.

Triggers
Como su propio nombre indica, los triggers son disparadores, es decir, trozos de código que se
ejecutan cuando ocurre un determinado evento.

En esta funcionalidad, accesible mediante el botón Triggers, se pueden determinar las acciones que
tendrán lugar cuando ocurra un determinado evento, como por ejemplo, al insertar una tupla en la base
de datos. Este código es dependiente del SGBD, y define la acción que tendrá lugar ante ciertos
eventos.

La Figura 115 muestra un ejemplo de definición de trigger.

221
Bases de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Figura 115

Restricciones
Bajo el nombre restricción, se agrupa todo un conjunto de funciones que define el rango de valores
que puede tomar un determinado atributo, y todas las reglas que debe verificar una tabla. No se
ahondará más en este tema, ya que ya se ha estudiado en el capítulo sobre diseño conceptual, y cuyo
comportamiento es similar en el diseño físico.

Creación de vistas
Se entiende por vista, una porción de la base de datos, accesible por un usuario. Recuérdese la
definición de vista recogida en el capítulo de introducción, y cuyo conjunto correspondía a la
definición del nivel externo de la base de datos. Una vista permite la introducción de un nivel de
seguridad. Es decir, se definirán consultas, que afecten a un determinado número de tablas, y cada una
de ellas podrá ser accedida por uno o varios usuarios. Si no queremos que un usuario acceda a una
determinada tabla, simplemente se le ofrecerán vistas que no impliquen dicha tabla.

Para definir una vista en Power Designor, pulsaremos el botón y a continuación pincharemos en
cualquier punto de la pantalla. Para editarla, bastará con hacer doble click sobre ella, y nos aparecerá
una pantalla como la que aparece en la Figura 116.

En ella podemos definir las tablas que implica, pulsando el botón Tables, y la query o consulta,
pulsando el botón Query. Además se puede dar la opción de modificar el contenido de las tablas
(opción Updatable) o simplemente consultar (opción Query Only). La query se podrá definir mediante
el lenguaje SQL, pulsando el botón con dicho nombre.

222
© Grupo EIDOS Apéndice B. Diseño físico con Power Designor

Figura 116

223
Ejemplo de diseño con Power Designor

Para irnos familiarizándonos con el uso de S-Designar, vamos a tratar de resolver un planteamiento
utilizando esta herramienta.

Enterprise SL es una empresa de venta al público, quiere informatizar su sistema, de cara al euro y al
año 2000. Para ello nos ha encargado que diseñemos una base de datos que permita la introducción y
recuperación eficiente de datos. El funcionamiento de Enterprise SL es el siguiente. Existen una serie
de proveedores que abastecen a dicha empresa. A su vez, Enterprise SL desea tener almacenados los
datos de todos sus clientes. Por otra parte, de cara a Hacienda, desea simplificar el tema de la
facturación. Para ello desea tener almacenados todos los pedidos. Además desea conocer en todo
momento la disponibilidad de productos en el almacén, para realizar pedidos de forma automática,
cada vez que las existencias son inferiores a las 10 unidades de cada producto.

Lo primero realizar es un diseño del esquema conceptual. Para ello abrimos la utilidad DataArchitect
de S-Designar, y creamos un nuevo modelo conceptual (.CDM). A continuación empezamos a definir
entidades:

• Proveedor: nos interesa saber su código de proveedor, nombre, CIF, dirección, ciudad y
provincia.

• Cliente: de que se desea conocer su código de cliente, NIF, nombre, apellidos, dirección,
ciudad, provincia y teléfono.

• Producto: código de producto, descripción y existencias.

• Pedido: código de pedido.


Base de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

• Linea_pedido: código de la línea de pedido y cantidad.

• Factura: IVA e importe en pesetas y euros.

Empezamos creando las entidades. Pulsamos el botón entidad en la paleta de componentes y acto
seguido pulsamos seis veces en cualquier punto de la pantalla. Ya tenemos creadas las seis entidades.
El siguiente paso es definir los atributos de cada una de ellas. Para quitar la selección se puede pulsar
el botón flecha en la paleta, o hacer click con el botón derecho del ratón. Empezaremos por la entidad
proveedor. Para ello hacemos doble click sobre cualquiera de las entidades y, en la ventana que nos
aparece teclearemos el nombre de la entidad (Proveedor), y acto seguido pulsamos el botón
Attributes. Para crear un nuevo atributo pulsamos el botón New y le damos un nombre (CIF), un
código (que será también CIF) y un tipo de dato (tipo carácter de longitud 10, A10). Así procederemos
con el resto de atributos, teniendo en cuenta que la clave de dicha entidad será el atributo
cod_proveedor, por lo que tacharemos la caja de selección correspondiente a Identifier de dicho
atributo. La definición completa es la mostrada en la

Figura 117

Ahora se nos plantean dos opciones:

1. Dejar que el usuario introduzca la ciudad y la provincia como texto libre, o

2. Tipificar las ciudades y provincias.

Nos decantaremos por esta última opción, ya que evitará el tener diferentes definiciones para una
misma ciudad (Ej.: Sta. Cruz Tenerife, Santa Cruz de Tenerife, Sta. Cruz Trfe., Etc.). Esto implica la
creación de otras dos nuevas entidades:

• Provincia: código de provincia y descripción.

• Ciudad: código de ciudad y descripción.

226
© Grupo EIDOS Apéndice C. Ejemplo de diseño con Power Designor

Por lo tanto creamos dos entidades más, siguiendo el mismo proceso indicado anteriormente. En la
Figura 118 mostraremos como quedaría la pantalla de definición de la entidad provincia.

Figura 118

El atributo cod_provincia será la clave de la entidad, y será de tipo numérico de dos dígitos. El atributo
desc_provincia será un texto de 20 caracteres.

La definición de la entidad ciudad queda como indica la Figura 119.

Figura 119

227
Base de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Seguimos definiendo entidades, y pasamos a ahora a hacerlo con cliente.

Figura 120

Lo único a destacar aquí es la clave de la entidad, que es el atributo cod_cliente, y los atributos
obligatorios que son Nombre y Apellidos.

En la Figura 121 definimos los atributos de la entidad Pedido.

Figura 121

Hacemos lo mismo con la entidad linea_pedido.

228
© Grupo EIDOS Apéndice C. Ejemplo de diseño con Power Designor

Figura 122

También definimos la entidad producto.

Figura 123

Y concluimos definiendo la entidad factura, como se observa en la Figura 124

En esta última definición, cabe destacar que se ha optado por no almacenar el importe en euros en un
nuevo campo, ya que ello supone un desperdicio de memoria, máxime cuando se sabe el cambio de
pesetas a euros. Lo único que se deberá realizar para calcularlo será dividir el importe en pesetas por
166,386, con lo que ya tenemos una regla de negocio para la entidad factura. Para crearla, pulsamos el

229
Base de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

botón Rules, y en la pantalla que nos aparece pulsamos List. Le damos el nombre Pesetas_a_euros,
y decimos que es de tipo Formula. Para definirla, pulsamos el botón Define y tecleamos lo que
muestra la Figura 125.

Figura 124

Figura 125

Una vez definida, sólo nos queda añadirla a la entidad, para lo que pulsaremos el botón Add en la
pantalla y escogeremos dicha regla.

230
© Grupo EIDOS Apéndice C. Ejemplo de diseño con Power Designor

Figura 126

Una vez definidas todas las entidades, el siguiente paso es crear las relaciones entre ellas. Podemos
observar varias relaciones entre pares de entidades:

• Un proveedor puede abastecer a la empresa de varios productos, y un producto puede ser


abastecido por varios proveedores: relación N-M. La cardinalidad máxima es N y la mínima es
1. Para crear una relación entre ambas entidades, pulsaremos el botón de relación en la paleta
de componentes, y a continuación uniremos ambas entidades. Haciendo doble click sobre la
relación creada, obtenemos la pantalla de definición, que debe quedar como la Figura 127.

Figura 127

231
Base de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

• Un cliente puede realizar muchos pedidos, pero un pedido sólo puede ser realizado por un
cliente. Esto implica una relación 1-N, y la ventana queda como la Figura 128.

Figura 128

• Un pedido puede tener muchas líneas de pedido, pero una línea de pedido sólo puede
corresponder a un pedido. Además, la relación en el sentido de linea_pedido es dependiente,
es decir, no se puede identificar una línea de pedido, si no se sabe el pedido al que
corresponde.

Figura 129

232
© Grupo EIDOS Apéndice C. Ejemplo de diseño con Power Designor

• En una línea de pedido sólo puede haber un producto, mientras que un producto puede estar en
varias líneas de pedido.

Figura 130

• Un cliente puede tener varias facturas, sin embargo una factura sólo puede corresponder a un
cliente.

Figura 131

233
Base de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

• Una provincia puede tener muchas ciudades, pero como mínimo una, y una ciudad sólo puede
pertenecer a una provincia.

Figura 132

• Una ciudad puede tener varios proveedores, pero un proveedor sólo puede pertenecer a una
ciudad. La cardinalidad mínima es uno, ya que no nos interesa tener almacenadas las ciudades
sin proveedores.

Figura 133

234
© Grupo EIDOS Apéndice C. Ejemplo de diseño con Power Designor

• Una ciudad puede tener varios clientes, pero un cliente sólo puede pertenecer a una ciudad.
Obsérvese, en la Figura 134 como no se ha incluido una relación entre provincia y cliente, ya
que sabiendo la ciudad a la que pertenece el cliente, podemos saber su provincia.

Figura 134

Pues bien, ya tenemos el esquema conceptual, que queda como muestra la Figura 135.

Figura 135

235
Base de datos con SQL Server 2000 – Transact SQL © Grupo EIDOS

Una vez obtenido el esquema conceptual, el siguiente paso es obtener el esquema físico. Para ello
pulsamos Ctrl-G y escogemos un SGBD, por ejemplo Microsoft Access 95. Pulsamos Ok. El esquema
físico queda como aparece la Figura 136.

Figura 136

En él podemos observar como se ha añadido una nueva relación, denominada RELATION_63, fruto
de la relación N-M entre las entidades producto y proveedor, y que almacena los productos que han
sido abastecidos por cada proveedor. Las flechas representan las operaciones de join que hay que
realizar para obtener la información de una tabla.

Figura 137

236
© Grupo EIDOS Apéndice C. Ejemplo de diseño con Power Designor

Lo primero que realizaremos será cambiar el nombre de la relación RELATION_63, ya que no queda
muy estético. Le daremos el nombre de Proveedor-Producto, y añadiremos un nuevo atributo, que será
la fecha en la que se ha realizado la venta. Para ello hacemos doble click en dicha entidad, pulsamos el
botón Columns, pulsamos el botón New, y tecleamos el nuevo atributo.

Crearemos ahora una vista, para que la secretaria encargada de realizar los pedidos, compruebe el
stock que queda. Para ello pulsamos el botón vista en la paleta de componentes, y pinchamos en
cualquier punto de la pantalla. Para definirla, hacemos doble click sobre ella, y establecemos una
consulta SQL.

Figura 138

No se preocupe demasiado si no entiende la anterior consulta, ya que en la siguiente parte se estudiará


a fondo la sintaxis de lenguaje SQL. Básicamente, lo que hace es recuperar todos los productos cuyo
stock es menor de 10 unidades.

237
Si quiere ver más textos en este formato, visítenos en: http://www.lalibreriadigital.com.
Este libro tiene soporte de formación virtual a través de Internet, con un profesor a su
disposición, tutorías, exámenes y un completo plan formativo con otros textos. Si desea
inscribirse en alguno de nuestros cursos o más información visite nuestro campus virtual en:
http://www.almagesto.com.

Si quiere información más precisa de las nuevas técnicas de programación puede suscribirse
gratuitamente a nuestra revista Algoritmo en: http://www.algoritmodigital.com. No deje de
visitar nuestra reviata Alquimia en http://www.eidos.es/alquimia donde podrá encontrar
artículos sobre tecnologías de la sociedad del conocimiento.

Si quiere hacer algún comentario, sugerencia, o tiene cualquier tipo de problema, envíelo a la
dirección de correo electrónico lalibreriadigital@eidos.es.

© Grupo EIDOS
http://www.eidos.es

You might also like