SQL Cc42a
SQL Cc42a
Auxiliar: SQL-92
Parte 1. SQL
El efecto producido por los conceptos de modelo relacional los lenguajes relacionales
(álgebra y cálculo) introducidos por E. Codd provocó tal impacto que significó que
comunidades comerciales y de investigación desarrollaran implementaciones de los
lenguajes relacionales. Tal vez el mayor esfuerzo se lo llevó SQL (Structured Query
Languaje), que junto con permitir consultas en la base de datos, contiene primitivas de
definición de tablas, actualización de la base de datos, definición de vistas otorgamientos de
privilegios, etc. A continuación se mostrarán aspectos del estándar ANSI de 1992, conocido
como SQL-92.
El dueño del esquema, o propietario del esquema puede otorgar privilegios de acceso y
actualización de la base de datos definida en el esquema a otros usuarios del sistema.
Numéricos exactos:
Integer enteros
Small Integer enteros pequeños
p: precisión: total de números o dígitos en el número
Numeric(p, e)
e: escala: cuantos números están a la derecha del punto decimal
p: precisión
Decimal(p,e)
e: escala
Numéricos aproximados:
Real
Double precision doble precisión
float flotante
Cadenas de caracteres:
Character(n) carácter
Character varying(n) carácter variable
Los campos de character siempre almacenan n caracteres, aún cuando tengan que rellenar
con blancos a la derecha para completar la longitud n. Los campos character varying sólo
almacenan el número real de caracteres que se introdujeron (hasta un máximo de n).
Cadenas de bits:
Bit(n)
Bit varying(n)
Estos campos se usan para banderas u otras máscaras de bits para el control.
Fechas y horas:
Date fecha
Time hora
Timestamp sello de tiempo
Time con tiempo zonal
Timestamp con tiempo zonal
El tipo Date se da en el orden año, mes, día con cuatro dígitos para el año. El Time se da en
horas (0 a 23), minutos, segundos y décimas de segundos. El Timestamp es la fecha más la
hora.
Intervalos:
Year-month año-mes
Day-time día-hora
Un intervalo es la diferencia entre dos fechas (año-mes) o entre dos horas (día-hora).
Definición de dominios:
Los tipos de datos con restricciones (constrains) y valores por defecto (default values) se
pueden combinar en la definición de dominios. Una definición de dominio es un tipo de
datos especializado que puede estar definido dentro de un esquema y utilizado en la
definición de columnas. Por ejemplo:
Esta definición dice que un dominio llamado IDENTIFICADOR tiene las siguientes
propiedades:
Definición de Tablas
Las definiciones de columnas de la tabla (que son los atributos del modelo relacional) están
compuestas por:
EDI_DIRECCION CHARACTER(12),
Las palabras ON DELETE indican que hacer en caso de borrar al referido. La cláusula ON
DELETE SET NULL le dice al sistema que si se borra la tupla a la que apunta la clave
externa entonces el valor de ésta se debe poner a cero, esto sirve para mantener la
integridad de referencias (si borro al referido, y quedan referencias apuntando a una tupla
borrada tenemos una falla en la integridad de referencia). La cláusula ON DELETE
CASCADE significa que si se borra la tupla referida en la relación, se realiza un borrado en
"cascada" de todas las tuplas que hacían referencia a ésta.
CASCADE
SET NULL
SET DEFAULT
Por último se debe decir que a diferencia de las relaciones en el modelo relaciona, no se
requiere que cada tabla SQL tenga una clave primaria. En otras palabras, si no se indica
ninguna clave, entonces dos filas de la tabla pueden tener valores idénticos. Lo malo es que
una tabla que no tenga clave primaria no puede ser referida mediante clave externa desde
otra tabla.
Adicionalmente SQL-92 define instrucciones para cambiar las definiciones de las tablas
(ALTER TABLE) o para borrar las tablas (DROP TABLE). Para borrar un esquema
completo se usa DROP SCHEMA, pero como borrar un esquema es una cosa seria, se tiene
que especificar que opción de borrado se usa:
Manipulación de datos
Consultas simples
Consultas simples: Una consulta que involucra una sola tabla de la base de datos. Ejemplo:
¿Quiénes son los fontanero?
SELECT TRA_NOMBRE
FROM TRABAJADOR
WHERE TRA_OFICIO = 'Fontanero'
Acá se muestran las tres cláusulas más usadas en SQL: la cláusula SELECT, la cláusula
FROM y la cláusula WHERE. Una buena regla es escribir cada cláusula en una línea aparte
y con sangrías, aunque se puede escribir todo en la misma línea.
Cláusula FROM: Lista las tablas que son referidas por la consulta.
Clausula WHERE: Nos da la condición para seleccionar las filas de las tablas indicadas.
Otro ejemplo: ¿Cuál es la tarifa semanal de cada electricista?, además entregue la salida
ordenada alfabéticamente.
Consulta: ¿Quiénes tienen una tarifa por hora entre $7000 y $9000, entregue toda la
información de la tabla?
SELECT *
FROM TRABAJADOR
WHERE TRA_TARIFA_HR >= 7000 AND TRA_TARIFA_HR <= 9000
Se pueden usar los siguientes operadores de comparación: =, <> (distinto), <, >, <=, >=.
Se pueden usar los siguientes conectores booleanos: AND, OR, NOT.
SELECT *
FROM TRABAJADOR
WHERE TRA_OFICIO IN ('Fontaneros', 'Albañiles', 'Electricistas')
Consulta: Encontrar todos los trabajadores cuyos oficios comiencen con "Elec". Para esto
necesitamos usar caracteres comodines. es decir, símboles especiales que valen por
cualquier cadena de caracteres.
SELECT *
FROM TRABAJADOR
WHERE TRA_OFICIO LIKE 'Elec%'
SQL tiene dos caracteres comodines, el % que vale por cero o cualquier cantidad de
caracteres, y _ que vale por exactamente un caracter cualquiera. El operador LIKE se usa
para comparar variables de caracteres literales cuando se utilizan comodines.
Consulta: Encuentre todas las asignaciones que comiencen en las dos próximas semanas.
SELECT *
FROM ASIGNACION
WHERE ASG_FECHA_INICIO BETWEEN CURRENT_DATE AND CURRENT_DATE + INTERVAL
'14' DAY
Consultas multi-tablas
Consulta: ¿Cuáles son los oficios de los trabajadores asignados al edificio 435?
SELECT TRA_OFICIO
FROM TRABAJADORES, ASIGNACION
WHERE TRA_ID = ASG_ID_TRABAJADOR
AND ASG_ID_EDIFICIO = 435
En este caso, la cláusula FROM calcula el producto cartesiano de las tablas indicadas y
luego con la cláusula WHERE filtramos las filas interesantes (aquellas en que TRA_ID es
igual a ASG_ID_TRABAJADOR) y luego las que nos interesan (las asignaciones al
edificio 435), y por último SELECT toma la columna que nos interesa. Ojo que cuando hay
problemas de que se repite un nombre de columna le ponemos como prefijo el nombre de la
tabla seguida por un punto, ejemplo: TRABAJADORES.TRA_ID, o
ASIGNACION.ASG_ID_EDIFICIO.
Subconsultas
Subconsulta: Una consulta dentro de una consulta.
Consulta: ¿Cuáles son los oficios de los trabajadores asignados al edificio 435?
SELECT TRA_OFICIO
FROM TRABAJADOR
WHERE TRA_ID IN (
SELECT ASG_ID_TRABAJADOR
FROM ASIGNACION
WHERE ASG_ID_EDIFICIO = 435
)
A veces es posible realizar una sola consulta, sin subconsulta, pero más compleja:
SELECT OFICIO
FROM TRABAJADORES, ASIGNACIONES
WHERE ASG_ID_EDIFICIO = 435
AND TRA_ID = ASG_ID_TRABAJADOR
Consulta: ¿Quienes son los trabajadores que no están asignados al edificio 435?
Además esta subconsulta tiene apellido, es una subconsulta correlacionada, es decir, es una
subconsulta cuyos resultados dependen de la fila que se está examinando por una consulta
más externa.
Funciones integradas
Consulta: ¿Cuáles son la tarifa por hora mayor y menor?
Consulta: ¿Cuál es el promedio de días que los trabajadores están asignados al edificio 435?
SELECT AVG(ASG_NUM_DIAS)
FROM ASIGNACION
WHERE ASG_ID_EDIFICIO = 435
SELECT SUM(ASG_NUM_DIAS)
FROM ASIGNACION, TRABAJADOR
WHERE TRA_ID = ASG_ID_TRABAJADOR
AND TRA_OFICIO = 'Fontanero'
AND ASG_ID_EDIFICIO = 312
La palabra clave DISTINCT se usa para que el sistema no cuente el mismo tipo de oficio
mas de una vez.
Como muestran todos estos ejemplos, si una función integrada aparece en una cláusula
SELECT, entonces nada más que funciones integradas pueden aparecer en dicha cláusula
SELECT. La una excepción ocurre en combinación con la cláusula GROUP BY.
GROUP BY y HAVING
Cláusula GROUP BY: Indica cuáles filas deben agruparse sobre un valor común de las
columna(s) especificada(s)
Cláusula HAVING: Una cláusula que impone condiciones a los grupos.
Consulta: Para cada supervisor, ¿Cuál es la tarifa por horas más alta que se le paga a un
trabajador que informe a este supervisor?
Consulta: Para cada supervisor que dirige a más de un trabajador, ¿cuál es la tarifa por
horas más alta que se le paga a un trabajador que informe a dicho supervisor?
Noten que la cláusula WHERE aplica a las filas, en cambio la cláusula HAVING a
grupos !!, aunque pueden trabajar juntos WHERE y HAVING.
Consulta: Para cada supervisor que dirige a más de un trabajador, ¿cuál es la tarifa por
horas más alta que se le paga a un electricista que informe a dicho supervisor?
Inserción:
INSERT INTO ASIGNACION (ASG_ID_TRABAJADOR, ASG_ID_EDIFICIO,
ASG_FECHA_INICIO)
VALUES (1284, 485, '2002-05-13')
Actualización:
UPDATE TRABAJADOR
SET TRA_TARIFA_HR = 1.05 * TRA_TARIFA_HR
WHERE ID_SUPV = 1520
Borrado:
Definición de vistas
Una vista es una porción restringida de la base de datos, y se obtiene de una tabla que
contiene información básica o real. Por ejemplo si quisieramos crear una vista de la tabla
TRABAJADOR pero que no muestre su tarifa por hora:
SELECT CLI_NOMBRE
FROM CLIENTE, EMBARQUE
WHERE CLI_ID = EMB_ID_CLI
AND EMB_DESTINO = 'Sioux'
¿Quiénes son los choferes que han conducido embarques de clientes que tienen renta anual
sobre los $20 millones a ciudades con población por encima del millón?
SELECT CAM_NOMBRE_CHOFER
FROM CLIENTE, EMBARQUE, CAMION, CIUDAD
WHERE CLI_RENTA_ANUAL > 20000000
CIU_POBLACION > 1000000
AND CLI_ID = EMB_ID_CLI
AND CAM_ID = EMB_ID_CAMION
AND CIU_NOMBRE = EMB_DESTINO
Indique el nombre y la renta anual de los clientes que han enviado embarques que pesan
más de 100 libras
Indique los choferes que han transportado embarques a cada una de las ciudades.
Esto es equivalente a determinar cuáles son los choferes tales que NO hay una ciudad a la
cual NO hayan llevado un embarque.
SELECT C1.CAM_NOMBRE_CHOFER
FROM CAMION C1
WHERE NOT EXISTS (
SELECT CIU_NOMBRE
FROM CIUDADES
WHERE NOT EXISTS (
SELECT *
FROM EMBARQUE, CAMION C2
WHERE EMB_DESTINO = CIU_NOMBRE
AND EMB_ID_CAMION = CAM_ID
AND C2.CAM_NOMBRE_CHOFER = C1.CAM_NOMBRE_CHOFER
)
)
De una lista de los clientes que hacen todos sus envíos a una sola ciudad. (Note que la
ciudad no tiene que ser la misma para cada cliente)
SELECT CLI_NOMB
FROM CLIENTE
WHERE 1 IN (
SELECT COUNT(DISTINC EMB_DESTINO)
FROM EMBARQUE
WHERE EMB_ID_CLIENTE = CLI_ID
)
Para cada ciudad que haya recibido al menos diez paquetes, ¿cuál es el peso medio de los
paquetes enviado a dicha ciudad?