Introducción a SQL y Bases de Datos Relacionales
Introducción a SQL y Bases de Datos Relacionales
Nos permite embeberlo en cualquier lenguaje (PHP, Java, ASP...) para trabajar en
combinación con cualquier sistema de bases de datos como pueda ser Access, MySQL, SQL
Server... asumiendo que en el uso de los diferentes sistemas de bases de datos pueden darse
unas diferencias de sintaxis mínimas, que no afectarán en ningún caso a la esencia del propio
lenguaje SQL.
Hemos comentado en la introducción que SQL es (a grandes rasgos) el lenguaje que permite
comunicar una aplicación programada en cualquier lenguaje con un sistema de base de datos.
Esto significa que SQL nos permitirá crear y manipular bases de datos, crear tablas, insertar
o eliminar datos, realizar consultas sobre ellos, ... todo tipo de operaciones sobre bases de
datos.
La historia de SQL (que se pronuncia deletreando en inglés las letras que lo componen, es
decir “ese-cu-ele” y no “siquel” como se oye a menudo) empieza en 1974 con la definición,
por parte de Donald Chamberlin y de otras personas que trabajaban en los laboratorios de
investigación de IBM, de un lenguaje para la especificación de las características de las bases
de datos que adoptaban el modelo relacional. Este lenguaje se llamaba SEQUEL (Structured
English Query Language) y se implementó en un prototipo llamado SEQUEL-XRM entre 1974 y
1975. Las experimentaciones con ese prototipo condujeron, entre 1976 y 1977, a una revisión
del lenguaje (SEQUEL/2), que a partir de ese momento cambió de nombre por motivos legales,
convirtiéndose en SQL. El prototipo (System R), basado en este lenguaje, se adoptó y utilizó
internamente en IBM y lo adoptaron algunos de sus clientes elegidos. Gracias al éxito de
este sistema, que no estaba todavía comercializado, también otras compañías empezaron
a desarrollar sus productos relacionales basados en SQL. A partir de 1981, IBM comenzó
a entregar sus productos relacionales y en 1983 empezó a vender DB2. En el curso de los
años ochenta, numerosas compañías (por ejemplo Oracle y Sybase, sólo por citar algunos)
comercializaron productos basados en SQL, que se convierte en el estándar industrial de hecho
por lo que respecta a las bases de datos relacionales.
En 1986, el ANSI adoptó SQL (sustancialmente adoptó el dialecto SQL de IBM) como
estándar para los lenguajes relacionales y en 1987 se transfomó en estándar ISO. Esta versión
del estándar va con el nombre de SQL/86. En los años siguientes, éste ha sufrido diversas
revisiones que han conducido primero a la versión SQL/89 y, posteriormente, a la actual SQL/92.
El hecho de tener un estándar definido por un lenguaje para bases de datos relacionales
abre potencialmente el camino a la intercomunicabilidad entre todos los productos que se
basan en él. Desde el punto de vista práctico, por desgracia las cosas fueron de otro modo.
Efectivamente, en general cada productor adopta e implementa en la propia base de datos
sólo el corazón del lenguaje SQL (el así llamado Entry level o al máximo el Intermediate level),
extendiéndolo de manera individual según la propia visión que cada cual tenga del mundo de
las bases de datos.
Actualmente, está en marcha un proceso de revisión del lenguaje por parte de los comités
ANSI e ISO, que debería terminar en la definición de lo que en este momento se conoce
como SQL3. Las características principales de esta nueva encarnación de SQL deberían ser su
transformación en un lenguaje stand-alone (mientras ahora se usa como lenguaje hospedado
en otros lenguajes) y la introducción de nuevos tipos de datos más complejos que permitan,
por ejemplo, el tratamiento de datos multimediales.
Puesto que SQL es un lenguaje diseñado para trabajar sobre bases de datos relacionales, es
imprescindible tener una clara referencia de qué son exactamente este tipo de bases de datos
y que propiedades las caracterizan, para entender como funcionan y poder trabajar con ellas
de una manera eficiente.
Una base de datos relacional es una base de datos que cumple con el modelo relacional,
que es el modelo más utilizado en la actualidad para modelar problemas reales y administrar
datos dinámicamente.
Las bases de datos relacionales permiten establecer interconexiones (relaciones) entre los
datos (que están guardados en tablas), y trabajar con ellos conjuntamente. Tras ser postuladas
sus bases en 1970 por Edgar Frank Codd, de los laboratorios IBM en San José (California), no
tardó en consolidarse como un nuevo paradigma en los modelos de base de datos.
Existen una serie de criterios importantes a tener en cuenta para garantizar la calidad del
diseño de la BD, algunos de los más esenciales se reflejan a continuación:
• Legibilidad: El diseño de una base de datos se redactará de una forma clara y concisa
para que pueda ser entendido rápidamente, suficientemente detallada para que explique
con total claridad el diseño del modelo, sus objetivos, sus restricciones... y en general todo
aquello que afecte al sistema en cualquier forma.
• Generalidad: Se intentará que la base de datos que diseñemos sea capaz de adaptarse a
cualquier circunstancia en la medida de lo posible.
• Precisión: Los cálculos efectuados deben ser lo más precisos posibles para un óptimo
funcionamiento de la base de datos.
• Protección: El diseño de la base de datos debe permitir la protección de los datos frente
a usos indebidos, por lo que hay que elaborar un sistema de accesos definiendo diferentes
usuarios con claves personalizadas y especificar los permisos de cada uno de ellos sobre los
datos almacenados.
Las bases de datos que implementan el modelo relacional son el tipo de bases de datos más
difundido actualmente, fundamentalmente debido a estos dos motivos:
1. nos ofrecen sistemas simples y eficaces para representar y manipular los datos.
2. se basan en un modelo teórico con bases muy sólidas.
Entidades
Una entidad representa un objeto del mundo real con existencia independiente (ya sea
física o conceptual), diferenciándose de forma unívoca de cualquier otro objeto.
Se puede definir cono entidad a cualquier objeto, real o abstracto, que existe en un contexto
determinado o puede llegar a existir y del cual deseamos guardar información, por ejemplo:
“CLIENTE”, “HOTEL”. Las entidades las podemos clasificar en:
• Regulares: aquellas que existen por sí mismas y que la existencia de un ejemplar en
la entidad no depende de la existencia de otros ejemplares en otra entidad. Por ejemplo
“CLIENTE”. La representación gráfica dentro del diagrama es la siguiente:
CLIENTE
• Débiles: son aquellas entidades en las que se hace necesaria la existencia de ejemplares
de otras entidades distintas para que puedan existir ejemplares en esta entidad. Un ejemplo
sería la entidad “ALBARÁN” que sólo existe si previamente existe el correspondiente pedido.
La representación gráfica dentro del diagrama es la siguiente:
ALBARÁN
Atributos
Las entidades se componen de atributos que son cada una de las propiedades o características
que tienen las entidades. Cada ejemplar de una misma entidad posee los mismos atributos,
tanto en nombre como en número, diferenciándose cada uno de los ejemplares por los valores
que toman dichos atributos. Si consideramos la entidad “CLIENTE” y definimos los atributos
Nombre, DNI, Direccion, contato podríamos obtener los siguientes registros:
{Luis Perez, 50699878, Juglares 26, luis@[Link]}
{Antonio López, 48697878, luna 25, antonio@[Link]}
{Ana Martin, 33333878, castilla 12, ana@[Link]}
Contácto Teléfono
Nombre Edad
Dentro del diagrama la entidad “CLIENTE” y sus atributos quedarían de la siguiente forma:
Contacto Teléfono
ALBARÁN
Nombre Edad
Existen atributos, llamados derivados, cuyo valor se obtiene a partir de los valores de otros
atributos. Pongamos como ejemplo la entidad “CLIENTE” que tiene los atributos “NOMBRE”,
“FECHA DE NACIMIENTO”, “EDAD”; el atributo “EDAD” es un atributo derivado por que se
calcula a partir del valor del atributo “FECHA DE NACIMIENTO”. Su representación gráfica es la
siguiente:
Ejemplo:
Se pide diseñar una base de datos para un pequeño hotel donde se tendrán en cuenta los
clientes y las habitaciones.
Clientes es una entidad, que podría guardar, como atributos, los siguientes:
• DNI
• nombre
• dirección
• contacto
Dominios
Se define dominio como un conjunto de valores que puede tomar un determinado atributo
dentro de una entidad. Por ejemplo:
Atributo Dominio
Fecha de Alta Calendario Gregoriano
Teléfono Conjunto de números de teléfonos
Edad 0 - 120
De forma casi inherente al término dominio aparece el concepto restricción para un atributo.
Cada atributo puede adoptar una serie de valores de un dominio restringiendo determinados
valores. El atributo “EDAD” toma sus valores del dominio N (números naturales) pero se puede
poner como restricción aquellos que estén en un intervalo por ejemplo de (0-120).
Claves
El modelo entidad - relación exige que cada entidad tenga un identificador, se trata de un
atributo o conjunto de atributos que identifican de forma única a cada uno de los ejemplares
de la entidad. De tal forma que ningún par de ejemplares de la entidad puedan tener el mismo
valor en ese identificador.
Relaciones
Las relaciones representan una asociación entre dos o más entidades, describiendo
dependencias entre ellas
Ejemplo:
Siguiendo el ejemplo anterior, la relación que completaría el diseño anterior sería la Reserva
(un Cliente reserva Habitaciones, o lo que es igual, una Habitación es reservada por un Cliente).
dni reserva
cliente habitación
Figura 1
En el caso que nos ocupa, se establecerían como claves primarias, es decir, las que se
utilizarán como índices únicos de identificación, el DNI de cada Cliente y el Número de cada
Habitación
Cardinalidad
Es importante tener en cuenta la cardinalidad de las relaciones entre entidades, es decir
cuántos elementos como máximo y como mínimo intervienen en la relación.
Ante la presencia de este tipo de relación nos podemos plantear el caso de unificar todos
los datos en única tabla pues no es necesario mantener ambas tablas a la misma vez.
Este tipo de relación se genera cuando aparecen tablas muy grandes, con gran cantidad
de campos, disgregando la tabla principal en dos para evitar tener una tabla muy grande.
También surge cuando los diferentes grupos de usuario cumplimentan una información
diferente para un mismo registros; en este caso se crean tantas tablas como registros,
evitando así tener que acceder a información que el usuario del grupo actual no necesita
Estudiemos la relación entre un tabla de clientes y una tabla de pedidos. Un cliente puede
realizar varios pedidos pero un pedido pertenece a un único cliente, por tanto se trata de
una relación uno a varios y la representamos A 1: n B. Estas relaciones suelen surgir de
aplicar la 1NF a una tabla.
Muchas a una (N,1): una entidad A está asociada a una entidad B, pero una entidad B está
asociada a varias entidades A.
Un caso muy característico de esta interrelación es la que surge entre las tablas de Puestos
de Trabajo y Empleados de una empresa. Un Empleado puede desempeñar realizar varias
funciones dentro de una empresa (desempeñar varios puestos de trabajo), y un puesto de
trabajo puede estar ocupado por varios empleados a la misma vez. Esta interrelación la
representamos como A n: n B.
Ambos casos pueden suponer un grave problema si definimos una relación con integridad
referencial y decimos eliminar en cascada (al eliminar una clave de la tabla A se eliminan los
elementos relacionados en la tabla B). Supongamos la relación recursiva existen en la relación
Empleado y Supervisor (ambos son empleados de la empresa). Está claro que un empleado
está supervisado por otro empleado.
Empleados
Código Nombre Supervisor
102 Juan NO
105 Luis SI
821 María NO
956 Martín SI
Para solucionar la relación debemos crear una tabla formada por dos campos. Ambos
campos deben ser el código del empleado pero como no podemos tener dos campos con el
mismo nombre a uno de ellos le llamaremos código supervisor.
Tabla Puente
Código Empleado Código Supervisor
102 105
105 956
821 105
956 105
Para terminar de resolver la interrelación recursiva basta con definir dos interrelaciones
entre la tabla empleados y la tabla puente de tipo 1: n. La primera relación se crea
utilizando las claves Empleados[Código] y Tabla Puente[Código Empleado]. La segunda entre
Empleados[Código] y Tabla Puente [Código Supervisor].
Las interrelaciones cíclicas o circulares no son muy frecuentes y no existe una metodología
estándar para su eliminación, normalmente son debidas a errores de diseño en la base de
datos, principalmente en el diseño conceptual del sistema de datos. Por tanto si llegamos a
este punto hay que volver a replantearse todo el diseño de la base de datos.
Atributos de las interrelaciones
En la mayoría de las interrelaciones definidas será conveniente exigir integridad relacional
entre las claves. Exigiendo la integridad referencial se consigue que en una relación de tipo
1: n o de tipo 1: 1, no se puede añadir ningún valor en la tabla destino si no existe en la tabla
origen. Dicho con un ejemplo: en la relación Clientes y Pedidos la tabla Pedidos contiene un
campo que se corresponde con el código del Cliente, si se exige la integridad referencia no se
podrá escribir un código de cliente en la tabla Pedidos que no exista en la tabla Clientes; de no
exigir la integridad referencial se podrán crear pedidos con códigos de clientes que no existen,
generando incongruencia de datos en la base de datos.
Las operaciones de álgebra relacional trabajan con relaciones, lo que significa que estas
operaciones usan una o más relaciones existentes para crear una nueva relación. Esta nueva
relación puede entonces usarse como entrada para una nueva operación. Este concepto
tan potente, la creación de una nueva relación a partir de relaciones existentes, hace
considerablemente más fácil la solución de las consultas, debido a que se puede experimentar
con soluciones parciales hasta encontrar la qué más se adecue a nuestras necesidades.
Intersección
La operación de intersección permite identificar filas que son comunes en dos relaciones.
Diferencia
La operación diferencia permite identificar filas que están en una relación y no en otra.
Tomando como referencia el caso anterior, deberíamos aplicar una diferencia entre la tabla
empleados y la tabla asistentes al curso para saber aquellos asistentes externos a la organización
que han asistido al curso.
Producto cartesiano
La operación producto consiste en la realización de un producto cartesiano entre dos tablas
dando como resultado todas las posibles combinaciones entre los registros de la primera y los
registros de la segunda.
Selección
La operación selección consiste en recuperar un conjunto de registros de una tabla o de
una relación indicando las condiciones que deben cumplir los registros recuperados, de tal
forma que los registros devueltos por la selección han de satisfacer todas las condiciones que
se hayan establecido. Esta operación es la que normalmente se conoce como consulta.
Los diferentes operadores que pueden emplearse en este tipo de consulta son los
operadores de comparación (=,>, <, >=, <=, <>), los operadores lógicos (and, or, xor) o la
negación lógica (not).
Proyección
La proyección es un caso concreto de la operación selección, que devuelve todos los
campos de aquellos registros que cumplen la condición que he establecido. Una proyección es
una selección en la que seleccionamos aquellos campos que deseamos recuperar.
Reunión
Se utiliza para recuperar datos a través de varias tablas conectadas unas con otras mediante
cláusulas JOIN, en cualquiera de sus tres variantes INNER, LEFT, RIGHT. La operación reunión se
puede combinar con las operaciones selección y proyección.
División
La operación división es la contraria a la operación producto.
Queda formada por las tuplas que al completarse con las tuplas de la segunda relación
permiten obtener la primera.
Asignación
Esta operación algebraica consiste en asignar un valor a5 uno o varios campos de una tabla.
1.4.5. Normalización
AUTORES Y LIBROS
NOMBRE NACION CODLIBRO TITULO EDITOR
Date POR 111 BHJ MH
[Link]. ESP 222 JJP AN
[Link]. ITA 333 PYC AN
Date FRAN 444 LMN RM
Se plantean una serie de problemas:
• Redundancia: cuando un autor tiene varios libros, se repite la nacionalidad.
• Anomalías de modificación: Si [Link]. y [Link]. desean cambiar de editor, se modifica
en los 2 lugares. A priori no podemos saber cuántos autores tiene un libro. Los errores son
frecuentes al olvidar la modificación de un autor. Se pretende modificar en un sólo sitio.
• Anomalías de inserción: Se desea dar de alta un autor sin libros, en un principio. NOMBRE
y CODLIBRO son campos clave, una clave no puede tomar valores nulos.
Asegurando:
• Integridad entre los datos: consistencia de la información.
El proceso de normalización nos conduce hasta el modelo físico de datos y consta de varias
fases denominadas formas normales, estas formas se detallan a continuación.
Definición de la clave
Antes de proceder a la normalización de la tabla lo primero que debemos de definir es
una clave, esta clave deberá contener un valor único para cada registro (no podrán existir dos
valores iguales en toda la tabla) y podrá estar formado por un único campo o por un grupo de
campos.
La solución en este caso es asignar un código de alumno a cada uno, un número que
identifique al alumno y que estemos seguros que es ú[Link] vez definida la clave podremos
pasar a estudiar la primera forma normal.
Podemos observar que el registro de código 1 si cumple la primera forma normal, cada
campo del registro contiene un único dato, pero no ocurre así con los registros 2 y 3 ya que en
el campo cursos contiene más de un dato cada uno. La solución en este caso es crear dos tablas
del siguiente modo:
TABLA A TABLA B
Código Nombre Código Curso
1 Ana 1 Chino
2 Luis 2 Francés
3 Juan 2 Informática
3 Inglés
3 Contabilidad
Como se puede comprobar ahora todos los registros de ambas tablas contienen valores
únicos en sus campos, por lo tanto ambas tablas cumplen la primera forma normal.
Una vez normalizada la tabla en 1NF, podemos pasar a la segunda forma normal.
Supongamos que construimos una tabla con los años que cada empleado ha estado
trabajando en cada departamento de una empresa:
Código Empleado Código Dpto. Nombre Departamento Años
1 4 Ana Contabilidad 6
2 2 Luis Sistemas 3
3 3 Juan I+D 1
4 1 Rosa Auditoria 10
2 4 Luis Contabilidad 5
Tomando como punto de partida que la clave de esta tabla está formada por los campos
código de empleado y código de departamento, podemos decir que la tabla se encuentra en
primera forma normal, por tanto vamos a estudiar la segunda:
1. El campo nombre no depende funcionalmente de toda la clave, sólo depende del código
del empleado.
2. El campo departamento no depende funcionalmente de toda la clave, sólo del código del
departamento.
3. El campo años si que depende funcionalmente de la clave ya que depende del código
del empleado y del código del departamento (representa el número de años que cada
empleado ha trabajado en cada departamento)
Por tanto, al no depender todos los campos de la totalidad de la clave la tabla no está en
segunda forma normal, la solución es la siguiente:
Podemos observar que ahora si se encuentras las tres tablas en segunda forma normal, con-
siderando que la tabla A tiene como índice el campo Código Empleado, la tabla B Código Departa-
mento y la tabla C una clave compuesta por los campos Código Empleado y Código Departamento.
Tercera forma normal (3NF)
Se dice que una tabla está en tercera forma normal si y solo si los campos de la tabla
dependen únicamente de la clave, dicho en otras palabras los campos de las tablas no dependen
unos de otros. Tomando como referencia el ejemplo anterior, supongamos que cada alumno
sólo puede realizar un único curso a la vez y que deseamos guardar en que aula se imparte el
curso. A voz de pronto podemos plantear la siguiente estructura:
Por esta última razón se dice que la tabla no está en 3NF. La solución sería la siguiente:
Tabla A Tabla B
Una vez conseguida la tercera forma normal, se puede estudiar la cuarta forma normal.
Comparemos ahora la clave (Figura) con el atributo Tamaño, podemos observar que Cua-
drado Grande está repetido; igual pasa con Círculo Azul, entre otras. Estas repeticiones son las
que se deben evitar para tener una tabla en 4NF.
Tamaño Color
Figura Tamaño Figura Color
Rectángulo Grande Rectángulo Verde
Rectángulo Mediano Rectángulo Azul
Triangulo Mediano Triangulo Amarillo
Triangulo Pequeño Triangulo Rojo
1.5.1. Comandos
1.5.2. Cláusulas
Son condiciones de modificación, que se utilizan para definir los datos que desea seleccionar
o manipular.
• FROM: para especificar la tabla de la cual se van a seleccionar los registros
• WHERE: para especificar las condiciones que deben reunir los registros que se van a
seleccionar
• GROUP BY: para separar los registros seleccionados en grupos específicos
• HAVING: para expresar la condición que debe satisfacer cada grupo
• ORDER BY: para ordenar los registros seleccionados de acuerdo con un orden específico
En una sentencia SQL de selección que incluya todas las posibles cláusulas, el orden de
ejecución de las mismas sería el siguiente:
1. Cláusula FROM
2. Cláusula WHERE
3. Cláusula GROUP BY
4. Cláusula HAVING
5. Cláusula SELECT
6. Cláusula ORDER BY
1.5.3. Operadores
• Lógicos
- AND: Es el “y” lógico. Evalúa dos condiciones y devuelve un valor de verdad sólo si
ambas son ciertas.
- OR: Es el “o” lógico. Evalúa dos condiciones y devuelve un valor de verdad si alguna de
las dos es cierta.
- NOT: Negación lógica. Devuelve el valor contrario de la expresión.
• De comparación
- < Menor que
- > Mayor que
- <> Distinto de
- <= Menor o igual que
- >= Mayor o igual que
- = Igual que
- BETWEEN: para especificar un intervalo de valores.
- LIKE: para la comparación de un modelo
- IN: para especificar registros de una base de datos
Estas funciones se usan dentro de una cláusula SELECT, en grupos de registros, para devolver
un valor único que se aplica a un grupo de registros.
• AVG: para calcular el promedio de los valores de un campo determinado.
• COUNT: para devolver el número de registros de la selección.
• SUM: para devolver la suma de todos los valores de un campo determinado.
• MAX: para devolver el valor más alto de un campo especificado.
• MIN: para devolver el valor más bajo de un campo especificado.
UNIDAD 2
2.1. Tipos de Datos
2.2. Consultas de acción
2.1. Tipos de Datos
Para poder trabajar con el lenguaje SQL es esencial conocer los tipos de datos que admite.
Estos tipos de datos SQL se clasifican en tipos de datos primarios y en sinónimos válidos
reconocidos por dichos tipos de datos.
Las consultas de acción son aquellas que no devuelven ningún resultado, sino que ejecutan
una operación.
Una sentencia de creación de tablas en SQL seguiría una estructura como la siguiente:
Ejemplo:
CREATE TABLE Clientes
( DNICliente INTEGER CONSTRAINT IndicePrimario PRIMARY KEY,
Nombre TEXT (50),
Direccion TEXT (50),
Contacto TEXT (10)
)
Como se muestra en los ejemplos previos, una tabla puede crearse directamente con el
campo que va a servir como clave, indicando que va a ser índice y de qué tipo, o bien puede
crearse la tabla únicamente con los campos que va a contener como información y más
adelante ya se incorporará el índice.
La cláusula CONSTRAINT se utiliza en las instrucciones ALTER TABLE y CREATE TABLE para
crear o eliminar índices.
Hay dos formas de establecer la sintaxis para esta cláusula, en función de si se desea crear
ó eliminar un índice de un único campo o si se trata de un campo multi-índice.
En los casos en que se desea crear un índice para un campo cuando se está utilizando
las instrucciones ALTER TABLE (que se detallará más adelante) o CREATE TABLE la cláusula
CONTRAINT debe aparecer inmediatamente después de la especificación del campo indexado.
Cuando se desea crear un índice con múltiples campos mientras se está utilizando las
instrucciones ALTER TABLE o CREATE TABLE la cláusula CONSTRAINT debe aparecer fuera de la
cláusula de creación de tabla.
Tipos de índices:
• UNIQUE: Crea un índice de clave única por lo que los registros de la tabla no pueden
contener el mismo valor en los campos indexados.
• PRIMARY KEY: Crea un índice primario el campo o los campos especificados. Al utilizar
este tipo de índice todos los campos de la clave principal deben ser únicos y no nulos, y
cada tabla sólo puede contener una única clave principal.
• FOREIGN KEY: Crea un índice externo, tomando como valor del índice campos contenidos
en otras tablas. Si la clave principal de la tabla externa consta de más de un campo, se
debe utilizar una definición de índice de múltiples campos, listando todos los campos de
referencia, el nombre de la tabla externa, y los nombres de los campos referenciados en
la tabla externa en el mismo orden que los campos de referencia listados. Si los campos
referenciados son la clave principal de la tabla externa, no necesita especificar los campos
referenciados.
Para crear un índice en una tabla que ya está definida se hará de la siguiente manera:
CREATE [ UNIQUE ] INDEX índice ON tabla (campo [ASC|DESC][,
campo [ASC|DESC], ...]) [WITH { PRIMARY | DISALLOW NULL | IGNORE
NULL }]
• Índice: Nombre del índice a crear.
• Tabla: Nombre de una tabla existente en la que se creará el índice.
• Campo: Nombre del campo o lista de campos que consituyen el índice.
• ASC|DESC: Indica el orden de los valores de los campos, ASC para un orden ascendente
(valor predeterminado) y DESC para orden descendente.
• UNIQUE: Indica que el índice no puede contener valores duplicados.
• DISALLOW NULL: Prohíbe valores nulos en el índice
• IGNORE NULL: Excluye del índice los valores nulos incluidos en los campos que lo
componen.
• PRIMARY: Asigna al índice la categoría de clave principal, en cada tabla sólo puede existir
un único índice que sea “Clave Principal”. Si un índice es clave principal implica que no
puede contener valores nulos ni duplicados.
Se puede utilizar CREATE INDEX para crear un pseudo índice sobre una tabla adjunta que
no tenga todavía un índice. Se utiliza la misma sintaxis para las tabla adjunta que para las
originales. Esto resulta especialmente útil para crear un índice en una tabla que sería de sólo
lectura debido a la falta de un índice.
Ejemplo:
CREATE INDEX Mi_Indice ON Clientes (Nombre, Dirección,
Contacto);
Crea un índice llamado Mi_Indice en la tabla empleados con los campos Nombre, Dirección
y Contacto.
Ejemplo:
CREATE UNIQUE INDEX Mi_Indice ON Clientes (DNI) WITH DISALLOW
NULL;
Crea un índice en la tabla Clientes utilizando el campo ID, obligando que el campo DNI no
contenga valores nulos ni repetidos, lo cual resultará de gran utilidad para nuestra tabla.
Figura 5: Creación de índices
Es posible modificar el diseño de una tabla ya existente, cambiando los campos o los índices
existentes de la siguiente forma:
Las operaciones que se pueden realizar para modificar la estructura de una tabla ya creada
son las siguientes:
• ADD COLUMN: para añadir un nuevo campo a la tabla, indicando el nombre, el tipo de
campo y opcionalmente el tamaño (para campos de tipo texto).
• ADD: para agregar un índice de multicampos o de un único campo.
• DROP COLUMN: para borrar un campo. Se especifica únicamente el nombre del campo.
• DROP: para eliminar un índice. Se especifica únicamente el nombre del índice a
continuación de la palabra reservada CONSTRAINT.
A continuación se presenta una serie de ejemplos para ilustrar como utilizar las operaciones
descritas anteriormente:
Ejemplo:
ALTER TABLE Clientes ADD COLUMN Descripcion TEXT;
Ejemplo:
ALTER TABLE Clientes DROP COLUMN Descripcion;
Ejemplo:
ALTER TABLE Reservas ADD CONSTRAINT RelacionReservas FOREIGN
KEY
(DNI) REFERENCES Clientes (DNI);
Añade un índice externo a la tabla Pedidos. El índice externo se basa en el campo DNI y se
refiere al campo DNI de la tabla Clientes.
Ejemplo:
ALTER TABLE Reservas DROP CONSTRAINT RelacionReservas;
Añade registros en una tabla ya sea un único registro ó los registros contenidos en otra
tabla diferente.
Se puede utilizar la instrucción INSERT INTO para agregar un registro único a una tabla,
utilizando la sintaxis de la consulta de adición de registro único. En este caso, su código
especifica el nombre y el valor de cada campo del registro. Debe especificar cada uno de los
campos del registro al que se le va a asignar un valor así como el valor para dicho campo.
Cuando no se especifica dicho campo, se inserta el valor predeterminado o Null.
Se puede especificar los valores de cada campo en un nuevo registro utilizando la cláusula
VALUES. Si se omite la lista de campos, la cláusula VALUES debe incluir un valor para cada
campo de la tabla, de otra forma fallará INSERT.
La tabla destino u origen puede especificar una tabla o una consulta. Si la tabla destino
contiene una clave principal, hay que asegurarse que es única, y con valores no nulos; si no es
así, no se agregarán los registros. Si se agregan registros a una tabla con un campo Contador, no
se debe incluir el campo Contador en la consulta. Se puede emplear la cláusula IN para agregar
registros a una tabla en otra base de datos.
Se pueden averiguar los registros que se agregarán en la consulta ejecutando primero una
consulta de selección que utilice el mismo criterio de selección y ver el resultado. Una consulta
de adición copia los registros de una o más tablas en otra. Las tablas que contienen los registros
que se van a agregar no se verán afectadas por la consulta de adición.
La condición SELECT puede incluir la cláusula WHERE para filtrar los registros a copiar.
En este caso se seleccionarán los campos 1,2,..., n de la tabla origen y se grabarán en los
campos 1,2,.., n de la Tabla.
Si Tabla y Tabla Origen poseen la misma estructura podemos simplificar la sintaxis de esta
forma:
En este tipo de consulta hay que tener especial atención con los campos contadores o
autonuméricos puesto que al insertar un valor en un campo de este tipo se escribe el valor que
contenga su campo homólogo en la tabla origen, no incrementándose como le corresponde.
Ejemplo:
INSERT INTO Clientes
SELECT ClientesAntiguos.*
FROM ClientesNuevos
Ejemplo:
SELECT Clientes.* INTO Manolos
FROM Clientes
WHERE Nombre = ‘Manolo’
Esta consulta crea una tabla nueva llamada manolos con igual estructura que la tabla
empleado y copia aquellos registros cuyo campo nombre sea exactamente Manolo.
Ejemplo:
INSERT INTO Clientes (Nombre, Direccion, Contacto)
VALUES
(
‘Juan García’, ‘C/Corona, 12’, ‘912456845’
)
Ejemplo:
INSERT INTO Manolos
SELECT Clientes.*
FROM Clientes
WHERE Nombre = ‘Manuel’
2.2.6. DELETE
Elimina los registros de una o más de las tablas listadas en la cláusula FROM que cumplan
la cláusula WHERE.
Esta consulta elimina los registros completos, no es posible eliminar el contenido de algún
campo en concreto.
Su sintaxis es:
DELETE FROM Tabla WHERE criterio
Una vez que se han eliminado los registros utilizando una consulta de borrado, no puede
deshacer la operación. Si desea saber qué registros se eliminarán, primero examine los
resultados de una consulta de selección que utilice el mismo criterio y después ejecute la
consulta de borrado. Una buena práctica consiste en mantener copias de seguridad de los
datos en todo momento. Si elimina los registros por equivocación se podrán recuperar desde
las copias de seguridad.
Ejemplo:
DELETE FROM Clientes
WHERE Nombre = ‘Juan García’
2.2.7. UPDATE
Su sintaxis es:
UPDATE Tabla SET Campo1=Valor1, Campo2=Valor2, CampoN=ValorN
WHERE Criterio
Es especialmente útil cuando se desea cambiar un gran número de registros o cuando éstos
se encuentran en múltiples tablas.
Como sucede en todas las consultas de acción, no se genera ningún resultado. Para saber
qué registros se van a cambiar, hay que examinar primero el resultado de una consulta de
selección que utilice el mismo criterio y después ejecutar la consulta de actualización.
Ejemplo:
UPDATE Habitaciones
SET Precio = Precio * 1.15
Ejemplo:
UPDATE Clientes
SET Contacto = 912345642
WHERE Nombre = Juan García
Se pueden cambiar varios campos a la vez.
Ejemplo:
UPDATE Habitaciones
SET Precio = Precio * 1.15,
DescuentoNiños = 0.40
WHERE TipoHabitación = ‘Familiar’
UNIDAD 3
3.1. Consultas de selección
3.2. Criterios de Selección
3.1. Consultas de selección
Este tipo de consultas se utilizan para conseguir que el motor de datos devuelva la
información que se requiere de las bases de datos.
La sintaxis de una consulta de selección básica es sencilla, como puede verse a continuación:
SELECT Campos
FROM Tabla
Ejemplo:
SELECT Nombre, Contacto
FROM Clientes
Esta consulta devuelve un conjunto de resultados con todos los registros con el campo
Nombre y Contacto de la tabla clientes.
Ejemplo:
SELECT Nombre, Contacto
FROM Clientes
WHERE Contacto = 915487548
En esta ocasión la sentencia devuelve únicamente aquellos registros, con el campo Nombre
y Contacto de la tabla clientes, que cumplan la condición de que el campo Contacto coincida
con 915487548.
Es posible especificar el orden en que se desean recuperar los registros de las tablas
mediante la cláusula:
ORDER BY Lista_de_Campos: Lista de campos representa los
campos a ordenar.
Ejemplo:
SELECT Nombre, Contacto
FROM Clientes
ORDER BY Nombre;
Ejemplo:
SELECT Nombre, Dirección, Contacto
FROM Clientes
ORDER BY Dirección, Nombre;
También es posible especificar el orden de los registros:
• ascendente mediante la claúsula ASC (se toma este valor por defecto)
• descendente mediante la claúsula DESC
Ejemplo:
SELECT Nombre, Dirección, Contacto
FROM Clientes
ORDER BY Dirección DESC, Nombre ASC;
Los predicados que se quieran incluir en una consulta deben colocarse entre la cláusula y el
primer nombre del campo que se quiere recuperar.
• ALL: Devuelve todos los campos de la tabla. Si no se incluye ninguno de los predicados
se asume ALL por defecto.
Ejemplo:
SELECT ALL FROM Clientes;
SELECT * FROM Clientes;
Ejemplo:
SELECT TOP 10 Nombre
FROM Clientes
ORDER BY Direccion DESC;
La palabra reservada PERCENT se puede usar para devolver un cierto porcentaje de registros
que caen al principio o al final de un rango especificado por la cláusula ORDER BY.
El valor que va a continuación de TOP debe ser un Integer sin signo.
Ejemplo:
SELECT TOP 10 PERCENT Nombre
FROM Clientes
ORDER BY Dirección DESC;
• DISTINCT: Con este predicado se omiten los registros cuyos campos seleccionados
coincidan totalmente (duplicados), es decir, que para que los valores de cada campo listado
en la instrucción SELECT se incluyan en la consulta, estos deben ser únicos.
Ejemplo:
SELECT DISTINCT Nombre
FROM Clientes;
3.1.4. Alias
Ejemplo:
SELECT DISTINCTROW Direccion AS calle
FROM Clientes;
Existen muchas posibilidades de filtrar los registros que se devuelven tras realizar una
consulta de selección, con el fin de recuperar solamente aquellos que cumplan una condiciones
preestablecidas.
Ejemplo:
#15-03-2009# ó #15-3-2009#.
SQL soporta una serie de operadores lógicos: AND, OR, XOR, Eqv, Imp, Is y Not.
AND:
Verdad AND Falso -> Falso
Verdad AND Verdad -> Verdad
Falso AND Verdad -> Falso
Falso AND Falso -> Falso
OR:
Verdad OR Falso -> Verdad
Verdad OR Verdad -> Verdad
Falso OR Verdad -> Verdad
Falso OR Falso -> Falso
XOR:
Verdad XOR Verdad -> Falso
Verdad XOR Falso -> Verdad
Falso XOR Verdad-> Verdad
Falso XOR Falso -> Falso
EQV:
Verdad Eqv Verdad -> Verdad
Verdad Eqv Falso -> Falso
Falso Eqv Verdad -> Falso
Falso Eqv Falso->Verdad
IMP:
Verdad Imp Verdad -> Verdad
Verdad Imp Falso-> Falso
Verdad Imp Null -> Null
Falso Imp Verdad -> Verdad
Falso Imp Falso -> Verdad
Falso Imp Null-> Verdad
Null Imp Verdad -> Verdad
Null Imp Falso -> Null
Null Imp Null -> Null
Ejemplo:
SELECT *
FROM Habitaciones
WHERE Precio > 25 AND Precio < 50;
La forma de indicar que deseamos recuperar los registros según el intervalo de valores de
un campo es utilizar el operador Between:
campo [Not] Between valor1 And valor2
Una consulta de este tipo devolvería los registros que contengan en “campo” un valor entre
valor1 y valor2 (ambos incluidos). Si se antepone la condición Not devolverá aquellos valores
no incluidos en el intervalo.
Ejemplo:
SELECT *
FROM Habitaciones
WHERE Numero Between 201 And 350;
3.2.3. Like
Como modelo puede especificar un valor completo, o bien se pueden utilizar caracteres
comodín para encontrar un rango de valores.
En la siguiente tabla se puede ver detalladamente el uso de los comodines en los modelos
de comparación:
Ejemplo:
Like ‘P[A-Z]?’
Devuelve los datos que comienzan con la letra P seguido de una letra entre A y Z y finalizando
por un carácter cualquiera.
Ejemplo:
Like ‘[E-M]#’
Devuelve los campos cuyo contenido empiece con una letra de la E a la M seguidas de un
dígito.
Figura 14: Sentencia con el comando Like
3.3.4. In
Este operador devuelve aquellos registros cuyo campo indicado este incluido en una lista.
expresión [Not] In(valor1, valor2, . . .)
Ejemplo:
SELECT *
FROM Clientes
WHERE Nombre IN (‘Juan’, ‘Daniel’, ‘Sandra’);
Se utiliza para determinar qué registros de las tablas enumeradas en la cláusula FROM
aparecerán en los resultados de la instrucción SELECT. Tras escribir esta cláusula se deben
especificar las condiciones que se desean como criterios de selección. Si no se emplea esta
cláusula, la consulta devolverá todas las filas de la tabla.
Es una cláusula opcional, pero cuando aparece debe ir a continuación de FROM para
generar un resultado válido.
SELECT Numero
FROM Habitaciones
WHERE Precio > 50;
SELECT *
FROM Reservas
WHERE Fecha_Reserva = #5-10-2009#;
• GROUP BY (opcional).
Esta cláusula consigue combinar aquellos registros con valores idénticos, en la lista de
campos especificados, en un único registro. Para cada registro se crea un valor sumario
si se incluye una función SQL agregada, como por ejemplo Sum o Count, en la instrucción
SELECT de la siguiente forma.
Mientras que los valores de resumen se omiten si no existe una función SQL agregada en
la instrucción SELECT, los valores Null en los campos GROUP BY se agrupan y no se omiten,
aunque no se evalúan.
Un campo de la lista de campos GROUP BY puede referirse a cualquier campo de las tablas
que aparecen en la cláusula FROM, incluso si el campo no esta incluido en la instrucción SELECT,
siempre y cuando la instrucción SELECT incluya al menos una función SQL agregada.
Todos los campos de la lista de campos de SELECT deben o bien incluirse en la cláusula
GROUP BY o como argumentos de una función SQL agregada.
Se utiliza la cláusula WHERE para excluir aquellas filas que no desea agrupar, y la cláusula
HAVING para filtrar los registros una vez agrupados.
Una vez que GROUP BY ha combinado los registros, HAVING muestra cualquier registro
agrupado por la cláusula GROUP BY que satisfaga las condiciones de la cláusula HAVING.
• Count
Se utiliza para calcular el número de registros devueltos por una consulta. Puede contar
cualquier tipo de datos, incluso texto, ya que cuenta el número de registros sin tener en
cuenta qué valores se almacenan en ellos.
SELECT Count(*) AS Total
FROM Clientes;
• Max, Min
Devuelven el mínimo o el máximo de un conjunto de valores contenidos en un campo
especifico de una consulta.
StDevP evalúa una población, y StDev evalúa una muestra de la población. Si la consulta
contiene menos de dos registros (o ningún registro para StDevP), estas funciones devuelven
un valor Null.
• Sum
Calcula la suma del conjunto de valores contenido en un campo especifico de una consulta.
• Var, VarP
Se utiliza para calcular una estimación de la varianza de una población (sobre el total de los
registros) o una muestra de la población (muestra aleatoria de registros) sobre los valores
de un campo.
4.1.1. Internas
Para realizar vinculaciones entre tablas se utiliza la cláusula INNER, que combina registros
de dos tablas (siempre que haya concordancia de valores en un campo común), con la siguiente
sintaxis:
SELECT campos
FROM tabla1 INNER JOIN tabla2 ON tabla1.campo1 comp tabla2.campo2
tabla1, tabla2
Nombres de las tablas desde las que se combinan los registros.
campo1, campo2
Nombres de los campos que se combinan. Si no son numéricos, los campos deben ser del
mismo tipo de datos y contener el mismo tipo de datos, pero no tienen que tener el mismo
nombre.
Comp.
Cualquier operador de comparación relacional: =, <,<>, <=, =>, ó >.
Una operación INNER JOIN se podrá utilizar en cualquier cláusula FROM, creando una
combinación por equivalencia que se conoce como unión interna.
Este tipo de combinaciones equivalentes son las más comunes; combinan los registros de
dos tablas siempre que haya concordancia de valores en un campo común a ambas tablas.
Cláusulas LEFT y RIGHT. LEFT toma todos los registros de la tabla de la izquierda aunque
no tengan ningún registro en la tabla de la izquierda. RIGHT realiza la misma operación pero al
contrario, toma todos los registros de la tabla de la derecha aunque no tenga ningún registro
en la tabla de la izquierda. Es decir, para los casos en los que se quiera hacer la unión de tabla1
y tabla2 pero haya correspondencias que no existen en tabla2, se emplea LEFT JOIN. Si por el
contrario, donde no existen todas las correspondencias es en tabla1, se utilizará RIGHT JOIN.
Para seleccionar todos los departamentos siendo que alguno de ellos no tiene ningún
empleado asignado se emplea LEFT JOIN, pero para seleccionar todos los empleados aún
cuando alguno no está asignado a ningún departamento, se usa ese caso RIGHT JOIN.
Para unir más de dos tablas se pueden enlazar varias cláusulas ON en una instrucción JOIN,
de la siguiente manera:
SELECT campos
FROM tabla1 INNER JOIN tabla2
ON tabla1.campo1 comp tabla2.campo2
INNER JOIN tabla3 ON tabla2.campo2 comp tabla3.campo3
Pueden emplearse operadores lógicos:
SELECT campos
FROM tabla1 INNER JOIN tabla2
ON (tabla1.campo1 comp tabla2.campo1 AND ON tabla1.campo2
comp tabla2.campo2)
OR ON (tabla1.campo3 comp tabla2.campo3)
Otra manera de instrucciones JOIN utiliza la siguiente sintaxis:
SELECT campos
FROM tabla1 INNER JOIN
( tabla2 INNER JOIN
[ ( ] tabla3 [INNER JOIN [( ]tablaN [INNER JOIN ...)]
ON tabla3.campo3 comp [Link])
]
ON tabla2.campo2 comp tabla3.campo3
)
ON tabla1.campo1 comp tabla2.campo2
Un LEFT JOIN o un RIGHT JOIN puede anidarse dentro de un INNER JOIN, pero un INNER
JOIN no puede anidarse dentro de un LEFT JOIN o un RIGHT JOIN.
La sintaxis puede variar ligeramente de un sistema gestor de bases de datos a otro. En SQL-
SERVER se debería añadir la palabra reservada OUTER: LEFT OUTER JOIN y RIGHT OUTER JOIN,
aunque en la práctica funciona correctamente de una u otra forma.
Existe una sintaxis en formato ANSI para los INNER JOIN que funciona en todos los sistemas.
SELECT tabla1.*, tabla2.*
FROM tabla1 INNER JOIN tabla2 ON tabla1.campo1 = tabla2. campo2
Las condiciones que vinculan a las tablas se especifican en la cláusula WHERE y en caso de
que haya más de una condición, se vinculan mediante el operador lógico AND.
Figura 19: Left y Right Join
Auto-combinación: Se utiliza para unir una tabla consigo misma, comparando valores de
dos columnas con el mismo tipo de datos.
Ejemplo:
La tabla Empleados contiene los datos de cada empleado, su puesto, su supervisor...
Este ejemplo mostraría el número, nombre y puesto de cada empleado, junto con el
número, nombre y puesto del supervisor de cada uno de ellos:
4.1.2. Externas
Para crear una consulta de unión se utiliza la operación UNION, combinando los resultados
de dos o más consultas o tablas independientes.
En una operación UNION todas las consultas deben pedir el mismo número de campos,
aunque los campos no tienen porqué tener el mismo tamaño o el mismo tipo de datos.
Ejemplo:
TABLE Cuentas
UNION ALL
SELECT * FROM Reservas
WHERE PrecioTotal > 300
4.2. Subconsultas
Las subconsultas son instrucciones SELECT anidadas dentro de una instrucción SELECT,
SELECT...INTO, INSERT...INTO, DELETE, o UPDATE, o incluso dentro de otra subconsulta.
Una subconsulta puede utilizarse en lugar de una expresión en la lista de campos de una
instrucción SELECT o en una cláusula WHERE o HAVING (una instrucción SELECT proporciona
un conjunto de uno o más valores especificados para evaluar en la expresión de la cláusula
WHERE o HAVING).
Es posible utilizar los predicados ANY o SOME para recuperar registros de la consulta principal
que satisfagan la comparación con cualquier otro registro recuperado en la subconsulta.
Ejemplo:
SELECT *
FROM Habitaciones
WHERE Precio ANY ( SELECT Precio
FROM Reservas
WHERE Descuento = 0 .25
)
Esta consulta devuelve todas las habitaciones cuyo precio es mayor que el de cualquier
habitación reservada con un descuento igual o mayor al 25 por ciento.
El predicado ALL se utiliza para recuperar aquellos registros de la consulta principal que
satisfacen la comparación con todos los registros recuperados en la subconsulta.
Ejemplo:
SELECT *
FROM Habitaciones
WHERE Precio ALL ( SELECT Precio
FROM Reservas
WHERE Descuento = 0 .25
)
Si se cambia ANY por ALL en el ejemplo anterior, la consulta devolverá únicamente aquellas
habitaciones cuyo precio sea mayor que el de todas las habitaciones reservadas con un
descuento igual o mayor al 25 por ciento. Esto es mucho más restrictivo.
Ejemplo:
SELECT *
FROM Habitaciones
WHERE Precio IN ( SELECT Precio
FROM Reservas
WHERE Descuento = 0 .25
)
Esta consulta devuelve todas las habitaciones reservadas con un descuento igual o mayor
al 25 por ciento.
Ejemplo:
Deseamos recuperar todos aquellos clientes que hayan realizado al menos una reserva:
SELECT [Link], [Link]éfono
FROM Clientes
WHERE EXISTS ( SELECT *
FROM Reservas
WHERE [Link] = [Link]
)
Se puede utilizar también alias del nombre de la tabla en una subconsulta para referirse a
tablas listadas en la cláusula FROM fuera de la subconsulta.
Ejemplo:
SELECT *
FROM Empleados AS T1
WHERE Salario = (SELECT Avg(Salario)
FROM Empleados
WHERE [Link] = [Link]
)
ORDER BY Titulacion
Devuelve los datos de los empleados cuyo salario es igual o mayor que el salario medio de
todos los empleados con la misma titulación.
Ejemplo:
SELECT *
FROM Empleados
WHERE Puesto LIKE ‘*Comercial’
AND Salario ALL ( SELECT Salario FROM Empleados
WHERE Puesto LIKE ‘*Jefe*’ OR Puesto LIKE ‘*Director*’
)
Devuelve una lista con el nombre, cargo y salario de todos los comerciales cuyo salario es
mayor que el de todos los jefes y directores.
Las consultas con parámetros son aquellas cuyas condiciones de búsqueda se definen
mediante parámetros, de la siguiente forma.
Si se ejecutan directamente desde la base de datos donde han sido definidas aparecerá un
mensaje solicitando el valor de cada uno de los parámetros.
Si deseamos ejecutarlas desde una aplicación hay que asignar primero el valor de los
parámetros y después ejecutarlas.
Se pueden utilizar nombres pero no tipos de datos en una cláusula WHERE o HAVING.
Ejemplo:
PARAMETERS PrecioMinimo Currency, FechaInicio DateTime;
SELECT IdReserva
FROM Reservas
WHERE Precio = PrecioMinimo AND FechaPedido = FechaInicio
4.4. Referencias Cruzadas
Una consulta de referencias cruzadas es aquella que nos permite visualizar los datos en filas
y en columnas, en forma de tabla.
función_agregada: Es una función SQL agregada que opera sobre los datos seleccionados.
Instrucción_select: Es una instrucción SELECT.
Campo_pivot: Es el campo o expresión que desea utilizar para crear las cabeceras de la
columna en el resultado de la consulta.
valor1, valor2: Son valores fijos utilizados para crear las cabeceras de la columna.
Ejemplo:
Partiendo de una tabla de productos y otra tabla de pedidos, podemos visualizar en total
de productos pedidos por año para un artículo determinado, tal y como se muestra en la tabla
anterior.
Para resumir datos utilizando una consulta de referencia cruzada, se seleccionan los valores
de los campos o expresiones especificadas como cabeceras de columnas de tal forma que
pueden verse los datos en un formato más compacto que con una consulta de selección.
Aquellos valores que son devueltos en campo pivot se utilizan como encabezados de
columna en el resultado de la consulta.
Es posible restringir el campo pivot para crear encabezados a partir de los valores fijos
(valor1, valor2) listados en la cláusula opcional IN, o también puede incluir valores fijos, para
los que no existen datos, para crear columnas adicionales.
Ejemplo:
TRANSFORM Sum(Total) AS Reservas
SELECT Numero, TipoHabitacion FROM Habitaciones
WHERE FechaReserva Between #01-01-2009# And #12-31-2009#
GROUP BY Numero
ORDER BY Numero
PIVOT DatePart(“m”, FechaReserva)
Muestra las reservas por mes para un año específico. Los meses aparecen de izquierda a
derecha como columnas y los nombres de los productos aparecen de arriba hacia abajo como
filas.
Para acceder a bases de datos externas se utiliza la cláusula IN. Se puede acceder a base de
datos dBase, Paradox o Btrieve.
Esta cláusula sólo permite la conexión de una base de datos externa a la vez. Una base de
datos externa es una base de datos que no sea la activa.
Para especificar una base de datos que no pertenece a Access Basic, se agrega un punto y
coma (;) al nombre y se encierra entre comillas simples.
También puede utilizar la palabra reservada DATABASE para especificar la base de datos
externa.
Ejemplo:
FROM Tabla IN ‘[dBASE IV; DATABASE=C:\DBASE\DATOS\REGISTROS;]’;
Para recuperar datos de una tabla de Paradox versión 3.x, hay que sustituir ‘Paradox 4.x;’
por ‘Paradox 3.x;’.
Existe otra clasificación que divide las funciones en dos grupos según operen sobre un dato
individual o un grupo de datos.
1. Funciones que operan sobre un dato individual.
Son conocidas como funciones escalares y llevan a cabo algún tipo de operación sobre
un dato individual, por ejemplo una secuencia de caracteres, un número o una fecha.
substring es una función escalar.
2. Funciones que actúan sobre un conjunto de datos
Son conocidas como funciones de agregado. Suelen actuar normalmente sobre una
columna de una serie de filas. SUM, por ejemplo, va sumando todos los valores de una
cierta columna en las distintas filas resultantes de una consulta.
Finalmente, podemos clasificar las funciones según el tipo de información sobre la que
actúan, teniendo:
1. Funciones de cadenas de caracteres como SUBSTRING.
2. Funciones numéricas como ABS
3. Funciones de fecha tal como EXTRACT.
Además tenemos otra categoría separada, conocida normalmente como funciones built-in
o integradas, constituida por funciones que nos devuelven información facilitada por el propio
RDBMS: la fecha y hora actual, el nombre del usuario, etc.
Se limitan a devolver un valor sin precisar ninguna información sobre la que operar.
NOMBRE DESCRIPCION
CURRENT_DATE Devuelve la fecha actual
CURRENT_TIME Devuelve la hora actual
CURRENT_USER y USER Identifica al usuario que está operando sobre la base de datos.
Hay que tener en cuenta que, a pesar de que estas funciones forman parte del estándar
SQL, no todos los RDBMS las contemplan incluso en algunos casos les dan otros nombres. Tam
bién hay que considerar si el usuario usa una cuenta para iniciar sesión en el sistema operativo
y es éste el que se encarga de personificarlo ante el RDBMS o, por el contrario, el usuario tiene
una cuenta específica para acceder a la base de datos. La inclusión de los datos devueltos por
estas funciones en una consulta se efectúa como si se tratase de columnas, aunque en realidad
no están almacenados en tabla alguna.
Por ejemplo el RDBMS de Microsoft no cuenta con las dos funciones CURRENT_DATE y
CURRENT_TIME, pero sí las demás citadas en la anterior tabla. Vamos a ver un ejemplo, en el
que mostramos todas las funciones que se pueden usar en el RDMS de Microsoft
Con este nombre se conocen las funciones que permiten operar sobre secuencias o cadenas
de caracteres, el estándar SQL cuenta con otra serie de funciones de cadena entre las cuales
están las siguientes:
Ejemplo:
str(numero,longitud,cantidaddecimales): convierte números a caracteres; el primer
parámetro indica el valor numérico a convertir, el segundo la longitud del resultado (debe ser
mayor o igual a la parte entera del número más el signo si lo tuviese) y el tercero, la cantidad
de decimales. El segundo y tercer argumento son opcionales y deben ser positivos.
Ejemplo:
Ejemplo:
Los argumentos numéricos deben ser positivos y menor o igual a la longitud de la primera
cadena, caso contrario, retorna “null”.
Si el tercer argumento es mayor que la primera cadena, se elimina hasta el primer carácter.
len(cadena): retorna la longitud de la cadena enviada como argumento. “len” viene de
length.
Ejemplo:
char(x): retorna un caracter en código ASCII del entero enviado como argumento.
Ejemplo:
Ejemplo:
Ejemplo:
replace(cadena,cadenareemplazo,cadenareemplazar): retorna la cadena con todas las
ocurrencias de la subcadena reemplazo por la subcadena a reemplazar. Ejemplo:
Ejemplo:
space(cantidad): retorna una cadena de espacios de longitud indicada por “cantidad”, que
debe ser un valor positivo.
Ejemplo:
Todas estas funciones se pueden utilizar enviando como argumento el nombre de un campo
de tipo carácter.
En el siguiente ejemplo mostramos el primer carácter del campo signatura de la tabla libros
de una base de datos:
5.4. Funciones fecha y hora
Además de las funciones integradas que hemos visto SQL ofrece algunas funciones para
trabajar con fechas y horas. Vamos a estudiar algunas de ellas:
Ejemplo:
Los valores para “partedefecha” pueden ser: year, quarter, month, day, week, hour, minute,
second y millisecond.
Ejemplos:
datename(partedefecha,fecha): retorna el nombre de una parte específica de una fecha.
Los valores para “partedefecha” pueden ser los mismos que para datepart
Ejemplos:
dateadd(partedelafecha,numero,fecha): agrega un intervalo a la fecha especificada, es
decir, retorna una fecha adicionando a la fecha enviada como tercer argumento, el intervalo de
tiempo indicado por el primer parámetro, tantas veces como lo indica el segundo parámetro.
Los valores para “partedefecha” pueden ser los mismos que para datepart
Ejemplo:
Ejemplo:
month(fecha): retorna el mes de la fecha especificada.
Ejemplo:
Ejemplo:
Ya hemos visto algunos operadores, conocidos como operadores aritméticos, que nos
permiten llevar a cabo las operaciones más básicas sobre los números: adición, sustracción,
producto y división. Estos operadores se complementan con una serie de funciones que
permiten operaciones más complejas.
El conjunto de funciones numéricas del lenguaje SQL estándar, no es muy extenso, además
cada RDBMS aporta funciones exclusivas, diferentes en cada producto, que puede usar para
obtener los resultados que con las funciones estándar no se puedan realizar.
Ejemplo:
Ejemplo:
floor(x): redondea hacia abajo el argumento “x”.
Ejemplo:
Ejemplo:
Ejemplos:
sign(x): si el argumento es un valor positivo devuelve 1;-1 si es negativo y si es 0, 0.
Ejemplo:
Ejemplo:
srqt(x): devuelve la raíz cuadrada del valor enviado como argumento.
Ejemplo:
UNIDAD 6
6.1. Crear y eliminar vistas
6.2. Filtrado de filas
6.3. Vistas con columnas derivadas
6.4. Actualización de datos a través de una vista
6.1. Crear y eliminar vistas
Una base de datos puede contener, aparte de las tablas donde se aloja la información
propiamente dicha, otros objetos que facilitan el trabajo con ella o mejoran su rendimiento.
Entre esos objetos se encuentran las vistas.
Las vistas son un recurso muy útil para facilitar el acceso a la información a aquellos usuarios
que no tienen un gran conocimiento del lenguaje SQL, así como un elemento de seguridad al
ocultar a dichos usuarios la estructura real de las tablas y ofrecerles únicamente aquellos datos
que precisan.
Una vista, es una consulta SQL almacenada en la propia base de datos. También conocidas
como tablas virtuales, las vistas tienen el objetivo de ofrecer a los usuarios de una base de
datos vistas diferentes de la misma información. Es decir, una vista no genera nuevos datos,
salvo datos derivados mediante el uso de funciones SQL, sino que a través de filtros, uniones,
agrupaciones y ordenaciones permiten obtener una visión diferente de esos mismos datos.
Una vista almacena una consulta como un objeto para utilizarse posteriormente. Las tablas
consultadas en una vista se llaman tablas base. En general, se puede dar un nombre a cualquier
consulta y almacenarla como una vista.
Podemos crear vistas con: un subconjunto de registros y campos de una tabla; una unión de varias
tablas; una combinación de varias tablas; un resumen estadístico de una tabla; un subconjunto de otra
vista, combinación de vistas y tablas.
Vamos a realizar un ejemplo que crea una vista llamada vista_socios de las tablas socios y
prestamos de la base de datos biblioteca.
Cuando se ejecuta la vista nos dice que los comandos se han completado correctamente,
ahora tenemos que mostrar los datos de la vista.
También podemos realizar consultas a una vista como si se tratara de una tabla:
Los nombres para vistas deben seguir las mismas reglas que cualquier identificador. Para
distinguir una tabla de una vista podemos fijar una convención para darle nombres, por
ejemplo, colocar el sufijo “vista” y luego el nombre de las tablas consultadas en ellas.
Los campos y expresiones de la consulta que define una vista deben tener un nombre. Se
debe colocar nombre de campo cuando es un campo calculado o si hay 2 campos con el mismo
nombre. En el ejemplo, al concatenar los campos “apellido” y “nombre” colocamos un alias; si
no lo hubiésemos hecho aparecería un mensaje de error porque dicha expresión debe tener
un encabezado, SQL Server no lo coloca por defecto.
Los nombres de los campos y expresiones de la consulta que define una vista deben ser
únicos (no puede haber dos campos o encabezados con igual nombre).
La eliminación de una vista, como la de cualquier otro objeto existente en la base de datos,
se lleva a cabo con la sentencia DROP, e
En el ejemplo anterior hemos visto que podemos filtrar las columnas de una vista pero
más útil que el filtrado de columnas, en la medida de que no es posible aplicar privilegios que
limiten las filas a las que puede accederse y la composición de la consulta resulta algo más
compleja al incluir la cláusula WHERE con su respectivo condicional de búsqueda, resulta la
creación de vistas que se encarguen del filtrado de filas.
Por ejemplo en una biblioteca si un operador necesita conocer los libros que hay disponibles,
que pueden prestarse, para atender la consulta de un socio, trabajando directamente sobre la
tabla libros se vería forzado a ir examinando la columna disponible fila a fila, para saber si está
o no disponible. También podría, suponiendo que contase con los conocimientos necesarios,
efectuar una consulta que incluyese la cláusula WHERE con la condición disponible=’ S’.
Pero sin duda le sería mucho más fácil, sin duda, utilizar una vista. Vamos a verlo con un
ejemplo:
Creamos la vista que nos permita obtener todos los libros disponibles.
Después ejecutamos la consulta para ver los libros disponibles, de este modo el operador
no tiene que recorrer todos los datos de la tabla libros
Aunque la vista esté definida como una consulta con un filtro de filas, para el usuario final
aparece como si fuese una tabla y, por tanto, como tal puede ejecutar cualquier consulta sobre
ella siempre que sus privilegios se lo permitan.
Por ejemplo un operador puede buscar en los libros disponibles aquel que tenga el código
4.
Las vistas de los ejemplos anteriores ofrecen siempre como resultado columnas tomadas
de tablas existentes en la base de datos, ya sean de una única tabla o de varias de ellas en
caso de que se efectúe algún tipo de unión o combinación. Las vistas pueden también generar
información propia a partir de columnas calculadas o derivadas, usando para ello los operadores
aritméticos y funciones que hemos ido conociendo en las unidades anteriores.
Cuando una vista va a usar en la consulta expresiones que generan columnas adicionales,
derivadas de las ya existentes, es necesario que en la cabecera, tras el nombre que va a asignase
a la vista, facilitemos entre paréntesis los nombres de las columnas.
Esto nos permite dar cualquier nombre a las columnas generadas por la vista, nombre que
no tiene necesariamente que coincidir con el que tienen originalmente las columnas en la
tabla. Otra opción, para asignar nombre a las columnas derivadas, es usar la cláusula AS tras
ese tipo de columnas y el nombre que ponemos a la columna:
Vamos a realizar un ejemplo que define una vista que facilita el nombre de cada autor y el
número de libros suyos que tenemos registrados de una tabla libros, empleando para ello la
función COUNT y la cláusula GROUP BY.
Ejecutamos una consulta sobre la vista para ver los datos:
Podemos observar que la columna numtitulos aparece como una columna más y no hay
referencia alguna a que sea resultado de un cálculo.
Una columna derivada no tiene necesariamente que agrupar los datos, como en este
ejemplo, pudiendo limitarse a añadir alguna columna.
6.4. Actualización de datos a través de una vista
El estándar SQL indica que una vista debe ser actualizable siempre que la operación a
ejecutar tenga sentido, si bien cada RDBMS añade sus propias restricciones al respecto.
Actualizable significa, en este contexto, que permite la inserción de filas, la modificación del
contenido de las columnas o bien la eliminación de filas. Obviamente esas operaciones no
afectan a la vista en sí, sino a las tablas de las que ésta toma los datos.
Las operaciones de actualización sobre una vista no pueden en ningún caso infringir las
restricciones definidas en las tablas de origen.
Vamos a crear una vista DatosSocios que nos permita introducir datos en un tabla socios.
Evitar que los usuarios puedan modificar ciertas columnas resulta muy fácil a través de una
vista. El operador que tiene acceso a DatosSocios, y el privilegio para efectuar modificaciones,
no podrá, por ejemplo, alterar la dirección, el código postal o fecha de alta, sencillamente
porque esas columnas no forman parte de la vista.
Lenguaje SQL 111