====== Diseño de Bases de Datos ======

Los pasos del diseño de una Base de Datos, representados en la siguiente figura, se pueden resumir en
  * **Recolección y análisis de requerimientos**: En este paso recogemos información del sistema para el que debemos diseñar la Base de Datos.

  * **Diseño conceptual**: Una vez recogidos todos los requisitos y conocido el problema, realizamos un primer esquema conceptual en algún lenguaje de alto nivel como es el //Modelo Entidad-Relación//

  * **Diseño lógico**: El diseño conceptual debe ser ahora transformado en un diseño lógico, que es la transformación de un modelo conceptual a un modelo de datos concreto con el fin de poder representar el problema, más adelante, en algún software concreto. En nuestro caso usaremos el //Modelo Relacional//.

  * **Diseño físico**: En este punto debemos aplicar el modelo lógico de datos del punto anterior sobre un SGBD concreto. Dependiendo del diseño físico escogido, tendremos un abanico de posibilidades en cuanto al software disponible. En nuestro caso hemos optado por un modelo relacional por lo que tendremos que escoger entre los SGBD relacionales disponibles. En este curso será //MySQL//.

{{ proceso.png |Proceso de diseño de una Base de Datos}}
===== Modelo Entidad/Relación =====

Es un modelo de datos que representa la realidad a través de //entidades// , que son objetos que existen y se distinguen de otros por sus características, que llamamos //atributos//. Además, estas entidades podrán o no estar relacionadas unas con otras a través de lo que se conoce como //relación//. Hay que tener en cuenta que se trata solamente de un modelo de representación, por lo que no tiene correspondencia real con ningún sistema de almacenamiento. Se utiliza en la etapa de Análisis y Diseño de una Base de Datos, por lo que habrá que convertirla a otro modelo antes de poder empezar a trabajar con ella.
    
Una //entidad// es un objeto que existe en una realidad que queremos representar, por ejemplo, un alumno, que se distingue de otro por sus características como pueden ser: el nombre, los apellidos, el número de expediente, . . .

Las entidades se representan por el siguiente símbolo:
{{ entidad.png }}
Esas características que hacen que unas entidades se distingan de otras, son los //atributos//. El nombre, los apellidos y el número de expediente serían atributos de la entidad alumno. Los atributos se representan por el siguiente símbolo:
{{ atributo.png }}
A su vez, podemos relacionar unas entidades con otras a través de lo que se conoce como //relación//. Por ejemplo, dos entidades alumno y asignatura podrían estar relacionadas entre sí puesto que un alumno //cursa// una asignatura (o varias). Conviene resaltar que una relación entre dos entidades no expresa obligatoriedad de relación sino posibilidad de relacionarse.

En este caso, no será necesario que todos los alumnos cursen una asignatura o que una asignatura sea cursada por todos los alumnos para que la relación se establezca. Por tanto, en este caso se establece que entre esas dos entidades existe una relación a la que podríamos llamar //cursa//. Las relaciones se representan por el siguiente símbolo:

{{ relacion.png }}
    
Si consideramos que dos entidades A y B están relacionadas a través de una relación R, deberemos determinar lo que se conoce como //cardinalidad de la relación//, que determina cuantas entidades de tipo A se relacionan, como máximo, con cuantas entidades de tipo B. Además, resulta conveniente, en cada caso, calcular cuántas entidades de tipo A se relacionan, cómo mínimo, con cuantas entidades de tipo B (que normalmente será 0 ó 1). De esa manera podremos indicar la obligatoriedad o no de relación entre elementos de las entidades A y B.

{{ relaciones.png }}

==== Relación uno a uno ====

En esta relación una entidad de tipo A sólo se puede relacionar con una entidad de tipo B, y viceversa. Por ejemplo, si suponemos dos entidades //Curso// y //Aula//, relacionadas a través de una relación //Se Imparte//, podremos suponer que un //Curso// se imparte en una //Aula// y en una //Aula// sólo se puede impartir un //Curso//. Se representaría como sigue:
        
{{ unoauno.png |Relación 1 a 1}}

==== Relación uno a muchos ====

Indica que una entidad de tipo A se puede relacionar con un número indeterminado de entidades de tipo B, pero a su vez una entidad de tipo B sólo puede relacionarse con una entidad de tipo A. Si suponemos una entidad \emph{Propietario} y otra entidad \emph{Vehículo} relacionadas a través de una relación \emph{Posee}, podremos suponer que un \emph{Propietario} puede poseer varios \emph{Vehículos}, mientras que cada Vehículo sólo puede pertenecer a un \emph{Propietario}.

Quedaría representado de la siguiente manera:

{{ unoamuchos.png |Relación 1 a N}}
==== Relación muchos a uno ====

Significa que una entidad de tipo A sólo puede relacionarse con una entidad de tipo B, pero una entidad de tipo B puede relacionarse con un número indeterminado de entidades de tipo A. En realidad se trata como una relación uno a muchos pero el sentido de la relación es el inverso.
==== Relación muchos a muchos ====

En este caso, tanto las entidades de tipo A y B, pueden relacionarse con un número indeterminado de entidades del otro tipo. Por ejemplo, si suponemos las entidades \emph{Alumno} y \emph{Asignatura} y una relación \emph{Cursa}, podremos suponer que un \emph{Alumno} cursa varias asignaturas mientras que una \emph{Asignatura} la cursan varios \emph{Alumnos}. Quedaría representado de la siguiente manera:

{{ muchosamuchos.png ||Relación N a M}}
==== Diagrama Entidad/Relación ====

Se conoce como Diagrama Entidad/Relación (E/R) al diagrama resultante de modelar un mundo real siguiendo el modelo Entidad/Relación. Como resultado, se modelan todas las entidades con sus atributos, así como todas las relaciones existentes entre ellas, junto con su cardinalidad.

{{ entidadrelacion.png ||Diagrama Entidad/Relación}}

==== Herencia ====

{{ herencia.png |Relación de Herencia Empleado/Encargado y Repartidor}}

También es posible representar otro tipo de relaciones entre objetos de nuestro sistema. La relación de herencia, representada como un triángulo (ver figura), expresa que un objeto es un subtipo de otro objeto. También se suele considerar al subtipo como una especialización del primero o al primero como una generalización del segundo.

En el caso del ejemplo, existen dos tipos de empleados que se relacionan de forma diferente con otros objetos del sistema, pero que a su vez pueden tener gran parte en común. Por ejemplo, trabajan de forma diferente pero muchos de los datos personales que almacenaremos de ambos son comunes. Es por eso que el objeto \emph{Empleado} se puede considerar una generalización de los dos tipos de trabajadores que hay en el sistema. Todos aquellos atributos y relaciones que tengan en común se podrá representar como atributos y funcionalidad del objeto \emph{Empleado} y los atributos y relaciones que tengan como trabajadores especializados serán representados en el correspondiente objeto. 

==== Reflexividad ====

{{ reflexividad.png |Reflexividad}}

Es posible que la misma entidad ocupe ambos lados de una relación. En ese caso estamos frente a lo que se conoce como relaciones reflexivas. La cardinalidad de la relación indicará si todos los elementos de la relación están relacionados reflexivamente o bien sólo algunos están relacionados entre sí. En el caso de la figura podríamos suponer una empresa en la que algunos empleados hacen de supervisor de otros empleados.
==== Atributos multivaluados ====

{{ multivaluados.png |Atributo multivaluado}}

Los atributos multivaluados son aquellos atributos que pueden contener una cantidad indeterminada de valores.

==== Atributos estructurados (o compuestos) ====

{{ estructurados.png |Atributo estructurado}}

Los atributos estructurados o compuestos son aquellos atributos que pueden estar compuestos por otros atributos. Normalmente son atributos que pueden descomponerse aunque dependiendo del contexto de la aplicación puede no interesar hacer esa descomposición y tratarlo como un atributo simple.

==== Atributos derivados ====

{{ derivados.png |Atributo derivado}}

Los atributos derivados (o calculados) son aquellos atributos cuyo valor puede ser deducido realizando algunas operaciones con otros atributos de la misma entidad o de otras entidades. En algunas situaciones se podría considerar redundante (puesto que su valor se puede deducir) pero en otras puede resultar cómodo almacenarlo ya calculado puesto que se puede ahorrar mucho tiempo de cómputo si se trata de un valor de díficil y/o recurrente cálculo.

==== Ejemplos de diseño ====

  * [[https://www.youtube.com/watch?v=Z6KE3R42N7E|Diseñar un modelo Entidad/Relación (entidades, atributos y relaciones)]]
  * [[https://www.youtube.com/watch?v=WqB4lYmzEtw|Diseñar un modelo Entidad/Relación (ciclos y redundancia]]
  * [[https://www.youtube.com/watch?v=_AG-fQ0Z5m0|Diseñar un modelo Entidad/Relación (atributos multivaluados, compuestos y derivados)]]


===== Modelo relacional =====

El modelo relacional es otro modelo de representación en el que los datos y sus relaciones se representan a
través de tablas, y en el que los atributos se traducen en campos de esas tablas. Es el modelo de representación que siguen la gran mayoría de los SGBD relacionales (MySQL, SQL Server, Oracle, Ms Access, entre otros) en la actualidad, puesto que es el modelo de datos más extendido.
        
Así, es necesario transformar nuestro modelo Entidad/Relación a un modelo relacional si queremos crear nuestra Base de Datos en algún SGBD relacional.

{{ tabla.png |Tabla}}

{{ modelo_relacional.jpg |Modelo relacional}}
==== Paso del modelo E/R al modelo relacional ====

El paso de un modelo E/R a un modelo relacional se puede llevar a cabo, en gran parte, siguiendo una serie de reglas o pautas, que se enumeran a continuación:

  * Toda **entidad** se transforma en una tabla
  * Todo **atributo** simple se transforma en columna de una tabla
  * Los **atributos estructurados** transforman los campos en los que se componen en nuevas columnas de la tabla
  * El **identificador único** de la entidad se convierte en clave primaria
  * Los **atributos multivaluados** generan una nueva tabla con tres columnas: un \emph{id}, el \emph{id} de la tabla de la que surgen propagado como \emph{clave ajena} y el valor del campo multivaluado
  * Toda **relación N:M** se transforma en una tabla que tendrá como clave primaria la concatenación de los atributos clave de las entidades que relaciona.
  * En la transformación de **relaciones 1:N** existen dos posibilidades:
    * Transformarlo en una tabla. Se hace como si se tratara de una relación N:M. Es conveniente realizarlo así en el caso de que se prevea que en un futuro la relación puede transformarse en N:M y cuando la relación tiene atributos propios
    * Propagar la clave. Se propaga el atributo principal de la entidad que tiene de cardinalidad máxima 1 a la que tiene cardinalidad máxima N, haciendo desaparecer a la relación
  * En la transformación de **relaciones 1:1** se tienen en cuenta las cardinalidades de las entidades que participan en ellas. Existen también dos soluciones:
    * Transformarlo en una tabla. Si las entidades poseen cardinalidades (0,1), la relación se convierte en una tabla
    * Propagar la clave. Si una de las entidades posee cardinalidad (0,1) y la otra (1,1), se propaga la clave de la entidad con cardinalidad (1,1) a la tabla resultante de la entidad de cardinalidad (0,1). Si ambas poseen cardinalidades (1,1), se puede propagar la clave de cualquiera de ellas a la tabla resultante de la otra
  * Las relaciones de **herencia** se pueden transforman de varias maneras. La más sencilla será crear una tabla por entidad (de la que se hereda y las que heredan), cada entidad transforma sus atributos siguiendo las reglas anteriores, y al final, la tabla que resulta de la entidad base (de la que se hereda) propaga su clave como clave ajena en cada una de las tablas que resultan de las entidades que heredaban.
        
Las situaciones más particulares habrá que estudiarlas y aplicar algún \emph{patrón de diseño} conocido, si lo hay, para generar el correspondiente modelo relacional. Estos casos no siempre se podrán reflejar en el correspondiente modelo Entidad-Relación puesto que algunos tienen que ver con exigencias técnicas o de tiempo, más que con el propio modelo de datos. Algunos casos particulares pueden ser:

  * **Datos temporales**: Cómo representar en un modelo relacional datos que tienen \emph{fecha de caducidad} (los precios de un producto del que queremos tener un histórico de precios, . . .)
  * **Datos eliminados**: Cómo representar en un modelo relacional datos que se desean eliminar, pero que por alguna razón necesitamos que sigan estando almacenados en la base de datos (productos descatalogados, alumnos que terminan sus estudios, . . .)
  * **Registro o auditoría**: Cómo podemos registrar las acciones de los usuarios o de la aplicación durante el ciclo de vida de la Base de Datos.
  * **Bloqueo de registros**: Cómo podemos bloquear el acceso a un registro para evitar la modificación simultánea del mismo dato por más de un usuario desde la aplicación que conecta con la Base de Datos.

En cualquier caso, aplicar correctamente al modelo relacional resultante las reglas de normalización eliminará todas las anomalías que nuestro modelo pueda contener. Así, hay que tener en cuenta que el modelo relacional que hemos obtenido en este momento todavía puede no ser el definitivo y puede sufrir transformaciones (e incluso se pueden añadir nuevas tablas) como resultado de aplicar las reglas de normalización que se pasan a explicar en el siguiente punto.

==== Ejemplos de transformaciones a modelo relacional ====

  * [[http://www.youtube.com/watch?v=_BzC1HebIYA|Transformar relaciones 1 a 1 al modelo relacional]]
  * [[http://www.youtube.com/watch?v=flxynkCABP0|Transformar relaciones N a M al modelo relacional]]
  * [[http://www.youtube.com/watch?v=cmyep2ccK8c|Transformar relaciones 1 a N al modelo relacional]]
  * [[http://www.youtube.com/watch?v=HMhjzALG638|Tranformar una herencia al modelo relacional]]
  * [[http://www.youtube.com/watch?v=vycSagvQ6X8|Transformar relaciones reflexivas al modelo relacional]]
  * [[http://www.youtube.com/watch?v=vycSagvQ6X8|Transformar atributos al modelo relacional]]
  * [[http://www.youtube.com/watch?v=c91FkQ3O--k|Ejemplo completo de diseño y transformación de modelo Entidad/Relación a modelo relacional]]
  * [[http://www.youtube.com/watch?v=IxO4q918Gek|Transformar un modelo Entidad/Relación a modelo relacional]]
==== Normalización de modelos relacionales ====

Uno de los retos en el diseño de toda Base de Datos es el obtener una estructura estable tal que:

  * El sistema no sufra de anomalías de almacenamiento
  * El modelo lógico pueda modificarse si aparecen nuevos requisitos

Una Base de Datos bien diseñada tiene mayor esperanza de vida, incluso en un ambiente dinámico donde puedan aparecer nuevos requisitos, que una Base de Datos con un diseño pobre. Como media, una Base de Datos puede     sufrir una reorganización cada seis años, dependiendo de lo dinámico que sean sus requisitos. Si la Base de       Datos se diseño bien seguirán teniendo un buen rendimiento aunque aumente el tamaño, y será lo suficientemente       flexible para soportar los nuevos requisitos y/o características adicionales.

Actualmente existen diversos riegos en el diseño de Bases de Datos relacionales. Los más habituales son la       redundancia de información y la inconsistencia de datos.

La normalización es el proceso de simplificar la relación entre los campos de un registro de forma que éste se       reemplaza por varios registros más simples y predecibles y, por tanto, más manejables. En definitiva, la        normalización busca simplificar el diseño para que éste sea más fácil incorporar nuevas funcionalidades con el       paso del tiempo y no baje su rendimiento cuando la cantidad de datos almacenados en ella aumenten       considerablemente.

La teoría de la normalización se basa en lo que se conoce como Formas Normales. Cada una de estas Formas       Normales establece una serie de restricciones que el diseño deberá cumplir para satisfacer dicha Forma. En este       curso veremos las tres primeras FN (Formas Normales).

=== Primera forma normal ===

Se dice que una tabla está en //primera forma normal// si una tabla posee las siguientes propiedades:

  * Cada columna tiene un valor único
  * El orden de las filas y las columnas no importa
  * Cada columna debe tener un único tipo de datos
  * Dos filas no contienen valores idénticos
  * Cada columna contiene un solo valor
  * Las columnas no pueden contener valores repetidos
            
Supongamos el caso más común, que un campo pueda tener más de un valor. Para normalizar una tabla que no está en primera forma normal por esta razón, se han de seguir estos pasos:

  * Se localizan los atributos correspondientes a la clave principal
  * Se realiza una proyección sobre la tabla y se descompone en varias, de manera que se hace la proyección de la clave sobre cada uno de los valores del atributo que no es atómico

Para el caso de tablas que incumplen la última de las propiedades y posee columnas con valores repetidos (una tabla de clientes con los campos teléfono 1, teléfono 2, teléfono 3, . . .) se opera de forma muy similar, puesto que se dichos valores se deben almacenar en una nueva tabla y utilizar la clave principal de la primera para referenciar estos nuevos valores.

{{ primera1.jpg |Tabla que no cumple la 1º FN}}

=== Segunda forma normal ===

Esta formal normal sólo debe ser considerada para aquellas tablas en las que la clave principal sea            compuesta. Si no fuera así, la tabla estaría, de forma directa, en segunda forma normal.

Decimos que una tabla está en //segunda forma normal// si se cumplen las siguientes condiciones:

  * Está en 1FN
  * Todo atributo secundario (que no pertenezca a la clave principal) tiene una dependencia funcional              total de la clave principal, y no de una parte de ella

//Se dice un atributo B depende funcionalmente de A (''A->B'') si cada valor de A se corresponde con un único valor de B. Visto de otra manera, si dado A puedo obtener B. Un caso típico podría ser ''DNI -> Nombre'', puesto que dado un DNI puedo obtener, de forma unívoca, el nombre de la persona//

Para convertir una tabla que no está en 2FN se creará una tabla con la clave y todas sus dependencias funcionales totales y otra tabla con la parte de la clave que tiene dependencias con los atributos secundarios.

En el ejemplo podemos ver como el campo //TelefonoProveedor// no depende totalmente de la clave           //(NombreProducto, NombreProveedor)//, sino únicamente del campo //NombreProveedor//.

{{ no2fn.png |Tabla que no cumple la 2ª FN (CP: NombreProducto-NombreProveedor)}}

{{ 2fn1.png |Aplicando la 2ª FN. Tabla Productos}}

{{ 2fn2.png |Aplicando la 2ª FN. Tabla Proveedores}}
            
=== Tercera forma normal ===

Se dice que una tabla está en //tercera forma normal// si:

  * Está en 2FN
  * No existen atributos no primarios (que no pertenezcan a la clave) que son transitivamente dependientes de cada posible clave de la tabla. Es decir, un atributo secundario sólo puede ser conocido a través de la clave principal y no por medio de un atributo no primario

Para convertir una tabla que no está en 3FN se realizará una proyección de la clave a los elementos que no           tengan dependencia funcional transitiva y otra tabla con una nueva clave a los elementos que anteriormente           tenían esta dependencia.

En el ejemplo, es posible conocer la edad del inscrito a través del número de licencia, y dada la edad           podemos conocer su categoría, tenemos una dependencia funcional transitiva. Lo importante es tener en cuenta           que la categoría depende de un atributo que no forma parte de la clave. Para normalizar, debemos descomponer           esa tabla en las tablas //Atletas// y //Categorías//

{{ no3fn.png |Tabla que no cumple la 3ª FN. Tabla Atletas}}

{{ 3fn1.png |Aplicando la 3ª FN. Tabla Atletas}}

{{ 3fn2.png |Aplicando la 3ª FN. Tabla Categorías}}
===== Bases de Datos relacionales =====

==== Introducción al lenguaje SQL ====

El lenguaje SQL (Structured Query Language) permite la comunicación con el SGBD. Actualmente es el lenguaje estándar para la gestión de Bases de Datos relacionales para ANSI (American National Standard Institute) e ISO        (International Standarization Organization). Entre las principales características de este lenguaje destaca que        es un lenguaje para todo tipo de usuarios ya que quién lo utiliza especifica qué quiere, pero no dónde ni cómo,        de manera que permite realizar cualquier consulta de datos por muy complicada que parezca.

=== Sentencias DDL ===

En el lenguaje SQL, dependiendo de las tareas que se quieran realizar, se distinguen dos tipos de sentencias.        Sentencias DDL (Data Definition Language) que sirven para especificar y gestionar estructuras de datos, y las        sentencias DML (Data Manipulation Language) que sirven para trabajar con los datos almacenados en dichas        estructuras.

Puesto que por ahora abordaremos aquellas sentencias que nos van a permitir crear nuestras Bases de Datos en un        SGBD relacional, comenzaremos por ver el grupo de sentencias DDL, que son las que se citan a continuación:

== Crear un objeto: CREATE ==

Es la sentencia utilizada para la creación de un objeto (base de datos, tabla, usuario, vista, procedimiento, . . .) en una Base de Datos.
           
La sintaxis para la creación de una tabla es la siguiente:
<code sql>
CREATE TABLE [IF NOT EXISTS] <nombre_tabla>
(
   <nombre_columna1>  <tipo_dato>  <restricciones>,
   <nombre_columna2>  <tipo_dato>  <restricciones>,
   ................................
)
</code>
Y para crear una Base de Datos:
<code sql>          
CREATE DATABASE [IF NOT EXISTS] <nombre_base_de_datos>
</code>

== Eliminar un objeto: DROP ==

Es la sentencia utilizada para eliminar objetos (tabla, usuario, vista, procedimiento, . . .) en una Base de            Datos.

La sintaxis para la eliminación de tablas es la siguiente:
<code sql>
DROP TABLE [IF EXISTS] <nombre_tabla>
</code>
Y para eliminar una Base de Datos:
<code sql>
DROP DATABASE [IF EXISTS] <nombre_base_de_datos>
</code>

== Modificar un objeto: ALTER ==

Es la sentencia utilizada para modificar objetos (tabla, usuario, vista, procedimiento, . . .) en una Base            de Datos.

La sintaxis para modificar una tabla es la siguiente:
<code sql>
    ALTER TABLE <nombre_tabla>
        [ ADD <definicion_columna> ]
        [ CHANGE <nombre_columna> <definicion_columna> ]
        [ DROP COLUMN <nombre_columna> ]
        [ ADD CONSTRAINT <restriccion> ]
</code>

== Conceder privilegios sobre un objeto: GRANT ==

Permite conceder privilegios sobre un objeto a un usuario de la Base de Datos.
<code sql>
    GRANT <privilegio>
    ON <objeto>
    TO <usuario>
    [WITH GRANT OPTIONS]
</code>

== Revocar privilegios sobre un objeto: REVOKE ==

Permite eliminar el privilegio sobre un objeto a un usuario.

<code sql>
    REVOKE <privilegio>
    ON <objeto>
    FROM <usuario>
</code>

== Conectar con una Base de Datos ==

Permite realizar la conexión con una Base de Datos de MySQL.
<code sql>
    USE <nombre_base_de_datos>
</code>

== Comentarios en lenguaje SQL ==

Existe la posibilidad de añadir comentarios al código del lenguaje SQL según la siguiente sintaxis:
<code sql>
    -- Esto es un comentario y MySQL no lo ejecuta
    /* Esto también es un comentario y 
       tampoco se ejecuta */
</code>

=== Tipos de datos ===

== Cadenas de caracteres ==

== Tipo CHAR, VARCHAR ==

Este tipo de datos permite almacenar cadenas de texto fijas (''CHAR'') o variables (''VARCHAR'').

El tipo ''CHAR'' permite almacenar cadenas de caracteres de longitud fija entre 1 y 255 caracteres. La longitud de la cadena se debe especificar entre paréntesis en el momento de la declaración (''cadena CHAR(25)''). 

Por otro lado, el tipo ''VARCHAR'' permite almacenar cadenas de caracteres variables de hasta 4.000            caracteres. La declaración del tipo ''VARCHAR'' es similar a la de un tipo CHAR (''cadena VARCHAR(25)''). La principal y única diferencia entre estos dos tipos, es que el tipo ''CHAR'' declara una cadena fija de la longitud que se especifica mientras que en la declaración de un tipo ''VARCHAR'' lo que se especifica es un tamaño máximo, la cadena sólo ocupará el tamaño necesario para almacenar el dato que contenga (hasta llegar al            máximo). En cualquier caso, no es posible almacenar cadenas de mayor tamaño al especificado en su            declaración, puesto que el SGBD truncará el valor almacenándose sólo hasta la longitud establecida.
            
== Tipo TEXT ==

El tipo ''TEXT'' permite almacenar cadenas de caracteres de hasta varios GB de longitud. Sólo se            recomienda su uso para almacenar textos realmente grandes, puesto que presenta ciertas restricciones, aunque            algunas pueden variar dependiendo del SGBD que se utiliza:
  * Sólo se puede definir una columna ''TEXT'' por tabla
  * No se pueden establecer restricciones en columnas de este tipo
  * No se permite su utilización en ciertas cláusulas

== Tipos numéricos ==

Para la representación de tipos de datos numéricos. Los tipos más utilizados son ''BIT'', ''TINYINT'', ''INT'', ''BIGINT'', ''FLOAT'' y ''REAL'', para la representación de números enteros de menor o mayor tamaño, y para números en coma flotante de menor o mayor precisión, respectivamente.
            
En ocasiones el rango de los valores negativos resultará prescindible (claves numéricas, valores de dinero, cantidades, . . .) por lo que será posible ampliar el rango positivo de un tipo numérico añadiendo la restricción ''UNSIGNED'' tras definir el tipo de éste.

<code sql>
        id INT UNSIGNED
</code>
            
Para el caso de los números de coma flotante conviene tener en cuenta los problemas de precisión \cite{url:float} que existen con estos tipos de datos.

== Tipos para fechas ==

Los tipos más utilizado para almacenar valores de fechas (''DATE'') o fechas con hora (''DATETIME''). Por defecto            el formato más utilizado es ''DD/MM/YY'' ó ''DD/MM/YYYY''.

También se puede usar el tipo ''TIMESTAMP'' para almacenar una marca de tiempo (fecha y hora). Además, permite el uso de la constante ''CURRENT\_TIMESTAMP'' en la definición de la columna al definirle un valor por defecto cuando se crea la tabla.

== Tipo booleano ==

Permite almacenar valores lógicos Verdadero/Falso o Sí/No. Realmente se define la columna como del tipo ''TINYINT'', que simplemente almacena los valores 0 y 1 para indicar los valores lógicos Verdadero y Falso, respectivamente. Así, podremos utilizar los valores ''TRUE'' ó ''FALSE'' o directamente asignar 1 ó 0 para asignar valor.

=== Restricciones ===

Las restricciones se pueden establecer, o no, a las columnas de cada tabla para forzar a que los datos almacenados
en ellas cumplan una serie de condiciones, con la finalidad de que la información sea más correcta. Por ejemplo,        podemos obligar a que un campo donde almacenamos el DNI de una persona tenga una longitud mínima, o bien un        campo donde almacenamos la categoría de un equipo de fútbol, sólo pueda tomar unos determinados valores        predefinidos (benjamín, juvenil, cadete, . . .) o bien podemos hacer que un campo no pueda repetirse, por        tratarse de un valor único (DNI, NSS, teléfono, email, . . .).

Hay que tener en cuenta que, por lo general, las restricciones se definen en línea con la definición del campo        (tal y como se muestra en la sintaxis de la sentencia de ''CREATE TABLE'', pero de forma opcional también        pueden ser definidas por separado justo debajo de la definición de todos los campos de la tabla.

== Clave primaria ==

Una clave primaria dentro de una tabla, es una columna o conjunto de columnas cuyo valor identifica            unívocamente a cada fila. Debe ser única, no nula y es obligatoria. Como máximo podremos definir una clave            primaria por tabla y es muy recomendable definirla.

Para definir una clave primaria utilizamos la restricción ''PRIMARY KEY''.
<code sql>
    dni VARCHAR(9) PRIMARY KEY
</code>
Y si lo hacemos al final de la definición de las columnas, quedaría así:
<code sql>
    PRIMARY KEY (dni)
</code>

Hay que tener en cuenta que a la hora de definir claves primarias compuestas (la componen 2 ó más campos de            la tabla), ésta deberá ser definida forzosamente tras la definición de los campos involucrados, siguiendo            esta sintaxis
<code sql>
    PRIMARY KEY (nombre, apellidos)
</code>

== Autonumérico ==

Especialmente útil en el caso de aquellas columnas que se definan como claves primarias de cada tabla, resulta añadir la restricción de campo autonumérico, siempre y cuando ésta sea una columna de tipo entero. De esa manera será el SGBD el encargado de asignarle valor de forma automática, siempre asignando un valor entero de forma secuencial a medida que se van insertando las filas en dicha tabla.

La forma de definirlo es añadiendo la restricción ''AUTO_INCREMENT'' en la definición de la columna que se ha definido como clave primaria:
<code sql>
    id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT
</code>

== Clave ajena ==

Una clave ajena está formada por una o varias columnas que hacen referencia a una clave primaria de otra o de            la misma tabla. Se pueden definir tantas claves ajenas como sea necesario (no hay límite). El valor de la            columna o columnas que son clave ajena será NULL, o bien el valor de la clave primaria de la tabla a la que            hacen referencia (integridad referencial). Así, a la hora de definir una clave ajena, deberemos indicar con            la cláusula ''REFERENCES'' la tabla a que ésta hace referencia (se tomará automáticamente la clave            primaria de ésta como campo con el que mantener la integridad referencial).

Habrá que tener en cuenta que mientras que un campo definido como clave ajena haga referencia a un campo            definido como clave primaria, la columna de la segunda tabla no podrá ser eliminada hasta que no lo haga la            columna que le hace referencia (integridad referencial). Para evitar estos problemas (aunque no siempre es            un problema) es posible definir la restricción de clave ajena añadiendo la cláusula ''ON DELETE'' o bien ''ON UPDATE'' para el caso de una actualización. De esa manera, cuando se vaya a eliminar o actualizar una fila a cuya clave primaria se haga referencia, podremos indicar a MySQL que operación queremos realizar con las filas que le hacen referencia:
  * **RESTRICT**: Se rechaza la operación de eliminación/actualización
  * **CASCADE**: Realiza la operación y se elimina o actualiza en cascada en las filas que hacen referencia
  * **SET NULL**: Realiza la operación y fija a ''NULL'' el valor en las filas que hacen referencia
  * **NO ACTION**: Se rechaza la operación de eliminación/actualización, como ocurre con la opción ''RESTRICT''

A continuación, un par de ejemplos que definen claves ajenas con diferentes cláusulas:
<code sql>
    curso VARCHAR(25) REFERENCES Cursos 
    curso VARCHAR(25) REFERENCES Cursos ON DELETE CASCADE
</code>
En el caso de que definamos la restricción de clave ajena al final de la tabla se utiliza la palabra            reservada \texttt{FOREIGN\ KEY}:
<code sql>
    FOREIGN KEY (curso) REFERENCES Cursos
    FOREIGN KEY (curso) REFERENCES Cursos ON DELETE CASCADE
</code>
Como ocurre con las claves primarias, si las claves ajenas son compuestas, se definen forzosamente al final de las definiciones de las columnas de la tabla, de la siguiente forma:
<code sql>
    FOREIGN KEY (curso, aula) REFERENCES Cursos
    FOREIGN KEY (curso, aula) REFERENCES Cursos ON DELETE CASCADE
</code>

= Definir claves ajenas en MySQL =

Para definir claves ajenas en MySQL habrá que tener en cuenta algunas consideraciones:

  * La columna deberá ser del mismo tipo (y atributos) que la columna de la que es clave ajena
  * La columna deberá ser un índice
  * Si la columna se define como obligatoria (''NOT NULL'') no podrá contener la claúsula (''SET NULL'') para los casos de borrado (''ON DELETE'') o actualización (''ON UPDATE'')
  * Ambas tablas (la referenciada y la que hace referencia) deberán ser de tipo InnoDB. A partir de la versión 5.5 de MySQL es el motor de almacenamiento por defecto para cualquier tabla. En caso contrario es necesario indicar lo siguiente al final de la creación de la tabla:

<code sql>
    CREATE TABLE tabla (
    . . .
    . . .
    ) ENGINE = Innodb;
</code>

Así, normalmente, en MySQL definiremos una clave ajena de la siguiente forma:

<code sql>
    id_cliente INT UNSIGNED,
    INDEX (id_cliente),
    FOREING KEY (id_cliente) 
        REFERENCES Clientes (id) 
        ON DELETE SET NULL ON UPDATE SET NULL,
</code>

En el caso anterior suponemos que la clave primaria a la cual se hace referencia está definida como sigue:

<code sql>
    CREATE TABLE Clientes (
        id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
        . . .
    );
</code>

== Campos obligatorios ==

Esta restricción obliga a que se le tenga que dar valor obligatoriamente a una columna. Por tanto, no podrá            tener el valor NULL. Se utiliza la palabra reservada ''NOT\ NULL''.
<code sql>
    apellidos VARCHAR(250) NOT NULL
</code>

== Valores por defecto ==

Se puede definir el valor que una columna tomará por defecto, es decir, si al introducir una fila no se            especifica valor para dicha columna. Se utiliza la palabra reservada ''DEFAULT''. 

<code sql>
    fecha TIMESTAMP DEFAULT CURRENT_TIMESTAMP  
    nombre VARCHAR(250) DEFAULT 'Sin nombre'
</code>

== Condiciones ==

De forma más genérica, podemos forzar a que los valores de determinados campos de la tabla cumplan una            ciertas condiciones. En caso contrario no se permitirá la inserción de esa fila en dicha tabla.

<code sql>
    nombre VARCHAR(250) CHECK (nombre = UPPER(nombre))
    edad INT CHECK (edad > 0)
    curso INT CHECK (curso BETWEEN 1 AND 2)
</code>

Hay que tener en cuenta que en MySQL está restricción no tiene ningún efecto y lo habitual es definir una columna como de tipo enumeración (''ENUM'' en MySQL) si queremos indicar que solamente una serie de valores (definidos) son válidos:

<code sql>
    curso ENUM ('0', '1', '2'),
    horario ENUM ('mañana', 'tarde', 'noche'),
</code>

== Valores únicos ==

La restricción ''UNIQUE'' evita valores repetidos en una misma columna. Al contrario que ocurre con la            restricción ''PRIMARY\ KEY'', la restricción de valor único se puede aplicar a varias columnas de una            misma tabla y admite el valor ''NULL''. Con respecto a esta última consideración, conviene saber que si una columna se define como ''UNIQUE'', sólo una de sus filas podrá contener el valor ''NULL''

<code sql>
    email VARCHAR(100) UNIQUE
</code>

=== Índices ===

Los índices se utilizan para obtener datos de las tablas de una forma más rápida. En definitiva, lo que el SGBD        hace es asociar el valor de una columna (sobre la que definimos el índice) con su posición en la tabla. De esa         manera será más rápido buscar sobre esa columna puesto que al encontrar el valor, el SGBD conocerá su posición        en la tabla.

Se recomienda su uso en aquellas columnas sobre las que se vayan a realizar búsquedas en una tabla. Por ejemplo,        si tenemos una tabla donde almacenamos información sobre Libros, nos podría interesar crear un índice en el        campo autor, puesto que puede ser muy común buscar qué libros ha escrito un autor determinado. Además, será un        valor que contendrá pocos valores repetidos, por lo que maximizará el beneficio de usar un índice.

<code sql>
    INDEX autor_index (autor)
</code>

Por otra parte, los índices presentan algún inconveniente como puede ser el hecho de que ocupan espacio en la        tabla, y dependiendo del caso podría llegar a ocupar más espacio que la propia tabla, por lo que hay que tener        cuidado a la hora de escoger una columna como índice. También hay que tener en cuenta que hay que actualizar el        índice cada vez que se modifica la columna en la tabla por lo que no resulta conveniente elegir como índices        aquellas columnas que creamos que van a escribirse con mucha frecuencia.

{{ indice.jpg |Uso de índices}}

=== Usuarios y privilegios ===

Como se vió en el tema anterior, una de las funciones del SGBD es la de proporcionar seguridad en el acceso a        los datos a través de mecanismos de control de acceso.

En SQL, y así lo hacen todos los SGBD relacionales, se sigue un modelo Usuario-Privilegio para otorgar acceso a        los objetos de la Base de Datos. Existen una serie de privilegios predefinidos y es el administrador del SGBD el        encargado de asignar o no los privilegios \cite{url:privilegios} a los usuarios sobre determinados objetos (tablas, procedimientos, . . .).

Supongamos que somos los administradores de un SGBD MySQL y tenemos que proporcionar acceso a una Base de Datos        para una aplicación \emph{Biblioteca} a un desarrollador de mi compañía:

<code sql>
    CREATE USER 'desarrollador' IDENTIFIED BY 'micontraseña';
    GRANT ALL PRIVILEGES ON biblioteca.* TO desarrollador;
</code>

Así, hemos creado la Base de Datos y el usuario, y hemos concedido todos los privilegios a dicho usuario sobre        esa Base de Datos.

=== Creación de scripts en MySQL ===

La forma más habitual de trabajo a la hora de lanzar órdenes en SQL sobre un SGBD relacional como MySQL es crear ficheros por lotes de órdenes SQL, lo que se conoce como //scripts SQL//, donde podemos escribir todas las sentencias SQL que queremos ejecutar una detrás de otra separadas por el carácter '';''.

Por ejemplo, para la creación de una nueva Base de Datos y sus tablas podríamos preparar un script SQL como el siguiente:

<code sql>
CREATE DATABASE IF NOT EXISTS pagina_web;
USE pagina_web;

CREATE TABLE IF NOT EXISTS usuarios (
    id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    . . .
    . . .
);
CREATE TABLE IF NOT EXISTS productos (
    . . .
    . . .
);
. . .
. . .

</code>

Una vez creado el script podremos lanzar su ejecución sobre MySQL y se ejecutarán todas las sentencias contenidas en él de forma secuencial. Es una forma muy útil de crear scripts para la creación de una Base de Datos y todas sus tablas y restricciones y también para crear scripts de actualización o parcheo de una Base de Datos existentes de forma que se incluyan todas las sentencias SQL que actualicen o arreglen los problemas que actualmente pueda haber (añadir una nueva tabla, eliminar un campo, añadir una nueva restricción, . . .).

Para estos casos a veces resulta útil desactivar las claves ajenas, realizar algunas operaciones sobre tablas que puedan tener relaciones con otras y volver a activarlas. De esa manera es posible realizar ciertas operaciones sin que las reglas de validación de la integridad referencial lancen ningún error.

<code sql>
-- Desactivar claves ajenas
SET FOREIGN_KEY_CHECKS = 0;
. . .
// Realizar algunos cambios en la estructura y datos de la Base de Datos
. . .
-- Activar claves ajenas
SET FOREIGN_KEY_CHECKS = 1;
</code>

=== Ejemplos de cómo crear un script en MySQL ===

  * [[http://www.youtube.com/watch?v=T317i5DXj5s|Crear el script a partir del modelo relacional]]
  * [[http://www.youtube.com/watch?v=4FlqXfi5Hi0|Cómo crear un script en SQL]]

===== Ejercicios =====

  - Se quiere diseñar una Base de Datos para almacenar todos los datos de un campeonato de fútbol sala que se organiza este año en la ciudad. Aquellos que quieran participar deberán formar un equipo (nombre, patrocinador,        color de la camiseta camiseta, color de la 2ª camiseta, categoría, . . .) e inscribirse en el campeonato. A medida que transcurran los partidos se irán almacenando los resultados de éstos, así como qué equipos lo jugaron, en qué campo se jugó, quién lo arbitró y alguna incidencia que pudiera haber ocurrido (en caso de que no ocurran incidencias no se anotará nada. Además, los participantes deberán rellenar una ficha de suscripción con algunos datos personales (nombre, apellidos, edad, dirección, teléfono, . . .)
  - Se quiere diseñar una Base de Datos para controlar el acceso a las pistas deportivas de Zaragoza. Se tendrán en cuenta los siguientes supuestos:
    * Todo aquel que quiera hacer uso de las instalaciones tendrá que registrarse y proporcionar su nombre, apellidos, email, teléfono, dni y fecha de nacimiento
    * Hay varios polideportivos en la ciudad, identificados por nombre, dirección, extensión (en m<sup>2</sup>)
    * En cada polideportivo hay varias pistas de diferentes deportes. De cada pista guardaremos un código que la identifica, el tipo de pista (tenis, fútbol, pádel, . . .), si está operativa o en mantenimiento, el precio y la última vez que se reservó
    * Cada vez que un usuario registrado quiera utilizar una pista tendrá que realizar una reserva previa a través de la web que el ayuntamiento ha creado. De cada reserva queremos registrar la fecha en la que se reserva la pista, la fecha en la que se usará y el precio. Hay que tener en cuenta que todos los jugadores que vayan a hacer uso de la pista deberán estar registrados en el sistema y serán vinculados con la reserva
  - Se desea diseñar una Base de Datos para una sucursal bancaria que contenga información sobre los clientes,        las cuentas, las sucursales y las transacciones producidas. Construir el modelo E/R teniendo en cuenta las        siguientes restricciones:
    * Una transacción viene determinada por su número de transacción, la fecha y la cantidad
    * Un cliente puede tener muchas cuentas
    * Una cuenta puede tener muchos clientes
    * Una cuenta sólo puede estar en una sucursal
  - Diseña el modelo E/R para una biblioteca con las siguientes restricciones:
    * Se quiere almacenar información sobre los libros de los que se dispone: titulo, editorial, número de           páginas y un resumen breve)
    * Se almacenará información sobre los autores: nombre, apellidos, fecha de nacimiento, fecha de          fallecimiento, nacionalidad y un breve resumen de su vida
    * De todos aquellos que se hagan socios de esta biblioteca se les hará una ficha con los siguientes           datos: nombre, apellidos, fecha de nacimiento, dirección, teléfono y e-mail
    * Por último, se quiere almacenar todos los libros que cogen prestados los socios para saber quién tiene           un determinado libro en cada momento y para conocer que lectores han leído alguna vez un libro determinado
  - Diseña el modelo E/R para la Base de Datos de una aplicación para la gestión de la secretaría de un       colegio:
    * Cuando un alumno venga a matricularse se le hará rellenar una ficha con sus datos que luego se           introducirá a la aplicación: DNI, número de expediente, nombre, apellidos, domicilio, teléfono y e-mail
    * Se tendrá ya almacenada información sobre todos los cursos que se imparten en el centro: un código, el nombre, aula donde se imparte y el horario
    * Se almacenarán todas las asignaturas de todos los cursos con el fin de conocer en que asignaturas se            matricula cada alumno. De cada una guardaremos el nombre, el profesor que la imparte y el número de horas a            la semana. Hay que tener en cuenta que todos los alumnos se matricularán al menos de una asignatura en algún            curso
    * Los profesores también están dentro de la Base de Datos, con la siguiente información: nombre,            apellidos, domicilio y e-mail. Un profesor podrá impartir como máximo 6 asignaturas y deberá impartir al            menos una. También habrá que almacenar el curso del que un profesor es tutor, teniendo en cuenta que puede            que no sea tutor de ningún curso
    * Hay que tener en cuenta que es importante almacenar las notas que cada alumno tiene en cada asignatura            a lo largo del curso en las distintas evaluaciones, así como las observaciones que los profesores podrán            anotar. Además, al principio de curso los alumnos escogerán con que compañero quieren realizar las prácticas            o trabajos de cada una de las asignaturas (será siempre con el mismo), información que almacenaremos también en la Base de Datos
  - La Base de Datos COMPAÑÍA se ocupa de los empleados, departamentos y proyectos de una empresa, de acuerdo con los siguientes requisitos:
    * La compañía está organizada en departamentos. Cada departamento tiene un nombre único, un número único            y un empleado que lo dirige. Se debe almacenar la fecha en que dicho empleado comenzó a dirigir ese            departamento. Hay que tener en cuenta que un departamento puede tener diferentes localizaciones.
    * Cada departamento controla un cierto número de proyectos, cada uno de los cuales tiene un nombre y un            número únicos y se realizan en un solo lugar
    * Se almacena el nombre, número de la Seguridad Social, dirección, salario, sexo y fecha de nacimiento            de cada empleado. Todo empleado está asignado a un departamento, pero puede trabajar en varios proyectos que            no tienen por que ser del mismo departamento. Nos interesa saber el número de horas que un empleado dedica a            cada uno de los proyectos asignados
    * También se quiere guardar la relación de las cargas familiares de cada empleado para administrar el            seguro médico. Almacenaremos el nombre, sexo y fecha de nacimiento de cada una de las cargas familiares y su            parentesco con el empleado
  - Se quiere diseñar una Base de Datos para uno de los hoteles del complejo Gran Scala:
    * En este hotel, los clientes se registran por Internet al solicitar su reserva, que podrá incluir una o varias        habitaciones. En cualquier caso la fecha de entrada y salida de todas las habitaciones de una misma reserva será la        misma. Además, debido a la exclusividad del hotel, cada habitación dispone de personal propio (uno o varios empleados, dependiendo del tipo de habitación). De los clientes almacenaremos nombre, apellidos, teléfono, email y fecha de nacimiento. Hay que tener en cuenta que guardaremos un histórico de todas las reservas que un cliente vaya realizando a lo largo del tiempo, pero en un momento dado un cliente sólo puede tener una reserva.
    * Es importante almacenar tanto la fecha de entrada y salida de cada una de las reservas, asi como las habitaciones que la componen. De cada habitación almacenamos el tipo, precio, extensión y el número de clientes que hasta el momento la han utilizado. Cada habitación tiene asignado un número determinado de empleados, de los que guardamos nombre, apellidos, horario y cargo que desempeñan. Hay que tener en cuenta que cada empleado sólo puede tener asignada una habitación donde trabajar.
    * A la hora de realizar el cobro de los servicios utilizados, será importante almacenar cuando un cliente hace un uso de los empleados de alguna de sus habitaciones, puesto que tiene un coste por tarea desempeñada. Habrá que anotar la fecha y hora en la que se hace uso de sus servicios y el precio del mismo. Asi, todos esos cargos se añadirán al precio de la propia reserva.
    * Por último, hay que tener en cuenta que será interesante tener en cuenta que las habitaciones tienen un precio pero éstas pueden ser reservadas a precios más bajos dependiendo de la oferta en vigor, que deberá guardarse también. Tanto el precio de la habitación como el precio que realmente paga el cliente por ella son datos que deben ser registrados.
  - Una empresa desea crear un sitio Web de comercio electrónico al que se podrán conectar clientes para        realizar sus compras. Se tiene que realizar el diseño de la Base de Datos que soporte la operativo de este sitio        Web.
    * Cuando un usuario intenta entrar en este sitio, se le pedirá un login y una contraseña. El sistema comprobará  si el usuario tiene cuenta y en caso negativo se le pedirán los siguientes datos de alta: NIF, correo, nombre, dirección, teléfono, login y password. Se comprobará si ya existía con distinto login para darle un mensaje de        error.
    * Una vez el usuario se ha dado de alta o ha entrado con su login y password correctos, puede visitar las        distintas secciones de la tienda virtual. Nuestra empresa quiere que quede constancia de las secciones visitadas        por los usuario y la fecha en la que la visitaron. Hay que tener en cuenta que un usuario podrá visitar varias        secciones. De cada sección se almacenará un código, nombre, descripción y fecha de creación.
    * Los usuarios pueden realizar sus compras utilizando un carrito virtual. Cuando un usuario decide utilizar el        carrito, el sistema creará uno almacenando la fecha de creación. El usuario entonces puede poner productos,        detallando cuantas unidades desea o bien eliminarlos. Un carrito puede contener varios productos y un producto        puede aparecer en carritos de diferentes usuarios.
    * De los productos se almacenará el código de producto, el nombre, la descripción y el precio por unidad. Cuando un usuario decide finalizar su compra, el sistema le pedirá entonces los datos bancarios (si es la primera vez que paga) y dará el carrito por finalizado. El usuario puede dejar un carrito lleno y no completar la compra en        esa sesión, para completarla otro día. El usuario debe poder comprobar cuál es el coste total de un carrito        antes de pagarlo. Además podrá comprobar el precio total de todos sus carritos anteriores y su contenido.
    * En este sitio Web los productos están organizados en las diferentes secciones teniendo en cuenta que un producto puede aparecer en varias secciones y una sección puede tener varios productos.
  - Se quiere crear una Base de Datos para una inmobiliaria que funciona de la siguiente manera:
    * La inmobiliaria se dedica a la venta o alquiler de inmuebles de diferentes tipos: pisos, chalets, locales,        plazas de garage, . . .
    * Los bienes inmuebles se identifican por un código numérico y su información es la dirección, población, código postal, precio de venta, precio de alquiler, fecha del último movimiento y observaciones. Habrá que tener en cuenta que un mismo inmueble puede estar sólo en alquiler, en venta, o ambas. Además, hay que saber que los precios son aproximados, puesto que el precio por el que realmente se alquile o venta puede ser diferente.
    * Hay varios agentes, que se identifican por su DNI, de los que guardaremos su nombre, dirección, población,        teléfono, horario (mañana/tarde), salario base y observaciones.
    * Se almacena información de cada uno de los clientes cuando éstos realizan alguna operación con la oficina, dni, dirección, población, teléfono y email.
    * Todos los movimientos, sean de venta o alquiler, se registran con toda la información necesaria, que habrá de determinarse.
    * Por último, habrá que tener en cuenta que a final de cada mes, los agentes recibirán una comisión, en función de las ventas que hayan realizado dependiendo del tipo de inmueble. Habrá que hacer las modificaciones necesarias en la Base de Datos para poder calcular y almacenar dicha información
  - Un sitio de juegos online por Internet desea contar con una base de datos para gestionar los usuarios,        juegos y partidas que se desarrollan en su plataforma. El funcionamiento del sitio es el siguiente:
    * Cuando un usuario entra en este sitio, se le pide el nombre de usuario y una contraseña. El sistema comprobará si el usuario tiene cuenta y en caso negativo se le pedirán los siguientes datos de alta antes de darle acceso: nombre, email, nick, login y contraseña. Se comprobará si ya existía algún usuario con el mismo nick y login para darle un mensaje de error en ese caso.
    * Una vez el usuario ha iniciado una sesión, puede visitar los distintos salones donde se están disputando las        partidas. No se desea que quede constancia de dichos salones en la base de datos. Si un usuario quiere entrar en        una partida o crear una nueva tiene que crear un avatar, que será su representación en el mundo virtual. Cada        usuario podrá tener diferentes avatares pero cada avatar sólo puede pertenecer a un usuario. De los avatares        queremos almacenar el aspecto y el nivel. Éstos se identificarán por el nick del propietario.
    * Hay que tener en cuenta que un avatar solo sirve para un tipo de juego, mientras que en un juego puede haber        registrado varios avatares de diferentes usuarios. De los tipos de juego se almacenarán un código, el nombre,        una descripción y un texto con las reglas del mismo.
    * Los usuarios podrán crear partidas de ese juego para que otros se unan a la partida, o bien podrán unirse a        partidas existentes, siempre utilizando el avatar correspondiente. De cada partida queremos almacenar el código,        nombre, una contraseña (opcional), fecha y hora de creación, el estado (en curso o finalizada) y también es        necesario conocer el avatar del usuario que la creó. Además, hay que tener en cuenta que una partida sólo puede        ser para un tipo de juego, aunque un juego puede tener varias partidas.
    * Las partidas se podrán dejar a medias para continuarlas otro día. Cuando un usuario la crea, puede dar una        contraseña de entrada para limitar el acceso. Aquellos usuarios que se unan a las partidas con contraseña        quedarán registrados de manera que si quieren abandonarla y unirse más tarde no tengan que volver a introducir        dicha contraseña. Nunca se permitirá a los usuarios volver a conectarse a partidas que han finalizado
    * Por último, para obtener las puntuaciones finales, se desean registrar los enfrentamientos que se producen en        cada partida entre los diferentes avatares de los usuarios, y el resultado de los mismos.
  - La empresa de comida rápida Burger King, con servicio a domicilio, desea crear una base de datos para gestionar todo su negocio. Actualmente sólo vende hamburguesas, ensaladas y bebidas, aunque también quiere registrar todas las ventas realizadas, así como la actividad de sus empleados.
    * Burger King tiene varios centros de comida rápida distribuidos por toda la comunidad de Aragón y atenderá        peticiones en todas las poblaciones. De cada centro se quiere almacenar un código, nombre, dirección, población        y un teléfono.
    * Aunque todos los centros pertenecen a Burger King, la empresa da libertad a cada uno para que oferten sus        propias hamburguesas y ensaladas. De dichas ofertas se almacena el número, nombre, descripción y precio. Hay que        tener en cuenta que una hamburguesa puede ser ofertada por más de un centro.
    * De los clientes a domicilio guardaremos su número, nombre, dirección y teléfono. Además, en cada pedido        almacenaremos los productos que se han adquirido así como la fecha del mismo. También es importante, para hacer        descuentos, saber la cantidad de pedidos totales por cliente.
    * Respecto a los empleados, hay que almacenar su DNI, nombre, dirección, teléfono y población. La empresa asignará empleados a los diferentes centros según las necesidades de cada uno. Un empleado sólo estará asignado un centro en un momento dado pero puede ser reasignado a otro distinto. Por ello, interesa conocer los centros en los que un empleado determinado ha trabajado y en qué fechas empezó y terminó en cada caso.
    * Además, para analizar sus ventas, se almacena información de todas las poblaciones en las que se ha abierto        algún centro: nombre, provincia y número de habitantes. Hay que tener en cuenta que en una misma población        podrá haber más de un centro.
  - El Gobierno de Aragón quiere mantener una base de datos de las fiestas celebradas en todos los pueblos de        la comunidad para el verano de 2012.
    * En particular se quiere almacenar la información referente a los grupos musicales que actúan en cada pueblo, los encierros que se celebran y las peñas de cada municipio. Toda esta información se utilizará para proporcionar ayudas económicas a los municipios que la soliciten.
    * De cada municipio se almacenará el nombre, el número de habitantes, la superficie de su término municipal, el        presupuesto de las últimas fiestas y el número de peñas que tiene. De cada grupo musical se mantener el nombre,        el año de formación, el precio por actuación y el número de componentes. Hay que tener en cuenta que un grupo        puede actuar en varios pueblos en diferentes fiestas y un municipio puede tener la actuación de varios grupos.        Por supuesto, un grupo puede repetir actuación en un mismo pueblo. Además, será importante mantener información        sobre las fechas en las que ha actuado cada grupo en cada uno de los pueblos.
    * En cuanto a los encierros, se almacenará el pueblo en el que se realizan, la fecha, la ganadería y el número de heridos producidos.
    * Las peñas se definen por el nombre, el número de socios y el año en que se crearon. Hay que tener en cuenta que una peña solo puede pertenecer a un pueblo y un pueblo puede tener varias peñas. También interesa conocer qué        peñas colaboran con la celebración de los encierros. Además, es importante conocer el número de heridos de cada        peña que se producen en un encierro determinado.
    * Por último, habrá que tener en cuenta que para cada actuación de un grupo musical, es una peña de dicho        municipio quién elige dicho grupo.
  - El Ayuntamiento de Zaragoza quiere implantar un sistema de control para las estaciones de bicicletas públicas que ha instalado recientemente. El objetivo es conocer donde están las bicicletas en cada momento y saber qué usuarios las han usado y cuando lo han hecho. Además, cada bicicleta tiene instalado un módulo de autodiagnóstico que detecta las averías para que éstas quede registradas y puedan ser reparadas por los técnicos del Ayuntamiento.
    * De cada bicicleta se almacenará su matrícula, cuantas marchas tiene, el color, si tiene o no cesta, la velocidad máxima y si está o no averiada.
    * Por otra parte, a los usuarios se les obliga a darse de alta a través de una web, aportando su DNI, nombre, apellidos, email, teléfono móvil y un número de cuenta.
    * Hay que tener en cuenta que habrá muchas estaciones repartidas por la ciudad y que los usuarios deben poder consultar información relativa a éstas desde una página web: el número asignado a la estación, dirección donde se encuentra, si está o no operativa, su capacidad máxima y el horario de apertura de dicha estación.
    * Cuando el módulo de diagnóstico detecta una avería, la envía al servidor central aportando un número de avería, una descripción breve de la misma y la fecha en la que tuvo lugar. Por supuesto, habrá que saber qué bicicleta está averiada. De esa manera los mecánicos del servicio podrán consultar el fichero de averías y repararlas. También es importante que quede guardado qué mecánico arregló una avería determinada (de ellos se guarda su código de empleado, nombre, apellidos y teléfono móvil) teniendo en cuenta que cada uno tiene asignadas dos estaciones de las que hacerse cargo, aunque las bicicletas pueden estar en cualquier estación.
    * Además, es necesario conocer en cada momento qué usuario tiene una bicicleta determinada asi como las bicicletas que han sido utilizadas por los usuarios y durante cuánto tiempo las usaron. En el caso de las averías también tienen que quedar registradas cuál fue el último usuario que usó la bicicleta averiada por si hubiera que multarlo.
  - Como desarrollador de la empresa \emph{EventoBook}, debes diseñar la Base de Datos de la aplicación estrella de la empresa. Se trata de una red social para que la gente se relacione con sus amigos y con eventos que tienen lugar en su ciudad de forma que puedan consultarlos, apuntarse y ver si sus amigos también van a acudir. Además, podrán opinar sobre ellos y compartir esas opiniones con el resto de los usuarios de esta red.
    * Cada nuevo usuario debe registrarse proporcionando su nombre, apellidos, email, una contraseña y su fecha de nacimiento. Por otro lado, cualquiera puede registrar eventos que podrán ser de dos tipos: deportivos y culturales, indicando en ambos casos nombre, descripción del evento, una URL, la dirección (compuesta de calle, código postal, población y provincia), la fecha de inicio, la fecha de finalización y el precio, si tienen. Además, dependiendo del tipo de evento se almacenarán algunos otros datos. De los eventos deportivos se almacena el deporte y los equipos que se enfrentan (cantidad variable) además de todos los datos anteriores. Si el evento es cultural se añaden el motivo (que tomará los valores música, pintura ó cine) y el nombre del artista que ha motivado dicho evento. En cualquier caso debe quedar constancia del usuario que creó el evento.
    * Los usuarios podrán indicar qué usuarios son conocidos suyos y el motivo (que tomará los valores trabajo, familia o amistad) y asi quedará almacenado. Además, los usuarios se podrán apuntar a los eventos de forma que será necesario conocer qué usuarios van a cada uno de ellos. Tras la celebración del evento el usuario que haya ido podrá dejar (o no) una opinión sobre el mismo donde podrá escribir una opinión libre sobre ese evento, una puntuación (de 1 a 10) y si lo recomendaría o no a sus amigos. Hay que tener en cuenta que las opiniones deben ser anónimas, de forma que no sea posible saber que usuario la ha escrito.
    * Han abierto un centro comercial en Zaragoza y para su gestión se debe diseñar una Base de Datos para        almacenar toda la información sobre el mismo. Es el centro comercial más grande del mundo por lo que tendrá varios tipos de establecimientos: tiendas de ropa, restaurantes y museos. De todos ellos se almacenará el nombre, número de local, capacidad máxima y su horario. Además, de las tiendas de ropa se almacenará el tipo de ropa que venden y si están de rebajas o no. Para los restaurantes se almacenará el nombre del chef y el estilo de comida que preparan; y para los museos se almacenará una lista con los pintores que exponen sus obras en cada momento.
    * Además, se almacenará la información de los clientes que asisten a estos establecimientos (si éstos lo autorizan) almacenando el nombre, apellidos, dirección, teléfono y email. También se almacenará en qué establecimientos han hecho alguna compra y la cantidad a la que ésta asciende. Se ofrecerán descuentos a aquellos clientes que vengan recomendados por otros, por lo que es interesante almacenar esta relación.
    * Puesto que también se celebran eventos de todo tipo en el centro comercial (almacenando el nombre del evento, fecha y tipo de evento, que podrá ser deportivo, festivo o cultural), se venderán entradas que los clientes podrán adquirir para asistir a los mismos. De las entradas se guardará la numeración, la fecha de compra, la butaca asignada y el tipo de entrada que podrá ser VIP, PREMIUM o NORMAL. Es importante que quede registrado a qué cliente pertenece cada entrada, ya que son personales.
  - La organización de la vuelta ciclista a España 2016 ha decidido crear una web para seguir el transcurso del evento en directo. Para ello debe diseñar una Base de Datos. Se desea almacenar información de todos los ciclistas (dorsal, nombre, apellidos, fecha de nacimiento, nacionalidad y el equipo al que pertenecen). De cada equipo de la vuelta almacenaremos el nombre, la marca a la que representa, la nacionalidad y el presupuesto. Además, cada equipo tendrá un líder, que será un corredor del equipo.
    * También se quiere almacenar todas las etapas de esta edición, almacenando el número de la etapa, el origen, el destino, la distancia en kms y el tipo de etapa (montaña o contrarreloj). Si la etapa es de montaña además se almacenarán los nombres de los puertos de montaña que atraviesa y la pendiente media de toda la etapa. Si fuera una contrarreloj se añade en que kilómetros intermedios se tomarán tiempos. Una vez terminada cada etapa se almacenará qué corredores han quedado en los tres primeros puestos y el tiempo que les ha costado.
    * Por último, en esta edición de la vuelta se quiere tener registrada cada bicicleta que use cualquier corredor, teniendo en cuenta que un corredor puede usar más de una bicicleta pero que una bicicleta determinada sólo puede haberla usado un corredor. De cada bicicleta almacenaremos la marca, el modelo y el estado (en uso, rota o en reparación) y también es necesario que queden registradas las fechas entre las que el corredor la utilizó en carrera.

----

(c) Santiago Faci <santi@codeandcoke.com>