CURSO SQL POSTGRESQL.pdf
-
Upload
alejandra-vidal -
Category
Documents
-
view
348 -
download
8
Transcript of CURSO SQL POSTGRESQL.pdf
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 1 de 253
Agosto de 2014
Curso de SQL - PostgreSQL
Ing. Mario Soto Cordones
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 2 de 253
Contenido Introducción ...................................................................................................................................... 13
Lección I - Bases de datos relacionales: “El modelo relacional” ....................................................... 14
¿Qué son las Bases de Datos (BD)? ............................................................................................... 14
El Sistema Gestor de Base de Datos (SGBD) ................................................................................. 14
El modelo Entidad-Relación (E-R) .................................................................................................. 14
Entidades......................................................................................................... 15
Relaciones ....................................................................................................... 16
Base de Datos Relacionales ........................................................................................................... 16
Ventajas .......................................................................................................... 16
Características ................................................................................................. 17
Motores de Bases de Datos Relacionales ..................................................................................... 18
PostgreSQL .................................................................................................................................... 19
Un poco de historia ......................................................................................... 19
Características ................................................................................................. 19
Lección II - Bases de datos relacionales: Consulta de bases de datos relacionales .......................... 21
Utilizando una Base de Datos Relacional ...................................................................................... 21
Consultas en lenguajes de alto nivel ............................................................................................. 21
Consultas y relaciones (tablas) ...................................................................................................... 22
Lenguajes de consultas ................................................................................................................. 22
Utilizando Álgebra Relacional ....................................................................................................... 23
Utilizando SQL ............................................................................................................................... 23
Lección III - Álgebra Relacional: Select, Project, Join ........................................................................ 24
Conceptos básicos de álgebra relacional ...................................................................................... 24
Operaciones relacionales: ............................................................................................................. 25
Selección (Select) .......................................................................................................................... 25
Proyección (Project) ...................................................................................................................... 28
Notación en Álgebra Relacional ....................................................................... 28
Producto cartesiano (Cross-Product) ............................................................................................ 29
Notación en Álgebra Relacional ....................................................................... 30
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 3 de 253
Natural Join ................................................................................................................................... 32
Notación en Álgebra Relacional ....................................................................... 32
Equivalencia con operadores básicos ............................................................... 32
Método ............................................................................................................ 32
ThetaJoin ....................................................................................................................................... 33
Notación en Álgebra Relacional ....................................................................... 34
Equivalencia con operadores básicos ............................................................... 34
Lección IV - Álgebra Relacional: Set operators, renaming, notation ................................................ 37
Operaciones de conjunto .............................................................................................................. 37
Unión............................................................................................................... 37
Notación en álgebra relacional ........................................................................ 38
Diferencia ........................................................................................................ 38
Notación en álgebra relacional ........................................................................ 39
Intersección ..................................................................................................... 40
Notación en algebra relacional ........................................................................ 40
Equivalencia con operadores anteriores .......................................................... 40
Operaciones dependientes e independientes .............................................................................. 41
Álgebra relacional como idioma restrictor.................................................................................... 41
Ejercicios Propuestos .................................................................................................................... 42
Lección V – Introducción al Lenguaje SQL ......................................................................................... 45
Características ............................................................................................................................... 45
Lenguaje de descripción de datos (DDL) ....................................................................................... 45
Ejemplos de DDL: ............................................................................................ 46
Lenguaje de manipulación de datos (DML) ................................................................................... 46
Ejemplos de DML ............................................................................................. 47
Álgebra relacional: ........................................................................................... 48
Comandos SQL: ............................................................................................... 48
Clave Primaria y Foránea ............................................................................................................... 52
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 4 de 253
Lección VI - Tipo de Datos ................................................................................................................. 56
Descripción .................................................................................................................................... 56
Tipo de Dato Serial ........................................................................................................................ 60
Lección VII – Sentencia SELECT Básica .............................................................................................. 61
Desde el Álgebra Relacional .......................................................................................................... 61
SELECT-FROM-WHERE ................................................................................................................... 62
Resultados Repetidos .................................................................................................................... 66
SELECT-BY-ORDER ......................................................................................................................... 67
Lección VIII - Variables de tablas y operadores de conjunto ............................................................ 70
Variables de tablas ........................................................................................................................ 70
Ejemplo 1 ........................................................................................................ 71
Ejemplo 2 ........................................................................................................ 72
Establecimiento de Operadores .................................................................................................... 74
Unión............................................................................................................... 74
Intersección ..................................................................................................... 76
Excepción ........................................................................................................ 76
Lección IX- Subconsultas en la cláusula WHERE................................................................................ 78
SELECT-FROM-WHERE (SELECT) .................................................................................................... 78
Ejemplo 1 ........................................................................................................ 80
Ejemplo 2 ........................................................................................................ 82
IN AND NOT IN .............................................................................................................................. 83
Ejemplo 3 ........................................................................................................ 83
EXISTS AND NOT EXISTS ................................................................................................................ 84
Ejemplo 4 ........................................................................................................ 84
CÁLCULOS MATEMÁTICOS ............................................................................................................ 85
Ejemplo 5 ........................................................................................................ 85
Lección X - Subconsultas en FROM y SELECT .................................................................................... 87
SELECT (SELECT)-FROM-WHERE .................................................................................................... 87
Ejemplo 1 ........................................................................................................ 87
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 5 de 253
Ejemplo 2 ........................................................................................................ 88
Ejemplo 3 ........................................................................................................ 89
Ejemplo 4 ........................................................................................................ 89
SELECT-FROM (SELECT)-WHERE .................................................................................................... 89
Ejemplo 5 ........................................................................................................ 90
RECAPITULACIÓN .......................................................................................................................... 91
Ejemplo extra .................................................................................................. 91
Lección XI - La familia de operadores JOIN ....................................................................................... 93
INNER JOIN .................................................................................................................................... 93
NATURAL JOIN ............................................................................................................................... 95
INNER JOIN USING (attrs) .............................................................................................................. 96
LEFT|RIGHT|FULL OUTER JOIN ..................................................................................................... 96
LEFT OUTER JOIN ........................................................................................................................... 97
RIGHT OUTER JOIN ........................................................................................................................ 97
FULL OUTER JOIN .......................................................................................................................... 98
Lección XII - Funciones de Agregación ............................................................................................ 100
Funciones de Agregación ............................................................................................................ 100
Función AVG() ................................................................................................ 101
Función COUNT() ........................................................................................... 101
SQL COUNT (nombre_columna) ..................................................................... 101
SQL COUNT(*) ................................................................................................ 102
SQL COUNT (DISTINCT nombre_columna) ..................................................... 102
Función MAX() ............................................................................................... 103
Función MIN() ................................................................................................ 103
Función SUM() ................................................................................................ 103
SQL GROUP BY ............................................................................................................................. 104
SQL HAVING ................................................................................................................................ 104
Lección XIII - SQL: Valores NULL ...................................................................................................... 106
CREATE TABLE ............................................................................................................................. 106
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 6 de 253
INSERT y UPDATE ........................................................................................................................ 107
SELECT ......................................................................................................................................... 108
Seleccionar atributos NULL ............................................................................ 108
Comparaciones con NULL .............................................................................. 109
Operaciones con NULL ................................................................................... 111
Operadores lógicos ......................................................................................................................... 111
Lección XIV - SQL: Declaraciones de las Modificaciones de Datos .................................................. 114
INSERT ......................................................................................................................................... 114
Contexto ....................................................................................................... 114
Ejemplo 1 ...................................................................................................... 115
Ejemplo 2 ...................................................................................................... 116
UPDATE ....................................................................................................................................... 116
Ejemplo 3 ...................................................................................................... 117
DELETE ......................................................................................................................................... 118
Ejemplo 4 ...................................................................................................... 118
Ejemplo 5 ...................................................................................................... 119
RECAPITULACIÓN ........................................................................................................................ 119
Ejemplo extra ................................................................................................ 119
Lección XV - Teoría del diseño Relacional: Información General .................................................... 122
Diseñar un esquema de base de datos ....................................................................................... 122
Ejercicio ......................................................................................................... 124
Diseño por descomposición ........................................................................................................ 124
Normalización ............................................................................................................................. 125
Formas normales ........................................................................................... 125
Lección XVI - Teoría del Diseño Relacional: Dependencia Funcional .............................................. 133
Dependencia Funcional ............................................................................................................... 133
Ejemplo 1: ..................................................................................................... 133
Ejemplo 2 ...................................................................................................... 134
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 7 de 253
Ejemplo 3 ...................................................................................................... 135
Dependencias funcionales y llaves .............................................................................................. 135
Reglas para las dependencias funcionales .................................................................................. 136
Ejemplo 4 ...................................................................................................... 137
Clausura y llaves .......................................................................................................................... 137
Ejemplo 5 ...................................................................................................... 137
Especificación funcionalmente dependiente para una relación ................................................. 138
Ejemplo 6 ...................................................................................................... 138
Lección XVII - Teoría del diseño relacional: Forma normal Boyce-Codd ......................................... 139
Conceptos previos ....................................................................................................................... 139
Tipos de claves (llaves) .................................................................................. 139
Forma normal Boyce-Codd.......................................................................................................... 140
Definición ...................................................................................................... 140
Descomposición para lograr la FNBC ............................................................. 141
Lección XVIII - Teoría de Diseño Relacional: Dependencias Multivaluadas (4ta forma normal) .... 145
Dependencias multivaluadas............................................................................................... 145
Introducción .................................................................................................. 145
Atributo de independencia y redundancia ..................................................... 145
Definición formal ........................................................................................... 146
Cuarta Forma Normal ............................................................................................................ 147
Definición ...................................................................................................... 147
Lección XIX - Lenguaje de modelado unificado: UML modelado de datos ..................................... 152
Clases......................................................................................................................................... 152
Ejemplo 1 ...................................................................................................... 153
Asociaciones ............................................................................................................................ 153
Ejemplo 2 ...................................................................................................... 153
Ejemplo 3 ...................................................................................................... 154
Ejemplo 4 ...................................................................................................... 155
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 8 de 253
Clase de asociación ................................................................................................................ 155
Ejemplo 5 ...................................................................................................... 155
Ejemplo 6 ...................................................................................................... 157
Subclases .................................................................................................................................. 157
Ejemplo 7 ...................................................................................................... 158
Composiciones y Agregaciones.......................................................................................... 158
Ejemplo 8 ...................................................................................................... 158
Ejemplo 9 ...................................................................................................... 159
Lección XX - Lenguaje de Modelado Unificado: UML y las bases de datos ..................................... 160
Clases......................................................................................................................................... 161
Asociaciones ............................................................................................................................ 162
Claves para las relaciones de asociación ....................................................... 162
Clase de asociación ................................................................................................................ 164
Subclases .................................................................................................................................. 165
Ejemplo de subclases .................................................................................... 166
Composición y Agregación .................................................................................................. 167
Composición ................................................................................................. 167
Agregación .................................................................................................... 167
Lección XXI - Restricciones y triggers: Introducción ........................................................................ 168
Restricciones ............................................................................................................................ 169
Ejemplo 1 ...................................................................................................... 169
Ejemplo 2 ...................................................................................................... 169
Ejemplo 3 ...................................................................................................... 169
Declarando y forzando restricciones ............................................................. 169
triggers ................................................................................................................................... 170
Ejemplo 4 ...................................................................................................... 170
Ejemplo 5 ...................................................................................................... 170
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 9 de 253
Lección XXII - Restricciones y triggers: Restricciones de múltiples tipos ........................................ 171
Contexto ................................................................................................................................... 171
Restricciones para evitar valores NULL ............................................................................. 172
Ejemplo 1 ...................................................................................................... 172
Ejemplo 2 ...................................................................................................... 172
Restricciones de clave primaria .......................................................................................... 172
Ejemplo 3 ...................................................................................................... 173
Ejemplo 4 ...................................................................................................... 173
Ejemplo 5 ...................................................................................................... 174
Ejemplo 6 ...................................................................................................... 175
Ejemplo 7 ...................................................................................................... 176
Restricciones de atributo y tupla ....................................................................................... 177
Ejemplo 8 ...................................................................................................... 177
Ejemplo 9 ...................................................................................................... 178
Ejemplo 10 .................................................................................................... 179
Ejemplo 11 .................................................................................................... 179
Restricciones generales ........................................................................................................ 180
Ejemplo 12 .................................................................................................... 180
Lección XXIII - Restricciones y triggers: Integridad Referencial .................................................. 181
Ejemplo...................................................................................................................................... 183
Aplicación de la integridad referencial (R.A a R.B) .......................................... 184
Ejemplo...................................................................................................................................... 184
Acciones especiales ....................................................................................... 185
Ejemplo ON DELETE SET NULL ............................................................................................ 189
Ejemplo CASCADE ..................................................................................................................... 190
Lección XXIV - Restricciones y Triggers: Triggers introducción y demostración ........................ 192
Triggers (disparadores) ........................................................................................................ 192
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 10 de 253
Definición ...................................................................................................... 192
Algunas aplicaciones de Triggers .................................................................. 193
Creación de un disparo ................................................................................. 193
Funciones ...................................................................................................... 195
Cuándo no deben usarse los Triggers ........................................................... 200
Lección XXV - Transacciones: Introducción .................................................................................. 201
Integridad de las transacciones .......................................................................................... 202
Nivel de Inconsistencia en Atributos .............................................................. 202
Nivel de Inconsistencia en Tuplas .................................................................. 203
Nivel de Inconsistencia en Tablas .................................................................. 203
Objetivo de la Concurrencia ................................................................................................ 204
Objetivo Principal .......................................................................................... 204
Resistencia a fallos del sistema .......................................................................................... 204
Solución para la concurrencia y fallos .............................................................................. 205
Lección XXVI - Transacciones: Propiedades .................................................................................... 206
Aislamiento (I) ......................................................................................................................... 206
Ejemplo ......................................................................................................... 207
Durabilidad (D) ........................................................................................................................ 209
Atomicidad (A) ......................................................................................................................... 210
Ejemplo ......................................................................................................... 210
Deshacer (Rollback) Transacción ................................................................... 211
Consistencia (C) ...................................................................................................................... 213
Lección XXVII – Vistas: Definición y usos ......................................................................................... 214
Definición ................................................................................................................................. 214
Usos de las vistas ................................................................................................................... 215
Creación de una vista ............................................................................................................ 215
Ejemplo 1 ...................................................................................................... 216
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 11 de 253
Ejemplo 2 ...................................................................................................... 217
Ejemplo 3 ...................................................................................................... 218
Ejemplo 4 ...................................................................................................... 219
Lección XXVIII - Vistas: Vistas y modificaciones automáticas..................................................... 220
Reglas ........................................................................................................................................ 221
Contexto ................................................................................................................................... 221
Modificación automática de vistas y tablas ..................................................................... 222
Ejemplo 1 ...................................................................................................... 223
Ejemplo 2 ...................................................................................................... 224
Ejemplo 3 ...................................................................................................... 224
Ejemplo 4 ...................................................................................................... 225
Conclusiones ........................................................................................................................... 225
Lección XXIX - Vistas: Vistas materializadas................................................................................ 226
Introducción ............................................................................................................................. 226
Definición ................................................................................................................................. 226
Ventaja .......................................................................................................... 226
Desventajas ................................................................................................... 226
Mantenimiento de las vistas ................................................................................................ 227
Creación de una vista ............................................................................................................ 227
Ejemplo ......................................................................................................... 230
Lección XXX – Mantenimiento de la Base de Datos ..................................................................... 233
Introducción ............................................................................................................................. 233
Rutinas de mantenimiento y monitoreo........................................................................... 233
Vacuum ......................................................................................................... 233
Reindexación ................................................................................................. 235
Ficheros de registro ....................................................................................... 236
Explain .......................................................................................................... 236
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 12 de 253
Lección XXXI - Servicios de Respaldo y Recuperación para Bases de Datos (BD) ...................... 238
Servicios en PostgreSQL ........................................................................................................ 239
SQL Dump ................................................................................................................................. 239
pg_dump ....................................................................................................... 239
Ejemplo 1 ...................................................................................................... 239
Ejemplo 2 ...................................................................................................... 242
Ejercicio propuesto ........................................................................................ 243
pg_dumpall ................................................................................................... 244
Respaldo a nivel de archivos ............................................................................................... 244
Rsync ............................................................................................................. 245
Conclusiones ........................................................................................................................... 245
Lección XXXII – Querys al Catalogo de PostgreSQL ......................................................................... 246
Obtener objetos del servidor PostgreSQL. ...................................................................... 246
Lección XXXIII. Consultas útiles de monitoreo. ............................................................................... 253
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 13 de 253
Introducción
Este Manual tiene como objetivo ser una Guía de Referencia durante el transcurso del curso SQL-
PostgreSQL.
En él podrán encontrar definiciones, notas, ejemplos practicos de casos de estudio que les servirán
en sus labores cotidianas con ésta poderosa herramienta llamada PostgreSQL.
En curso no contempla administración de PostgreSQL, ni tampoco Tunning de PostgreSQL ni
implementaciones de Alta Disponibilidad, pues ellas son materia de un curso de Administración
Avanzada de PostgreSQL.
Espero que este este Manual y en curso en sí les sea de mucha utilidad y les resulte entretenido.
Mario Soto Cordones
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 14 de 253
Lección I - Bases de datos relacionales: “El
modelo relacional”
¿Qué son las Bases de Datos (BD)?
Una BD es un conjunto de datos interrelacionados, almacenados sin redundancias
innecesarias, de forma independiente de los programas que acceden a ellos.
El Sistema Gestor de Base de Datos (SGBD)
Un SGBD es un conjunto de programas que permiten crear y mantener una BD,
asegurando su integridad, confidencialidad y seguridad. Por tanto debe permitir:
Definir una base de datos: especificar tipos, estructuras y restricciones de
datos.
Construir la base de datos: guardar los datos en algún medio controlado
por el mismo SGBD.
Manipular la base de datos: realizar consultas, actualizarla, generar
informes.
Algunas de las características deseables en un SGBD son:
Control de la redundancia: la redundancia de datos tiene varios efectos
negativos (duplica el trabajo al actualizar, desperdicia espacio en disco,
puede provocar inconsistencia de datos) aunque a veces es deseable por
cuestiones de rendimiento.
Restricción de los accesos no autorizados: cada usuario ha de tener unos
permisos de acceso y autorización para realizar operaciones sobre la BD.
Cumplimiento de las restricciones de integridad: el SGBD ha de ofrecer
recursos para definir y garantizar el cumplimiento de las restricciones de
integridad.
El modelo Entidad-Relación (E-R)
Cuando se utiliza una BD para gestionar información, se está plasmando una parte del
mundo real en una serie de tablas, registros y campos; creándose un modelo parcial de
la realidad. Antes de crear físicamente estas tablas en la BD se debe realizar un modelo
de datos.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 15 de 253
El modelo de datos más utilizado es denominado Entidad-Relación (E-R). En el modelo
E-R se representa una situación real a través de entidades y relaciones entre dichas
entidades:
Entidades
Los objetos que aparecen en la vida real, corresponden a una entidad. Por ejemplo:
alumnos, empleados, aviones, coches, alojamientos, etc. Una entidad da lugar a
una tabla en la BD.
Estas entidades están compuestas por varios atributos, que vienen a ser sus
propiedades. Por ejemplo: la entidad Alumnos, tendrá los
atributos nombre, #pasaporte, nacionalidad, fecha de nacimiento, etc.
Los atributos también reciben el nombre de columnas en la terminología de BD. De
entre los atributos habrá uno o un conjunto de ellos, que no asegura la unicidad de una
fila; a este atributo o conjunto de atributos se le llama clave de la entidad, en el caso de
los alumnos, sería el #pasaporte. En toda entidad siempre hay al menos una clave que
en el peor de los casos estará formada por todos los atributos de la tabla. Ya que
pueden haber varias claves y necesitamos elegir una, lo haremos atendiendo a estas
normas:
Que sea única.
Que se tenga pleno conocimiento de ella.- ¿Por qué en las empresas se
asigna a cada cliente un número de cliente?.
Que sea pequeña, ya que será muy utilizada por el SGBD.
Cada entidad tendrá un número ilimitado de elementos. Por ejemplo: un elemento de la
entidad alumnos será un alumno en sí; así el alumno Juan será un elemento, José será
otro. Cada uno de esos elementos también recibe el nombre de fila o tuplas en la
terminología de BD.
Combinando estos tres conceptos tenemos una estructura del tipo tabla, elemento
esencial en una BD relacional.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 16 de 253
Nota
En los textos se utilizan ciertos sinónimos:
Para referirse a una fila se puede usar el término tupla o registro.
Para referirse a una columna se puede usar el término campo o atributo.
Relaciones
Las entidades no están aisladas sino que están relacionadas entre sí. Estas relaciones
reflejan las interacciones lógicas existentes entre entidades. Las relaciones pueden ser
de tres tipos:
Relaciones 1 - 1: Las entidades que intervienen en la relación se asocian una a una (Ej:
la entidad HOMBRE, la entidad MUJER y entre ellos la relación MATRIMONIO).
Relaciones 1 - N: Una ocurrencia de una entidad está asociada con muchas (n) de otra
(Ej: la entidad EMPRESA, la entidad TRABAJADOR y entre ellos la relación TRABAJAR-EN).
Relaciones M - N: Cada ocurrencia, en cualquiera de las dos entidades de la relación,
puede estar asociada con muchas (n) de la otra y viceversa (Ej: la entidad ALUMNO, la
entidad ASIGNATURA y entre ellos la relación MATRÍCULA).
Base de Datos Relacionales
Es una BD que utiliza como estructura de almacenamiento tablas. Las interconexiones
(relaciones) entre los datos (que están guardados en tablas), se generan a través de
atributos comunes entre ellas llamadas claves primarias y foráneas.
Ventajas
Sistemas de bases de datos utilizados por las empresas comerciales más
importantes.
Modelo simple.
Consultas a través de lenguajes de alto nivel.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 17 de 253
Implementación eficiente.
Características
Se compone de varias tablas o relaciones.
No existen dos o más tablas con el mismo nombre.
Una tabla es un conjunto de registros (filas y columnas).
La relación entre una tabla padre y un hijo se lleva a cabo por medio de
claves primarias y foráneas.
Las claves primarias representan la clave principal de un registro dentro
de una tabla y éstas deben cumplir con la integridad de los datos.
Las claves foráneas se colocan en la tabla hija, contienen el mismo valor
que la clave primaria del registro padre; por medio de éstas se
implementan las relaciones.
Ejemplo
Se tiene una base de datos que contiene dos tablas: una denominada Empleados, que
almacena datos de los empleados de una empresa, y otra con el nombre Despachos,
que almacena los datos de los despachos que tiene la empresa. Los empleados que
trabajan para una empresa pueden estar vinculados con los despachos de la empresa,
porque a cada empleado se le asigna un despacho concreto para trabajar.
Tabla Despachos
edificioPrincessPrincessPrincessGreyDiagonalnumero120121122230110super
ficie1012152010
La tabla Despachos posee 3 atributos (edificio,
numero−−−−−−−−−−−−,superficie) y 5 registros (o filas). Esta tabla posee un
conjunto de atributos cuyos valores combinados dan la unicidad a cada fila. Se trata de
los atributos edificio y numero; se les llama clave primaria compuesta.
Tabla Empleados
DNI40.444.25533.567.71155.898.42577.232.144nombreAlexGeorgeDerekAri
zonaapellidoKarevO'MalleyShepherdRobbinsDNIjefe40.783.15040.444.2554
0.444.25540.444.255edificiodespPrincessNULLDiagonalGreynumerodesp120
NULL110230
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 18 de 253
La tabla Empleados posee 6 atributos (DNI−−−−,nombre, apellido,
DNIjefe, edificiodesp, numerodesp) y 4 registros (o filas), en el segundo registro se
aprecia que George no posee despacho asignado por lo que se agrega el valor
“unknown” o “undefined” que se define como NULL. Esta tabla posee un atributo cuyo
valor es único en cada tupla que es atributo DNI y se le llama clave primaria.
En Empleados, existe una clave foránea formada por los
atributos edificiodesp y numerodesp que referencia la clave primaria de Despachos.
De este modo, se cumple que todos los valores que no son nulos de los
atributos edificiodesp y numerodesp son valores que existen para los
atributos edificio y numero de Despachos. Esta clave foránea indica, para cada
empleado, el despacho donde trabaja. Además, el atributo DNIjefe es otra clave foránea
que referencia la clave primaria de la misma tabla Empleados, e indica, para cada
empleado, quien es su jefe.
Ejemplo en SQL
La creación de relaciones (tablas) en SQL
CREATE TABLE Despachos(edificio VARCHAR(50), numero INTEGER, superficie INTEGER, PRIMARY KEY(edificio,numero)); CREATE TABLE Empleados(DNI VARCHAR(50), nombre VARCHAR(50), apellido VARCHAR(50), DNIjefe VARCHAR(50), edificiodesp VARCHAR(50), numerodesp INTEGER, PRIMARY KEY(DNI), FOREIGN KEY(edificiodesp,numerodesp) REFERENCES Despachos(edificio,numero));
Motores de Bases de Datos Relacionales
Hoy en día existen muchas empresas y sitios web que necesitan mantener de forma
eficiente un gran volumen de datos. Muchos de ellos optan por soluciones comerciales
(Oracle Database o IBM DB2 entre otras ), aunque muchas otras confían en el software
libre optando por una solución como PostgreSQL o MySQL. Cabe mencionar que un
motor de BD relacional (BDR) es equivalente a un SGBDR.
Es muy común la pregunta, entre las personas que se adentran por primera vez en el
mundo de las bases de datos libres, ¿Qué motor de bases de datos debo usar? ¿MySQL
o PostGreSQL?. A continuación se verán algunos detalles de ambos motores.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 19 de 253
PostgreSQL
PostGreSQL es un sistema de gestión de bases de datos objeto-relacional basado en el
proyecto POSTGRES, de la Universidad de Berkeley. El director de este proyecto es el
profesor Michael Stonebraker, patrocinado por Defense Advanced Research Projects
Agency (DARPA), Army Research Office (ARO), National Science Foundation (NSF), y ESL,
Inc.
Un poco de historia
PostGreSQL fue derivado del proyecto Postgres, lleva más de una década de desarrollo,
siendo hoy en día, el sistema libre más avanzado, soportando la gran mayoría de las
transacciones SQL, control concurrente y un variado conjunto de “language bindings”
como por ejemplo C, C++, Java, Python, PHP y muchos más.
La implementación de Postgres DBMS comenzó en 1986, y no hubo una versión
operativa hasta 1987. La versión 1.0 fue liberada en Junio de 1989 a unos pocos
usuarios, tras la cual se liberó la versión 2.0 en Junio de 1990 debido a fuertes críticas
sobre el sistema de integridad referencial, que obligó a su reimplementación. La versión
3.0 apareció en el año 1991.
En 1994, Andrew Yu y Jolly Chen añadieron un intérprete de SQL a este gestor.
Postgres95, como así se llamó fue liberado a Internet como un proyecto libre
(OpenSource). Estaba escrito totalmente en C, y la primera versión fue un 25% más
pequeña que Postgres, y entre un 30 y un 50% más rápida. A parte de la corrección de
algunos bugs, se mejoró el motor interno, se añadió un nuevo programa monitor, y se
compiló usando GNU Make y el compilador gcc.
En 1996, los desarrolladores decidieron cambiar el nombre al SGDB, y lo llamaron
PostGreSQL para reflejar la relación entre Postgres y las versiones recientes de SQL.
Características
Implementación del estándar SQL92/SQL99.
Licencia BSD.
Por su arquitectura de diseño, escala muy bien al aumentar el número de
CPUs y la cantidad de RAM.
Soporta transacciones y desde la versión 7.0, claves foráneas (con
comprobaciones de integridad referencial).
Tiene mejor soporte para triggers y procedimientos en el servidor.
Incorpora una estructura de datos array.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 20 de 253
Incluye herencia entre tablas (aunque no entre objetos, ya que no
existen), por lo que a este SGBD se le incluye entre los gestores objeto-
relacionales.
Implementa el uso de rollback’s, subconsultas y transacciones, haciendo
su funcionamiento mucho más eficaz.
Se pueden realizar varias operaciones al mismo tiempo sobre la misma
tabla sin necesidad de bloquearla.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 21 de 253
Lección II - Bases de datos relacionales:
Consulta de bases de datos relacionales
Utilizando una Base de Datos Relacional
Los pasos necesarios a la hora de crear una Base de Datos Relacional (BDR) son:
Diseñar el esquema, es decir, la estructura de las tablas y las relaciones, usando
un DDL (Data Definition Language).
Ingresar los datos iniciales.
Ejecutar operaciones de consulta y mantención usando en DML (Data
Manipulation Language).
Nota
Existen las llamadas “Operaciones Básicas” de DML que se pueden realizar en una Base de
Datos Relacional:
1. Consultar: SELECT
2. Almacenar: INSERT
3. Actualizar: UPDATE
4. Borrar: DELETE
Nota
Existen las llamadas “Operaciones Básicas” de DDL que se pueden realizar en una Base de
Datos Relacional:
1. Almacenar: CREATE
2. Borrar: DROP
Por ahora sólo se nombran junto a sus funciones SQL relacionadas. A medida que el
curso avance, se profundizará el contenido.
Consultas en lenguajes de alto nivel
Existen lenguajes de alto nivel que permiten realizar consultas relativamente simples en
la BD, sin la necesidad de escribir complejos algoritmos.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 22 de 253
Una ‘consulta a la BD’, puede entenderse como una pregunta que se le realiza para
obtener ‘cierta información’. Algunos ejemplos pueden ser:
“Todos los estudiantes con nota mayor o igual a 55”.
“Todas los departamentos de Ingeniería con una cantidad mayor o igual a 1000
alumnos”.
“Los 5 primeros estudiantes con mejor promedio de notas en el ramo de
Química”.
Independiente del lenguaje que se utiliza, se debe tener en cuenta que:
Algunas consultas son fáciles de formular, otras son un poco más
difíciles.
Algunos SGBD las ejecutan de forma eficiente, otros no.
Los 2 puntos anteriores no son dependientes uno del otro, puede existir
una consulta fácil de formular, pero difícil de ejecutar de forma eficiente,
dependiendo del DBMS.
El lenguaje utilizado para ejecutar consultas puede modificar/actualizar
información de la BD, a esto se le llama Data Manipulation Language
(DML).
Consultas y relaciones (tablas)
Las consultas realizadas a las tablas de una BD al momento de ser ejecutadas
producen, como resultado, tablas; las cuales pueden ser:
Cerradas: Cuando la estructura del objeto que se obtiene de la consulta, es
igual a la estructura de los objetos consultados, se tiene una tabla cerrada.
Compuestas: Cuando la consulta se hace sobre, al menos una tabla que
corresponde al resultado de una consulta previa. En otras palabras,
corresponde a la consulta del resultado de una consulta.
Lenguajes de consultas
Algunos de los lenguajes de consultas son
Álgebra Relacional: Lenguaje formal y matemático
SQL: Lenguaje actual e implementado que nace del Álgebra Relacional.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 23 de 253
Si bien se profundizará sobre ambos, a medida que avance el curso, se deja la
siguientes tablas:
Tabla Alumnos
id12345idRamo12113nombreAlumnoRobertRobertHarryJaneMaryprome
dioNota4570556035
Tabla Ramos
id123nombreRamoProgramacionBase de datosEstructuras de datos
Consultar por el id de los alumnos con promedio de notas mayor o igual a 55 en el
ramo de “Programación”:
Utilizando Álgebra Relacional
πAlumnos.idσ≥ 55 AND Ramos.nombreRamo ='Programacion'(Alumnos ⊳ ⊲Ramos)
Se puede decir que:
π, realiza un PROJECT sobre una tabla, es decir selecciona una columna. Por
otro lado:
σ, selecciona una fila que cumpla con una cierta condición, en el ejemplo
dado se seleccionan las filas que cumplen con tener nota mayor a 55 y que
el nombreRamo sea programación.
⊳⊲, realiza un JOIN entre dos relaciones en la Lección 3 se profundiza
acerca de estos operadores y sus respectivos significados.
Utilizando SQL
SELECT ALUMNOS.ID FROM ALUMNOS, Ramos WHERE ALUMNOS.ID_ramo=Ramos.ID AND ALUMNOS.promedio_nota>=55 AND Ramos.nombreRamo='Programacion';
En las próximas Lecciónes, se estudiará con mayor detalle tanto el álgebra
relacional, como el lenguaje SQL.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 24 de 253
Lección III - Álgebra Relacional: Select,
Project, Join
Conceptos básicos de álgebra relacional
Algebra, en general, consiste de operadores y operandos atómicos, por ejemplo, en el
álgebra de la aritmética, los operandos atómicos son variable como r, y constantes
como 15. Los operadores son los usuales en la aritmética:
Suma,
Resta,
Multiplicación,
División.
Cualquier álgebra nos permite construir expresiones mediante la aplicación de
operadores a operandos atómicos y/o otras expresiones del álgebra. En general, los
paréntesis son necesarios para agrupar operadores y sus operandos, por ejemplo, en
aritmética tenemos expresiones tales como (x+y)∗z ó ((x+7)/(y−3))+x.
El Álgebra Relacional es otro ejemplo del álgebra. Sus operandos atómicos son:
1. Variables que representan relaciones.
2. Constantes que son relaciones finitas.
Nota
En algunos textos de álgebra relacional o SQL, una relación es sinónimo de una tabla.
Como mencionamos, en el álgebra relacional clásica, todos los operandos y sus
resultados de expresiones son conjuntos. Los operadores del álgebra relacional
tradicional se divide en cuatro grandes categorías:
a. Los conjuntos habituales de operaciones unión, intersección,
y diferencia se aplica a las relaciones.
b. Las operaciones que eliminan parte de una relación: selección elimina
algunas filas (o tuplas), y proyección elimina algunas columnas.
c. Las operaciones que combinan las tuplas de dos relaciones, como
el producto cartesiano, que empareja las tuplas de dos relaciones en
todas las maneras posibles y varios tipos de operadores unión, los cuales
forman parejas de tuplas de dos relaciones selectivamente.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 25 de 253
d. Una operación llama “renombrar” que no afecta las tuplas de una
relación, pero que cambia el esquema de relación, es decir, lo nombres
de los atributos y/o los nombres de la relación misma.
Debemos por lo general referirnos a las expresiones del álgebra relacional como
consultas. A pesar de que aún no tengan los símbolos necesarios para mostrar muchas
de las expresiones del algebra relacional, se debería familiarizar con las operaciones
degrupo (a); y por lo tanto reconocer: R∪S como un ejemplo de una expresión de
álgebra relacional. Donde R y S son operandos atómicos para relaciones, cuyos
conjuntos de tuplas son desconocidas. Esta consulta pregunta por la unión de
cualquiera tuplas que están en las relaciones nombradas R y S.
Las tres operaciones más comunes en conjuntos son unión, intersección,
y diferencia, que serán vistas en la Lección 4.
Nota
Resumiendo Álgebra Relacional se define como un conjunto de operaciones que se ejecutan
sobre las relaciones (tablas) para obtener un resultado, el cual es otra relación.
Operaciones relacionales:
Los operadores relacionales se utilizan para filtrar, cortar o combinar tablas.
Selección (Select)
Este operador se aplica a una relación R produciendo una nueva relación con un
subconjunto de tuplas de R. Las tuplas de la relación resultante son las que satisfacen
una condición C sobre algún atributo de R. Es decir selecciona filas (tuplas) de una
tabla según un cierto criterio C. El criterio C es una expresión condicional, similar a las
declaraciones del tipo “if”, es “booleana” esto quiere decir que para cada tupla
de R toma el valor Verdad(true) o Falso(false).
Valores de atributos con “NULL” no cumplirán ninguna condición.
Cada condición simple o cláusula C tiene el
formato: <Atributo> <Comparador> <Atributo o Constante del Dominio>}.
donde, el campo Comparador es un operador lógico, que pueden
ser {=,≥,>,<,≠,≤}.
o = : símbolo de igual que.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 26 de 253
o ≠: significa no igual a, en algunos libros este símbolo esta
representado por !=.
o ≥: mayor que o igual a.
o >: mayor que.
o <: menor que.
o ≤: menor que o igual a.
Los operadores lógicos que se utilizan, también llamados operadores relacionales, nos
proporcionan un resultado a partir de que se cumpla o no una cierta condición. Son
símbolos que se usan para comparar dos valores. Si el resultado de la comparación es
correcto la expresión considerada es verdadera, en caso contrario es falsa. Por ejemplo,
11>4 (once mayor que cuatro) es verdadera, se representa por el valor true del tipo
básico boolean, en cambio, 11<4 (once menor que cuatro) es falsa se representa por el
valor false.
Las cláusulas C pueden conectarse con otros operadores lógicos, que al igual que los
anteriores que se usaban como comparador (entre atributos o atributo y constante),
arrojan booleano (true o false) de resultado:
NOT: El operador NOT denota una salida verdadera si la entrada es falsa, y una
salida falsa si la entrada es verdadera. Su notación en algebra es: ¬ C1.
AND: El operador AND denota una salida verdadera si y sólo si sus entradas son
verdaderas. Si C1 se cumple y C2 también se cumple, la salida será verdadera.
La notación en algebra de un AND es: C1 ∧ C2.
OR: El operador OR denota una salida verdadera si hay alguna de las entradas (o
ambas) verdaderas. Si C1 y/o C2 es o son verdaderas, la expresión será
verdadera. La notación en algebra de un OR es: C1 ∨ C2.
Notación en Álgebra Relacional
Para representar Select en álgebra relacional se utiliza la letra griega sigma σ. Por lo
tanto, si utilizamos la notación σc R queremos decir que se aplica la condición C a
cada tupla de R. Si la condición es Verdad true, dicha tupla pertenecerá al resultado y
si es Falsafalse, dicha tupla no será seleccionada. El esquema de la relación resultante
es el mismo esquema R, se muestran los atributos en el mismo orden que se usan en
la tabla R.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 27 de 253
Ejemplo 1
Tabla Ingenieros
id123234345143nombreLeonTomasJoseJosefaedad39344525añosTrabajados1
510211
Seleccionar las tuplas de la tabla Ingenieros que cumplan con tener una edad mayor a
30 años:
Respuesta
σedad>30Ingenieros
En la imagen se ve que selecciona solo las filas que cumplen con la condición que se
pedía (tener una edad mayor a 30 años), la tupla de “Josefa” queda fuera de la selección
por no cumplir la condición (pues 25 < 30). De esta forma la tabla queda:
Tabla Ingenieros
id123234345nombreLeonTomasJoseedad393445añosTrabajados151021
Ejemplo 2
Seleccionar de la tabla Ingenieros las personas que tienen más de 30 años y que lleven
menos de 16 años trabajando:
Respuesta
σ(edad>30∧añosTrabajados<16) Ingenieros
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 28 de 253
Al tener el operador lógico AND se pide que cumplan dos condiciones simultáneamente.
Primero que la edad sea mayor de 30 años, al igual que en el ejemplo anterior, la tupla
de “Josefa” queda fuera de la selección. Luego de las tuplas que quedan se evalúa la
segunda condición. En la imagen se aprecia, que solo se seleccionan las filas que no
tengan X en alguna de las condiciones.
Así finalmente quedaría la tabla:
Tabla Ingenieros
id123234nombreLeonTomasedad3934añosTrabajados1510
Proyección (Project)
El operador Proyección se utiliza para producir una nueva relación desde R. Esta nueva
relación contiene sólo algunos de los atributos de R, es decir, realiza la selección de
algunas de las columnas de una tabla R.
Notación en Álgebra Relacional
Project en Álgebra Relacional se representa por la letra griega pi:
π(A1,...,An)R
El resultado es una relación seleccionando solo los atributos A1,...,An de la relación R.
Si A1,...,An no incluye una llave (o clave), podrían producirse tuplas repetidas en el
resultado, las cuales serán eliminadas.
Ejemplo 1
Tabla Ingenieros
id123234345143nombreLeonTomasJoseJosefaedad39344525añosTrabajados1
510211
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 29 de 253
Escoger columnas de id y nombre de la tabla de Ingenieros:
Respuesta
π(id,nombre)Ingenieros
La tabla finalmente queda como:
Tabla Ingenieros
id123234345143nombreLeonTomasJoseJosefa
Ejemplo 2
Seleccionar id y nombre de los Ingenieros que tienen más de 30 años.
Respuesta
π(id,nombre)(σedad>30Ingenieros)
Se aprecia que las tuplas que no cumplan con la condición de selección quedan fuera
del resultado, luego se realiza un Project sobre las filas del resultado, separando solo
las columnas que contienen los atributos id y nombre. Finalmente la tabla queda de la
siguiente manera:
Tabla Ingenieros
id123234345nombreLeonTomasJose
Producto cartesiano (Cross-Product)
En teoría de conjuntos, el producto cartesiano de dos conjuntos es una operación que
resulta en otro conjunto cuyos elementos son todos los pares ordenados que pueden
formarse tomando el primer elemento del par del primer conjunto, y el segundo
elemento del segundo conjunto. En el Álgebra Relacional se mantiene esta idea con la
diferencia que R y S son relaciones, entonces los miembros de R y S son tuplas, que
generalmente consisten de más de un componente, cuyo resultado de la vinculación de
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 30 de 253
una tupla de R con una tupla de S es una tupla más larga, con un componente para
cada uno de los componentes de las tuplas constituyentes. Es decirCross-
product define una relación que es la concatenación de cada una de las filas de la
relación R con cada una de las filas de la relación S.
Notación en Álgebra Relacional
Para representar Cross-product en Álgebra Relacional se utiliza la siguiente
terminología:
R×S
Por convención para la sentencia anterior, los componentes de R preceden a los
componentes de S en el orden de atributos para el resultado, creando así una nueva
relación con todas las combinaciones posibles de tuplas de R y S. El número de tuplas
de la nueva relación resultante es la multiplicación de la cantidad de tuplas de R por la
cantidad de tuplas que tenga S (producto de ambos). Si Ry S tienen algunos atributos
en común, entonces se debe inventar nuevos nombres para al menos uno de cada par
de atributos idénticos. Para eliminar la ambigüedad de un atributo a, que se encuentra
en R y S, se usa R.a para el atributo de R y S.a para el atributo de S.
Cabe mencionar que por notación que: R×S≠S×R
Ejemplo 1
Con las tablas dadas realice el Cross-product de R con S:
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 31 de 253
Con azul se resaltan las tuplas que provienen de R que preseden y se mezclan con las
de S resaltadas en verde.
Con las tablas dadas realice el Cross-product de S con R:
Ejemplo 2
Dada las siguientes tablas:
Tabla Ingenieros
id123234143nombreLeonTomasJosefad#393425
Tabla Proyectos
proyectoACU0034USM7345duracion30060
Escriba la tabla resultante al realizar la siguiente operación:
Ingenieros×Proyectos
Respuesta
Ingenieros×Proyectos
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 32 de 253
id123123234234143143nombreLeonLeonTomasTomasJosefaJosefad#393934
342525proyectoACU0034USM7345ACU0034USM7345ACU0034USM7345
duracion300603006030060
Natural Join
Este operador se utiliza cuando se tiene la necesidad de unir relaciones vinculando sólo
las tuplas que coinciden de alguna manera.NaturalJoin une sólo los pares de tuplas
de R y S que sean comunes. Más precisamente una tupla r de R y una tupla s de S se
emparejan correctamente si y sólo si r y s coinciden en cada uno de los valores de los
atributos comunes, el resultado de la vinculación es una tupla, llamada joined tuple.
Entonces, al realizar NaturalJoin se obtiene una relación con los atributos de ambas
relaciones y se obtiene combinando las tuplas de ambas relaciones que tengan el
mismo valor en los atributos comunes.
Notación en Álgebra Relacional
Para denotar NaturalJoin se utiliza la siguiente simbología: R⊳⊲S.
Equivalencia con operadores básicos
NaturalJoin puede ser escrito en términos de algunos operadores ya vistos, la
equivalencia es la siguiente:
R⊳⊲S=πR.A1,...,R.An,S.A1,...,S.An(σR.A1=S.A1∧...∧R.An=S.An(R×S))
Método
1. Se realiza el producto cartesiano R×S .
2. Se seleccionan aquellas filas del producto cartesiano para las que los
atributos comunes tengan el mismo valor.
3. Se elimina del resultado una ocurrencia (columna) de cada uno de los
atributos comunes.
Ejemplo 1
R
a14b25c36
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 33 de 253
S
c763d524
Con las tablas dadas realice el NaturalJoin de R y S:
El atributo que tienen en común R y S es el atributo c, entonces las tuplas se unen
donde c tiene el mismo valor en R y S
R⊳⊲S
a14b25c36d42
Ejemplo 2
Realizar NaturalJoin a las siguientes tablas:
Tabla Ingenieros
id123234143090nombreLeonTomasJosefaMariad#39342534
Tabla Proyectos
d#3934proyectoACU0034USM7345
Respuesta
Ingenieros⊳⊲Proyectos
id123234090nombreLeonTomasMariad#393434proyectoACU0034USM7345
USM7345
ThetaJoin
Define una relación que contiene las tuplas que satisfacen el predicado C en el Cross-
Product de R×S. Conecta relaciones cuando los valores de determinadas columnas
tienen una interrelación específica. La condición C es de la
forma R.ai<operador_de_comparación> S.bi, esta condición es del mismo tipo que se
utiliza Select . El predicado no tiene por que definirse sobre atributos comunes. El
término “join” suele referirse a ThetaJoin.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 34 de 253
Notación en Álgebra Relacional
La notación de ThetaJoin es el mismo símbolo que se utiliza para NaturalJoin, la
diferencia radica en que ThetaJoin lleva el predicado C:
R⊳⊲CS
C = <Atributo> <Comparador> <Atributo o Constante del Dominio> Donde: <Comparad
or> ∈{=,≥,>,<,≠,≤}
Equivalencia con operadores básicos
Al igual NaturalJoin, ThetaJoin puede ser escrito en función de los operadores vistos
anteriormente:
R⊳⊲CS=σF(R×S)
Método
1. Se forma el producto cartesiano R×S .
2. Se selecciona, en el producto, solo la tupla que cumplan la condición C.
Ejemplo 1
R
a132b323c595d714
S
a1132c5593e2927
Escriba la tabla resultante al realizar la siguiente operación:
R⊳⊲(a>=e)S
Respuesta
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 35 de 253
Se compara el atributo a de la primera fila de R con cada uno de los valores del
atributo e de la tabla S. En este caso ninguna de las comparaciones devuelve el valor
verdadero (true).
Luego se compara el atributo a de la segunda fila de R con cada uno de los valores del
atributo e de la tabla S. En este caso 2 comparaciones devuelven el valor verdadero
(true), por lo que en la relación de resultado quedará la segunda fila de R mezclada
con la primera y tercera fila de S.
De igual forma ahora se compara el valor de a de la tercera tupla de R, nuevamente 2
tuplas de S cumplen con la condición.
S
R.a3322b2233R.c9955d1144S.a1313S.c5959e2222
Ejemplo 2
Con el esquema conceptual siguiente, hallar los nombres de los directores de cada
departamento:
Dpto(numDpto−−−−−−−−, nombre, nIFDirector, fechaInicio)
Empleado(nIF−−−, nombre, direccion, salario, dpto, nIFSupervisor)
Respuesta
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 36 de 253
π(Dpto.nombre,empleado.nombre)(Dpto⊳⊲nIFDirector=NIFEmpleado)
Tuplas con “Null” en los “Atributos de la Reunión”, no se incluyen en el
resultado.
Ejercicio propuesto
Considere la siguiente base de datos:
1. Persona(nombre−−−−−−, edad, genero) : nombre es la clave.
2. Frecuenta(nombre, pizzeria−−−−−−−−−−−−−) : (nombre, pizzeria)
es la clave.
3. Come(nombre, pizza−−−−−−−−−−−) : (name, pizza) es la clave.
4. Sirve(pizzeria, pizza−−−−−−−−−−−, precio): (pizzeria, pizza) es la
clave.
Escribir expresiones en álgebra relacional para las siguientes dos preguntas:
Seleccionar a las personas que comen pizzas con extra queso.
Seleccionar a las personas que comen pizzas con extra queso y
frecuentan la pizzería X.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 37 de 253
Lección IV - Álgebra Relacional: Set
operators, renaming, notation
Operaciones de conjunto
Unión
En matemáticas, se denomina álgebra de conjuntos a las operaciones básicas que
pueden realizarse con conjuntos, como la unión, intersección, etc. Un conjunto es una
colección de objetos considerada como un objeto en sí. La Unión de dos
conjuntos A y B es el conjunto que contiene todos los elementos de A y de B. El
símbolo ∪ es el utilizado para representar Unión.
El operador Unión es conmutativo es decir A∪B=B∪A. Cabe recordar que una
operación es conmutativa cuando el resultado de la operación es el mismo, cualquiera
que sea el orden de los elementos con los que se opera.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 38 de 253
De manera análoga, la Unión de dos relaciones R y S, es otra relación que contiene las
tuplas que están en R, o en S, o en ambas, eliminándose las tuplas
duplicadas. R y S deben ser unión-compatible, es decir, definidas sobre el mismo
conjunto de atributo (R yS deben tener esquemas idénticos. Deben poseer las mismas
columnas y su orden debe ser el mismo).
Notación en álgebra relacional
R∪S
Si se realiza R∪S es lo mismo que S∪R , es decir se obtiene el mismo resultado. Esto
debido a la propiedad de conmutatividad derivada de la álgebra de conjuntos.
Ejemplo
Dadas las siguientes relaciones:
Tabla Ingenieros
id123234345143nombreLeonTomasJoseJosefaedad39344525
Tabla Jefes
id123235nombreLeonMariaedad3929
Aplicar el operador Unión:
Tabla Ingenieros∪Jefes
id123234345143235nombreLeonTomasJoseJosefaMariaedad3934452529
Como se mencionó anteriormente, realizar la operación Jefes∪Ingenieros daría como
resultado la misma tabla anterior, debido a la propiedad de conmutatividad.
Diferencia
Volviendo a la analogía de álgebra de conjuntos, la diferencia entre dos
conjuntos A y B es el conjunto que contiene todos los elementos de A que no
pertenecen a B.
A−B
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 39 de 253
B−A
Como se aprecia en las imágenes la operación Diferencia, en conjuntos, no es
conmutativa, al igual que la resta o sustracción, operador aprendido en aritmética
básica. Es decir, si se cambia el orden de los conjuntos a los que se aplica la
operación Diferencia, se obtendrán resultados distintos. Por lo tanto:
A−B≠B−A
De la misma forma la diferencia de dos relaciones R y S, es otra relación que contiene
las tuplas que están en la relación R, pero no están en S. R y S deben ser unión-
compatible (deben tener esquemas idénticos).
Notación en álgebra relacional
R−S
Es importante resaltar que R−S es diferente a S−R.
Ejemplo
Empleando las mismas tablas dadas en el ejemplo anterior,
realice Ingenieros−Jefes y Jefes−Ingenieros:
Ingenieros - Jefes
id234345143nombreTomasJoseJosefaedad344525
Jefes - Ingenieros
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 40 de 253
id235nombreMariaedad29
Como se puede apreciar, ambas operaciones dieron como resultado distintas
relaciones, tal como se había mencionado anteriormente.
Intersección
En álgebra de conjuntos la Intersección de dos conjuntos A y B es el conjunto que
contiene todos los elementos comunes de A y B. El símbolo ∩ representa
la Intersección de dos conjuntos. Al igual que el operador Unión, Intersección es
conmutativo, entonces se cumple que A∩B=B∩A .
A∩B
De forma homóloga en álgebra relacional, Intersección define una relación que
contiene las tuplas que están tanto en la relación Rcomo en S. R y S deben ser unión-
compatible (mismos atributos y mismo orden).
Notación en algebra relacional
R∩S
Si se realiza R∩S es lo mismo que S∩R, es decir se obtiene el mismo resultado, se
puede decir que Intersección es conmutativa.
Equivalencia con operadores anteriores
R∩S=R−(R−S)
Ejemplo
Utilizando las mismas tablas del ejemplo anterior, encontrar la Intersección de la tabla
de Ingenieros con la de Jefes:
Ingenieros∩Jefes
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 41 de 253
id123nombreLeonedad39
Importante
Para aplicar estas operaciones a relaciones, necesitamos que R y S sean unión-compatible:
R y S deben tener esquemas con conjuntos de atributos idénticos, y de
tipos (dominios) para cada atributo deben ser las mismas en R y S.
Antes de computar el conjunto-teórico unión, intersección, o diferencia
de conjuntos de tuplas, las columnas de R y S deben ser ordenadas
para que el orden de los atributos sean los mismos para ambas
relaciones.
Operaciones dependientes e independientes
Algunas de las operaciones que se han descrito en las Leccións 3 y 4, pueden ser
expresadas en términos de operadores de algebra relacional. Por ejemplo, la
intersección puede ser expresada en términos de conjuntos de
diferencia: R∩S=R−(R−S). Es decir, si R y S son dos relaciones con el mismo
esquema, la intersección de R y S puede ser resuelta restando primero S de R para
formar una relación T que consiste en todas aquellas tuplas en R pero no en S.
Cuando se resta T de R, dejamos solo esas tuplas de R que están también en S.
Álgebra relacional como idioma restrictor
Hay dos maneras en las cuales podemos usar expresiones de algebra relacional para
expresar restricción:
1. Si R es una expresión de algebra relacional, entonces R=0 es una restricción que
dice “El valor de R debe ser vacio,” o equivalentemente “No hay tuplas en el resultado
de R.”
2. Si R y S son expresiones de algebra relacional, entonces R⊂S es una restricción que
dice “Cada tupla en resultado deR debe estar también en resultado de S.” Por
supuesto, el resultado de S puede contener tuplas adicionales no producidas en R.
Estas formas para expresar restricción son de hecho equivalentes en lo que pueden
expresar, pero algunas veces uno de los dos es más clara o más sucinta. Es decir, la
restricción R⊂S pudo también ser escrito R−S=0. Para ver por qué, observe que si
cada tupla en R está también en S, entonces seguramente R−S es vacío. A la inversa,
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 42 de 253
si R−S no contiene tuplas, entonces cada tupla en R debe estar en S (o de lo que
sería R−S).
Por otra parte, una restricción de la primera forma, R=0, también pudo haber sido
escrita como R⊂0. Técnicamente, 0 no es una expresión de algebra relacional, pero ya
que hay expresiones que evalúan a 0, tal como R−R, no hay nada malo en
usar 0 como una expresión de algebra relacional. Tenga en cuenta que estas
equivalencias sostienen se sostienen incluso si R y S son bolsas, dado que hacemos la
interpretación convencional de R⊂S: cada tupla t aparece en S al menos tantas veces
como aparece en R.
Ejercicios Propuestos
Ejercicio 1
Las relaciones base que forman la base de datos de un video club son las siguientes:
Socio(codsocio−−−−−−−,nombre,direccion,telefono): almacena los datos
de cada uno de los socios del video club: código del socio, nombre, dirección y
teléfono.
Pelicula(codpeli−−−−−−,titulo,genero): almacena información sobre cada
una de las películas de las cuales tiene copias el vídeo club: código de la
película, título y género (terror, comedia, etc.).
Cinta(codcinta−−−−−−−,codpeli): almacena información referente a las
copias que hay de cada película (copias distintas de una misma película tendrán
distinto código de cinta).
Prestamo(codsocio,codcinta,fecha−−−−−−−−−−−−−−−−−−,presdev):
almacena información de los préstamos que se han realizado. Cada préstamo es
de una cinta a un socio en una fecha. Si el préstamo aún no ha finalizado,
presdev tiene el valor ‘prestada’; si no su valor es ‘devuelta’.
ListaEspera(codsocio,codpeli−−−−−−−−−−−−,fecha): almacena
información sobre los socios que esperan a que haya copias disponibles de
películas, para tomarlas prestadas. Se guarda también la fecha en que comenzó
la espera para mantener el orden. Es importante tener en cuenta que cuando el
socio consigue la película esperada, éste desaparece de la lista de espera.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 43 de 253
En las relaciones anteriores, son claves primarias los atributos y grupos de atributos
que aparecen en negrita. Las claves ajenas se muestran en los siguientes diagramas
referenciales:
Resolver las siguientes consultas mediante el álgebra relacional (recuerde que en la
Lección 3 también se dieron algunos operadores de álgebra relacional):
1.1. Seleccionar todos los socios que se llaman: “Charles”.
Respuesta
σnombre='Charles'(Socio)
1.2. Seleccionar el código socio de todos los socios que se llaman: “Charles”.
Respuesta
πcodsocio(σnombre='Charles'(Socio))
1.3. Seleccionar los nombres de las películas que se encuentran en lista de espera.
Respuesta
πtitulo(Pelicula⊳⊲ListaEspera)
1.4. Obtener los nombres de los socios que esperan películas.
Respuesta
πnombre(Socio⊳⊲ListaEspera)
1.5. Obtener los nombres de los socios que tienen actualmente prestada una película
que ya tuvieron prestada con anterioridad.
Respuesta
πnombre({(Prestamo⊳⊲(presdev='prestada')Cinta)∩(Prestamo⊳⊲(presdev='devuelta')Cinta
)}⊳⊲Socio)
1.6. Obtener los títulos de las películas que nunca han sido prestadas.
Respuesta
πtitulo{(πcodpeliPelicula−πcodpeli(Prestamo⊳⊲Cinta))⊳⊲Pelicula}
(todas las películas) menos (las películas que han sido prestadas alguna vez)
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 44 de 253
1.7. Obtener los nombres de los socios que han tomado prestada la película “WALL*E”
alguna vez o que están esperando para tomarla prestada.
Respuesta
πnombre(σtitulo='WALL*E'(Socio⊳⊲Prestamo⊳⊲Cinta⊳⊲Pelicula)∪σtitulo='WALL*E'(
Socio⊳⊲ListaEspera⊳⊲Pelicula))
1.8. Obtener los nombres de los socios que han tomado prestada la película “WALL*E”
alguna vez y que además están en su lista de espera.
Respuesta
πnombre(σtitulo='WALL*E'(Socio⊳⊲Prestamo⊳⊲Cinta⊳⊲Pelicula)∩σtitulo='WALL*E'
(Socio⊳⊲ListaEspera⊳⊲Pelicula))
Ejercicio 2
Considere la base de datos con el siguiente esquema:
1. Persona(nombre−−−−−−, edad, genero) : nombre es la clave.
2. Frecuenta(nombre, pizzeria−−−−−−−−−−−−−) : (nombre, pizzeria)
es la clave.
3. Come(nombre, pizza−−−−−−−−−−−) : (name, pizza) es la clave.
4. Sirve(pizzeria, pizza−−−−−−−−−−−, precio): (pizzeria, pizza) es la
clave.
Escribir las expresiones de álgebra relacional para las siguientes nueve consultas.
(Precaución: algunas de las siguientes consultas son un poco desafiantes).
Encuentre todas las pizzerías frecuentadas por al menos una persona
menor de 18 años.
Encuentre los nombres de todas las mujeres que comen pizza ya sea con
champiñones o salchichón (o ambas).
Encuentre los nombres de todas las mujeres que comen pizzas con los
dos ingredientes, champiñones y salchichón.
Encuentre todas las pizzerías que sirven al menos una pizza que Amy
come por menos de 10 dólares.
Encuentre todas las pizzerías que son frecuentadas por solo mujeres o
solo hombres.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 45 de 253
Para cada persona, encuentre todas las pizzas que la persona come, que
no son servidas por ninguna pizzería que la persona frecuenta. Devuelve
toda dicha persona (nombre)/ pizza pares.
Encuentre los nombres de todas las personas que frecuentan solo
pizzerías que sirven al menos una pizza que ellos comen.
Encuentre la pizzería que sirve la pizza más barata de salchichón. En el
caso de empate, vuelve todas las pizzerías que venden las pizzas de
salchichón más baratas.
Lección V – Introducción al Lenguaje SQL
SQL (Lenguaje de consulta estructurado) es un tipo de lenguaje vinculado con la gestión
de bases de datos de carácter relacional que permite la especificación de distintas
clases de operaciones. Gracias a la utilización del álgebra y de cálculo relacional, el
lenguaje SQL brinda la posibilidad de realizar consultas que ayuden a recuperar
información de las bases de datos de manera sencilla.
Características
Algunas de las características de este lenguaje son:
Compatible con todos los sistemas de bases de datos comerciales importantes.
Estandarizada - nuevas características en el tiempo.
Interactiva a través de interfaz gráfica de usuario o del sistema.
Declarativa, basada en álgebra relacional.
Lenguaje de descripción de datos (DDL)
DDL (Lenguaje de descripción de datos) es un lenguaje que permite definir la base de
datos (su estructura o “schemas”), tiene una sintaxis similar a los lenguajes de
programación.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 46 de 253
Ejemplos de DDL:
CREATE TABLE nombre_tabla; DROP TABLE nombre_tabla; ALTER TABLE nombre_tabla ADD id INTEGER;
Descripción de los comandos
CREATE:
Para crear una nueva base de datos, índice o almacenamiento de consultas.
Un argumento CREATE en SQL crea un objeto dentro del sistema de
administración de la base de datos relacional (RDBMS).
El tipo de objetos que se pueden crear depende de qué RDBMS esta siendo
utilizado, pero la mayoría soporta la creación de tablas, índices, usuarios y bases
de datos.
Algunos sistemas (tales como PostgreSQL) permiten CREATE y otros comandos
DDL, dentro de transacciones, y por lo tanto pueden ser revertidos
DROP:
Para destruir una base de datos, tabla, índice o vista existente.
Un argumento DROP en SQL remueve un objeto dentro del sistema de
administración de la base de datos relacional (RDBMS).
El tipo de objetos que se pueden eliminar depende de que RDBMS esta siendo
utilizado, pero la mayoría soporta la eliminación de tablas, índices, usuarios y
bases de datos.
Algunos sistemas (tales como PostgreSQL) permiten DROP y otros comandos
DDL, dentro de transacciones, y por lo tanto pueden ser revertidos
ALTER:
Se utiliza para modificar la estructura de la tabla, como en los casos siguientes:
o Añadir una columna
o Eliminar una columna
o Cambiar el nombre de una columna
o Cambiar el tipo de datos para una columna
Lenguaje de manipulación de datos (DML)
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 47 de 253
DML (Lenguaje de manipulación de datos) se refiere a los comandos que permiten a un
usuario manipular los datos de las tablas, es decir, consultar tablas, añadir filas, borrar
filas y actualizar columnas.
Ejemplos de DML
SELECT atributo FROM nombre_tabla; INSERT INTO nombre_tabla(atributo_1,...,atributo_n) VALUES (dato_1,...,dato_n); DELETE FROM nombre_tabla WHERE condicion; UPDATE nombre_tabla SET atributo = nuevo dato WHERE condicion;
Descripción de comandos
SELECT
Devuelve el resultado de un conjunto de registros de una o mas tablas.
Un argumento SELECT devuelve cero o más filas de una o más tablas de una base
de datos o vistas de base de datos.
En la mayoría de las aplicaciones SELECT es el comando DML mas usado.
Como SQL es un lenguaje de programación declarativo,
consultas SELECT especifican el conjunto de resultado, pero no como calcularlo.
La base de datos traduce la consulta a un “plan de consulta”, que puede variar
dependiendo de la ejecución, la versión de la base de datos y el software de
base de datos.
Esta funcionalidad es llamada “optimizador de consulta”, puesto que es
responsable de buscar el mejor plan de ejecución para la consulta, tomando en
cuenta las restricciones aplicables.
Instrucción SELECT básica
SELECT A1, ..., An FROM R1, ..., Rm WHERE condición
Significado:
SELECT A1,…,An: Atributos que retorna
FROM R1,…,Rm: relaciones o tablas
WHERE condición: combinar, filtrar
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 48 de 253
Lo que busca esta consulta es mostrar las columnas A1,…,An de las tablas o
relaciones R1,…,Rm, siguiendo alguna condición.
Álgebra relacional:
πA1,…,An(σcondición(R1×…×Rm))
Comandos SQL:
INSERT - agrega uno o más registros a una tabla de una base de datos
relacional.
DELETE - elimina uno o más registros de una tabla. Un subconjunto de datos
puede ser eliminado si existe una condición, de lo contrario todos los registros
serán eliminados.
UPDATE - cambia los datos de uno o más registros de una tabla. Una fila o un
subconjunto de filas puede ser actualizadas utilizando una condición.
Ejemplo práctico
Nota
Para realizar estos ejercicios, debe utilizar Postgresql mediante la conexión ssh o también
puede instalarlo en su computador.
Si tiene un sistema Linux puede utilizar el gestor de paquetes del sistema operativo.
Para usuarios que utilicen Debian / Ubuntu pueden ejecutar el siguiente comando
como root:
sudo apt-get install postgresql postgresql-client postgresql-contrib libpq-dev
Para usuarios que utilicen Red Hat/Scientific Linux/Fedora/CentOS
yum -y install postgresql postgresql-libs postgresql-contrib postgresql-server postgresql-docs
Después que finalice el proceso de instalación, es necesario ingresar al entorno ** psql **
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 49 de 253
Para usuarios que utilicen Debian / Ubuntu pueden ejecutar el siguiente comando
como root
sudo su postgres -c psql
Para usuarios que utilicen Red Hat/Scientific Linux/Fedora/CentOS
Iniciar el servicio. Debería decir OK si todo esta correcto
service postgresql start
Cambiamos la contraseña del usuario Postgresql
passwd postgres
Ejecutar Postgresql (ingresar la contraseña que cambiamos anteriormente)
su postgres
Comenzamos el servicio
/etc/init.d/postgresql start
Debe aparecer el mensaje “bash-4.1 $”, ahora ingresamos a Postgresql ingresando
psql
Primero que todo debemos crear una base de datos para comenzar nuestros ejercicios.
La llamaremos example:
postgres=# create database example; CREATE DATABASE
Luego de haber creado nuestra base de datos, necesitamos ingresar a ella para
comenzar a realizar las distintas operaciones:
postgres=# \c example psql (8.4.14) Ahora está conectado a la base de datos «example».
Ahora comenzamos a crear una tabla llamada cliente con las variables id que se define
como serial en que al ir agregando datos se autoincrementará automáticamente en la
base de datos example:
example=# CREATE TABLE cliente (id SERIAL, nombre VARCHAR(50), apellido VARCHAR(50), edad INTEGER, direccion VARCHAR(50), pais VARCHAR(25));
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 50 de 253
Y recibiremos el siguiente mensaje:
NOTICE: CREATE TABLE creará una secuencia implícita «cliente_id_seq» para la columna serial «cliente.id» CREATE TABLE
Para agregar datos a la tabla cliente se realiza de la siguiente manera:
example=# INSERT INTO cliente (nombre,apellido,edad,direccion,pais) VALUES ('John', 'Smith', 35, '7635 N La Cholla Blvd', 'EEUU'); INSERT 0 1
Agregar más datos a la tabla cliente
example=# INSERT INTO cliente (nombre,apellido,edad,direccion,pais) VALUES ('John', 'Smith', 35, '7635 N La Cholla Blvd', 'EEUU'); INSERT 0 1 example=# INSERT INTO cliente (nombre,apellido,edad,direccion,pais) VALUES ('Judith', 'Ford', 20, '3901 W Ina Rd', 'Inglaterra'); INSERT 0 1 example=# INSERT INTO cliente (nombre,apellido,edad,direccion,pais) VALUES ('Sergio', 'Honores', 35, '1256 San Luis', 'Chile'); INSERT 0 1 example=# INSERT INTO cliente (nombre,apellido,edad,direccion,pais) VALUES ('Ana', 'Caprile', 25, '3456 Matta', 'Chile'); INSERT 0 1
Seleccionar todos los datos de la tabla cliente
example=# SELECT * FROM cliente; id | nombre | apellido | edad | direccion | pais ---+--------+----------+------+-----------------------+------------ 1 | John | Smith | 35 | 7635 N La Cholla Blvd | EEUU 2 | John | Smith | 35 | 7635 N La Cholla Blvd | EEUU 3 | Judith | Ford | 20 | 3901 W Ina Rd | Inglaterra 4 | Sergio | Honores | 35 | 1256 San Luis | Chile 5 | Ana | Caprile | 25 | 3456 Matta | Chile (5 rows)
Nota
El asterisco (*) que está entre el SELECT y el FROM significa que se seleccionan todas las
columnas de la tabla.
Si deseamos seleccionar la columna nombre con apellido la consulta debería ser
SELECT nombre, apellido FROM cliente;
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 51 de 253
Como cometimos el error de agregar en la segunda fila datos repetidos, pero se
puede eliminar de la siguiente manera
example=# DELETE FROM cliente WHERE id=2; DELETE 1
Verificamos que se haya eliminado
example=# SELECT * FROM cliente; id | nombre | apellido | edad | direccion | pais ---+--------+----------+------+-----------------------+------------ 1 | John | Smith | 35 | 7635 N La Cholla Blvd | EEUU 3 | Judith | Ford | 20 | 3901 W Ina Rd | Inglaterra 4 | Sergio | Honores | 35 | 1256 San Luis | Chile 5 | Ana | Caprile | 25 | 3456 Matta | Chile (4 rows)
Si se desea actualizar la dirección del cliente Sergio de la tabla cliente
example=# UPDATE cliente SET direccion='1459 Patricio Lynch' WHERE id=4; UPDATE 1
Se puede seleccionar la tabla cliente para verificar que se haya actualizado la
información
example=# SELECT * FROM cliente; id | nombre | apellido | edad | direccion | pais ---+--------+----------+------+-----------------------+------------ 1 | John | Smith | 35 | 7635 N La Cholla Blvd | EEUU 3 | Judith | Ford | 20 | 3901 W Ina Rd | Inglaterra 5 | Ana | Caprile | 25 | 3456 Matta | Chile 4 | Sergio | Honores | 35 | 1459 Patricio Lynch | Chile (4 rows)
Para borrar la tabla cliente
example=# DROP TABLE cliente; DROP TABLE
Seleccionamos la tabla cliente, para verificar que se haya eliminado
example=# SELECT * FROM cliente;
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 52 de 253
Recibiremos el siguiente mensaje:
ERROR: no existe la relación «cliente» LÍNEA 1: SELECT * FROM cliente; ^
Clave Primaria y Foránea
En las bases de datos relacionales, se le llama clave primaria a un campo o a una
combinación de campos que identifica de forma única a cada fila de una tabla. Por lo
que no pueden existir dos filas en una tabla que tengan la misma clave primaria.
Y las claves foráneas tienen por objetivo establecer una conexión con la clave primaria
que referencia de otra tabla, creándose una asociación entre las dos tablas.
Ejemplo Práctico
Primero crearemos la tabla profesores en que ID_profesor será la clave primaria y está
definido como serial que automáticamente irá ingresando los valores 1, 2, 3 a cada
registro.
postgres=# CREATE TABLE profesores(ID_profesor serial, nombre VARCHAR(30), apellido VARCHAR(30), PRIMARY KEY(ID_profesor));
Recibiremos el siguiente mensaje:
NOTICE: CREATE TABLE creará una secuencia implícita «profesores_id_profesor_seq» para la columna serial «profesores.id_profesor» NOTICE: CREATE TABLE / PRIMARY KEY creará el índice implícito «profesores_pkey» para la tabla «profesores» CREATE TABLE
Ahora vamos a crear la tabla de cursos en que ID_curso será la clave primaria de esta
tabla y ID_profesor será la clave foránea, que se encargará de realizar una conexión
entre estas dos tablas.
postgres=# CREATE TABLE cursos(ID_curso serial, titulo VARCHAR(30), ID_profesor INTEGER, PRIMARY KEY(ID_curso), FOREIGN KEY(ID_profesor) REFERENCES profesores(ID_profesor));
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 53 de 253
Recibiremos el siguiente mensaje:
NOTICE: CREATE TABLE creará una secuencia implícita «cursos_id_curso_seq» para la columna serial «cursos.id_curso» NOTICE: CREATE TABLE / PRIMARY KEY creará el índice implícito «cursos_pkey» para la tabla «cursos» CREATE TABLE
Se insertarán algunos datos para poder realizar una selección y poder visualizar el
funcionamiento de la clave primaria y foránea
postgres=# INSERT INTO profesores(nombre, apellido) VALUES('Alfred','JOHNSON'); INSERT 0 1 postgres=# INSERT INTO profesores(nombre, apellido) VALUES('Alisson','DAVIS'); INSERT 0 1 postgres=# INSERT INTO profesores(nombre, apellido) VALUES('Bob','MILLER'); INSERT 0 1 postgres=# INSERT INTO profesores(nombre, apellido) VALUES('Betty','WILSON'); INSERT 0 1 postgres=# INSERT INTO profesores(nombre, apellido) VALUES('Christin','JONES'); INSERT 0 1 postgres=# INSERT INTO profesores(nombre, apellido) VALUES('Edison','SMITH'); INSERT 0 1
Quedando la tabla de la siguiente manera si seleccionamos todas las columnas.
postgres=# SELECT * FROM profesores; id_profesor | nombre | apellido -------------+----------+---------- 1 | Alfred | JOHNSON 2 | Alisson | DAVIS 3 | Bob | MILLER 4 | Betty | WILSON 5 | Christin | JONES 6 | Edison | SMITH (6 rows)
Nota
Como se puede ver en la tabla de profesores, el “id_profesor” que lo definimos como tipo
de dato serial se autoincremento automáticamente sin necesidad de ingresarlo nosotros,
además se definió como una clave primaria.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 54 de 253
Ahora insertamos los datos de la tabla cursos.
postgres=# INSERT INTO cursos(titulo, ID_profesor) VALUES('Base de datos',2); INSERT 0 1 postgres=# INSERT INTO cursos(titulo, ID_profesor) VALUES('Estructura de datos',5); INSERT 0 1 postgres=# INSERT INTO cursos(titulo, ID_profesor) VALUES('Arquitectura de computadores',1); INSERT 0 1 postgres=# INSERT INTO cursos(titulo, ID_profesor) VALUES('Recuperacion de informacion',3); INSERT 0 1 postgres=# INSERT INTO cursos(titulo, ID_profesor) VALUES('Teoria de sistemas',4); INSERT 0 1 postgres=# INSERT INTO cursos(titulo, ID_profesor) VALUES('Sistemas de informacion',6); INSERT 0 1
Quedando la tabla de siguiente manera.
postgres=# SELECT * FROM cursos; id_curso | titulo | id_profesor ----------+------------------------------+------------- 1 | Base de datos | 2 2 | Estructura de datos | 5 3 | Arquitectura de computadores | 1 4 | Recuperacion de informacion | 3 5 | Teoria de sistemas | 4 6 | Sistemas de informacion | 6 (6 rows)
Nota
Un profesor puede tener asignado más de un curso, no existe restricción.
Ahora queremos tener solo una tabla con el “nombre”, “apellido” del profesor y el
“titulo” de la asignatura que dicta. Para esto realizamos una selección de la siguiente
manera:
postgres=# SELECT nombre, apellido, titulo FROM profesores, cursos WHERE profesores.id_profesor=cursos.id_profesor; nombre | apellido | titulo ----------+----------+------------------------------ Alisson | DAVIS | Base de datos Christin | JONES | Estructura de datos Alfred | JOHNSON | Arquitectura de computadores Bob | MILLER | Recuperacion de informacion Betty | WILSON | Teoria de sistemas
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 55 de 253
Edison | SMITH | Sistemas de informacion (6 rows)
Aquí es donde tiene la importancia la clave primaria y foránea, puesto que en la
condición podemos realizar una igualdad entre los “id_profesor” de la
tabla profesores y cursos.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 56 de 253
Lección VI - Tipo de Datos
Descripción
En SQL se tienen varios tipos de datos. Cuando creamos una tabla con la instrucción
create table, tenemos que especificar el tipo de dato de cada columna. [1]
1. Cadenas de caracteres de largo fijo y variable: Un atributo de una tabla de
tipo CHAR(n) denota una cadena de longitud fija de n carácteres. Es decir, si un
atributo es de tipo CHAR(n), entonces en cualquier tupla el componente para
este atributo será una cadena de n caracteres. VARCHAR(n) denota una cadena de
hasta n caracteres.
2. Cadenas de bits de longitud fija o variable: Estas cadenas son análogas a las
cadenas de caracteres fijos y variables de longitud, pero sus valores son cadenas
de bits en lugar de carácteres. El tipo BIT(n) denota cadenas de bits de longitud
n y BIT VARYING (n) es una cadena de bits de longitud variable.
3. Tipo de dato booleanos: BOOL denota un atributo cuyo valor es lógico. Los
valores posibles de este tipo de atributo son TRUE, FALSE, y ANTONIANA.
4. Tipo de dato entero: INTEGER denota típicos valores enteros. El
tipo SMALLINT también denota números enteros, pero el número de bits
permitidos puede ser menor.
5. Tipo de dato flotante: Podemos utilizar el tipo FLOAT para los típicos números
de punto flotante.
6. Tipo de dato Fecha/Hora: Pueden ser representados por DATE y TIME. Estos
valores son esencialmente cadenas de carácteres de una forma especial. Además
existe un tipo de dato llamado TIMESTAMP. El formato que deben tener se
muestra en la siguiente tabla:
TipoDATETIMESTAMPTIMEDescripciónFecha ANSI SQL "aaaa-mm-
dd".Fecha y hora "aaaa-mm-dd hh:mm:ss".Hora ANSI SQL "hh:mm:ss".
Ejemplo práctico
A continuación se mostrarán ejemplos realizados con PostgreSQL de los tipos de datos
nombrados anteriormente.
Este ejemplo trata del juego adivina quién donde se realizan preguntas como: tu
personaje tiene gafas, es rubio, es alto. La tabla queda de la siguiente manera
utilizando los valores booleanos para crear las tablas:
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 57 de 253
postgres=# CREATE TABLE Adivina_quien(Personaje VARCHAR(30), GAFAS BOOL, RUBIO BOOL, ALTO BOOL);
CREATE TABLE
postgres=# INSERT INTO Adivina_quien(Personaje,GAFAS,RUBIO,ALTO) VALUES('Tomas',true,false,true);
INSERT 0 1
postgres=# SELECT*FROM Adivina_quien;
personaje | gafas | rubio | alto
-----------+-------+-------+------
Tomas | t | f | t
(1 fila)
Se mostrará a continuación un ejemplo en que se utilicen los tipos de
datos VARCHAR, CHAR y DATETIME.
Creamos la tabla persona con el id de tipo serial, nombre y apellido de
tipo VARCHAR con un largo variable hasta 25 carácteres, genero de
tipo CHAR con solo un carácter y la fecha de nacimiento que es un tipo de
dato DATETIME.
postgres=# CREATE TABLE persona(id serial, nombre VARCHAR(25), apellido VARCHAR(25), genero CHAR(1), fecha_nac DATE);
Retornando lo siguiente PostgreSQL
NOTICE: CREATE TABLE creará una secuencia implícita «persona_id_seq» para la columna serial «persona.id» CREATE TABLE
Ahora ingresamos los datos de una persona:
postgres=# INSERT INTO persona(nombre,apellido,genero,fecha_nac) VALUES('Paul','Anderson','M','1983-02-12'); INSERT 0 1
Finalmente seleccionamos la tabla para ver los datos que se ingresaron:
postgres=# SELECT * FROM persona; id | nombre | apellido | genero | fecha_nac ----+--------+----------+--------+------------ 1 | Paul | Anderson | M | 1983-02-12 (1 fila)
Supongamos que en el siguiente ejemplo un alumno está registrando las notas
de sus ramos de la universidad en una tabla llamada notas, ingresando el
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 58 de 253
nombre del ramo como VARCHAR de un largo de 30 carácteres, nota_1 y nota_2
del tipo INTEGER y finalmente su promedio de notas que es del tipo FLOAT.
postgres=# CREATE TABLE notas(id serial, ramo VARCHAR(30), nota_1 INTEGER, nota_2 INTEGER, promedio FLOAT);
Retornando PostgreSQL
NOTICE: CREATE TABLE creará una secuencia implícita «notas_id_seq» para la columna serial «notas.id» CREATE TABLE
Ingresando datos
postgres=# INSERT INTO notas(ramo,nota_1,nota_2,promedio) VALUES('Base de datos', 57, 36, 46.5); INSERT 0 1
Advertencia
Para ingresar un dato tipo FLOAT, el valor no lleva una “coma”, sino que un “punto”
Ahora se realizará el siguiente ejemplo en el que se creará la
tabla test_datatype con los tipos de datos BIT(n) y BIT VARYING(n). Que en este
caso será data1 con un largo fijo de 4 y data2 con un largo variable de 6.
postgres=# CREATE TABLE test_datatype_bit(data1 BIT(4), data2 BIT VARYING(6));
CREATE TABLE
Se ingresarán los datos de la siguiente manera.
postgres=# INSERT INTO test_datatype_bit(data1,data2) VALUES(B'1010',B'10110'); INSERT 0 1 postgres=# INSERT INTO test_datatype_bit(data1,data2) VALUES(B'1011',B'101101'); INSERT 0 1
Los siguientes datos ingresador retornaron un error puesto que no cumplen con
el largo fijo y variable definido en la creación de la tabla test_datatype_bit
postgres=# INSERT INTO test_datatype_bit(data1,data2) VALUES(B'101',B'10110'); ERROR: el largo de la cadena de bits 3 no coincide con el tipo bit(4)
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 59 de 253
postgres=# INSERT INTO test_datatype_bit(data1,data2) VALUES(B'1011',B'1011011'); ERROR: la cadena de bits es demasiado larga para el tipo bit varying(6)
En este ejemplo se utilizará el tipo de dato SMALLINT y TIMESTAMP. Se mostrará
una tabla en que quedará registrado el ingreso de los trabajadores a la empresa.
postgres=# CREATE TABLE registro(id_registro serial, nombre VARCHAR(30), apellido VARCHAR(30), ingreso TIMESTAMP, anos_trabajados SMALLINT);
Retornando lo siguiente
NOTICE: CREATE TABLE creará una secuencia implícita «registro_id_registro_seq» para la columna serial «registro.id_registro» CREATE TABLE
Ingresamos los datos del registro de la siguiente manera.
postgres=# INSERT INTO registro(nombre,apellido,ingreso,anos_trabajados) VALUES('Elliott', 'ALLEN', '2012-10-23 14:05:08', 13); INSERT 0 1
Ahora realizamos una selección de la tabla registro para verificar como
quedaron los datos que ingresamos.
postgres=# SELECT * FROM registro; id_registro | nombre | apellido | ingreso | anos_trabajados -------------+---------+----------+---------------------+----------------- 1 | Elliott | ALLEN | 2012-10-23 14:05:08 | 13 (1 fila)
Nota
La diferencia entre INTEGER y SMALLINT no se puede notar en este tipo de
ejemplos, pero INTEGER soporta -2147483648 a +2147483647 y SMALLINT -
32768 a +32767.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 60 de 253
Tipo de Dato Serial
En el siguiente ejemplo un alumno está registrando las notas de sus ramos de la
universidad en una tabla llamada notas, ingresando el nombre del ramo
como VARCHAR de un largo de 30 carácteres, nota_1 y nota_2 del tipo INTEGER
y finalmente su promedio de notas que es del tipo FLOAT.
El id, es de tipo serial, es decir es un numero entero que tiene una secuencia
asociada. Al crear la tabla notas e indicar que el campo id es serial, se crea de
forma implícita una secuencia asociada al campo id.
postgres=# CREATE TABLE notas(id serial, ramo VARCHAR(30), nota_1 INTEGER, nota_2 INTEGER, promedio FLOAT);
Retornando PostgreSQL
NOTICE: CREATE TABLE creará una secuencia implícita «notas_id_seq» para la columna serial «notas.id» CREATE TABLE
Ingresando datos
postgres=# INSERT INTO notas(ramo,nota_1,nota_2,promedio) VALUES('Base de datos', 57, 36, 46.5); INSERT 0 1
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 61 de 253
Lección VII – Sentencia SELECT Básica
Corresponde a la forma más simple de hacer una consulta en SQL, la cual sirve para
preguntar por aquellas tuplas de una relación que satisfagan una condición. Es análoga
a la selección en álgebra relacional. Esta consulta, al igual que la mayoría de las
realizadas en este lenguaje de programación, utiliza 3 palabras clave: SELECT - FROM -
WHERE.
En palabras simples, lo que se busca con esta consulta es seleccionar cierta información
(SELECT) de alguna tabla (FROM) que satisfaga (WHERE) ciertas condiciones. Por ejemplo:
Obtener los nombres de los alumnos que hayan nacido en el mes de Noviembre SELECT "los nombres" FROM "alumnos" WHERE "hayan nacido en el mes de Noviembre"
Cabe destacar que en este ejemplo, se infiere la existencia de una tabla de
nombre alumnos que alberga datos personales de ciertos estudiantes.
Desde el Álgebra Relacional
El operador de selección en el Álgebra relacional hace uso de la palabra clave WHERE.
Por lo general, las expresiones que siguen a esta keyword incluyen expresiones
condicionales. Podemos construir expresiones mediante la comparación de valores
(como por ejemplo tipos de datos enteros, cadenas de caracteres, etc) utilizando los 6
operadores más comunes de comparación:
= “igual a”
<> “distinto a” o “no igual a”
< “menor que”
> “mayor que”
<= “menor o igual a”
>= “mayor o igual a”
Estos operadores tienen el mismo significado que en el lenguaje C, siendo el único
diferente el símbolo “<>” que corresponde a “distinto a”; el lenguaje C utiliza el
símbolo ”!=” para este comparador. Siguiendo la comparación entre estos lenguajes, el
símbolo de igualdad en SQL corresponde a “=”, mientras que en C es “==”.
Estos valores pueden ser comparados incluyendo constantes y atributos de las
relaciones nombradas después de la palabra clave FROM. En el ejemplo, correspondería
al atributo del mes de nacimiento del individuo con el mes de Noviembre.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 62 de 253
Algunos ejemplos de comparación:
StudioName = 'Ubisoft' : se compara que el atributo studioName sea 'Ubisoft' mesesVidaUtil <> 5 : se compara que el atributo mesesVidaUtil no sea igual a 5 mesNacimiento = 'Noviembre': se compara que el atributo mesNacimiento sea igual a 'Noviembre'
SELECT-FROM-WHERE
Trabajemos bajo el siguiente ejemplo, el cual consiste en seleccionar toda la
información de la relación (o tabla) Empleados cuyos atributos departamento sea
‘Informatica’ y que su atributo ano_ingreso sea mayor o igual al año 2005.
Para comenzar a realizar este ejemplo, primero debemos crear la tabla Empleados de la
siguiente manera.
postgres=# CREATE TABLE Empleados(id_empleado serial, nombre_empleado VARCHAR(30), departamento VARCHAR(30), ano_ingreso INTEGER);
retornando lo siguiente PostgreSQL.:
NOTICE: CREATE TABLE creará una secuencia implícita «empleados_id_empleado_seq» para la columna serial «empleados.id_empleado» CREATE TABLE
Ahora insertaremos algunos datos en la tabla Empleados.
postgres=# INSERT INTO Empleados(nombre_empleado, departamento, ano_ingreso) VALUES('Edgar', 'Administracion', 2000); INSERT 0 1 postgres=# INSERT INTO Empleados(nombre_empleado, departamento, ano_ingreso) VALUES('Andrew', 'Comercial', 2009); INSERT 0 1 postgres=# INSERT INTO Empleados(nombre_empleado, departamento, ano_ingreso) VALUES('Valerie', 'Informatica', 2000); INSERT 0 1 postgres=# INSERT INTO Empleados(nombre_empleado, departamento, ano_ingreso) VALUES('Karl', 'Informatica', 2008); INSERT 0 1 postgres=# INSERT INTO Empleados(nombre_empleado, departamento, ano_ingreso) VALUES('Kevin', 'Finanzas', 2010); INSERT 0 1
Finalmente podemos realizar la consulta que nos interesa.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 63 de 253
postgres=# SELECT * FROM Empleados WHERE departamento='Informatica' AND ano_ingreso>=2005; id_empleado | nombre_empleado | departamento | ano_ingreso -------------+-----------------+--------------+------------- 4 | Karl | Informatica | 2008 (1 fila)
Nota
Podemos notar que la consulta retorna el registro que se cumplian las dos condiciones.
Podemos realizar la siguiente consulta, encontrar en la tabla Empleados el registro de
la(s) personas que sean del departamento de ‘Informática’ o que su año de ingreso sea
mayor o igual al año 2005.
postgres=# SELECT * FROM Empleados WHERE departamento='Informatica' OR ano_ingreso>=2005; id_empleado | nombre_empleado | departamento | ano_ingreso -------------+-----------------+--------------+------------- 2 | Andrew | Comercial | 2009 3 | Valerie | Informatica | 2000 4 | Karl | Informatica | 2008 5 | Kevin | Finanzas | 2010 (4 filas)
Nota
Podemos observar que la consulta realizada retorna los registros que cumplen con una de
las dos condiciones o cuando se cumplen las dos al mismo tiempo.
Esta consulta presentó un ejemplo básico de una consulta SELECT - FROM - WHERE de la
mayoría de las consultas SQL. La palabra claveFROM selecciona la relación o relaciones
de donde se obtiene la información (tablas). En estos ejemplos, se utilizaron dos
comparaciones unidas por la condición “AND” y “OR”.
El atributo departamento de la tabla Empleados es probada por igualdad contra la
constante ‘Informática’. Esta constante corresponde a una cadena de caracteres de
largo variable que en SQL como se detalló en la Lección anterior se denomina como
VARCHAR(n) y que al momento del ingreso de los datos a las tablas se escribe entre
comillas simples.
Como se mencionó anteriormente, la consulta del tipo SELECT - FROM - WHERE busca la
información de una o más relaciones que cumplan con ciertas condiciones. Hasta ahora
sólo se ha visto qué pasa si se comparan atributos de las relaciones con constantes.
Pero ¿cómo se pueden comparar los valores almacenados de atributos que están en
varias relaciones?.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 64 de 253
El ejemplo anterior se podría realizar de otra manera para poder combinar dos
relaciones (tablas) a la hora de realizar la consulta, pero primero debemos realizar
la creación de la tabla Empleados y Departamentos.
Advertencia
Antes de realizar la creación de las tablas, hay que borrar la tabla Empleados con
un DROP TABLE Empleados.
Para poder realizar el ejemplo debemos crear la tabla de Departamentos.
postgres=# CREATE TABLE Departamentos(id_departamento serial, departamento VARCHAR(30), PRIMARY KEY(id_departamento));
retornando PostgreSQL que la tabla Departamentos ha sido correctamente creada.:
NOTICE: CREATE TABLE creará una secuencia implícita «departamentos_id_departamento_seq» para la columna serial «departamentos.id_departamento» NOTICE: CREATE TABLE / PRIMARY KEY creará el índice implícito «departamentos_pkey» para la tabla «departamentos» CREATE TABLE
Y ahora creamos la tabla Empleados.
postgres=# CREATE TABLE Empleados(id_empleados serial, nombre_empleado VARCHAR(30), id_departamento INTEGER, ano_ingreso INTEGER, PRIMARY KEY(id_empleados), FOREIGN KEY(id_departamento) REFERENCES Departamentos(id_departamento));
Retornando PostgreSQL que la tabla Empleados ha sido correctamente creada.:
NOTICE: CREATE TABLE creará una secuencia implícita «empleados_id_empleados_seq» para la columna serial «empleados.id_empleados» NOTICE: CREATE TABLE / PRIMARY KEY creará el índice implícito «empleados_pkey» para la tabla «empleados» CREATE TABLE
Ahora debemos ingresar los datos en la tabla Departamentos y Empleados.
postgres=# INSERT INTO Departamentos(departamento) VALUES('Administracion'); INSERT 0 1 postgres=# INSERT INTO Departamentos(departamento) VALUES('Informatica'); INSERT 0 1 postgres=# INSERT INTO Departamentos(departamento) VALUES('Finanzas'); INSERT 0 1 postgres=# INSERT INTO Departamentos(departamento) VALUES('Comercial'); INSERT 0 1
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 65 de 253
postgres=# INSERT INTO Empleados(nombre_empleado, id_departamento, ano_ingreso) VALUES('Edgar', 1, 2000); INSERT 0 1 postgres=# INSERT INTO Empleados(nombre_empleado, id_departamento, ano_ingreso) VALUES('Andrew', 4, 2009); INSERT 0 1 postgres=# INSERT INTO Empleados(nombre_empleado, id_departamento, ano_ingreso) VALUES('Valerie', 2, 2000); INSERT 0 1 postgres=# INSERT INTO Empleados(nombre_empleado, id_departamento, ano_ingreso) VALUES('Karl', 2, 2008); INSERT 0 1 postgres=# INSERT INTO Empleados(nombre_empleado, id_departamento, ano_ingreso) VALUES('Kevin', 3, 2010); INSERT 0 1
Ahora realizamos la siguiente consulta, encontrar en la tabla Empleados el registro de
la(s) personas que sean del departamento de ‘Informatica’ y que su año de ingreso sea
mayor o igual al año 2005.
postgres=# SELECT * FROM Empleados, Departamentos WHERE Empleados.id_departamento=Departamentos.id_departamento AND Empleados.ano_ingreso>=2005 AND Departamentos.departamento='Informatica'; id_empleados | nombre_empleado | id_departamento | ano_ingreso | id_departamento | departamento --------------+-----------------+-----------------+-------------+-----------------+-------------- 4 | Karl | 2 | 2008 | 2 | Informatica (1 fila)
Nota
Es posible dar referencia a un atributo de cada tabla con nombre_tabla.atributo, para
realizar las condiciones.
Independientemente del tipo de consulta, el resultado de una comparación es un valor
booleano, es decir retorna valores TRUE o FALSE, los cuales se pueden combinar con
sus operadores AND, OR y NOT, con sus respectivos significados.
A modo de repaso, los operadores lógicos mencionados son:
AND: Retorna TRUE siempre y cuando TODOS los atributos a comparar
sean TRUE. Si hay AL MENOS UN valor FALSE, retornará FALSE.
Su tabla de verdad es:
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 66 de 253
PTrueTrueFalseFalseQTrueFalseTrueFalseANDTrueFalseFal
seFalse
OR: Retorna TRUE siempre y cuando AL MENOS UNO de los atributos a
comparar sea TRUE. Si TODOS los valores son FALSE, retornará FALSE.
Su tabla de verdad es:
PTrueTrueFalseFalseQTrueFalseTrueFalseORTrueTrueTrue
False
NOT: Retorna el valor cont
rario al valor actual, es decir que si el valor es TRUE, retorna FALSE y vice
versa.
Su tabla de verdad es
PTrueFalseNOT PFalseTrue
Nota
SQL no distingue entre mayúsculas y minúsculas. Por ejemplo, FROM (palabra reservada) es
equivalente a from, inclusive a From. Para los nombres de atributos, relaciones, etc., también
ocurre lo mismo. El único caso en que se distingue entre mayúsculas y minúsculas es al
momento de encerrar un string entre ‘ ‘. Por ejemplo ‘PALABRA’ es diferente a ‘palabra’.
Resultados Repetidos
Al realizar una consulta SELECT, no hay omisión de resultados repetidos, este
“problema” se soluciona agregando DISTINCT a la consulta.
SELECT FROM WHERE SELECT DISTINCT FROM WHERE
En el ejemplo anterior también es posible eliminar los resultados repetidos, puesto que
existen muchas personas que trabajan en el mismo departamento, pero si eliminamos
las repeticiones solo nos retornaran los departamentos que existen.
Primero mostraremos un resultado con una consulta con repeticiones.
postgres=# SELECT Departamentos.departamento, Empleados.id_departamento FROM Empleados, Departamentos WHERE
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 67 de 253
Empleados.id_departamento=Departamentos.id_departamento; departamento | id_departamento ----------------+----------------- Administracion | 1 Comercial | 4 Informatica | 2 Informatica | 2 Finanzas | 3 (5 filas)
Nota
Según los datos que se ingresaron en la tabla Empleados existe más de una persona en el
departamento de ‘Informática’.
Y ahora realizamos una consulta sin repeticiones.
postgres=# SELECT DISTINCT Departamentos.departamento, Empleados.id_departamento FROM Empleados, Departamentos WHERE Empleados.id_departamento=Departamentos.id_departamento; departamento | id_departamento ----------------+----------------- Administracion | 1 Informatica | 2 Comercial | 4 Finanzas | 3 (4 filas)
Nota
Se puede notar que solo nos retorna los departamentos que existen.
SELECT-BY-ORDER
Hasta este momento, es posible obtener datos de una tabla utilizando los comandos
SELECT y WHERE. Sin embargo, muchas veces es necesario enumerar el resultado en un
orden particular. Esto podría ser en orden ascendente, en orden descendente, o podría
basarse en valores numéricos o de texto. En tales casos, podemos utilizar la palabra
clave ORDER BY para lograr esto.
SELECT "L" FROM "R" WHERE "C" ORDER BY "O" [ASC, DESC];
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 68 de 253
donde:
“L” corresponde a la lista de atributos que se requieren, por lo general se
asocia a una(s) columna(s).
“R” corresponde al nombre de la relación, que por lo general se asocia a
una tabla.
“C” corresponde a la condición de la selección.
“O” corresponde a cómo será ordenada la lista “L”.
ASC corresponde a un orden ascendente (corresponde a la opción por
defecto)
DESC corresponde a uno descendente.
Estrictamente, su sintaxis corresponde a ORDER BY y luego una lista de atributos que
definirán los campos a ordenar:
SELECT atributo1, atributo2 ... FROM Clientes ORDER BY atributo_ordenar_primero, atributo_ordenar_segundo...
Como se puede apreciar, con la sentencia ORDER BY se pueden ordenar las consultas a
través de múltiples atributos. En este caso todos los campos estarían ordenados de
forma ascendente (ASC).
Podemos utilizar los mismos ejemplos que creamos anteriormente ordenando los
nombres de los empleados de la tabla Empleados.
postgres=# SELECT * FROM Empleados ORDER BY nombre_empleado; id_empleados | nombre_empleado | id_departamento | ano_ingreso --------------+-----------------+-----------------+------------- 2 | Andrew | 4 | 2009 1 | Edgar | 1 | 2000 4 | Karl | 2 | 2008 5 | Kevin | 3 | 2010 3 | Valerie | 2 | 2000 (5 filas)
Que es lo mismo que escribir.
postgres=# SELECT * FROM Empleados ORDER BY nombre_empleado ASC; id_empleados | nombre_empleado | id_departamento | ano_ingreso --------------+-----------------+-----------------+------------- 2 | Andrew | 4 | 2009 1 | Edgar | 1 | 2000 4 | Karl | 2 | 2008 5 | Kevin | 3 | 2010 3 | Valerie | 2 | 2000
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 69 de 253
(5 filas)
Y de forma descendiente sería de la siguiente manera.
postgres=# SELECT * FROM Empleados ORDER BY nombre_empleado DESC; id_empleados | nombre_empleado | id_departamento | ano_ingreso --------------+-----------------+-----------------+------------- 3 | Valerie | 2 | 2000 5 | Kevin | 3 | 2010 4 | Karl | 2 | 2008 1 | Edgar | 1 | 2000 2 | Andrew | 4 | 2009 (5 filas)
También es posible realizarlo con números o fechas.
postgres=# SELECT * FROM Empleados ORDER BY ano_ingreso DESC; id_empleados | nombre_empleado | id_departamento | ano_ingreso --------------+-----------------+-----------------+------------- 5 | Kevin | 3 | 2010 2 | Andrew | 4 | 2009 4 | Karl | 2 | 2008 1 | Edgar | 1 | 2000 3 | Valerie | 2 | 2000 (5 filas)
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 70 de 253
Lección VIII - Variables de tablas y
operadores de conjunto
Variables de tablas
Consideremos las siguientes tablas:
College (cName, state, enrollment) Student (sID, sName, Average) Apply (sID, cName, major, decision)
las cuales representar un sistema simple de postulación de estudiantes a
establecimientos educacionales, y son creadas mediante:
CREATE TABLE College(id serial, cName VARCHAR(20), state VARCHAR(30), enrollment INTEGER, PRIMARY KEY(id)); CREATE TABLE Student(sID serial, sName VARCHAR(20), Average INTEGER, PRIMARY kEY(sID)); CREATE TABLE Apply(sID INTEGER, cName VARCHAR(20), major VARCHAR(30), decision BOOLEAN, PRIMARY kEY(sID, cName, major));
Se utilizarán 4 establecimientos educacionales:
INSERT INTO College (cName, state, enrollment) VALUES ('Stanford','CA',15000); INSERT INTO College (cName, state, enrollment) VALUES ('Berkeley','CA',36000); INSERT INTO College (cName, state, enrollment) VALUES ('MIT','MA',10000); INSERT INTO College (cName, state, enrollment) VALUES ('Harvard','CM',23000);
4 estudiantes:
INSERT INTO Student (sName, Average) Values ('Amy', 60); INSERT INTO Student (sName, Average) Values ('Edward', 65); INSERT INTO Student (sName, Average) Values ('Craig', 50); INSERT INTO Student (sName, Average) Values ('Irene', 49);
y 6 postulaciones:
INSERT INTO Apply (sID, cName, major, decision) VALUES (1, 'Stanford', 'science', True); INSERT INTO Apply (sID, cName, major, decision) VALUES (1, 'Stanford', 'engineering', False); INSERT INTO Apply (sID, cName, major, decision) VALUES (2, 'Berkeley', 'natural hostory', False);
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 71 de 253
INSERT INTO Apply (sID, cName, major, decision) VALUES (3, 'MIT', 'math', True); INSERT INTO Apply (sID, cName, major, decision) VALUES (3, 'Harvard', 'science', False); INSERT INTO Apply (sID, cName, major, decision) VALUES (4, 'Stanford', 'marine biology', True);
Ejemplo 1
En este ejemplo se busca la información del nombre e id de los alumnos, que postulan
a uno o más establecimientos educacionales con determinado Average:
SELECT Student.sID, sName, Apply.cName, Average FROM Student, Apply WHERE Apply.sID = Student.sID;
cuya salida es:
sid | sname | cname | Average ----+--------+----------+----- 1 | Amy | Stanford | 60 1 | Amy | Stanford | 60 2 | Edward | Berkeley | 65 3 | Craig | MIT | 50 3 | Craig | Harvard | 50 4 | Irene | Stanford | 49
Nota
Existe un supuesto duplicado en las primeras filas. Esto es debido a que Amy postuló a
“science” y a “engineering” en Stanford. Esto puede evitarse utilizando SELECT DISTINCT en
lugar de SELECT.
también es posible realizarla como:
SELECT S.sID, sName, A.cName, Average FROM Student S, Apply A WHERE A.sID = S.sID;
cuya salida es:
sid | sname | cname | Average ----+---------+----------+----- 1 | Amy | Stanford | 60 1 | Amy | Stanford | 60 2 | Edward | Berkeley | 65 3 | Craig | MIT | 50 3 | Craig | Harvard | 50
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 72 de 253
4 | Irene | Stanford | 49
Nota
Al igual que en la consulta anterior, es posible evitar el valor duplicado utilizando SELECT
DISTINCT en lugar de SELECT.
Como se aprecia, es posible asignar variables a las relaciones “R” y utilizar dichas
variables tanto en la lista “L” como en la condición “C”. ¿Cuál es la utilidad de esto?, más
allá de escribir menos (dependiendo del nombre de la variable utilizada); en los casos
en que se deben comparar múltiples instancias de la misma relación, como se verá en
el ejemplo 2.
Nota
El por qué de la nomenclatura “L”, “R” y “C” y su significado están explicados en la Lección 7
Ejemplo 2
Cuidado con los duplicados!!
Si el lector se fija en la situación descrita, los nombres de algunos atributos de
diferentes relaciones y/o tablas se repiten, lo cual podría plantear la interrogante ¿a que
tabla se refiere el atributo en cuestión?. Para resolver este problema, se escribe de la
siguiente manera:
"NombreTabla.atributo"
Concretamente en el ejemplo anterior, el alcance de nombres lo protagonizan sID de la
tabla Student y sID de la tabla Apply. La diferencia se realiza a través de:
Student.sID o S.sID Apply.sID o A.sID
Para la realización de este ejemplo, suponga que llegan los papeles de un postulante
más, por lo que el administrador de la base de datos deberá agregar la información
necesaria, es decir:
INSERT INTO Student (sName, Average) Values ('Tim', 60);
En variadas ocasiones, los nombres de los atributos se repiten, dado que se comparan
dos instancias de una tabla. En el este ejemplo, se buscan todos los pares de
estudiantes con el mismo Average:
SELECT S1.sID, S1.sName, S1.Average, S2.sID, S2.sName, S2.Average
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 73 de 253
FROM Student S1, Student S2 WHERE S1.Average = S2.Average;
Al momento de realizar esta consulta (dos instancias de una tabla), el resultado
contendrá uno o varios duplicados; por ejemplo, consideremos a los 5 estudiantes:
sid | sname | Average ----+--------+----- 1 | Amy | 60 2 | Edward | 65 3 | Craig | 50 4 | Irene | 49 5 | Tim | 60
Nota
La tabla de arriba se obtuvo realizando la consulta :SQL: ‘SELECT * FROM Student;’
Los pares de estudiantes serán:
Amy - Tim
pero la salida muestra:
sid | sname | Average | sid | sname | Average ----+--------+-----+-----+--------+----- 1 | Amy | 60 | 5 | Tim | 60 1 | Amy | 60 | 1 | Amy | 60 2 | Edward | 65 | 2 | Edward | 65 3 | Craig | 50 | 3 | Craig | 50 4 | Irene | 49 | 4 | Irene | 49 5 | Tim | 60 | 5 | Tim | 60 5 | Tim | 60 | 5 | Amy | 60
lo cual se puede evitar modificando la consulta
SELECT S1.sID, S1.sName, S1.Average, S2.sID, S2.sName, S2.Average FROM Student S1, Student S2 WHERE S1.Average = S2.Average and S1.sID <> S2.sID;
es decir, que el id del estudiante S1 sea diferente al id del estudiante S2; en cuyo caso
la salida de la consulta es:
sid | sname | Average | sid | sname | Average ----+--------+-----+-----+--------+----- 1 | Amy | 60 | 5 | Tim | 60 5 | Tim | 60 | 1 | Amy | 60
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 74 de 253
Establecimiento de Operadores
Los Operadores de conjunto son 3:
Unión
Intersección
Excepción
A continuación se explicará cada uno con un ejemplo:
Unión
El operador “UNION”, permite combinar el resultado de dos o más sentencias SELECT. Es
necesario que estas tengan el mismo número de columnas, y que, además tengan los
mismos tipos de datos, por ejemplo, si se tienen las siguientes tablas:
Employees_Norway: E_ID E_Name 1 Hansen, Ola 2 Svendson, Tove 3 Svendson, Stephen 4 Pettersen, Kari Employees_USA: E_ID E_Name 1 Turner, Sally 2 Kent, Clark 3 Svendson, Stephen 4 Scott, Stephen
Que se pueden crear mediante el comando CREATE TABLE:
CREATE TABLE Employees_Norway (E_ID serial, E_Name varchar(50), PRIMARY KEY(E_ID)); CREATE TABLE Employees_USA ( E_ID serial, E_Name varchar(50), PRIMARY KEY(E_ID));
y pobladas con los datos mostrados a continuación:
INSERT INTO Employees_Norway (E_Name) VALUES ('Hansen, Ola'), ('Svendson, Tove'), ('Svendson, Stephen'), ('Pettersen, Kari');
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 75 de 253
INSERT INTO Employees_USA (E_Name) VALUES ('Turner, Sally'), ('Kent, Clark'), ('Svendson, Stephen'), ('Scott, Stephen');
El resultado de la siguiente consulta que incluye el operador UNION:
SELECT E_Name FROM Employees_Norway UNION SELECT E_Name FROM Employees_USA;
es:
e_name -------------- Turner, Sally Svendson, Tove Svendson, Stephen Pettersen, Kari Hansen, Ola Kent, Clark Scott, Stephen
Hay que tener en cuenta que existe en ambas tablas un empleado con el mismo
nombre “Svendson, Stephen”. Sin embargo en la salida sólo se nombra uno. Si se desea
que aparezcan “UNION ALL”:
SELECT E_Name as name FROM Employees_Norway UNION ALL SELECT E_Name as name FROM Employees_USA;
Utilizando “as” es posible cambiar el nombre de la columna donde quedará resultado:
name --------------- Hansen, Ola Svendson, Tove Svendson, Stephen Pettersen, Kari Turner, Sally Kent, Clark Svendson, Stephen Scott, Stephen
se aprecia que la salida contiene los nombres de los empleados duplicados:
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 76 de 253
Nota
En el ejemplo anterior, se utiliza “as name” en ambos SELECT. Es un hecho curioso que, si se
utilizan diferentes nombres junto al “as”, digamos “as nombre1” y “as nombre2”, queda
como nombre de la tabla UNION el primero en ser declarado, en este caso nombre1.
Intersección
Muy similar al operador UNION, INTERSECT también opera con dos sentencias SELECT.
La diferencia consiste en que UNION actúa como un OR, e INTERSECT lo hace como
AND.
Nota
Las tablas de verdad de estos OR y AND se encuentran en la Lección 7.
Es decir que INTERSECT devuelve los valores repetidos.
Utilizando el ejemplo de los empleados, y ejecutando la consulta:
SELECT E_Name as name FROM Employees_Norway INTERSECT SELECT E_Name as name FROM Employees_USA;
su salida es:
e_name ---------- Svendson, Stephen
Excepción
Similar a los operadores anteriores, su estructura se compone de dos o mas sentencias
SELECT, y el operador EXCEPT. Es equivalente a la diferencia en el álgebra relacional.
Utilizando las mismas tablas de los empleados, y realizando la siguiente consulta:
SELECT E_Name as name FROM Employees_Norway EXCEPT SELECT E_Name as name FROM Employees_USA;
Su salida es:
e-name ----------- Pettersen, Kari Svedson, Tove
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 77 de 253
Hansen, Ola
Es decir, devuelve los resultados no repetidos en ambas tablas.
Hay que tener en cuenta que, a diferencia de los operadores anteriores, la salida de este
no es conmutativa, pues si se ejecuta la consulta de forma inversa,es decir:
SELECT E_Name as name FROM Employees_USA EXCEPT SELECT E_Name as name FROM Employees_Norway;
su salida será:
e-name ------------ Turner, Sally Kent, Clark Scott, Stephen
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 78 de 253
Lección IX- Subconsultas en la cláusula
WHERE
Una subconsulta es una consulta que retorna un único valor y que está anidada dentro
de un SELECT, INSERT. UPDATE o DELETE, o incluso otra subconsulta. Una subconsulta
puede ser utilizada en cualquier lugar donde una expresión está permitida.
SELECT-FROM-WHERE (SELECT)
Hasta ahora se han visto las consultas del tipo SELECT, WHERE, FROM, y algunos de sus
derivados, como lo son el uso de JOIN y operadores lógicos AND, OR, NOT, que son
normalmente utilizados para filtrar resultados mediante la manipulación de una serie
de condiciones.
Sin embargo Las subconsultas son otra manera de filtrar consultas. Una subconsulta es
una sentencia SELECT que aparece dentro de otra sentencia SELECT y que
normalmente son utilizadas para filtrar una cláusula WHERE con el conjunto de
resultados de la subconsulta.
Una subconsulta tiene la misma sintaxis que una sentencia SELECT normal
exceptuando que aparece encerrada entre paréntesis.
Como es usual, se utilizará el ejemplo de la base de datos “Admisión a la Universidad”.
College (cName, state, enrollment) Student (sID, sName, Average) Apply (sID, cName, major, decision)
cuyas tablas son creadas mediante:
CREATE TABLE College(id serial, cName VARCHAR(20), state VARCHAR(30), enrollment INTEGER, PRIMARY KEY(id)); CREATE TABLE Student(sID serial, sName VARCHAR(20), Average INTEGER, PRIMARY kEY(sID)); CREATE TABLE Apply(sID INTEGER, cName VARCHAR(20), major VARCHAR(30), decision BOOLEAN, PRIMARY kEY(sID, cName, major));
Se utilizarán 4 establecimientos educacionales:
INSERT INTO College (cName, state, enrollment) VALUES ('Stanford','CA',15000); INSERT INTO College (cName, state, enrollment) VALUES ('Berkeley','CA',36000);
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 79 de 253
INSERT INTO College (cName, state, enrollment) VALUES ('MIT', 'MA',10000); INSERT INTO College (cName, state, enrollment) VALUES ('Harvard', 'CM',23000);
8 estudiantes:
INSERT INTO Student (sName, Average) Values ('Amy', 60); INSERT INTO Student (sName, Average) Values ('Edward', 65); INSERT INTO Student (sName, Average) Values ('Craig', 50); INSERT INTO Student (sName, Average) Values ('Irene', 49); INSERT INTO Student (sName, Average) Values ('Doris', 45); INSERT INTO Student (sName, Average) Values ('Gary', 53); INSERT INTO Student (sName, Average) Values ('Doris', 70); INSERT INTO Student (sName, Average) Values ('Tim', 60);
y 21 postulaciones:
INSERT INTO Apply (sID, cName, major, decision) VALUES (1, 'Stanford', 'science' , True); INSERT INTO Apply (sID, cName, major, decision) VALUES (1, 'Stanford', 'engineering' , False); INSERT INTO Apply (sID, cName, major, decision) VALUES (1, 'Berkeley', 'science' , True); INSERT INTO Apply (sID, cName, major, decision) VALUES (1, 'Berkeley', 'engineering' , False); INSERT INTO Apply (sID, cName, major, decision) VALUES (2, 'Berkeley', 'natural history', False); INSERT INTO Apply (sID, cName, major, decision) VALUES (3, 'MIT' , 'math' , True); INSERT INTO Apply (sID, cName, major, decision) VALUES (3, 'Harvard' , 'math' , False); INSERT INTO Apply (sID, cName, major, decision) VALUES (3, 'Harvard' , 'science' , False); INSERT INTO Apply (sID, cName, major, decision) VALUES (3, 'Harvard' , 'engineering' , True); INSERT INTO Apply (sID, cName, major, decision) VALUES (4, 'Stanford', 'marine biology' , True); INSERT INTO Apply (sID, cName, major, decision) VALUES (4, 'Stanford', 'natural history', False); INSERT INTO Apply (sID, cName, major, decision) VALUES (5, 'Harvard' , 'science' , False); INSERT INTO Apply (sID, cName, major, decision) VALUES (5, 'Berkeley', 'psychology' , True); INSERT INTO Apply (sID, cName, major, decision) VALUES (5, 'MIT' , 'math' , True); INSERT INTO Apply (sID, cName, major, decision) VALUES (6, 'MIT' , 'science' , False); INSERT INTO Apply (sID, cName, major, decision) VALUES (7, 'Stanford', 'psychology' , True);
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 80 de 253
INSERT INTO Apply (sID, cName, major, decision) VALUES (7, 'Stanford', 'science' , True); INSERT INTO Apply (sID, cName, major, decision) VALUES (7, 'MIT' , 'math' , True); INSERT INTO Apply (sID, cName, major, decision) VALUES (7, 'MIT' , 'science' , True); INSERT INTO Apply (sID, cName, major, decision) VALUES (7, 'Harvard' , 'science' , False); INSERT INTO Apply (sID, cName, major, decision) VALUES (8, 'MIT' , 'engineering' , True);
La situación que se pretende describir con estas tablas de ejemplo es la postulación de
estudiantes a centros educacionales. En concreto la postulación del estudiante sID a la
mención académica major impartida en el centro educacional cName, cuya aprobación,
o decisión, será “True o False”.
Ejemplo 1
El primer ejemplo de subconsulta corresponderá al listado de IDs y Nombres de los
estudiantes que han postulado para estudiar “science” en algún centro educacional.
SELECT sID, sName FROM Student WHERE sID in (SELECT sID FROM Apply WHERE major = 'science');
cuya salida es:
sid | sname ----+------- 6 | Gary 1 | Amy 3 | Craig 7 | Doris 5 | Doris (5 rows)
Nota
En el ejemplo existen dos personas distintas llamadas Doris.
Como se mencionó anteriormente, tanto las subconsultas como el uso de JOIN y
operadores lógicos en la clausula WHERE son formas de filtrar resultados, por tanto, la
consulta se puede reformular como:
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 81 de 253
SELECT Student.sID, sName FROM Student, Apply WHERE Student.sID = Apply.sID AND major = 'science';
Advertencia
En la consulta se debe especificar que el atributo sID corresponde al de la tabla Student, pues
la tabla Apply también cuenta con dicho atributo. Si no se toma en cuenta este detalle, es
probable que la consulta termine en un error con resultados no deseados.
en cuyo caso la salida será:
sid | sname ----+------- 1 | Amy 1 | Amy 3 | Craig 6 | Gary 7 | Doris 7 | Doris 7 | Doris 5 | Doris (8 rows)
Las 3 filas “extra” se deben, a que al utilizar join y operadores lógicos, se toman en
cuenta todos los resultados, por ejemplo Amy postuló en dos ocasiones a science. Al
utilizar la subconsulta, se eliminan estos resultados duplicados, haciendo la consulta
más fiel a la realidad pues se pregunta por aquellos estudiantes que han postulado a
“science”, no cuántas veces postuló cada uno. No obstante si se agrega la
clausula DISTINCT, se obtiene la misma respuesta que al utilizar una subconsulta. Es
decir que para la consulta:
SELECT DISTINCT Student.sID, sName FROM Student, Apply WHERE Student.sID = Apply.sID AND major = 'science';
su salida será:
sid | sname ----+------- 6 | Gary 1 | Amy 3 | Craig 7 | Doris 5 | Doris
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 82 de 253
(5 rows)
Ejemplo 2
Este ejemplo corresponderá sólo al listado de Nombres de los estudiantes que han
quedado seleccionados para estudiar ciencias en algún centro educacional.
SELECT sName FROM Student WHERE sID in (SELECT sID FROM Apply WHERE major = 'science' and decision ='t' );
cuya salida es:
sname ------- Amy Doris (2 rows)
Nota
Ambas Doris no corresponden a un duplicado, ya que el atributo sID de una es 5 y de la
otra es 7.
Y se obtienen los mismos 5 estudiantes. De forma análoga al ejemplo anterior, se
realizará el equivalente a la subconsulta utilizandoJOIN y operadores lógicos:
SELECT sName FROM Student, Apply WHERE Student.sID = Apply.sID AND major = 'science';
cuya salida es:
sname ------- Amy Amy Craig Gary Doris Doris Doris Doris (8 rows)
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 83 de 253
Por tanto, y al igual que el ejemplo anterior, se utilizará DISTINCT, es decir:
SELECT DISTINCT sName FROM Student, Apply WHERE Student.sID = Apply.sID AND major = 'science';
cuya salida es:
sname ------- Amy Craig Doris Gary (4 rows)
Pero solo hay 4 estudiantes. Esto se debe a que en ejemplo anterior, se utilizó tanto
el sID como el sName, como ambas Doris cuentan con un sID diferente, no se tomaba
en cuenta como duplicado, pero en esta consulta, al solo contar con sName, ambas
Doris se toman como 2 instancias de la misma y se elimina una.
En este caso, la única forma de obtener el “número correcto de duplicados” es
utilizando subconsultas.
IN AND NOT IN
IN y NOT IN permiten realizar filtros de forma más específica, que permiten responder
preguntas como la del ejemplo 3
Ejemplo 3
En el siguiente ejemplo se quiere saber el sID y el sName de aquellos estudiantes que
postularon a “science”, pero no a “engineering”:
SELECT sID, sName FROM Student WHERE sID in (SELECT sID FROM Apply WHERE major = 'science') and sID not in (SELECT sID FROM Apply WHERE major = 'engineering');
cuya salida corresponde precisamente a:
sid | sname -----+------- 5 | Doris 6 | Gary 7 | Doris
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 84 de 253
(3 rows)
Nota
Es posible corroborar el resultado ejecutando :sql:´SELECT * FROM Apply;´ y verificar
manualmente.
La consulta realizada en este ejemplo es posible realizarla de otra manera:
SELECT sID, sName FROM Student WHERE sID in (SELECT sID FROM Apply WHERE major = 'science') and not sID in (SELECT sID FROM Apply WHERE major = 'engineering');
cuya salida es equivalente a la anterior.
EXISTS AND NOT EXISTS
EXISTS es una función SQL que devuelve verdadero cuando una subconsulta retorna al
menos una fila.
Ejemplo 4
En este ejemplo se busca el nombre de todos los establecimientos educacionales que
están en el mismo estado. Si se ejecuta:
SELECT cName, state FROM College;
cuya salida es:
cname | state ---------+------- Stanford | CA Berkeley | CA MIT | MA Harvard | CM (4 rows)
el resultado esperado debiese contener el par Stanford - Berkeley
La consulta que pretende resolver esta pregunta es:
SELECT cName, state FROM College C1 WHERE exists
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 85 de 253
(SELECT * FROM College C2 WHERE C2.state = C1.state);
Nota
Lo que realiza esta consulta es verificar que por cada resultado obtenido en C1, lo compara
con todos los resultados en C2.
cuya salida es:
cname | state ---------+------- Stanford | CA Berkeley | CA MIT | MA Harvard | CM (4 rows)
Esto pasa debido a que C1 y C2 pueden ser el mismo establecimiento. Por ende, es
necesario dejar en claro que C1 y C2 son diferentes.
SELECT cName, state FROM College C1 WHERE exists (SELECT * FROM College C2 WHERE C2.state = C1.state and C1.cName <> C2.cName);
en cuyo caso la salida corresponde a la correcta, es decir:
cname | state ---------+------- Stanford | CA Berkeley | CA (2 rows)
CÁLCULOS MATEMÁTICOS
Es posible realizar cálculos matemáticos (valor más alto, valor más bajo) utilizando
subconsultas:
Ejemplo 5
Se busca el establecimiento con mayor cantidad de alumnos. La consulta que se
realizará corresponde a buscar todos los establecimientos donde no exista otro
establecimiento que su cantidad de alumnos sea mayor que la primera.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 86 de 253
SELECT cName, state FROM College C1 WHERE not exists (SELECT * FROM College C2 WHERE C2.enrollment > C1.enrollment);
Donde el resultado corresponde a Berkeley.
Nota
De forma análoga es posible calcular el establecimiento con menor cantidad de alumnos,
cambiando el signo matemático > por <
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 87 de 253
Lección X - Subconsultas en FROM y
SELECT
En la Lección 9, se pudo ver cómo se utilizan las subconsultas en la condición C:
SELECT L FROM R WHERE C;
En esta Lección se verá como utilizarlas tanto en L como en R
Para los ejemplos de esta subsección, se usarán los valores utilizados en la Lección
anterior (Lección 9).
SELECT (SELECT)-FROM-WHERE
Es posible utilizar una subconsulta como una columna dentro de la selección.
Ejemplo 1
Supongamos que se terminó el periodo de postulaciones y desea obtener una lista de
los estudiantes y cuantas veces fueron aceptados.
SELECT sid, sname, (SELECT COUNT (*) FROM apply A WHERE A.sid = S.sid and A.decision = 't') as acepted FROM student S ORDER BY acepted DESC;
cuya salida será:
sid | sname | acepted ----+--------+-------- 7 | Doris | 4 5 | Doris | 2 1 | Amy | 2 4 | Irene | 1 3 | Craig | 2 8 | Tim | 1 6 | Gary | 0 2 | Edward | 0
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 88 de 253
Ejemplo 2
Se desea saber el promedio de un determinado alumno y su diferencia con el promedio
más alto del grupo de alumnos. Podría conseguirse averiguando el promedio más alto
de grupo, y luego, en otra consulta, calcular la diferencia con el del valor del promedio
del alumno en cuestión (en este caso Doris). Esto es posible realizarlo en una sola
consulta:
SELECT sname, average, average-(SELECT max(average) FROM student ) as diferencia FROM student WHERE sname ='Doris';
cuya salida será:
sname | average | diferencia ------+---------+----------- Doris | 45 | -25 Doris | 70 | 0
Para distinguir a ambas Doris, se puede agregar el atributo sID a la consulta:
SELECT sid, sname, average, average-(SELECT max(average) FROM student ) as diferencia FROM student WHERE sname ='Doris';
en cuyo caso la salida será:
sid | sname | average | diferencia ----+-------+---------+----------- 5 | Doris | 45 | -25 7 | Doris | 70 | 0
por lo que, efectivamente se distingue cual persona es la que tiene el promedio 45 y
cual el 70.
Nota
En este ejemplo se utiliza la función de SQL: MAX(atributo) ; la cual retorna el mayor valor de
una columna. Si se aplica en una columna de tipo string, el método de comparación
corresponde al valor ASCII de la primera letra. Por otro lado la función MIN(atributo), retorna
el menor valor de una columna.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 89 de 253
Hay que tener la precaución de retornar un sólo valor a la hora de realizar una
subconsulta dentro de un SELECT. De otra forma se retornará un error, como se ve en el
ejemplo 3.
Ejemplo 3
Supongamos que se trabaja bajo el contexto del ejemplo 2, pero sin utilizar la función
MAX, que retorna sólo un valor:
SELECT sname, average, average-(SELECT average FROM student ) as diferencia FROM student WHERE sname ='Doris';
en cuyo caso la salida corresponderá al siguiente error:
ERROR: more than one row returned by a subquery used as an expression.
Ejemplo 4
Supongamos que se desea saber el nombre de cada alumno, su promedio, y su
diferencia respecto al promedio más bajo del curso:
SELECT sname, average, average-(SELECT min(average) FROM student ) as diferencia FROM student;
en cuyo caso la salida será:
sname | average | diferencia -------+---------+----------- Amy | 60 | 15 Edward | 65 | 20 Craig | 50 | 5 Irene | 49 | 4 Doris | 45 | 0 Gary | 53 | 8 Doris | 70 | 25 Tim | 60 | 15
SELECT-FROM (SELECT)-WHERE
Otro uso que se les da a las subconsultas es en la palabra reservada FROM. En el FROM
de la consulta, es posible utilizar una subconsulta. De todos modos es necesario
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 90 de 253
agregarle un alias, pues el resultado de la subconsulta no tiene un nombre establecido.
En caso de no hacerlo, aparece el siguiente error:
ERROR: subquery in FROM must have an alias HINT: For example, FROM (SELECT ...) [AS] foo.
Como ya se ha mencionado, en la sección del FROM, se listan las tablas desde donde se
sacarán los datos para crear las relaciones. Por lo tanto la subconsulta de este estilo
corresponde a crear una nueva tabla desde donde se podrán extraer datos.
Ejemplo 5
Para demostrar el funcionamiento de la subconsulta dentro del FROM, supongamos que
se desea extraer el id y nombre de cada alumno dentro de la tabla student:
SELECT sid, sname FROM student;
cuya salida es:
sid | sname ----+-------- 1 | Amy 2 | Edward 3 | Craig 4 | Irene 5 | Doris 6 | Gary 7 | Doris 8 | Tim
Lo cual es equivalente a la consulta:
SELECT sid, sname FROM (SELECT * FROM student) as example;
cuya salida es:
sid | sname ----+-------- 1 | Amy 2 | Edward 3 | Craig 4 | Irene 5 | Doris 6 | Gary 7 | Doris 8 | Tim
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 91 de 253
Es decir son equivalentes, pues el alias “example”, contiene toda la información de la
tabla student.
RECAPITULACIÓN
Las subconsultas se utilizan cuando la consulta a realizar es demasiado compleja,
Como se ha mencionado en la Lección anterior, es posible realizar Prácticas de
inserción, actualización y eliminación de datos en las subconsultas.
Ejemplo extra
Nota
A continuación se verán ejemplos de subconsultas en actualización y eliminación de datos. Su
sintaxis y propiedades se explicarán en la Lección 14 (semana 4). Ahora se exponen para
dejar en claro que las subconsultas se pueden utilizar en cualquiera de las 4 operaciones
básicas.
Consideremos que se quiere saber el nombre y la calificación del estudiante con el
menor promedio, además de su diferencia con el mejor promedio.
SELECT sname, average, average- (SELECT max(average) FROM student) as diferencia FROM student WHERE average = (SELECT min(average) FROM student );
cuya salida es:
sname | average | diferencia -------+---------+----------- Doris | 45 | -25
Supongamos que el caso de la alumna que tiene el promedio más bajo, Doris,
corresponde a un error de planilla. Se decide actualizar el promedio utilizando
subconsultas (considerando que es la única alumna con el menor promedio):
UPDATE student SET average = 100 WHERE average = (SELECT min(average) FROM student);
en cuyo caso, y tras realizar un :sql:´SELECT * FROM student´, la salida es:
sid | sname | average ----+--------+--------- 1 | Amy | 60 2 | Edward | 65
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 92 de 253
3 | Craig | 50 4 | Irene | 49 6 | Gary | 53 7 | Doris | 70 8 | Tim | 60 5 | Doris | 100
Sin embargo, se descubre que Doris de id = 5, hizo trampa. Ella se metió de forma
remota y sin permiso al servidor de datos donde se encontraban las planillas de notas,
y procedió a alterar aquellas que aportaban en su promedio. Como castigo se opta por
eliminarla del proceso de postulación. El encargado realiza la acción a través de
subconsultas, considerando que Doris es la única alumna con promedio 100, que
corresponde a la máxima calificación:
DELETE FROM student where average = (SELECT max(average) FROM student);
Cuya salida tras realizar el SELECT * de rigor, es:
sid | sname | average ----+--------+--------- 1 | Amy | 60 2 | Edward | 65 3 | Craig | 50 4 | Irene | 49 6 | Gary | 53 7 | Doris | 70 8 | Tim | 60
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 93 de 253
Lección XI - La familia de operadores
JOIN
La sentencia SQL JOIN permite consultar datos de 2 o más tablas. Dichas tablas estarán
relacionadas entre ellas de alguna forma, a través de alguna de sus columnas. El
propósito del JOIN es unir información de diferentes tablas, para no tener que repetir
datos entre las tablas.
INNER JOIN
La sentencia INNER JOIN es el sentencia JOIN por defecto que consiste en combinar
cada fila de una tabla con cada fila de la otra tabla, seleccionado las filas que cumplan
con una determinada condición.
Esta es la estructura que se ocupa para este tipo de JOIN.
SELECT * FROM tabla_1 INNER JOIN tabla_2 ON condicion
Aquí se muestra un diagrama de como funciona esta consulta.
A continuación se mostrara un ejemplo de una tabla Personas y una de Ordenes de
compras que realizaron.
Realizamos la creación de las tablas Personas y Ordenes.
CREATE TABLE Personas(id_persona serial, nombre VARCHAR(30), apellido VARCHAR(30), direccion VARCHAR(30), ciudad VARCHAR(30), PRIMARY kEY(id_persona)); CREATE TABLE Ordenes(id_orden serial, numero_orden INTEGER, persona INTEGER, PRIMARY KEY(id_orden), FOREIGN KEY(persona) REFERENCES Personas(id_persona));
Ahora insertamos algunos datos.
INSERT INTO Personas(nombre, apellido, direccion, ciudad) VALUES('Allen' , 'Doyle' , '772 Azores' , 'New York');
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 94 de 253
INSERT INTO Personas(nombre, apellido, direccion, ciudad) VALUES('Amy' , 'Looper' , '4525 North Oracle Rd.', 'Miami'); INSERT INTO Personas(nombre, apellido, direccion, ciudad) VALUES('Bibi' , 'Mingus' , '3901 W Ina Rd' , 'Los Angeles'); INSERT INTO Personas(nombre, apellido, direccion, ciudad) VALUES('Caden' , 'Anderson', '7635 N La Cholla Blvd', 'Chicago'); INSERT INTO Personas(nombre, apellido, direccion, ciudad) VALUES('Calvin', 'Dixson' , 'CALLE WALLABY 42' , 'San Francisco'); INSERT INTO Ordenes(numero_orden, persona) VALUES(226345,3); INSERT INTO Ordenes(numero_orden, persona) VALUES(345478,2); INSERT INTO Ordenes(numero_orden, persona) VALUES(218909,2); INSERT INTO Ordenes(numero_orden, persona) VALUES(567432,5); INSERT INTO Ordenes(numero_orden, persona) VALUES(675209,5);
Y realizamos la consulta para unir las dos tablas, de acuerdo a la condición que
detallemos.
postgres=# SELECT Personas.nombre, Personas.apellido, Ordenes.numero_orden FROM Personas INNER JOIN Ordenes ON Personas.id_persona=Ordenes.persona; nombre | apellido | numero_orden --------+----------+-------------- Bibi | Mingus | 226345 Amy | Looper | 345478 Amy | Looper | 218909 Calvin | Dixson | 567432 Calvin | Dixson | 675209 (5 filas)
También podemos mostrar todos los atributos.
postgres=# SELECT * FROM Personas INNER JOIN Ordenes ON Personas.id_persona=Ordenes.persona; id_persona | nombre | apellido | direccion | ciudad | id_orden | numero_orden | persona ------------+--------+----------+-----------------------+---------------+----------+--------------+--------- 3 | Bibi | Mingus | 3901 W Ina Rd | Los Angeles | 1 | 226345 | 3 2 | Amy | Looper | 4525 North Oracle Rd. | Miami | 2 | 345478 | 2 2 | Amy | Looper | 4525 North Oracle Rd. | Miami | 3 | 218909 | 2 5 | Calvin | Dixson | CALLE WALLABY 42 | San Francisco | 4 | 567432 | 5 5 | Calvin | Dixson | CALLE WALLABY 42 | San Francisco | 5 | 675209 | 5 (5 filas)
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 95 de 253
Nota
Se observa que se unen las dos tablas Personas y Ordenes cumpliendo la condición que
definimos.
NATURAL JOIN
En el caso de existir columnas con el mismo nombre en las relaciones que se combinan,
solo se incluirá una de ellas en el resultado de la combinación.
Se crearán dos tablas llamadas Alimentos y Compañia, para realizar el ejemplo que
mostrará como funciona el NATURAL JOIN.
CREATE TABLE COMPANIA(id_compania serial, nombre_compania VARCHAR(30), ciudad VARCHAR(30), PRIMARY KEY(id_compania)); CREATE TABLE ALIMENTOS(id_alimento serial, nombre_alimento VARCHAR(30), id_compania INTEGER, PRIMARY KEY(id_alimento), FOREIGN KEY(id_compania) REFERENCES COMPANIA(id_compania));
Ingresamos datos a las tablas.
INSERT INTO COMPANIA(nombre_compania, ciudad) VALUES('Order All' , 'Boston'); INSERT INTO COMPANIA(nombre_compania, ciudad) VALUES('Akas Foods' , 'Delhi'); INSERT INTO COMPANIA(nombre_compania, ciudad) VALUES('Foodies' , 'London'); INSERT INTO COMPANIA(nombre_compania, ciudad) VALUES('sip-n-Bite' , 'New York'); INSERT INTO COMPANIA(nombre_compania, ciudad) VALUES('Jack Hill Ltd', 'London'); INSERT INTO ALIMENTOS(nombre_alimento, id_compania) VALUES('Chex Mix', 2); INSERT INTO ALIMENTOS(nombre_alimento, id_compania) VALUES('Cheez-lt', 3); INSERT INTO ALIMENTOS(nombre_alimento, id_compania) VALUES('BN Biscuit', 3); INSERT INTO ALIMENTOS(nombre_alimento, id_compania) VALUES('Mighty Munch',5); INSERT INTO ALIMENTOS(nombre_alimento, id_compania) VALUES('Pot Rice', 4);
Ahora podemos realizar la consulta del NATURAL JOIN.
postgres=# SELECT * FROM ALIMENTOS NATURAL JOIN COMPANIA; id_compania | id_alimento | nombre_alimento | nombre_compania | ciudad -------------+-------------+-----------------+-----------------+---------- 2 | 1 | Chex Mix | Akas Foods | Delhi 3 | 2 | Cheez-lt | Foodies | London 3 | 3 | BN Biscuit | Foodies | London 5 | 4 | Mighty Munch | Jack Hill Ltd | London
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 96 de 253
4 | 5 | Pot Rice | sip-n-Bite | New York (5 filas)
Nota
Al realizar el NATURAL JOIN, retorna una tabla con solo una columna llamada id_compania, que
estaba repetida en las dos tablas ALIMENTOSy COMPANIA y la unión de las otras columnas.
INNER JOIN USING (attrs)
Al realizar el INNER JOIN con la cláusula USING(attrs).
A continuación mostraremos el ejemplo anterior utilizando la
cláusula USING(id_compania) que es la columna que se repite en las dos tablas.
postgres=# SELECT * FROM ALIMENTOS INNER JOIN COMPANIA USING(id_compania); id_compania | id_alimento | nombre_alimento | nombre_compania | ciudad -------------+-------------+-----------------+-----------------+---------- 2 | 1 | Chex Mix | Akas Foods | Delhi 3 | 2 | Cheez-lt | Foodies | London 3 | 3 | BN Biscuit | Foodies | London 5 | 4 | Mighty Munch | Jack Hill Ltd | London 4 | 5 | Pot Rice | sip-n-Bite | New York (5 filas)
LEFT|RIGHT|FULL OUTER JOIN
Se creará el siguiente ejemplo para realizar estas tres consultas.
Crearemos las tablas tabla_A y tabla_B.
CREATE TABLE tabla_A(id serial, nombre VARCHAR(30), PRIMARY KEY(id)); CREATE TABLE tabla_B(id serial, nombre VARCHAR(30), PRIMARY KEY(id));
Ingresamos datos a las tablas.
INSERT INTO tabla_A(nombre) VALUES('Pirate'); INSERT INTO tabla_A(nombre) VALUES('Monkey'); INSERT INTO tabla_A(nombre) VALUES('Ninja'); INSERT INTO tabla_A(nombre) VALUES('Spaghetti'); INSERT INTO tabla_B(nombre) VALUES('Rutabaga'); INSERT INTO tabla_B(nombre) VALUES('Pirate'); INSERT INTO tabla_B(nombre) VALUES('Darth Vader'); INSERT INTO tabla_B(nombre) VALUES('Ninja');
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 97 de 253
LEFT OUTER JOIN
La sentencia LEFT OUTER JOIN ó LEFT JOIN combina los valores de la primera tabla
con los valores de la segunda tabla que cumplan con la condición. Si no existe ninguna
coincidencia, el lado derecho contendrá null (o vacío).
SELECT * FROM tabla_1 LEFT OUTER JOIN tabla_2 ON tabla_1.columna = tabla_2.columna
Ahora realizamos la consulta con el ejemplo que definimos al comienzo.
postgres=# SELECT * FROM tabla_A LEFT OUTER JOIN tabla_B ON tabla_A.nombre=tabla_B.nombre; id | nombre | id | nombre ----+-----------+----+-------- 1 | Pirate | 2 | Pirate 2 | Monkey | | 3 | Ninja | 4 | Ninja 4 | Spaghetti | | (4 filas)
Nota
Podemos observar que retorna todos los atributos de la tabla_A (izquierda) y de la tabla_B, solo
retorna los atributos que cumplen con la condición que establecimos.
RIGHT OUTER JOIN
La sentencia RIGHT OUTER JOIN ó RIGHT JOIN combina los valores de la primera tabla
con los valores de la segunda tabla. Siempre devolverá las filas de la segunda tabla,
incluso aunque no cumplan la condición.
SELECT * FROM tabla_1 RIGHT OUTER JOIN tabla_2 ON tabla_1.columna = tabla_2.columna
A continuación se muestra un diagrama de la consulta.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 98 de 253
Ahora realizamos la siguiente consulta.
postgres=# SELECT * FROM tabla_A RIGHT OUTER JOIN tabla_B ON tabla_A.nombre=tabla_B.nombre; id | nombre | id | nombre ----+--------+----+------------- | | 1 | Rutabaga 1 | Pirate | 2 | Pirate | | 3 | Darth Vader 3 | Ninja | 4 | Ninja (4 filas)
Nota
Se observa que el retorno de la consulta son todos los atributos de tabla_B (derecha) y solo los
atributos que cumplen con la condición que definimos de tabla_A.
FULL OUTER JOIN
La sentencia FULL OUTER JOIN ó FULL JOIN combina los valores de la primera tabla con
los valores de la segunda tabla. Siempre devolverá las filas de las dos tablas, aunque no
cumplan la condición.
SELECT * FROM tabla_1 FULL OUTER JOIN tabla_2 ON tabla_1.columna = tabla_2.columna
A continuación se muestra el diagrama de la consulta.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 99 de 253
Ahora se realizará el ejemplo de la consulta.
postgres=# SELECT * FROM tabla_A FULL OUTER JOIN tabla_B ON tabla_A.nombre=tabla_B.nombre; id | nombre | id | nombre ----+-----------+----+------------- | | 3 | Darth Vader 2 | Monkey | | 3 | Ninja | 4 | Ninja 1 | Pirate | 2 | Pirate | | 1 | Rutabaga 4 | Spaghetti | | (6 filas)
Nota
Se observa que se retornan todos los atributos de tabla_A y tabla_B, aunque no cumpla con la
condición.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 100 de 253
Lección XII - Funciones de Agregación
Funciones de Agregación
Las Funciones de Agregación realizan un cálculo sobre un conjunto de datos y regresan
un solo valor.
Algunas funciones útiles de agregado son:
AVG() - Retorna el valor promedio
COUNT() - Retorna el número de filas
MAX() - Retorna el mayor valor
MIN() - Retorna el menor valor
SUM() - Retorna la suma
Para mostrar el funcionamiento de dichas funciones, consideraremos el siguiente
ejemplo:
Se creará una tabla de Ordenes, que tendrá los atributos
de id, fecha de orden, precio de la orden y el cliente.
postgres=# CREATE TABLE Ordenes(id serial, fecha_ordenes DATE, precio_ordenes INTEGER, cliente VARCHAR(30), PRIMARY KEY(id));
Ingresaremos datos a la tabla Ordenes.
postgres=# INSERT INTO Ordenes(fecha_ordenes, precio_ordenes, cliente) VALUES('2010/09/23', 1120,'Alison'); INSERT 0 1 postgres=# INSERT INTO Ordenes(fecha_ordenes, precio_ordenes, cliente) VALUES('2007/02/21',1990,'Alicia'); INSERT 0 1 postgres=# INSERT INTO Ordenes(fecha_ordenes, precio_ordenes, cliente) VALUES('2006/06/09',400,'Alison'); INSERT 0 1 postgres=# INSERT INTO Ordenes(fecha_ordenes, precio_ordenes, cliente) VALUES('2006/04/01',700,'Alison'); INSERT 0 1 postgres=# INSERT INTO Ordenes(fecha_ordenes, precio_ordenes, cliente) VALUES('2005/03/30',2120,'Brad'); INSERT 0 1 postgres=# INSERT INTO Ordenes(fecha_ordenes, precio_ordenes, cliente) VALUES('2011/11/17',160,'Alicia'); INSERT 0 1
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 101 de 253
Función AVG()
La función AVG() retorna el valor promedio de una columna numérica.
En SQL la sintaxis es de la siguiente manera:
SELECT AVG(nombre_columna) FROM nombre_tabla;
Para calcular el precio promedio de las ordenes se realiza la siguiente consulta:
postgres=# SELECT AVG(precio_ordenes) AS precio_promedio FROM Ordenes; precio_promedio ----------------------- 1081.6666666666666667 (1 fila)
Nota
En la consulta se utilizó la palabra “AS”, esto es
para darle un nombre a la tabla de retorno en este
caso se llamará “precio_promedio”.
También podemos calcular con SELECT anidados, el precio de las ordenes que son
mayores al promedio calculado, retornando el id,fecha de orden, precio_ordenes y
el cliente.
postgres=# SELECT id, fecha_ordenes, precio_ordenes, cliente FROM Ordenes WHERE precio_ordenes > (SELECT AVG(precio_ordenes) FROM Ordenes); id | fecha_ordenes | precio_ordenes | cliente ----+---------------+----------------+--------- 1 | 2010-09-23 | 1120 | Alison 2 | 2007-02-21 | 1990 | Alicia 5 | 2005-03-30 | 2120 | Brad (3 filas)
Función COUNT()
La función COUNT() retorna el número de filas según los criterios que especificaron.
En SQL la sintaxis que se utiliza para realizar la consulta es:
SQL COUNT (nombre_columna)
COUNT(nombre_columna) retorna el número de valores que se encuentran en la columna
especificada. Los valores NULL no se cuentan.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 102 de 253
SELECT COUNT(nombre_columna) FROM nombre_tabla;
Realizaremos la consulta COUNT(clientes) para retornar la cantidad de cliente que
tengan el nombre de Alison existen en la tablaOrdenes.
postgres=# SELECT COUNT(cliente) AS cliente_Alison FROM Ordenes WHERE cliente='Alison'; cliente_alison ---------------- 3 (1 fila)
SQL COUNT(*)
COUNT(*) retorna el número de registros de una tabla.
SELECT COUNT(*) FROM nombre_tabla;
Se realizará la consulta COUNT(*), que retornara el número de ordenes de la
tabla Ordenes.
postgres=# SELECT COUNT(*) AS numero_ordenes FROM Ordenes; numero_ordenes ---------------- 6 (1 fila)
SQL COUNT (DISTINCT nombre_columna)
COUNT(DISTINCT nombre_columna) retorna el número de valores distintos a la columna
especificada.
SELECT COUNT(DISTINCT nombre_columna) FROM nombre_tabla;
Se realizará la consulta COUNT(DISTINCT cliente), que retornará la cantidad
de clientes distintos que existen en la tabla Ordenes, que son Alison, Alicia y Brad.
postgres=# SELECT COUNT(DISTINCT cliente) AS numero_de_clientes FROM Ordenes; numero_de_clientes -------------------- 3 (1 fila)
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 103 de 253
Función MAX()
La función MAX() retorna el máximo valor de la columna seleccionada.
En SQL la sintaxis utilizada es de la siguiente manera:
SELECT MAX(nombre_columna) FROM nombre_tabla;
Se realizará la consulta MAX(precio_ordenes) que retornará el mayor precio de las
ordenes en la tabla Ordenes.
postgres=# SELECT MAX(precio_ordenes) AS mayor_precio FROM Ordenes; mayor_precio -------------- 2120 (1 fila)
Función MIN()
La función MIN() retorna el mínimo valor de la columna seleccionada.
En SQL la sintaxis utilizada es de la siguiente manera:
SELECT MIN(nombre_columna) FROM nombre_tabla;
Se realizará la consulta MIN(precio_ordenes) que retornará el menor precio de las
ordenes en la tabla Ordenes.
postgres=# SELECT MIN(precio_ordenes) AS menor_precio FROM Ordenes; menor_precio -------------- 160 (1 fila)
Función SUM()
La función SUM() retorna la suma total de una columna numérica.
En SQL la sintaxis utilizada es de la siguiente manera:
SELECT SUM(nombre_columna) FROM nombre_tabla;
Se realizará la consulta SUM(precio_ordenes) que retornará el precio total de las
ordenes que se encuentran en la tabla Ordenes.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 104 de 253
postgres=# SELECT SUM(precio_ordenes) AS precio_total FROM Ordenes; precio_total -------------- 6490 (1 fila)
SQL GROUP BY
La instrucción GROUP BY se utiliza en conjunción con las funciones de agregado para
agrupar el conjunto de resultados de una o más columnas.
SELECT nombre_columna, funcion_de_agregacion(nombre_columna) FROM nombre_tabla WHERE condicion GROUP BY nombre_columna;
La siguiente consulta utilizará la instrucción GROUP BY, para realizar
la suma por cliente de los precios de ordenes en la tabla Ordenes.
postgres=# SELECT cliente, SUM(precio_ordenes) FROM Ordenes GROUP BY cliente; cliente | sum ---------+------ Alison | 2220 Brad | 2120 Alicia | 2150 (3 filas)
SQL HAVING
La cláusula HAVING se utiliza en SQL, puesto que la palabra clave WHERE no puede
utilizarse con las funciones de agregado en sus condiciones.
En SQL la sintaxis que se utiliza es de la siguiente manera:
SELECT nombre_columna, funcion_de_agregacion(nombre_columna) FROM nombre_tabla WHERE condicion GROUP BY nombre_columna HAVING funcion_de_agregacion(nombre_columna) operador valor;
Ahora queremos saber si alguno de los clientes tiene un precio total de ordenes mayor
a 2130.
postgres=# SELECT cliente, SUM(precio_ordenes) FROM Ordenes GROUP BY cliente HAVING SUM(precio_ordenes)>2130; cliente | sum ---------+------
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 105 de 253
Alison | 2220 Alicia | 2150 (2 filas)
Realizaremos la consulta anterior, agregando la cláusula WHERE con la condición que
el cliente se igual a “Alison”.
postgres=# SELECT cliente, SUM(precio_ordenes) FROM Ordenes WHERE cliente='Alicia' GROUP BY cliente HAVING SUM(precio_ordenes)>2130; cliente | sum ---------+------ Alicia | 2150 (1 fila)
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 106 de 253
Lección XIII - SQL: Valores NULL
NULL indica que un valor es desconocido o que aún no existe un valor asignado dentro
de una base de datos. NULL no pertenece a ningún dominio de datos (no pertenece a
los enteros, ni a los booleanos, ni a los flotantes, etc), se puede considerar como un
marcador que indica la ausencia de un valor.
Nota
NULL no debe confundirse con un valor 0, ya que el valor 0 pertenece a algún tipo de dato
(entero o flotante) mientras que, como ya se mencionó, NULL es la falta de un dato.
CREATE TABLE
En forma predeterminada, una columna puede ser NULL. Si se desea no permitir un
valor NULL en una columna, se debe colocar una restricción en esta columna
especificando que NULL no es ahora un valor permitido.
Forma general:
CREATE TABLE nombreTabla (atributo1 tipoAtributo NOT NULL, atributo2 tipoAtributo);
La consulta anterior crea una tabla llamada nombreTabla, con dos atributos. El primero
atributo1 no acepta valores nulos (NULL), esto debido a que es acompañado de la
instrucción NOT NULL, atributo2 puede no tener valores, es decir se puede dar que
atributo2 contenga, en alguna de sus filas, valores desconocidos.
Para ilustrar las particularidades y utilidad de NULL se utilizará el siguiente ejemplo:
Una tabla de clientes que almacena el rut, apellido, nombre, deuda y
dirección Cliente(rut−−−,nombre,apellido, deuda,direccion) .
Se crea la tabla Cliente donde las columnas “rut”, “nombre” y “apellido” no
incluyen NULL, mientras que “direccion” y “deuda” puede incluir NULL. Es decir, se
podría desconocer la dirección del usuario sin que esto traiga problemas a la base de
datos. La consulta SQL que realiza esta acción es la siguiente:
postgres=# CREATE TABLE Cliente (rut int NOT NULL, nombre varchar (30) NOT NULL, apellido varchar(30)NOT NULL, deuda int, direccion varchar (30));
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 107 de 253
CREATE TABLE
INSERT y UPDATE
Los valores NULL se pueden insertar en una columna si se indica
explícitamente NULL en una instrucción INSERT. De igual forma se puede actualizar un
valor con UPDATE especificando que es NULL en la consulta.
Forma general:
INSERT INTO nombreTabla (atributo1,atributo2) values(valorValido, null); UPDATE nombreTabla SET atributo2= null WHERE condición;
Continuando con el ejemplo anterior, se inserta un cliente:
postgres=# INSERT INTO Cliente (rut,nombre,apellido,deuda,direccion) values(123,'Tom', 'Hofstadter', 456, null); INSERT 0 1
Al insertar los valores del cliente ‘Tom Hofstadter’, se almacenó el atributo dirección
como NULL, es decir sin valor asignado. Antes de exponer cómo funciona UPDATE, se
agregan nuevos clientes para mostrar de mejor manera las siguientes consultas:
postgres=# INSERT INTO Cliente (rut, nombre, apellido, deuda, direccion) values (412,'Greg', 'Hanks',33, 'Cooper'), (132,'Mayim ', 'Bialik',null, 'Barnett 34'), (823,'Jim', 'Parsons',93, null),(193,'Johnny', 'Galecki',201, 'Helberg 11'), (453,'Leslie', 'Abbott',303,null), (583,'Hermione', 'Weasley',47, 'Leakey 24'), (176,'Ron', 'Granger',92,'Connor 891'), (235,'Hannah', 'Winkle',104, null), (733,'Howard', 'Brown',null, null); INSERT 0 9
Realizando una consulta SELECT, para ver todos los clientes que se insertaron, se
puede apreciar un espacio vacío en los valores que llevaban NULL al momento de
hacer INSERT. Tal es el caso de la dirección de ‘Tom Hofstadter’ o la deuda ‘Mayim
Bialik’ .
postgres=# SELECT * FROM Cliente; rut | nombre | apellido | deuda | direccion -----+----------+------------+-------+------------ 123 | Tom | Hofstadter | 456 | 412 | Greg | Hanks | 33 | Cooper
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 108 de 253
132 | Mayim | Bialik | | Barnett 34 823 | Jim | Parsons | 93 | 193 | Johnny | Galecki | 201 | Helberg 11 453 | Leslie | Abbott | 303 | 583 | Hermione | Weasley | 47 | Leakey 24 176 | Ron | Granger | 92 | Connor 891 235 | Hannah | Winkle | 104 | 733 | Howard | Brown | | (10 filas)
Ahora se puede actualizar un cliente:
postgres=# UPDATE Cliente SET direccion=null WHERE rut=412; UPDATE 1
Se actualiza el cliente de rut 412, dejando su dirección sin valor conocido.
Realizando nuevamente un SELECT para visualizar la tabla cliente, se puede apreciar
que el cliente con rut 412, ‘Greg Hanks’, ahora aparece con una dirección sin un valor
asignado.
postgres=# SELECT * FROM Cliente; rut | nombre | apellido | deuda | direccion -----+----------+------------+-------+------------ 123 | Tom | Hofstadter | 456 | 132 | Mayim | Bialik | | Barnett 34 823 | Jim | Parsons | 93 | 193 | Johnny | Galecki | 201 | Helberg 11 453 | Leslie | Abbott | 303 | 583 | Hermione | Weasley | 47 | Leakey 24 176 | Ron | Granger | 92 | Connor 891 235 | Hannah | Winkle | 104 | 733 | Howard | Brown | | 412 | Greg | Hanks | 33 | (10 filas)
SELECT
Seleccionar atributos NULL
Para comprobar si hay valores NULL, se usa IS NULL o
IS NOT NULL en la cláusula WHERE.
Forma general:
SELECT atributo1 FROM nombreTabla WHERE atributo2 IS NULL
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 109 de 253
Utilizando el mismo ejemplo, Seleccionar todos los nombres y apellidos de los clientes
donde la dirección es NULL:
postgres=# SELECT nombre,apellido FROM Cliente WHERE direccion IS NULL; nombre | apellido --------+------------ Tom | Hofstadter Jim | Parsons Leslie | Abbott Hannah | Winkle Howard | Brown Greg | Hanks (6 filas)
Seleccionar todos los nombres y apellidos de los clientes donde la dirección es distinta
a NULL:
postgres=# SELECT nombre,apellido FROM Cliente WHERE direccion IS NOT NULL; nombre | apellido ----------+---------- Mayim | Bialik Johnny | Galecki Hermione | Weasley Ron | Granger (4 filas)
Al utilizar la instrucción IS NOT NULL se seleccionan todos los clientes que tienen una
dirección conocida, es decir que poseen algún valor designado en la base de datos.
Comparaciones con NULL
La comparación entre dos NULL o entre cualquier valor y un NULL tiene un
resultado desconocido pues el valor de cada NULL es desconocido. También se
puede decir que no existen dos NULL que sean iguales.
La siguiente consulta selecciona el nombre y apellido de los clientes que poseen una
deuda mayor a 100 o menor/igual a 100. Se puede apreciar que esta consulta abarcaría
a todos los clientes, pues cualquier número entero es mayor, menor o igual a 100.
postgres=# SELECT nombre,apellido FROM Cliente WHERE deuda > 100 or deuda <=100;
Sin embargo al realizar la consulta retorna la siguiente tabla:
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 110 de 253
nombre | apellido ----------+------------ Tom | Hofstadter Jim | Parsons Johnny | Galecki Leslie | Abbott Hermione | Weasley Ron | Granger Hannah | Winkle Greg | Hanks (8 filas)
Se puede notar que no se incluye a todos los clientes, esto ocurre pues el atributo
deuda admitía valores nulos, y como se mencionó, un NULL no se puede comparar con
ningún valor, pues arroja un resultado desconocido.
La forma de obtener todos los clientes es la siguiente:
postgres=# SELECT nombre,apellido FROM Cliente WHERE deuda > 100 or deuda <=100 or deuda IS NULL; nombre | apellido ----------+------------ Tom | Hofstadter Mayim | Bialik Jim | Parsons Johnny | Galecki Leslie | Abbott Hermione | Weasley Ron | Granger Hannah | Winkle Howard | Brown Greg | Hanks (10 filas)
Ahora, se prueba la comparación con otra sentencia:
postgres=# SELECT nombre,apellido FROM Cliente WHERE deuda > 100 or nombre= 'Howard'; nombre | apellido --------+------------ Tom | Hofstadter Johnny | Galecki Leslie | Abbott Hannah | Winkle Howard | Brown (5 filas)
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 111 de 253
‘Howard’ tiene deuda NULL, anteriormente se demostró que NULL no se puede
comparar, entonces no cumple con: deuda > 100. A pesar de esto, aparece en el
resultado de la consulta, pues cumple con la segunda condición: nombre= ‘Howard’.
Con esto se quiere explicar que no necesariamente, por tener un valor NULL dentro de
sus atributos, pasa a ser completamente “invisible”, es decir mientras no se compare
solamente el atributo NULL puede estar en el resultado.
A modo de resumen se puede decir que:
A = NULL no se puede decir que A tenga el mismo valor que NULL.
A <> NULL no se puede decir que A tenga distinto valor a NULL.
NULL = NULL es imposible saber si ambos NULL son iguales.
Operaciones con NULL
Recordar que NULL significa desconocido. Al realizar suma donde uno de
los datos es desconocido, la suma también es desconocida:
postgres=# SELECT (SELECT deuda FROM cliente WHERE rut=132)+( SELECT deuda FROM cliente WHERE rut=583) as suma; suma ------ (1 fila)
La sentencia suma la deuda del cliente 132 que es NULL con la deuda del cliente 583
que es 47, NULL + 47 arroja como resultado NULL. Lo mismo ocurre con la resta,
multiplicación y división.
Operadores lógicos
Cuando hay valores NULL en los datos, los operadores lógicos y de comparación
pueden devolver un tercer resultado UNKNOWN(desconocido) en lugar de
simplemente TRUE (verdadero) o FALSE (falso). Esta necesidad de una lógica de
tres valores es el origen de muchos errores de la aplicación.
Se agrega una nueva columna que contenga valores booleanos:
postgres=# ALTER table Cliente add actual bool; ALTER TABLE
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 112 de 253
Se insertan algunos valores para la nueva columna actual. Esta columna describe si un
cliente es actual o dejó de ser cliente de la compañía.
postgres=# UPDATE Cliente SET actual=true WHERE rut=412; UPDATE 1 postgres=# UPDATE Cliente SET actual=true WHERE rut=123; UPDATE 1 postgres=# UPDATE Cliente SET actual=true WHERE rut=193; UPDATE 1 postgres=# UPDATE Cliente SET actual=false WHERE rut=733; UPDATE 1 postgres=# UPDATE Cliente SET actual=false WHERE rut=823; UPDATE 1 postgres=# UPDATE Cliente SET actual=false WHERE rut=453; UPDATE 1 postgres=# SELECT * FROM Cliente; rut | nombre | apellido | deuda | direccion | actual -----+----------+------------+-------+------------+-------- 132 | Mayim | Bialik | | Barnett 34 | 583 | Hermione | Weasley | 47 | Leakey 24 | 176 | Ron | Granger | 92 | Connor 891 | 235 | Hannah | Winkle | 104 | | 412 | Greg | Hanks | 33 | | t 123 | Tom | Hofstadter | 456 | | t 193 | Johnny | Galecki | 201 | Helberg 11 | t 733 | Howard | Brown | | | f 823 | Jim | Parsons | 93 | | f 453 | Leslie | Abbott | 303 | | f (10 filas)
IS UNKNOWN retorna los valores que no son false ni true. A continuación se muestra
su uso, seleccionando de la tabla cliente todos los nombres que en su atributo actual,
no poseen valor.
postgres=# SELECT nombre FROM cliente WHERE actual IS UNKNOWN; nombre ---------- Mayim Hermione Ron Hannah (4 filas)
IS NOT UNKNOWN funciona de la misma forma solo que retorna los valores que poseen
algún valor asignado, ya sea true o false.
Para los operadores and y or que involucran NULL, de manera general se puede decir:
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 113 de 253
NULL or false = NULL
NULL or true = true
NULL or NULL = NULL
NULL and false = false
NULL and true = NULL
NULL and NULL = NULL
not (NULL) El inverso de NULL también es NULL.
Nota
Para minimizar las Prácticas de mantenimiento y los posibles efectos en las consultas o
informes existentes, debería minimizarse el uso de los valores desconocidos. Es una buena
práctica plantear las consultas e instrucciones de modificación de datos de forma que los
datos NULLtengan un efecto mínimo.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 114 de 253
Lección XIV - SQL: Declaraciones de las
Modificaciones de Datos
Como ya se ha dicho en algunas de las Leccións anteriores, existen 4 operaciones
básicas relacionadas con la manipulación de datos en una tabla SQL:
Selección -> SELECT Inserción -> INSERT Actualización -> UPDATE Eliminación -> DELETE
En esta Lección se verán en profundidad, las operaciones que permiten mantener una
base de datos, es decir, INSERT, UPDATE y DELETE.
INSERT
Para insertar datos, existen al menos dos formas. Una se ha visto desde las primeras
Leccións (INSERT INTO):
INSERT INTO table VALUES (atributo1, atributo2 ...);
Es decir que se insertará en la tabla, los valores correspondientes a sus atributos de la.
Para poder utilizar esta forma, es necesario que la cantidad de valores asociados a los
atributos, sea igual a la cantidad de atributos de la tabla, y que estén en el mismo
orden respecto a los tipos de datos y los datos que se quieran insertar. El ejemplo 1
aclarará posibles dudas:
Contexto
Utilicemos la tabla “Student”, que ya se ha utilizado en Leccións anteriores:
Student (sID, sName, Average)
y creemos una nueva tabla llamada Student_new, con una estructura similar, pero vacía:
CREATE TABLE Student_new (sID serial, sName VARCHAR(20), Average INTEGER, PRIMARY KEY(sID));
Es decir, cuenta con 3 atributos, los cuales son: el identificador o sID de carácter entero
y serial, lo cual significa que si no se especifica un valor, tomará un valor entero; el
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 115 de 253
nombre o sName que corresponde a una cadena de caracteres, y el promedio
o Average, es decir un número entero.
Ejemplo 1
Supongamos que planilla de estudiantes albergada en la tabla Student ya fue enviada y
no se puede modificar, es por ello que se necesita crear una nueva planilla (otra tabla
student), y agregar a los nuevos alumnos postulantes.
Por lo tanto es posible agregar un estudiante mediante:
INSERT INTO Student_new VALUES (1,'Betty', 78);
cuya salida, después de ejecutar el :
SELECT * FROM Student_new;
es
sid | sname | average -----+-------+--------- 1 | Betty | 78 (1 row)
Al utilizar el atributo sID como serial, es posible omitir el valor de este atributo a la hora
de insertar un nuevo estudiante:
INSERT INTO Student_new (sName, Average) VALUES ('Wilma', 81);
Pero, esto resulta en el siguiente error:
ERROR: duplicate key value violates unique constraint "student_new_pkey" DETAIL: Key(sid)=(1) already exists.
Esto se debe a que sID es clave primaria, y serial tiene su propio contador, que parte de
1 (el cual no está ligado necesariamente a los valores de las diversas filas que puedan
existir en la tabla). Hasta este punto, sólo se pueden seguir añadiendo alumnos
agregado de forma explícita todos y cada uno de los atributos de la tabla, sin poder
prescindir en este caso de sID y su característica de ser serial, pues la tupla atributo-
valor (sID)=(1) está bloqueada.
Nota
Es posible eliminar directamente la fila que corresponde a ‘Betty’, pero ese paso se reserva
a la subsección de DELETE, presentada más adelante en esta Lección
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 116 de 253
Ejemplo 2
Es posible modificar la inserción de ‘Betty’ para que sea similar a la de ‘Wilma’.
Nota
A continuación se usará el comando SQL DROP TABLE, que permite eliminar una tabla
entera.
DROP TABLE Student_new; CREATE TABLE Student_new(sID serial, sName VARCHAR(20), Average INTEGER, PRIMARY kEY(sID)); INSERT INTO Student_new (sName, Average) VALUES ('Betty', 78); INSERT INTO Student_new (sName, Average) VALUES ('Wilma', 81);
Como se ha modificado la consulta de ‘Betty’, se utiliza el contador propio del atributo
serial, por lo que no hay conflictos.
Si se selecciona toda la información de la tabla:
SELECT * FROM Student_new;
la salida es:
sid | sname | average -----+-------+--------- 1 | Betty | 78 2 | Wilma | 81 (2 rows)
UPDATE
Es posible modificar o “actualizar” datos a través del comando UPDATE, cuya sintaxis
es:
UPDATE table SET Attr = Expression WHERE Condition;
Es decir que se actualiza de la tabla el atributo Attr (el valor anterior, por el valor
“Expression”), bajo una cierta condición “Condition”
Nota
Es importante destacar que la condición puede variar, puede ser de carácter sumamente
complejo, una sub-consulta, una sentencia que involucre otras tablas. “Expression” también
puede ser un valor que involucre otras tablas, no necesariamente corresponde a un valor de
comparación directa. Se aplica lo mismo para la condición.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 117 de 253
Es necesario destacar que, si bien se puede actualizar un atributo, también se pueden
actualizar varios a la vez:
UPDATE table SET Attr1 = Expression1, Attr2 = Expression2,..., AttrN = ExpressionN WHERE Condition;
Ejemplo 3
Bajo el contexto del ejemplo 2, supongamos que la nota de ‘Wilma’ corresponde a un
91 en lugar de 81. Se desea corregir este error de tipéo, a través del comando UPDATE.
Es necesario recordar que dependiendo de la cantidad de atributos de la tabla, es
posible realizar de muchas formas la actualización:
UPDATE Student_new SET Average = 91 WHERE sName = 'Wilma';
o
UPDATE Student_new SET Average = 91 WHERE Average = 81;
Ambos casos no son erróneos, pues realizan el cambio pedido. No obstante, es
necesario tener la costumbre de trabajar con atributos que sean únicos, es decir la clave
primaria (en este caso el atributo sID). La razón corresponde a que en caso de haber
más de una Wilma se cambiaría el promedio de ambas, lo mismo para el caso de que
varias personas cuenten con un promedio igual a 81. Por lo tanto la consulta ideal
corresponde a:
UPDATE Student_new SET Average = 91 WHERE sID = 2;
Verificando a través de la ejecución de un select:
SELECT * FROM Student_new;
la salida es:
sid | sname | average -----+-------+--------- 1 | Betty | 78 2 | Wilma | 91
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 118 de 253
(2 rows)
Es decir, se actualizó correctamente la nota de ‘Wilma’.
DELETE
Es posible eliminar filas de información, que cumplan una determinada condición. Esto
es especialmente útil en casos donde se desee borrar filas específicas en lugar de tener
que borrar toda una tabla.
La sintaxis del comando DELETE es:
DELETE FROM table WHERE Condition;
Es decir que de la tabla, se elimine el(los) valor(es) que cumpla(n) con la condición
“Condition”.
Nota
Es importante destacar que la condición puede variar, puede ser de carácter sumamente
complejo, una sub-consulta, una sentencia que involucre otras tablas.
Ejemplo 4
Si nos situamos temporalmente al final del ejemplo 1, con el error:
ERROR: duplicate key value violates unique constraint "student2_pkey" DETAIL: Key(sid)=(1) already exists.
Al querer insertar a ‘Wilma’, es posible eliminar la fila correspondiente a ‘Betty’ y volver
insertar ambas como se hizo en el ejemplo 2, sin la necesidad de borrar la tabla, crearla
y agregar todo de nuevo:
DELETE FROM Student_new WHERE sID = 1;
Si verificamos:
SELECT * FROM Student_new;
la salida es:
sid | sname | average ----+--------+---------
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 119 de 253
Lo cual permite eliminar la fila correspondiente a ‘Betty’ y dejar la tabla vacía.
Posteriormente es posible comenzar a llenarla de nuevo mediante las últimas 2
consultas del ejemplo 2, es decir:
INSERT INTO Student_new (sName, Average) VALUES ('Betty', 78); INSERT INTO Student_new (sName, Average) VALUES ('Wilma', 81);
Y verificando:
SELECT * FROM Student_new;
la salida es:
sid | sname | average ----+--------+--------- 1 | Betty | 78 2 | Wilma | 81
Ejemplo 5
Supongamos que ‘Wilma’ se enoja por el error de tipéo y desea salir del proceso de
postulación. Es por ello que debe ser eliminada de la nueva planilla de estudiantes:
DELETE FROM Student_new WHERE sID = 2;
RECAPITULACIÓN
A continuación se expondrá un ejemplo que implique el uso de todos los comandos
aprendidos en esta Lección.
Ejemplo extra
Tomando en cuenta el ejemplo 5, supongamos que ‘Betty’ pasa a la etapa de
postulaciones y decide postular a 2 Establecimientos educacionales. Postula a Ciencias
e Ingeniería en Stanford y a Historia Natural en Berkeley, es aceptada en todo lo que ha
postulado. La tabla Apply igual que la tabla Student: ya se había enviado sin posibilidad
de modificar. Es por ello que se crea la tabla Apply_new, con las mismas características
que Apply:
CREATE TABLE Apply_new(sID INTEGER, cName VARCHAR(20), major VARCHAR(30), decision BOOLEAN, PRIMARY kEY(sID, cName, major)); INSERT INTO Apply_new (sID, cName, major, decision) VALUES (1, 'Stanford',
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 120 de 253
'science' , True); INSERT INTO Apply_new (sID, cName, major, decision) VALUES (1, 'Stanford', 'engineering' , True); INSERT INTO Apply_new (sID, cName, major, decision) VALUES (1, 'Berkeley', 'natural history' , True);
Verificando la salida:
SELECT * FROM Apply_new;
se tiene que:
sid | cname | major | decision -----+----------+-----------------+---------- 1 | Stanford | science | t 1 | Stanford | engineering | t 1 | Berkeley | natural history | t (3 rows)
Supongamos ahora que hubo un error en la gestión de papeles respecto a la
postulación a ingeniería: Básicamente ‘Betty’ no quedó aceptada en dicha mención, por
lo tanto se debe modificar
UPDATE Apply_new SET decision = false WHERE sid = 1 and cname = 'Stanford' and major = 'engineering';
Lo que resulta en el cambio en la tabla:
sid | cname | major | decision -----+----------+-----------------+---------- 1 | Stanford | science | t 1 | Berkeley | natural history | t 1 | Stanford | engineering | f (3 rows)
Supongamos ahora que ‘Betty’, por suerte, es una persona distraída y debido a sus
enormes ganas de entrar a ciencias no se percata del error. El responsable de error, por
temor a poner en juego su reputación, decide eliminar el registro de la postulación, en
lo que considera un plan maestro, pues la tabla Apply_new no cuenta con un contador
serial que pudiese causar algún conflicto.
DELETE FROM Apply_new WHERE sid = 1 and cname = 'Stanford' and major = 'engineering';
Lo que resulta en el cambio en la tabla:
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 121 de 253
sid | cname | major | decision -----+----------+-----------------+---------- 1 | Stanford | science | t 1 | Berkeley | natural history | t (2 rows)
y en la impunidad del responsable.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 122 de 253
Lección XV - Teoría del diseño Relacional:
Información General
Diseñar un esquema de base de datos
Por lo general existen muchos diseños posibles.
Algunos son (mucho) mejor que otros.
¿Cómo elegir?.
El diseño de una base de datos relacional puede abordarse de dos formas:
Obteniendo el esquema relacional directamente: Objetos y reglas captadas del
análisis del mundo real, representadas por un conjunto de esquemas de
relación, sus atributos y restricciones de integridad.
Diseño del esquema conceptual: realizando el diseño del esquema “conceptual”
de la BD (modelo E/R) y transformándolo a esquema relacional.
En los esquemas de bases de datos es posible encontrar anomalías que serán
eliminadas gracias al proceso de normalización.
Estas anomalías son:
La redundancia de los datos: repetición de datos en un sistema.
Anomalías de actualización: inconsistencias de los datos como resultado de
datos redundantes y actualizaciones parciales.
Anomalías de eliminación: pérdidas no intencionadas de datos debido a que se
han borrado otros datos.
Anomalías de inserción: imposibilidad de adicionar datos en la base de datos
debido a la ausencia de otros datos.
A continuación se muestra una tabla y luego el detalle de los problemas que presenta:
Nombre_autorCortázar, JulioRosasco, José LuisRosasco, José LuisColoane,
FranciscoPaísArgChiChiChiCod_libro97860711107259789561224056956131
36699789563473308Titulo_libroCuentos Completos 1 Julio CortazarDonde
Estas, ConstanzaHoy Día es MañanaGolfo De PenasEditorAlfaguaraZig-
ZagAndrés BelloAlfaguaraDirección_editorialPadre Mariano 82Los
Conquistadores 1700Ahumada 131Padre Mariano 82
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 123 de 253
Redundancia: cuando un autor tiene varios libros, se repite su país de origen.
Anomalías de modificación: Si se cambia la dirección de la editorial “Alfaguara”,
se deben modificar dos filas. A priori no se puede saber cuántos autores tiene
un libro. Los errores son frecuentes al olvidar la modificación de un autor.
Anomalías de inserción: Se desea ingresar a un autor sin libros. “Nombre_autor”
y “Cod_libro” son campos claves, por lo que las claves no pueden ser valores
nulos.
Al eliminar estas anomalías se asegura:
Integridad entre los datos: consistencia de la información.
Otro ejemplo se muestra en la siguiente tabla:
Aplicar(SSN, sNombre, cNombre, HS, HSciudad, hobby)
Nota
La notación que se utiliza en la tabla es:
HS = high school (escuela secundaria).
123 Ann de PAHS (P.A) y GHS (P.A) juega tenis y toca la trompeta y postuló a Stanford,
Berkeley y al MIT
Los datos ingresados en la tabla podrían ser los que se muestran a continuación:
123123123..AnnAnnAnn..StanfordBerkeleyBerkeley..PAHSPAHSPAHSGHS
.P.AP.AP.A..tenistenistrompeta..
Redundancia: captura información muchas veces como por ejemplo “123 Ann”,
“PAHS”, “tenis” o “MIT”.
Anomalía de actualización: actualizar datos de diferente manera como “corneta”
por “trompeta”.
Anomalía de eliminación: eliminación inadvertida de datos.
Una correcta forma de realizar la tabla anterior sin anomalías es:
Estudiante(SSN, sNombre);
Aplicar(SSN, cNombre);
Escuela_secundaria(SSN, HS);
Ubicado(HS, HSciudad);
Aficiones(SSN, hobby);
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 124 de 253
Ejercicio
Considere la posibilidad de una base de datos que contiene información sobre los
cursos tomados por los estudiantes. Los estudiantes tienen un ID único de estudiante y
nombre; cursos tienen un número único de curso y título, los estudiantes toman un
curso de un año determinado y reciben una calificación.
¿Cuál de los siguientes esquemas recomiendan?
a. Tomo(SID, nombre, cursoNum, título, año, calificación)
b. Curso(cursoNum, título, año), Tomó(SID, cursoNum, calificación)
c. Estudiante(SID, nombre), Curso(cursoNum, título), Tomo(SID, cursoNum, año,
calificación)
d. Estudiante(SID, nombre), Curso(cursoNum, título), Tomo(nombre, título, año,
calificación)
La alternativa correcta es la letra (c), puesto que en el enunciado se dice que existen
estudiantes con un ID único, que en este caso será “SID” y un “nombre”; los cursos
tienen un ID único que es “cursoNum” y un “titulo”, además que los estudiantes toman
un curso en un año determinado “año” y reciben una calificación “grado”, pero el
atributo “cursoNum” actúa como clave foránea de la tabla Curso con la cual se podrá
obtener el titulo del curso y también debe poseer una clave primaria para poder
identificar el curso tomado que será “SID”.
Diseño por descomposición
Comienza con las “mega” relaciones que contienen todo.
Descomponer en partes más pequeñas, se obtienen mejores relaciones con la
misma información.
¿Se puede descomponer automáticamente?
Descomposición automática:
“Mega” relaciones + propiedades de los datos.
El sistema descompone basándose en las propiedades.
Conjunto final de relaciones satisface la forma normal.
o no hay anomalías, hay pérdida de información.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 125 de 253
Normalización
Proceso que analiza las dependencias entre los atributos de una relación de tal manera
de combinar los atributos, en entidades y asociaciones menos complejas y más
pequeñas. Consiste en un conjunto de reglas denominadas Formas Normales (FN), las
cuales establecen las propiedades que deben cumplir los datos para alcanzar una
representación normalizada. En este paso se toma cada relación, se convierte en una
entidad (relación o tabla) no normalizada y se aplican las reglas definidas para 1FN,
2FN, 3FN, Boyce Codd y 4FN.
Formas normales
La siguiente imagen muestra los tres principales niveles que se utilizan en el diseño de
esquemas de bases de datos.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 126 de 253
El proceso de normalización es fundamental para obtener un diseño de base de datos
eficiente. En una entidad no normalizada generalmente expresada en forma plana
(como una tabla), es muy probable que existan uno o más grupos repetitivos, no
pudiendo en ese caso ser un atributo simple su clave primaria.
A continuación se dará una definición y un ejemplo de las formas normales:
Primera formal normal (1FN)
Una tabla está normalizada o en 1FN, si contiene sólo valores atómicos en la
intersección de cada fila y columna, es decir, no posee grupos repetitivos. Para poder
cumplir con esto, se deben pasar a otra tabla aquellos grupos repetitivos generándose
dos tablas a partir de la tabla original. Las tablas resultantes deben tener algún atributo
en común, en general una de las tablas queda con una clave primaria compuesta. Esta
forma normal genera tablas con problemas de redundancia, y por ende, anomalías de
inserción, eliminación o modificación; la razón de esto es la existencia de lo que se
denomina dependencias parciales.
Ejemplo
Se dice que una tabla está encuentra en primera forma normal (1FN) si y solo si cada
uno de los campos contiene un único valor para un registro determinado. Supongamos
que deseamos realizar una tabla para guardar los cursos que están realizando los
estudiantes de informática de la USM, podríamos considerar el siguiente diseño.
Código123NombrePatriciaMargaritaJoaoCursosEstructura de datosBases de
datos, Teoría de sistemasEstructura de datos, Bases de datos
Se puede observar que el registro 1 cumple con la primera forma normal, puesto que
cada campo cumple con la condición de tener solo un dato, pero esta condición no se
cumple con el registro 2 y 3, en el campo de Cursos, ya que en ambos existen dos
datos. La solución a este problema es crear dos tablas del siguiente modo.
Tabla 1
Código123NombrePatriciaMargaritaJoao
Tabla 2
Código12233CursosEstructura de datosBases de datosTeoría de
sistemasEstructura de datosBases de datos
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 127 de 253
Como se puede comprobar, ahora todos los registros de las dos tablas cumplen con la
condición de tener en todos sus campos un solo dato, por lo tanto la Tabla 1 y Tabla
2 están en primera forma normal.
Segunda forma normal (2FN)
Una tabla está en 2FN, si está en 1FN y se han eliminado las dependencias parciales
entre sus atributos. Una dependencia parcial se da cuando uno o más atributos que no
son clave primaria, son sólo dependientes de parte de la clave primaria compuesta, o
en otras palabras, cuando parte de la clave primaria determina a un atributo no clave.
Este tipo de dependencia se elimina creando varias tablas a partir de la tabla con
problemas: una con los atributos que son dependientes de la clave primaria completa y
otras con aquellos que son dependientes sólo de una parte. Las tablas generadas deben
quedar con algún atributo en común para representar la asociación entre ellas. Al
aplicar esta forma normal, aún se siguen teniendo problemas de anomalías pues
existen dependencias transitivas.
Ejemplo
La segunda forma normal compara todos y cada uno de los campos de la tabla con la
clave definida. Si todos los campos dependen directamente de la clave se dice que la
tabla está en segunda forma normal.
Se construye una tabla con los años que cada profesor ha estado trabajando en cada
departamento de la USM.
Código_profesor12342Código_departamento63236NombreJavierLuisCeciliaN
oraLuisDepartamentoElectrónicaEléctricaInformáticaEléctricaElectrónicaAños
_trabajados3158220
La clave de esta tabla está conformada por el Código_profesor y Código_departamento,
además se puede decir que está en primera forma normal, por lo que ahora la
transformaremos a segunda forma normal.
El campo Nombre no depende funcionalmente de toda la clave, solo depende de
la clave Código_profesor.
El campo Departamento no depende funcionalmente de toda la clave, solo
depende de la clave Código_departamento.
El campo Años_trabajados si depende funcionalmente de las
claves Código_profesor y Código_departamento (representa los años trabajados
de cada profesor en el departamento de la universidad).
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 128 de 253
Por lo tanto al no depender funcionalmente todos los campos de la tabla anterior no
está en segunda forma normal, entonces la solución es la siguiente:
Tabla A
Código_profesor1234NombreJavierLuisCeciliaNora
Tabla B
Código_departamento236DepartamentoInformáticaEléctricaElectrónica
Tabla C
Código_empleado12342Código_departamento63236Años_trabajados3158220
Se puede observar que la Tabla A tiene como índice la clave Código_empleado, Tabla
B tiene como clave Código_departamento y laTabla C que tiene como clave
compuesta Código_empleado y Código_departamento, encontrándose finalmente estas
tablas en segunda forma normal.
Tercera forma normal (3FN)
Una tabla está en 3FN, si está en 2FN y no contiene dependencias transitivas. Es decir,
cada atributo no primario depende solo de la clave primaria, no existiendo
dependencias entre atributos que no son clave primaria. Este tipo de dependencia se
elimina creando una nueva tabla con el o los atributo(s) no clave que depende(n) de
otro atributo no clave, y con la tabla inicial, la cual además de sus propios atributos,
debe contener el atributo que hace de clave primaria en la nueva tabla generada; a este
atributo se le denomina clave foránea dentro de la tabla inicial (por clave foránea se
entiende entonces, a aquel atributo que en una tabla no es clave primaria, pero sí lo es
en otra tabla).
Ejemplo
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 de la primera forma
normal, un alumno solo puede tomar un curso a la vez y se desea guardar en que sala
se imparte el curso.
Código123NombrePatriciaMargaritaJoaoCursoEstructura de datosTeoría de
sistemasBases de datosSalaABC
Veamos las dependencias de cada campo respecto a la clave:
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 129 de 253
Nombre depende directamente del Código.
Curso depende de igual manera del Código.
La Sala depende del Código, pero está más ligado al Curso que el alumno está
realizando.
Es por este último punto que se dice que la tabla no está en 3FN, pero a continuación
se muestra la solución:
Tabla A
Código123NombrePatriciaMargaritaJoaoCursoEstructura de datosTeoría de
sistemasBases de datos
Tabla B
CursoEstructura de datosTeoría de sistemasBases de datosSalaABC
Boyce-Codd forma normal (FNBC)
Es una versión ligeramente más fuerte de la Tercera forma normal (3FN). La forma
normal de Boyce-Codd requiere que no existan dependencias funcionales no
triviales de los atributos que no sean un conjunto de la clave candidata. En una tabla en
3FN, todos los atributos dependen de una clave. Se dice que una tabla está en FNBC si y
solo si está en 3FN y cada dependencia funcional no trivial tiene una clave candidata
como determinante.
Dependencias funcionales y FNBC
Aplicar(SSN, sNombre, cNombre)
Redundancia, anomalías de actualización y eliminación.
Almacenamiento del SSN-sNombre para una vez por cada universidad.
Dependencia funcional SSN-> sNombre
SSN siempre tiene el mismo sNombre
En caso de almacenar sNombre cada SSN sólo una vez
Boyce-Codd forma normal si a-> b entonces a es una clave
Descomponer: Estudiante(SSN, sNombre) Aplicar(SSN, cNombre)
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 130 de 253
siendo finalmente SSN una clave primaria.
Ejemplo
Tenga en cuenta la relación Tomo(SID, nombre, cursoNum, título). Los estudiantes
tienen el carné de estudiante y un nombre único, los cursos tienen un número único
curso y título. Cada tupla de la relación codifica el hecho de que un estudiante dado
tomó el curso. ¿Cuáles son todas las dependencias funcionales para la relación tomó?
a. sID → cursoNum
b. sID → nombre, cursoNum → titulo
c. nombre → sID, titulo → cursoNum
d. cursoNum → sID
La respuesta correcta es la alternativa (b), puesto que un id de estudiante que único
“sID”, está asignado a solo un estudiante y un id del curso que es único “cursoNum”
tiene asignado un título. Las otras alternativas no son porque, la alternativa (a) dice un
estudiante sólo puede tomar un curso, la alternativa (c) dice que los nombres de los
estudiantes y los títulos de los cursos son únicos y la alternativa (d) dice que los cursos
sólo pueden ser tomados por un estudiante.
Cuarta forma normal (4FN)
La 4NF se asegura de que las dependencias multivaluadas independientes estén
correcta y eficientemente representadas en un diseño de base de datos. La 4NF es el
siguiente nivel de normalización después de la forma normal de Boyce-Codd (BCNF).
Una tabla está en 4NF si y solo si esta en Tercera forma normal o en BCNF y no posee
dependencias multivaluadas no triviales. La definición de la 4NF confía en la noción de
una dependencia multivaluada. Una tabla con una dependencia multivaluada es donde
hay una existencia de dos o más relaciones independientes de muchos a muchos que
causa redundancia; que es suprimida por la cuarta forma normal.
Dependencias multivaluadas y 4FN
Aplicar(SSN, cNombre, HS)
Redundancia, anomalías de actualización y eliminación.
Efecto multiplicativo: C colegios o H escuelas secundarias, por lo que se
generarán “C * H” ó “C + H” tuplas.
No es dirigida por BCNF: No hay dependencias funcionales.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 131 de 253
La dependencia multivalor SSN->>cNombre ó SSN->>HS
SSN cuenta todas las combinaciones de cNombre con HS.
En caso de almacenar cada cName y HS, para obtener una vez un SSN.
Nota
La flecha ->> significa muchos
Cuarta Forma Normal si A->>B entonces A es una clave
Descomponer: Aplicar(SSN, cNombre) Escuela_secundaria(SSN, HS)
Ejemplo 1
Tenga en cuenta la relación Informacion_estudiante(SID, dormitorio, cursoNum). Los
estudiantes suelen vivir en varios dormitorios y tomar muchos cursos en la universidad.
Supongamos que los datos no capta en que dormitorio(s) un estudiante estaba en la
hora de tomar un curso específico, es decir, todas las combinaciones de cursos
dormitorio se registran para cada estudiante. ¿Cuáles son todas las dependencias para
la relación Informacion_estudiante?
a. sID->>dormitorio
b. sID->>cursoNum
c. sID->>dormitorio, sID->>cursoNum
d. sID->>dormitorio, sID->>cursoNum, dormitorio->>cursoNum
La alternativa correcta es (c), puesto que para un estudiante hay muchos dormitorios y
un estudiante puede tomar muchos cursos. La alternativa (a) y (b) ambos omiten una
dependencia, la alternativa (d) dice que todos los estudiantes de cada dormitorio toman
el mismo conjunto de cursos.
Ejemplo 2
Una tabla está en cuarta forma normal si y sólo si para cualquier combinación clave-
campo no existen valores duplicados.
Geometría
FiguraCuadradoCuadradoCuadradoCírculoCírculoCírculoColorRojoAzulAzul
BlancoAzulAzulTamañoGrandeGrandeMedianoMedianoPequeñoMediano
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 132 de 253
Vamos a comparar el atributo clave Figura con Tamaño, se puede notar que Cuadrado
Grande está repetido; de igual manera Círculo Azul, entre otros registros. Son estas
repeticiones que se deben evitar para tener una tabla en 4FN.
La solución a la tabla anterior es la siguiente:
Tamaño
FiguraCuadradoCuadradoCírculoCírculoTamañoGrandeMedianoMedianoPequ
eño
Color
FiguraCuadradoCuadradoCírculoCírculoColorRojoAzulBlancoAzul
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 133 de 253
Lección XVI - Teoría del Diseño
Relacional: Dependencia Funcional
Dependencia Funcional
Dados dos atributos A y B de una relación R, se dice que B depende funcionalmente de
A, si cada valor de A tiene asociado un único valor de B. En otras palabras: si en
cualquier instante, conocido el valor de A podemos conocer el valor de B. Tanto A como
B pueden ser conjuntos de atributos. La dependencia funcional se simboliza del
siguiente modo:
R.A→R.B
Por ejemplo en la relación R(Nif−−−−, Nombre, Dirección), los
atributos Nombre y Dirección dependen funcionalmente de Nif.
Nif→(Nombre,Dirección)
Las dependencias funcionales son generalmente útiles para:
Almacenamiento de datos - compresión
Razonamiento acerca de las consultas - Optimización
Ejemplo 1:
Estudiante(SSN, sNombre, dirección, HScodigo, HSnombre, HSciudad, GPA, prioridad)
Aplicar(SSN, cNombre, estado, fecha, principal)
Supongamos que la prioridad es determinada por GPA
GPA > 3,8 prioridad = 1
3,3 < GPA <= 3,8 prioridad = 2
GPA <= 3,3 prioridad = 3
Dos tuplas con el mismo GPA tienen la misma prioridad
∀t,u∈Estudiante
t.GPA=u.GPA⇒t.priority=u.priority
GPA→prioridad
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 134 de 253
De forma general sería:
∀t,u∈R
t.A=u.A⇒t.B=u.B
A→B
∀t,u∈R
t.[A1,...,An]=u.[A1,...,An]=>t.[B1,...,Bn]=u.[B1,...,Bn]
A1,A2,...,An→B1,B2,...,Bn
A¯¯¯→B¯¯¯
Ejemplo 2
Considere la posibilidad de una relación R (A, B, C, D, E) con dependencias funcionales:
A,B→C
C,D→E.
Supongamos que hay un máximo de 3 valores diferentes para cada uno de A, B y D.
¿Cuál es el número máximo de valores diferentes para la E?
a. 27
b. 9
c. 3
d. 81
La alternativa correcta es (a), puesto que hay a lo sumo 3 * 3 = 9 combinaciones de
valores de A, B, así que por A, B -> C como máximo 9 valores diferentes para C con un
máximo de 3 valores diferentes para D, por C,D -> E hay en la mayoría de 9 * 3 = 27
valores diferentes para E.
Las dependencias funcionales para las tablas son:
Student(SSN, sNombre, dirección, HScodigo, HSnombre, HSciudad, GPA, prioridad)
SSN→sNombre
SSN→dirección
HScodigo→HSnombre,HSciudad
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 135 de 253
HSnombre,HSciudad→HScodigo
SSN→GPA
GPA→prioridad
SSN→prioridad
Apply(SSN, cNombre, estado, fecha, principal)
cNombre→fecha
SSN,cNombre→principal
SSN→estado
Ejemplo 3
Para la relación Aplicar(SSN, cNombre, estado, fecha, principal), lo que en el mundo real
es capturado por restricción SSN,fecha -> cNombre?
a. Un estudiante sólo puede aplicar a un colegio.
b. Un estudiante puede aplicar a cada colegio una sola vez.
c. Un estudiante debe aplicar a todos los colegios en la misma fecha.
d. Toda solicitud de un estudiante a un colegio específico debe estar en la misma
fecha.
La alternativa correcta es (d), puesto que cualquiera de las dos tuplas con el mismo
SSN-cNombre combinación también deben tener la misma fecha. Así que si un
estudiante (SSN) se aplica a una universidad (cNombre) más de una vez, deben estar en
la misma fecha.
Dependencias funcionales y llaves
Relación sin duplicados
Supongamos A¯¯¯ todos los atributos
Dependencia funcional Trivial
A¯¯¯→B¯¯¯B¯¯¯⊆A
Dependencia funcional no Trivial
A¯¯¯→B¯¯¯B¯¯¯⊈A
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 136 de 253
Dependencia funcional completamente Trivial
A¯¯¯→B¯¯¯A¯¯¯∩B¯¯¯=⊘
Reglas para las dependencias funcionales
Regla de la división
A¯¯¯→B1,B2,…,Bn
A¯¯¯→B1A¯¯¯→B2…
¿Se puede también dividir a la izquierda?
A1,A2,…,An→B¯¯¯
A1→B¯¯¯A2→B¯¯¯…
No se puede realizar una división a la izquierda
Combinación de las reglas
A¯¯¯→B1
A¯¯¯→B2
A¯¯¯→B…
A¯¯¯→Bn
⇒A¯¯¯→B1,B2,…,Bn
Reglas de dependencia trivial
A¯¯¯→B¯¯¯B¯¯¯⊆A
A¯¯¯→B¯¯¯entoncesA¯¯¯→A¯¯¯∪B¯¯¯
A¯¯¯→B¯¯¯entoncesA¯¯¯→A¯¯¯∩B¯¯¯
Regla transitiva
A¯¯¯→B¯¯¯B¯¯¯→A¯¯¯thenA¯¯¯→C¯¯¯
Cierre de atributos
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 137 de 253
Dada una relación, dependientemente funcional, un conjunto de atributos A¯¯¯
Encuentre todos los B de forma que A¯¯¯→B
Ejemplo 4
Un ejemplo de cierre de atributos es:
Estudiante(SSN, sNombre, dirección, HScodigo, HSnombre, HSciudad, GPA, prioridad)
SSN→sNombre, dirección, GPA
GPA→prioridad
HScodigo→HSnombre, HSciudad
{SSN, HScodigo}+→(todos los atributos)(llave)
{SSN, HScodigo, sNombre, dirección, GPA, prioridad, HSnombre, HSciudad}
Clausura y llaves
¿Es A¯¯¯ una llave para R?
Calcular A+¯¯¯¯¯ Si = todos atributos, entonces A¯¯¯ es una llave.
¿Cómo podemos encontrar todas las llaves dado un conjunto de dependencias
funcionales?
Considerar cada subconjunto A¯¯¯ de los atributos.
A+→ todos los atributos
es llave
Ejemplo 5
Tenga en cuenta la relación R (A, B, C, D, E) y supongamos que tenemos las
dependencias funcionales:
AB→C
AE→D
D→B
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 138 de 253
¿Cuál de los siguientes pares de atributos es una clave para R?
a. AB
b. AC
c. AD
d. AE
La alternativa correcta es (d), puesto que {AB}+ = {ABC}; {AC}+ = {AC}; {AD}+ = {ABCD};
{AE}+ = {ABCDE}.
Especificación funcionalmente dependiente para una
relación
S1 y S2 conjunto funcionalmente dependiente.
S2 “sigue de” S1 si cada instancia de relación satisfacer S1 si también satisface S2
S2: {SSN, prioridad}
S1: {SSN → GPA, GPA → prioridad}
Nota
Se observa que S1 satisface S2
Ejemplo 6
Consideremos la relación R (A, B, C, D, E) y el conjunto de dependencias funcionales S1
= {AB → C, AE → D, D → B}.
¿Cuál de los siguientes conjuntos de S2 FD NO se deduce de S1?
a. S2 = {AD → C}
b. S2 = {AD → C, AE → B}
c. S2 = {ABC → D, D → B}
d. S2 = {ADE → BC}
La alternativa correcta es (c), puesto que el uso de las FDs en S1: {AD}+ = {ABCD}; {AE}+
= {ABCDE}; {ABC}+ = {ABC}; {D}+ = {B}; {ADE}+ = {ABCDE}
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 139 de 253
Lección XVII - Teoría del diseño
relacional: Forma normal Boyce-Codd
Conceptos previos
Tipos de claves (llaves)
Llave primaria, clave candidata y superclave se refieren a un atributo o un conjunto de
atributos que permiten identificar unívocamente un registro. Es decir que no existe en
esa relación un registro que tenga el mismo valor en ese (esos) atributo(s).
Superclave: (llave compuesta) es un conjunto de uno o más atributos que,
tomados colectivamente, permiten identificar unívocamente cada registro de la
tabla. Es un subconjunto de atributos que permite distinguir de forma única
cada una de las tuplas. Si se une otro atributo al subconjunto anterior, el
resultado seguirá siendo una superclave.
Ejemplo
El atributo idCliente de la relación Cliente es suficiente para distinguir una fila de
un Cliente de las otras. Así, idCliente es una superclave. Análogamente, la combinación
de nombre y idCliente es una superclave del conjunto de relación Cliente. El
atributonombre de cliente no es una superclave, porque varias personas podrían tener
el mismo nombre.
El concepto de una superclave no es suficiente para lo que aquí se propone, ya que,
como se ha visto, una superclave puede contener atributos innecesarios. Si K es una
superclave, entonces también lo es cualquier superconjunto de K. A menudo interesan
las superclaves tales que los subconjuntos propios de ellas no son superclave.
Tales superclaves mínimas se llaman claves candidatas.
Clave candidata: Cuando una superclave, se reduce al mínimo de atributos que
la componen, pero aún así sirve para identificar la tupla, entonces ésta pasa a
ser una clave candidata. La clave (o llave) candidata es solo a nivel conceptual.
En una relación más de un atributo podría llegar a ser llave primaria, pues
pueden identificar a cada tupla, es decir que no existen dos valores para ese
atributo que sean iguales. Dichos atributos que se proponen a reconocer una
tupla, se denominan clave candidata porque son candidatos a ser clave primaria.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 140 de 253
Ejemplo
Es posible que conjuntos distintos de atributos pudieran servir como clave candidata.
Supóngase que una combinación de nombre ydirección es suficiente para distinguir
entre los miembros del conjunto de la relación Cliente. Entonces, los
conjuntos {idCliente} y{nombre, calle} son claves candidatas. Aunque los
atributos idCliente y nombre juntos puedan distinguir las tuplas de Cliente, su
combinación no forma una clave candidata, ya que el atributo idCliente por sí solo es
una clave candidata.
Clave primaria: Una vez que se elige cual de los atributos de la clave candidata
será el que permitirá identificar cada registro en una tabla, dicho atributo se
pasa a llamar llave primaria. Se puede decir que la clave primaria es una clave
candidata, elegida por el diseñador de la base de datos, para identificar
unívocamente las tuplas.
Nota
Otro concepto que se utilizará es el de dependencia funcional(DF) que se puede repasar en
la Lección16
Forma normal Boyce-Codd
La definición original de la 3FN no trataba satisfactoriamente el caso de una relación
que tenía dos o más claves candidatas compuestas y que tenían al menos un atributo
en común. Es por esto que se crea la forma normal de Boyce-codd(FNBC), que es una
forma normal estrictamente más sólida que la 3FN, la cual atiende los caso que no
cubre correctamente la 3FN.
Nota
No es tan frecuente encontrar relaciones con más de una claves candidatas compuestas y
con al menos un atributo en común. Para una relación en donde no suceden, las 3FN y FNBC
son equivalentes.
Definición
Un esquema de relación R está en FNBC si, para todas las dependencias funcionales de
la forma A->B, donde A y B son subconjuntos de R, se cumplen las siguientes
condiciones:
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 141 de 253
A->B es una dependencia funcional (DF) trivial: (B es subconjunto de A).
Entonces se mantiene la condición de FNBC, debido a que sólo una DF no trivial
puede violar esta condición.
A es una superclave del esquema R: Si se tiene A -> B, pero no B-> A, entonces
A es la superclave y cada dependencia no trivial contiene A en la izquierda, por
tanto no hay violación a la condición FNBC.
Toda dependencia funcional trivial tiene una clave candidata como su
determinante.
Un diseño de base de datos está en FNBC si cada miembro del conjunto de esquemas
de relación que constituye el diseño está en FNBC.
Vale la pena señalar que la definición FNBC es conceptualmente más simple que la
definición anterior de la 3FN, ya que no hace referencias explícitas a la primera y
segunda formas normales como tales, ni al concepto de dependencia transitiva.
Además, aunque (como ya indicamos) la FNBC es estrictamente más sólida que la 3FN,
se sigue dando el caso que cualquier relación dada puede descomponerse sin pérdida
en una colección equivalente de relaciones FNBC.
Descomposición para lograr la FNBC
En algunas ocasiones con la elección de descomposiciones adecuadas, se puede romper
cualquier esquema de relación en una colección de subconjuntos de sus atributos con
las siguientes propiedades importantes:
1. Estos subconjuntos son los esquemas de relaciones en FNBC.
2. Los datos de la relación original se representa fielmente por los datos en las
relaciones resultantes de la descomposición. A grandes rasgos, tenemos que ser
capaces de reconstruir la relación original con exactitud a partir de las relaciones
descompuestas.
Lo anterior sugiere que tal vez lo único que se debe hacer es romper un esquema de
relación en subconjuntos de dos atributos, y el resultado estará en FNBC. Sin embargo,
tal descomposición arbitraria puede no satisfacer la condición (2). De hecho, se debe
ser más cuidadosos y utilizar el DF debido a guiar la descomposición. La estrategia de
descomposición que vamos a seguir es buscar un DF
trivial A1A2...An−>B1B2...Bm que viola FNBC, es decir, A1,A2,...,An no es una
superclave. Vamos a añadir a la derecha tantos atributos como son funcionalmente
determinado por A1,A2,...,An . Este paso no es obligatorio, pero a menudo se reduce
la cantidad de trabajo realizado, y lo vamos a incluir en nuestro algoritmo. La Figura
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 142 de 253
que se muestra a continuación ilustra cómo los atributos se dividen en dos esquemas
de relación que se superponen. Uno es de todos los atributos involucrados en la
violación de DF, y el otro es el lado izquierdo de la DF además de todos los atributos
que no participan en la DF, es decir, todos los atributos excepto los B’s que no son A’s.
Ejemplo 1
Película: título | año | duración | género | director | actor --------------+------+----------+--------+-----------------+------------- Forrest Gump | 1994 | 142 | Drama | Robert Zemeckis | Tom Hanks Forrest Gump | 1994 | 142 | Drama | Robert Zemeckis | Robin Wright Forrest Gump | 1994 | 142 | Drama | Robert Zemeckis | Gary Sinise The Godfather | 1972 | 175 | Crime | Mario Puzo | Marlon Brando Matrix | 1999 | 136 | Action | Wachowski | Keanu Reeves Matrix | 1999 | 136 | Action | Wachowski | Laurence Fishburne
La Relación Películas no es en FNBC. Para ver por qué, primero tenemos que determinar
qué conjuntos de atributos son claves. Nuestra hipótesis será que {título, año,
actor} son en conjunto una clave, para demostrar que es una clave en primer lugar,
tenemos que verificar que identifica inequívocamente una tupla. Para ello supongamos
que dos tuplas tienen igual valor en estos tres atributos:{título, año, actor}. Al ser la
misma película, los otros atributos {duración, género, director} serán iguales también.
Así, dos tuplas diferentes no pueden concordar en {título, año, actor} pues en realidad
sería la misma tupla.
Ahora, debemos argumentar que ningún subconjunto propio de {título, año,
actor} determina funcionalmente a todos los demás atributos. Primero se observa que el
título y el año no determinan a actor, porque muchas películas tienen más de un actor.
Por lo tanto, {título, año} no es una clave. {año, actor} no es una clave, porque
podríamos tener un actor en dos películas en el mismo año, por lo tanto: actor año -
> título no es un DF. Asimismo, sostenemos que {título, actor} no es una clave,
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 143 de 253
porque dos películas con el mismo título, realizada en diferentes años, de vez en
cuando tienen un actor en común.
Como {título, año, actor} es una clave, cualquier conjunto de atributos que contienen
estos tres es una superclave. Los mismos argumentos anteriores se pueden utilizar
para explicar por qué no existe un conjunto de atributos que no incluya a los tres
atributos{título, año, actor} que pudiera ser una superclave. Por lo tanto, afirmamos
que {título, año, actor} es la única clave para Películas.
Sin embargo, tenga en cuenta:
título año-> duración género actor
Desafortunadamente, el lado izquierdo de la anterior DF no es una superclave. En
particular, se sabe que el título y el año no determinan funcionalmente el atributo actor.
Por lo tanto, la existencia de esta DF viola la condición FNBC y nos dice que Películas no
está en FNBC.
Por otro lado:
Películas2: título | año | duración | género | director --------------+------+----------+--------+----------------- Forrest Gump | 1994 | 142 | Drama | Robert Zemeckis The Godfather | 1972 | 175 | Crime | Mario Puzo Matrix | 1999 | 136 | Action | Wachowski
año título -> duración género director
La única clave para Películas2 es {título, año}. Por otra parte, la única DF no trivial debe
tener por lo menos título y año en el lado izquierdo, y por lo tanto su lado izquierdo
debe ser superclave. Por lo tanto, Películas2 está en FNBC.
Ejemplo 2
Se tiene un esquema de relación y sus respectivas dependencias funcionales:
cliente = (nombreC, dirección, ciudadC)
nombreC -> dirección ciudad
sucursal = (nombreS, activo,ciudadS)
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 144 de 253
nombreS -> activo ciudadS
Puede afirmarse que cliente está en FNBC. Obsérvese que una clave candidata para la
relación es nombreC. Las únicas dependencias funcionales no triviales que se cumplen
en cliente tienen a nombreC a la izquierda de la flecha. Dado que nombreC es una clave
candidata, las dependencias funcionales con nombreC en la parte izquierda no violan la
definición de FNBC. De manera parecida, se puede demostrar fácilmente que relación
sucursal está en FNBC.
Ejemplo 3
Clases: ID | asignatura | profesor ----+------------+---------- 121 | Lenguaje | Paul 121 | Matemáticas| David 345 | Lenguaje | Paul 567 | Matemáticas| Robert 567 | Lenguaje | Julia 563 | Matemáticas| Robert
La tabla está en 3FN pues no posee dependencias transitivas, pero no está en forma de
Boyce - Codd, ya que (ID, asignatura)->profesor y profesor->asignatura.
En este caso la redundancia ocurre por mala selección de clave. La redundancia de la
asignatura es completamente evitable. La solución sería:
ID | profesor ----+---------- 121 | Paul 121 | David 345 | Paul 567 | Robert 567 | Julia 563 | Robert asignatura | profesor -----------+---------- Lenguaje | Paul Matemáticas| David Matemáticas| Robert Lenguaje | Julia
En las formas de Boyce-Codd hay que tener cuidado al descomponer ya que se podría
perder información por una mala descomposición.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 145 de 253
Lección XVIII - Teoría de Diseño
Relacional: Dependencias Multivaluadas
(4ta forma normal)
Dependencias multivaluadas
Introducción
Una dependencia multivaluada es una afirmación donde dos atributos o conjuntos de
atributos son independientes uno de otro. Si A implica B, las dependencias
funcionales prohíben que haya dos tuplas con igual valor de A y distinto valores de B,
es decir A tiene asociado un único valor de B. Al contrario las dependencias
multivaluadas permiten que un mismo valor de A tenga asociado diferente valor de B,
pero exige que estén presentes en la relación de una forma determinada. Por este
motivo, las dependencias funcionales se conocen también como dependencias de
generación de igualdad y las dependencias multivaluadas se denominandependencias
de generación de tuplas.
Atributo de independencia y redundancia
En bases de datos, la redundancia hace referencia al almacenamiento de los mismos
datos varias veces en diferentes lugares. Esto puede traer problemas como incremento
en el procesamiento, desperdicio de espacio de almacenamiento e inconsistencia de
datos. Si una base de datos está bien diseñada, debería haber mínima redundancia de
datos, es decir una redundancia de datos controlada, que se emplea para mejorar el
rendimiento en las consultas a las bases de datos.
Ejemplo
Suponga que se tiene información acerca de nombres de cursos, profesores y textos. La
tupla indica que dicho curso puede ser enseñado por cualquiera de los profesores
descritos y que utiliza como referencias todos los textos especificados. Para un curso
dado, puede existir cualquier número de profesores y cualquier cantidad de textos
correspondientes. Los profesores y los textos son independientes entre sí; es decir,
independientemente de quién imparta el curso, se utilizan los mismos textos.
curso | profesor | texto ---------------+----------+---------------------------- Base de datos | Ullman | A First Course in Database
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 146 de 253
Base de datos | Ullman | Database System Concepts Base de datos | Widom | A First Course in Database Base de datos | Widom | Database System Concepts Programación | Ullman | Rapid GUI Programming Programación | Ullman | Learning Python Programación | Ullman | Python Algorithms
Se puede observar que el ejemplo involucra una buena cantidad de redundancia, la cual
conduce a algunas anomalías de actualización. Por ejemplo, para agregar la
información que el curso de Base de datos puede ser impartido por un nuevo profesor,
llamado Hetland, es necesario insertar dos nuevas tuplas; una para cada uno de los
textos.
curso | profesor | texto ---------------+----------+---------------------------- Base de datos | Ullman | A First Course in Database Base de datos | Ullman | Database System Concepts Base de datos | Widom | A First Course in Database Base de datos | Widom | Database System Concepts Base de datos | Hetland | A First Course in Database Base de datos | Hetland | Database System Concepts Programación | Ullman | Rapid GUI Programming Programación | Ullman | Learning Python Programación | Ullman | Python Algorithms
Los problemas en cuestión son generados por el hecho que los profesores y los textos
son completamente independientes entre sí.
La existencia de relaciones con la problemática de la Forma Normal de Boyce-Codd
(FNBC) como la del ejemplo llevaron a presentar la noción de las dependencias
multivaluadas.
Las dependencias multivaluadas son una generalización de las dependencias
funcionales, en el sentido de que toda dependencia funcional(DF) es una dependencia
multivaluada (DMV), aunque lo opuesto no es cierto (es decir, existen DMVs que no son
DFs).
Definición formal
Sea R una relación y sean A, B y C subconjuntos de los atributos de R. Entonces decimos
que B es multidependiente de A, si y solamente si en todo valor válido posible de R, el
conjunto de valores B que coinciden con un determinado par (valor A, valor C) depende
sólo del valor de A y es independiente del valor de C.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 147 de 253
Es fácil mostrar que dado R{A,B,C}, A->->B es válida si y solamente si también es
válida A->->C. Las dependencias multivaluadas siempre van en pares. Por esta razón, es
común representar ambas en un solo enunciado de esta manera:
A->->B|C
A partir de la definición de dependencia multivaluada se puede obtener la regla
siguiente:
Si A->B, entonces A->->B.
En otras palabras, cada dependencia funcional es también una dependencia
multivaluada.
Las dependencias multivaluadas se utilizan de dos maneras:
1. Para verificar las relaciones y determinar si son legales bajo un conjunto dado de
dependencias funcionales y multivaluadas.
2. Para especificar restricciones del conjunto de relaciones legales; de este modo,
sólo habrá que preocuparse de las relaciones que satisfagan un conjunto dado
de dependencias funcionales y multivaluadas.
Cuarta Forma Normal
La Cuarta Forma Normal (4FN) tiene por objetivo eliminar las dependencias
multivaluadas. La 4FN asegura que las dependencias multivaluadas independientes
estén correcta y eficientemente representadas en un diseño de base de datos. La 4FN es
el siguiente nivel de normalización después de la Forma Normal de Boyce-Codd (FNBC).
Definición
Una relación está en 4FN si y sólo si, en cada dependencia multivaluada A->-
>B no trivial, A es clave candidata. Una dependencia multivaluada A->->B es
trivial cuando B es parte de A. Esto sucede cuando A es un conjunto de
atributos, y B es un subconjunto de A.
Nota
Si una relación tiene más de una clave, cada una es una clave candidata. Una de ellas es
arbitrariamente designada como clave primaria, el resto son secundarias.
Es otras palabras una relación está en 4FN si esta en Tercera Forma Normal o en FNBC y
no posee dependencias multivaluadas no triviales. Como se mencionó, una relación
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 148 de 253
posee una dependencia multivaluada cuando la existencia de dos o más relaciones
independientes muchos a muchos que causan redundancia; y es esta redundancia la
que es suprimida por la Cuarta Forma Normal.
Ejemplo 1
Consideremos nuevamente el ejemplo anterior de cursos, profesores y textos. Se
consigue una mejora si se descompusiera en sus dos proyecciones: Profesores
(curso,profesor) y Textos (curso,texto).
Profesores: curso | profesor ---------------+---------- Base de datos | Ullman Base de datos | Widom Programación | Ullman Textos: curso | texto ---------------+----------------------------- Base de datos | A First Course in Database Base de datos | Database System Concepts Programación | Rapid GUI Programming Programación | Learning Python Programación | Python Algorithms
Para agregar la información que el curso de Base de datos puede ser impartido por un
nuevo profesor, sólo tenemos que insertar una tupla en la relación Profesores:
Profesores: curso | profesor ---------------+---------- Base de datos | Ullman Base de datos | Widom Base de datos | Hetland Programación | Ullman
También se observa que se puede recuperar la relación inicial al juntar nuevamente
Profesores y Textos, de manera que la descomposición es sin pérdida.
En este ejemplo hay dos DMVs válidas:
CURSO ->-> PROFESOR
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 149 de 253
CURSO ->-> TEXTO
La primera DMV se lee como “Profesor es multidependiente de Curso” o manera
equivalente, “Curso multidetermina a Profesor”.
Ejemplo 2
Se tiene una relación entre estudiantes, ramo y deporte. Los estudiantes pueden
inscribirse en varios ramos y participar en diversos deportes. Esto quiere decir que el
atributo sid no será único, de esta forma la única clave candidata posible es la
combinación de los atributos (sid, ramo, deporte). El estudiante 1 tiene los ramos física
y programación, participa en natación y tenis. El estudiante 2 sólo tiene el ramo
matemáticas y participa en voleibol.
sid | ramo | deporte ----+--------------+------------ 1 | física | natación 1 | programación | natación 1 | física | tenis 1 | programación | tenis 2 | matemáticas | voleibol
La relación entre sid y ramo no es una dependencia funcional porque los estudiantes
pueden tener distintos ramos. Un valor único de sid puede poseer muchos valores de
ramo. Esto también se aplica a la relación entre sid y deporte.
Se puede notar entonces que tal dependencia por atributos es una dependencia
multivaluada. Se aprecia la redundancia en el ejemplo pues el estudiante 1 tiene cuatros
registros. Cada uno de los cuales muestra uno de sus ramos junto con uno de sus
deportes. Si los datos se almacenaran con menos filas: si hubiera sólo dos tuplas, uno
para física y natación y uno para programación y tenis, las implicaciones serían
engañosas. Parecería que el estudiante 1 sólo nadó cuando tenía física como ramo y
jugó tenis sólo cuando tenía programación como ramo. Esa interpretación no es lógica.
Sus ramos y sus deportes son independientes entre sí. Para prevenir tales engañosas
conclusiones se almacenan todas las combinaciones de ramos y deportes.
Si el estudiante 1 decide que quiere inscribirse en fútbol, se deben agregar dos tuplas
con el fin de mantener la consistencia en los datos, se debe agregar una fila para cada
uno de sus ramos, como en se muestra a continuación:
sid | ramo | deporte ----+--------------+------------ 1 | física | fútbol 1 | programación | fútbol
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 150 de 253
1 | física | natación 1 | programación | natación 1 | física | tenis 1 | programación | tenis 2 | matemáticas | voleibol
Esta relación está en FNBC (2FN porque todo es clave primaria; 3FN porque no tiene
dependencias transitivas; y FNBC porque no tiene determinantes que no son claves). A
pesar de esto se aprecia esta anomalía de actualización, pues hay que hacer
demasiadas actualizaciones para realizar un cambio en los datos.
Lo mismo ocurre si un estudiante se desea inscribir un nuevo ramo. También existe
anomalía si un estudiante des-inscribe un ramo pues se deben eliminar cada uno de los
registros que contienen tal materia. Si participa en cuatro deportes, habrá cuatro tuplas
que contengan el ramo que ha dejado y deberán borrarse las cuatro tuplas.
Para evitar tales anomalías se construyen dos relaciones, donde cada una almacena
datos para solamente uno de los atributos multivaluados. Las relaciones resultantes no
tienen anomalías:
Ramos: sid | ramo ----+------------- 1 | física 1 | programación 2 | matemáticas Deportes: sid | deporte ----+---------- 1 | fútbol 1 | natación 1 | tenis 2 | voleibol
A partir de estas observaciones, se define la 4FN: Una relación está en 4FN si está en
FNBC y no tiene dependencias multivaluadas.
Ejemplo 3
Se tiene una tabla de Agenda con atributos multivaluados:
Agenda(nombre, teléfono, correo)
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 151 de 253
Se buscan las claves y las dependencias. Las claves candidatas deben identificar de
forma unívoca cada tupla. De modo los tres atributos deben formar la clave candidata.
Pero las dependencias que se tienen son:
nombre ->-> teléfono
nombre ->-> correo
Y nombre no es clave candidata de esta relación, por lo que se debe separar esta
relación en 2 relaciones:
Teléfonos(nombre,teléfono)
Correos(nombre,correo)
Ahora en las dos relaciones se cumple la 4FN.
Nota
De manera general una relación se separa en tantas relaciones como atributos multivaluados
tenga.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 152 de 253
Lección XIX - Lenguaje de modelado
unificado: UML modelado de datos
Dentro del modelado de BD Relacionales, los métodos más conocidos son los
diagramas de Entidad-Relación (ER), vistos en la primera semana, y el Lenguaje de
Modelado Unificado (UML, por sus siglas en inglés). Ambos comparten la característica
de ser gráficos; es decir que UML, al igual que ER está compuesto por “símbolos” bajo
una serie de reglas. Además, ambos comparten la cualidad de que pueden ser
traspasados a lenguaje de BD de forma relativamente autónoma.
Por otro lado, cabe destacar que ER es mucho más antiguo que UML, superándole en
edad en el orden de décadas. UML es un lenguaje más amplio, es decir, no solo se
utiliza para modelar BD, sino que es utilizado para modelar software también.
En lugar de crear las relaciones de forma directa en la BD, el diseñador realiza un
modelado de alto nivel, de modo que la situación que se está enfrentando con la BD
pueda verse en su totalidad. Posteriormente el diseñador, una vez que valida su
modelo, procede a su traducción al lenguaje de la BD.
Esta situación no presenta trabajo innecesario (correspondiente al modelado y a la
posterior creación de relaciones en la BD), pues afortunadamente la gran mayoría de
estas herramientas permiten realizar una traducción al lenguaje de la BD.
Nota
Existen variadas herramientas a la hora de graficar diagramas UML. Algunas de
ellas son: DIA, StarUML o Umbrello entre otras.
Existen 5 conceptos claves en UML:
1. Clases
2. Asociaciones
3. Clases de asociación
4. Subclases
5. Composiciones y agregaciones
Clases
Las clases se componen de: nombre, atributos y métodos. Para quienes hayan
experimentado alguna vez con la programación orientada a objetos probablemente se
sientan algo familiarizados.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 153 de 253
A la hora de realizar modelos de BD, es necesario agregar un identificador para el
atributo corresponde que a la clave primaria, además de un método de eliminación.
No obstante en está Lección se pondrá más énfasis en los atributos, pues está enfocada
más al modelado de datos que a su operación a través de sus métodos.
Ejemplo 1
Retomemos el caso de los Estudiantes y Establecimientos Educacionales. Dibujemos
ambas relaciones como clases en UML:
Asociaciones
Las Asociaciones corresponden a como se relacionan 2 clases.
Ejemplo 2
El ejemplo 1 terminó con 2 clases separadas, es decir, Estudiantes y Establecimientos
Educacionales. Sin embargo, y como ya se ha visto en ejemplos de Leccións anteriores,
los estudiantes postulan a estos establecimientos, por lo tanto la relación es postular:
Es decir que el Estudiante postula a un Establecimiento. Es posible direccionar esta
relación para lograr mayor claridad a la hora de ver los diagramas:
Sin embargo no marca la diferencia a la hora de traducir a relaciones, es necesario
cuantificar la relación
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 154 de 253
Multiplicidad
Es necesario determinar cuántas veces un objeto de una clase puede relacionarse con
objetos de otra clase. Supongamos que se han creado las clases C1 y C2, la
multiplicidad apunta a:
"Cada objeto de la clase C1 está asociado (a través de la relación A)a al menos 'm' y a lo más 'n' objetos de la clase C2"
La notación para ello corresponde a m..n, es decir que el valor mínimo es m y el
máximo n. Ambos valores van separados por .. (dos puntos).
Cabe mencionar que estas relaciones pueden ser bidireccionales
Algunos casos especiales son:
m..* -> a lo menos 'm' a lo más cualquier valor superior a 'm' 0..n -> a lo menos '0' a lo más 'n' 0..* -> a lo menos '0' a lo más cualquier valor superior a '0', es decir , sin restricción. 1..1 -> sólo 1 valor.
Existen varios tipos de multiplicidad, con su respectiva notación. Ellos son:
1. uno a uno: 0..1 - 0..1
2. muchos a uno: 0..* - 0..1
3. muchos a muchos: 0..* - 0..*
4. completa: 1..* - 1..1 o 1..1 - 1..* o 1..* - 1..*
Nota
En la multiplicidad completa, no deben quedar objetos sin relacionarse.
Ejemplo 3
Supongamos que cada Estudiante debe postular a lo menos a 1 Establecimientos y a lo
más a 3. Por otro lado, cada establecimiento puede recibir a lo más 50000
postulaciones.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 155 de 253
Ejemplo 4
Con el fin de diversificar y bajo el siguiente contexto, supongamos que tenemos
personas que realizan giros en bancos. Dependiendo del tipo de cuenta, supongamos
que existe una cuenta que permite a lo más 3 giros por mes. Por su parte, el banco no
tiene restricción de giros que puede recibir.
Clase de asociación
Esto se produce cuando la multiplicidad de las relaciones impide definir con exactitud
qué objeto de la clase C1 está asociado a qué objeto de la clase C2.
Ejemplo 5
Supongamos que tenemos a varios Estudiantes que desean postular a diferentes
Establecimientos Educacionales.
No obstante no hay información que permita definir qué estudiante realiza la
postulación, es por ello que se crea una clase de asociación, en este caso postulación
(Apply).
Nota
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 156 de 253
Cabe recordar que si no se especifica la multiplicidad de la relación, se define 1..1 por
defecto.
Sin embargo en este modelo no se permite el caso de que un Estudiante postule
múltiples veces a un mismo Establecimiento Educacional. Es por ello que es una buena
práctica que, en caso de utilizar este tipo de clases, se utilice como Clave Primaria (PK),
las PK de las clases que están relacionadas.
El siguiente diagrama clarificará la idea:
Eliminar clases de asociación innecesarias
Usando las clases genéricas C1, C2 de atributos A1, A2 y A3, A4 respectivamente.
Supongamos que la relación entre ellas es de multiplicidad (* - 1..1) o (* - 0..1).
Supongamos que existe una clase de asociación AC de atributos B1 y B2. Todo
ordenado de acuerdo a la siguiente imagen:
Es posible mover los atributos B1 y B2 a la clase C1, pues dada la multiplicidad un
objeto de la clase C1 está asociado a 1 objeto de la clase C2. Por lo tanto, la clase de
asociación se puede eliminar.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 157 de 253
Nota
La clase de asociación se puede eliminar cuando hay multiplicidad (* - 1..1) o (* - 0..1). De
hecho está pensada para dejar en claro que la asociación entre objetos en caso de que la
multiplicidad sea m, n o * en ambos lados de la relación.
Auto asociaciones
Corresponden a asociaciones entre una clase y si misma.
Ejemplo 6
Supongamos que se desea modelar en UML a la Universidad Técnica Federico Santa
María (UCHILE), su Casa Central y Campus. Supongamos que existen los
atributos NumAlumnos, Dirección, Nombre, Campus.
Existe una sola Casa Central, pero varios Campus, supongamos que por temas de
presupuesto, solo existen 7 campus.
En UML, es posible etiquetar la relación.
Subclases
Las clases se dividen:
1. Superclase/ Clase Padre: De carácter general, contiene información que
heredarán las diversas subclases.
2. Subclases/ Clases Hijas: De carácter específico, contiene información extra a la
que hereda de la superclase.
Estos conceptos nacen de la programación orientada a objetos.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 158 de 253
Ejemplo 7
Supongamos que dentro de la clase Estudiantes, se desea diferenciar a los estudiantes
extranjeros de los estudiantes nacionales. Se podría pensar en crear dos clases nuevas,
llamadas Estudiantes Nacionales y Estudiantes Extranjeros:
Sin embargo, hay atributos que se repiten en ambas, ellos son: sID, sName, Average. Es
por ello que se pueden separar en una superclase llamada Estudiante (la misma
utilizada en las otras Leccións), y crear 2 subclases llamadas Extranjeros y Nacionales.
Como se puede observar, los atributos mencionados son heredados por ambas
subclases. Ambas además agregan información más específica, como lo son
el país y pasaporte en el caso de los Extranjeros; la región y RUN en el caso de
los Nacionales. Esta técnica es muy útil para la reutilización.
Nota
Las Subclases heredan propiedades de las superclases / clase padre, es decir no solo
atributos, sino que también asociaciones u operaciones están disponibles en las subclases /
clases hijas.
Composiciones y Agregaciones
Ambas corresponden a la forma de representar que un objeto tiene como contenido a
otro, esto quiere decir que un objeto de un tipo, puede contener a otro.
Ejemplo 8
Supongamos que un objeto de tipo ciudad tiene una lista de objetos de tipo aeropuerto,
esto quiere decir, que una ciudad, tiene un número de aeropuertos.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 159 de 253
Nota
Hay que destacar, que la cardinalidad del extremo que lleva el rombo, es siempre uno.
Otro ejemplo puede ser que un medio de transporte tiene varias ruedas.
Nos está diciendo que los objetos rueda forman parte del objeto medio de transporte.
Pero, su ciclo de vida no está atado al del objeto medio de transporte. Es decir, si el
automóvil se destruye las ruedas pueden seguir existiendo independientemente.
En la misma linea, la composición, es una relación más fuerte de los objetos, así como
la agregación, es el hecho de que un objeto posea a otro, la composición es cuando la
relación entre ambos objetos es tal, que el primero no tiene sentido solo, y el segundo,
necesita definir al primero para ampliar su significado
Ejemplo 9
El avión tiene sentido por si solo. Está claro que está compuesto de 2 alas, esta relación
es de mucha fuerza, mucho más que el caso de los aeropuertos, y está claro, que un
avión siempre tendrá sus dos alas, y estas siempre serán del mismo avión.
La composición corresponde a aquellos objetos de los que depende un objeto para que
este llegue a funcionar, en éste caso el avión no puede funcionar sin las 2 alas.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 160 de 253
Lección XX - Lenguaje de Modelado
Unificado: UML y las bases de datos
Este lenguaje de modelado se caracteriza por:
Fácil de usar, se apoya en muchos diagramas (gráficos).
Es fácil traducirlo al modelo de DBMS.
En siguiente imagen anterior se observa que el lenguaje UML, puede ser traducido en
relaciones (o tablas) de una base de datos.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 161 de 253
Son cinco los conceptos claves:
1. Clases
2. Asociaciones
3. Clases de asociación
4. Subclases
5. Composición y Agregación
Los diseños pueden ser traducidos automáticamente a relaciones o tablas
Clases
Cada clase se convierte en una relación (o tabla) con su clave primaria
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 162 de 253
Según las clases descritas anteriormente tenemos las siguientes relaciones:
Estudiante(sID−−−−,sNombre,GPA)
Universidad(cNombre−−−−−−−−,estado,inscripción)
Asociaciones
Relación con la clave de cada lado.
Se obtendrán las mismas relaciones del ejemplo anterior, pero se agregará una nueva
relación con las claves primarias de ambas clases.
Aplicado(sID,cNombre)
Claves para las relaciones de asociación
Depende de la multiplicidad
Multiplicidad 1-1
Cada objeto de A está asociado con un objeto de B, y cada objeto
de B está asociado con un objeto de A.
Cualquiera de las dos tablas relacionadas implementará una
columna con el ID de la otra tabla.
Esta columna será la clave foránea para relacionarlas.
Multiplicidad 1-n
Cada objeto A está asociado con más objetos B, pero cada objeto
B está asociado con un objeto A.
Implementando la clave foránea ID en la tabla “muchos” a la tabla
“uno”.
Por ejemplo:
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 163 de 253
Ahora al tener una multiplicidad 1-n, se debe agregar la clave primaria Atr1_clase1 de
la Clase1 a la Clase2(que es la que posee la multiplicidad “muchos”), quedando como
clave foránea de la Clase2.
Finalmente, las relaciones quedan de la siguiente manera:
Clase1(Atr1_clase1−−−−−−−−−,Atr2_clase1)
Clase2(Atr1_clase2−−−−−−−−−,Atr2_clase2,Atr1_clase1)
Si la relación hubiese sido de 0..1-n, el atributo Atr1_clase1 sería NULL.
Ahora se mostrará otro ejemplo:
Las relaciones para este ejemplo serían:
Estudiante(sID−−−−,sNombre,GPA,cNombre)
Universidad(cNombre−−−−−−−−,estado,inscripción)
Al poseer este tipo de multiplicidad (1-n), se agrega a la clase Estudiante (muchos) la
clave primaria cNombrede la clase Universidad.
Multiplicidad n-m
Cada objeto A está asociado con más objetos B, y a su vez, cada
objeto B está asociado a más objetos A.
En el modelo relacional se usa una tabla auxiliar asociativa para
representar la relación.
Dicha tabla tendrá al menos dos columnas, cada una
representando la clave foránea a las dos tablas que relaciona.
Con lo anterior se transforma la relación n-m a dos relaciones (1-
n, 1-m).
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 164 de 253
Ejemplo
Supongamos que tenemos 0..2 en el lado derecho, por lo que los estudiantes pueden
solicitar hasta un máximo de 2 universidades. ¿Existe todavía una forma de “plegarse”
la relación de asociación en este caso, o que tenemos una relación
independiente Aplicado?
a. Sí, hay una manera.
b. No, si no es 0..1 ó 1..1 aplicado entonces se requiere.
La alternativa correcta es (a), puesto que se debería crear la relación Estudiante(sID,
sNombre, GPA, cNombre1, cNombre2), suponiendo que se permiten valores nulos.
Clase de asociación
Las clases de asociación permiten añadir atributos, operaciones y otras características a
las asociaciones.
Las relaciones de estas clases queda de la siguiente manera:
Estudiante(sID−−−−,sNombre,GPA)
Universidad(cNombre−−−−−−−−,estado,inscripción)
Aplicado(sID,cNombre,Fecha,Decisión)
Otro ejemplo que detalla más claramente las clases de asociación
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 165 de 253
El diagrama permite apreciar que una Persona puede trabajar para una sola Compañía.
Necesitamos conservar la información sobre el período de tiempo que trabaja cada
empleado para cada Compañía.
Para lograrlo, añadimos un atributo Período a la asociación Empleo.
Subclases
Si la clase “A” hereda de la clase “B”, entonces “B” es la superclase de “A”. “A”
es subclase de “B”. Los objetos de una subclase pueden ser usados en las circunstancias
donde son usados los objetos de la superclase correspondiente. Esto se debe al hecho
que los objetos de la subclase comparten el mismo comportamiento que los objetos de
la superclase.
1. Las relaciones de las subclases contienen una clave de la superclase más
atributos especializados.
S(K−−,A)
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 166 de 253
S1(K−−,B)
S2(K−−,C)
2. Las relaciones de las subclases contienen todos los atributos.
S(K−−,A)
S1(K−−,A,B)
S2(K−−,A,C)
3. Una relación que contiene todos los atributos de la superclase y la subclase.
S(K−−,A,B,C)
Ejemplo de subclases
Las relaciones de este ejemplo son:
Estudiante(sID−−−−,sNombre)
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 167 de 253
Est_extranjeros(sID−−−−,País)
Est_nacionales(sID−−−−,Estado,SS#)
AP_Estudiante(sID−−−−)
AP_Curso(Curso#−−−−−−−,Titulo)
Tomó(sID,Curso#,Año,Nota)
Composición y Agregación
Composición
La composición es un tipo de relación estática, en donde el tiempo de vida del objeto
incluido está condicionado por el tiempo de vida del que lo incluye (el objeto base se
construye a partir del objeto incluido, es decir, es parte/todo).
Ejemplo
Las relaciones se definen de la siguiente manera:
Universidad(cNombre−−−−−−−−,Estado)
Departamento(dNombre−−−−−−−−,Edificio,cNombre)
Agregación
La agregación es un tipo de relación dinámica, en donde el tiempo de vida del objeto
incluido es independiente del que lo incluye (el objeto base utiliza al incluido para su
funcionamiento).
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 168 de 253
Ejemplo
Las relaciones son de la misma manera que el ejemplo anterior pero al poseer una
diferente multiplicidad el valor del atributocNombre de la clase Departamento, puede
tómar el valor NULL.
Nota
El software utilizado en esta Lección para realizar los diagramas es “Umbrello”.
Lección XXI - Restricciones y triggers:
Introducción
Ambos están orientados a Bases de Datos Relacionales o RDB por sus siglas en inglés.
Si bien SQL no cuenta con ellos, en las diversas implementaciones del lenguaje se ha
corregido este “error”. Lamentablemente no cuenta con un estándar, por lo que existe
gran cantidad de variaciones.
Las restricciones, también llamadas restricciones de integridad, permiten definir los
estados permitidos dentro de la Base de Datos (BD).
Los triggers, en cambio, monitorean los cambios en la BD, chequean condiciones, e
inician acciones de forma automática. Es por ello que se les considera de naturaleza
dinámica, a diferencia de las restricciones de integridad, que son de naturaleza estática.
Ambos se analizarán en detalle en las próximas Leccións.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 169 de 253
Restricciones
Imponen restricciones de datos permitidos, más allá de aquellos impuestos por la
estructura y los tipos de datos en la BD.
Supongamos que estamos bajo el contexto del sistema de selección de estudiantes,
visto en algunas Leccións anteriores:
Ejemplo 1
Para que el estudiante sea aceptado, su promedio debe ser mayor a 50:
Average > 50
Ejemplo 2
El establecimiento X no puede tener más de 45000 alumnos:
Enrollment < 45000
Ejemplo 3
El criterio para la decisión es Verdadero, Falso o NULL:
Decisión: 'T', 'F', **NULL**
Las restricciones se utilizan para:
1. Evitar errores a la hora de ingresar datos (INSERT).
2. Evitar errores a la hora de modificar datos (UPDATE).
3. Forzar consistencia de datos.
Existen diversos tipos de restricciones. Ellas se clasifican en:
1. NOT NULL : No permiten valores nulos.
2. Key : Permiten sólo valores únicos, asociados a la llave primaria.
3. Integridad Referencial: Relacionados con la llave foránea y múltiples tablas.
4. Basado en atributos : Restringe el valor de un atributo.
5. Basado en tupla : Restringe el valor de una tupla. Más especifico que el anterior.
6. Generales : Restringen toda la BD.
Declarando y forzando restricciones
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 170 de 253
Se puede forzar el chequeo después de cada modificación peligrosa, es decir aquellas
que violan una restricción. No es necesario modificar después de un cambio de
promedio en la tabla de Estudiantes, eso sólo ralentizaría el sistema.
Otra forma de forzar chequeos es después de cada transacción. Este concepto, se verá
más adelante, pero es posible adelantar que una tras acciones corresponden a un
conjunto de operaciones que al finalizar modifican la BD.
triggers
La lógica del trigger es:
"Cuando pasa algo, se chequea una condición. Si es cierta se realiza una acción"
Como ya se mencionó, a diferencia de las restricciones, un trigger detecta un evento,
verifica alguna condición de activación y en caso de ser cierta, realiza una acción.
Contextualizándonos en el sistema de admisión de Estudiantes:
Ejemplo 4
Si la capacidad de un Establecimiento X, sobrepasa los 30000, el sistema debe
comenzar a rechazar a los nuevos postulantes:
Enrollment > 30000 -> rechazar nuevos postulantes
Ejemplo 5
Si un alumno tiene promedio mayor a 49.5, queda aceptado:
Student with Average > 49.5 -> Decision='True'
Los triggers se utilizan para:
1. Mover la lógica desde la aplicación a Sistema Administrador de la Base de Datos
(BDMS), lo cual permite un sistema más modular y automatizado.
2. Forzar restricciones. Ningún sistema implementado soporta todas las
restricciones de otro, es decir no existe un estándar actual. Un caso es el
ejemplo 5, en el cual algún DBMS podría redondear hacía abajo en lugar de hacia
arriba; con el trigger esto se podría resolver. Además existen restricciones que
no se pueden escribir de forma directa, pero si utilizando triggers.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 171 de 253
3. Forzar restricciones utilizando lógica reparadora. Un error se puede detectar y
realizar una acción, que puede ser por ejemplo, si existe la restricción 0 <=
Average <= 100, y alguien por error de tipeo ingresa un promedio -50,
un triggerpodría cambiar este valor a 0, por ejemplo cualquier valor que no
esté en el rango, cambiarlo a 0.
A modo de introducción, un trigger esta definido por
CREATE trigger name BEFORE|AFTER|INSTEAD OF events [referencing-variables] [FOR EACH ROW] WHEN (condition) action
Es decir que cada trigger tiene un nombre que es activado por eventos (antes, durante
o después). Se toman ciertas variables y por cada fila se revisa una condición se realiza
una acción.
Lección XXII - Restricciones y triggers:
Restricciones de múltiples tipos
Como se pudo apreciar en la Lección anterior, existen varios tipos de restricciones, las
cuales se dividen en:
1. Restricciones que no permiten valores NULL.
2. Restricciones de clave primaria.
3. Restricciones de atributo y tupla.
4. Restricciones generales.
Contexto
En esta Lección se utilizará el ejemplo del sistema de Postulación de Estudiantes a
Establecimientos Educacionales:
Student(sID, sName, Average); College(cName, State, Enrollment); Apply(sID, cName, Major, Desicion);
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 172 de 253
Comencemos a ver los diversos tipos de restricciones:
Restricciones para evitar valores NULL
Como su nombre lo indica, su idea es evitar que cierto atributo contenga valores nulos.
Ejemplo 1
Creemos una tabla de estudiantes, en la cual no se permita tener el campo ‘Average’
vacío.
CREATE TABLE Student (sID SERIAL, sName VARCHAR(50) Average INT NOT NULL, PRIMARY KEY (sID) );
Y posteriormente realicemos una serie de inserciones:
INSERT INTO Student (sName, Average) VALUES ('Amy', 60); INSERT INTO Student (sName, Average) VALUES ('Tim', null); INSERT INTO Student (sName, Average) VALUES (null, 90);
Lo cual para la segunda inserción, el siguiente error aparecerá:
ERROR: null value in column "average" violates not-null constraint
Ejemplo 2
Si probamos utilizando comandos de actualización (UPDATE)
Digamos que el promedio de ‘Amy’ es incorrecto, pero aún no se sabe cual es, por lo
que la persona encargada de realizar este trabajo (que no sabe la restricción que tiene
la tabla), decide poner un valor NULL:
UPDATE Student SET Average = null where sid = 1;
No obstante y para sorpresa de la persona, aparece:
ERROR: null value in column "average" violates not-null constraint
Restricciones de clave primaria
Recordando, una clave primaria es una clave que se utiliza para identificar de
forma única a cada linea en una tabla.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 173 de 253
Probemos este tipo de restricción con un par de ejemplos:
Ejemplo 3
Creemos una tabla de estudiantes (digamos estudiantes2 para no provocar
confusiones), en la cual se declare explícitamente su clave primaria.
CREATE TABLE Student2 (sID INT PRIMARY KEY, sName VARCHAR(50), Average INT);
Y luego insertamos algunos datos:
INSERT INTO Student2 VALUES (123,'Amy', 60); INSERT INTO Student2 VALUES (234,'Tim', 70); INSERT INTO Student2 VALUES (123,'Bob', 55);
Con las primeras dos inserciones no hay problemas, no obstante con la tercera, aparece
el siguiente error:
ERROR: duplicate key value violates unique constraint "student2_pkey" DETAIL: Key (sid)=(123) already exists.
Esto ocurre dado que, se definió sID como la clave primaria de la tabla.
Ejemplo 4
Similar al caso del Ejemplo 2, si se desea actualizar el valor del atributo sID,
UPDATE Student2 SET sID = 123 where sid = 234;
el siguiente error aparece:
ERROR: duplicate key value violates unique constraint "student2_pkey" DETAIL: Key (sid)=(123) already exists.
Cabe destacar que si se desea actualizar un sID que no existe por ‘123’, no aparece
dicho error, pero, no hay actualización:
UPDATE Student2 SET sID = 123 where sid = 999;
La salida es:
UPDATE 0
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 174 de 253
Ejemplo 5
Un caso curioso se da cuando se desea realizar varios cambios a la vez. El estado actual
de la tabla Student2 es:
sid | sname | average ----+-------+-------- 123 | Amy | 60 234 | Tim | 70
¿Qué ocurre si deseamos restar 111 a ambos sID?
UPDATE Student2 SET sID = sID - 111;
La salida es:
UPDATE 2
y el estado de la tabla es:
sid | sname | average ----+-------+-------- 12 | Amy | 60 123 | Tim | 70
Es decir no hay problemas. Pero ¿Qué pasa si se desea sumar 111 en lugar de restar?
UPDATE Student2 SET sID = sID + 111;
La salida es:
ERROR: duplicate key value violates unique constraint "student2_pkey" DETAIL: Key (sid)=(123) already exists.
Es decir, el orden de operaciones es FIFO, pues en la operación de resta no hubo
problemas: el sID de ‘Amy’ pasa de 123 a 12, luego el de ‘Tim’ de 234 a 123.
En el segundo caso al sumar, el sID de ‘Amy’ pasa de 12 a 123, pero genera conflicto
con el de ‘Tim’.
Nota
FIFO es acrónimo de “First In First Out”, es decir se atiende primero al primero que llega.
Este modelo de atención es conocido como cola.
Existe más de una forma de definir claves primarias:
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 175 de 253
Ejemplo 6
Por lo general, en SQL sólo se permite una clave primaria (de allí el nombre), al igual
que varias de sus implementaciones. Esta clave permite realizar un orden rápido y
eficiente.
Nota
Es posible definir más de un atributo como clave primaria propiamente tal, pero se reserva
el método para el próximo ejemplo.
Supongamos que se desea realizar la tabla Student otra vez, debido a fallas. En lugar de
DROP TABLE Student;
crear otra tabla, se utiliza el comando: En esta nueva tabla se desea que las claves
primarias sean sID y sName.
CREATE TABLE Student (sID INT PRIMARY KEY, sName VARCHAR(50) PRIMARY KEY, Average INT);
No obstante la salida es:
ERROR: multiple primary keys for table "student" are not allowed LINE1: ... E student (sID PRIMARY KEY, sNname VARCHAR(50) PRIMARY KE... ^
Una forma de evitar este error es utilizar UNIQUE en lugar de PRIMARY KEY, para el
atributo sName.
CREATE TABLE Student (sID INT PRIMARY KEY, sName VARCHAR(50) UNIQUE, Average INT);
En cuyo caso la salida será:
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "student_pkey" for table "student" NOTICE: CREATE TABLE / UNIQUE will create implicit index "student_sname_key" for table "student" CREATE TABLE
Al utilizar UNIQUE se permite tener incluso todos los atributos, que no son clave
primaria, como clave (no primaria). UNIQUE funciona comparando sólo los valores de la
columna en cuestión. Si se repite un valor, a pesar no haber claves conflictos en la clave
primaria, habrá error de todos modos:
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 176 de 253
INSERT INTO Student VALUES (123,'Amy', 60); INSERT INTO Student VALUES (234,'Tim', 70); INSERT INTO Student VALUES (345,'Bob', 55); INSERT INTO Student VALUES (456,'Amy', 90);
Para las primeras 3 inserciones no hay problemas. Si bien en la cuarta no hay conflicto
con la clave primaria:
ERROR: duplicate key value violates unique constraint "student_sname_pkey" DETAIL: Key (sname)=(Amy) already exists.
Es decir que se comparan sólo los valores de la columna/atributo sName. Como ‘Amy’
ya está, aparece el error de arriba.
Ejemplo 7
Como se dijo en la nota del ejemplo anterior, es posible definir un grupo de atributos
como clave primaria.
Para variar un poco las cosas, utilicemos la tabla College.
Supongamos que se desea crear la tabla College con 2 atributos como clave
primaria: cName y State.
Por el ejemplo 6 ya sabemos que algo como lo siguiente, no funcionará:
CREATE TABLE College (cName VARCHAR(50) PRIMARY KEY, State VARCHAR (30) PRIMARY KEY, Enrollment INT);
Pues no se permite el uso de múltiples claves primarias. Sin embargo es posible si se
define la clave primaria al final, única, pero de varios atributos:
CREATE TABLE College (cName VARCHAR(50), State VARCHAR(30), INT Enrollment, PRIMARY KEY (cName, State));
En este caso la salida será:
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "college_pkey" for table "college" CREATE TABLE
Si nos fijamos, la clave primaria se compone de cName y State. A esto se le conoce
como clave compuesta, pues no es ni una ni la otra, sino la combinación de ambas. Por
ejemplo si se hubiese dejado solo cName como clave primaria y State como UNIQUE, no
se permitirían las inserciones de este tipo:
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 177 de 253
INSERT INTO College VALUES ('MIT', 'CA',20000); INSERT INTO College VALUES ('Harvard', 'CA', 34000);
Nota
Los datos de las inserciones de arriba no tienen correlación con los datos utilizados en
otras Leccións o los reales. Sólo se utilizan para explicar el ejemplo.
Pues con UNIQUE en la columna State, no se permitiría ‘CA’ dos veces. No obstante al ser
un clave primaria compuesta, si se permite. En este caso una violación a la restricción,
sería el caso de 2 filas que compartan los mismos valores en ambos atributos, es decir
encName y State
Nota
Para el caso de PostgreSQL, en una atributo declarado como UNIQUE, se permite el múltiple
uso de valores NULL. Por otra parte si e desea utilizar NULL en una clave primaria (PK), no
está permitido.
Restricciones de atributo y tupla
Este tipo de restricción busca limitar los valores de entrada (o actualización) permitidos;
con el fin de evitar errores como por ejemplo insertar valores negativos cuando sólo se
permiten positivos. Para ello se utiliza la palabra reservada CHECK.
Ejemplo 8
Si creamos la tabla estudiantes 3, cuya característica principal es verficar que, en las
operaciones de inserción y actualización, los promedios estén dentro del valor
permitido:
CREATE TABLE Student3 (sID INT, sName VARCHAR(50), Average INT CHECK(Average>=0 and Average<=100));
Para comprobar el chequeo, hagamos algunas inserciones:
INSERT INTO Student3 VALUES (123,'Amy', 60); INSERT INTO Student3 VALUES (234,'Tim', 70); INSERT INTO Student3 VALUES (345,'Bob', -55); INSERT INTO Student3 VALUES (456,'Clara', 190);
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 178 de 253
Con las primeras dos inserciones no hay problemas, pero con la tercera y cuarta, el
siguiente error aparece:
ERROR: new row for relation "student3" violates check constriaint "student3_average_check"
pues violan la restricción del promedio.
Ejemplo 9
Es posible además, restringir cadenas de caracteres, como el caso del atributo sName.
Supongamos que se desea denegar la entrada o actualización de nombres groseros o
sin sentido, limitemos el caso a las cadenas: ‘amY’ y ‘amy ‘:
DROP TABLE Student3; CREATE TABLE Student3 (sID INT, sName VARCHAR(50) CHECK(sName <> 'amY' and sName <> 'amy '), Average INT CHECK(Average>=0 and Average<=100));
Si realizamos algunas inserciones:
INSERT INTO Student3 VALUES (123,'amY', 60); INSERT INTO Student3 VALUES (234,'amy', 70); INSERT INTO Student3 VALUES (345,'amy ',55); INSERT INTO Student3 VALUES (454,'Amy',90);
Tanto para la primera inserción como para la tercera se tiene:
ERROR: new row for relation "student3" violates check constraint "student3_sname_check"
Para las segunda y cuarta inserciones, no existe tal error pues, y como se mencionó
dentro de las primeras semanas, el único caso en que SQL es sensible al uso de
mayúsculas y minúsculas es para cadenas de caracteres que estén dentro de comillas
simples (‘’). por lo tanto ‘amY’ o ‘amy ‘ que son las cadenas restringidas difieren de
‘Amy’ y de ‘amy’.
Nota
Es sumamente importante que si se desea declarar cadenas de caracteres y que además se
quieran restringir valores específicos (como ocurre en el Ejemplo 9), el largo permitido no
sea ni demasiado largo, como para tener que restringir cada caso específico, ya sea: ‘amy’,
‘amy ‘, ‘amy ‘,... o ‘Amy’, ‘Amy ‘... considerando todas las combinaciones posibles; ni
demasiado corto para tener problemas de inserción con datos reales.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 179 de 253
Al igual que en los primeros ejemplos, si se desea actualizar los atributos que cuentan
con el tipo de restricción de este apartado, con valores que están fuera de rango o
dentro de las restricción, se obtendrá un error de tipo:
ERROR: new row for relation "**table**" violates check constraint "**table**_*atribute*_check"
Donde table se refiere a la relación en cuestión y atribute al atributo que cuenta con la
restricción del tipo CHECK.
Es posible, además utilizar este tipo de restricción para evitar valores NULL, como se
verá en el siguiente ejemplo.
Ejemplo 10
Supongamos que deseamos creamos la tabla de postulación Apply, pero que el
atributo desicion, de tipo booleano, no admita valores nulos, utilizando restricciones de
atributo y tupla.
CREATE TABLE Apply (sID INT, cName VARCHAR(50), Major VARCHAR(11), decision BOOL, CHECK(decision IS NOT NULL));
Y luego insertamos algunos datos:
INSERT INTO Apply VALUES (123, 'MIT', 'engineering', true); INSERT INTO Apply VALUES (123, 'Stanford', 'engineering', null);
Para la primera inserción no hay problemas, pero para la segunda:
ERROR: new row for relation "apply" violates check constraint "apply_decision_check"
Si se quisiera actualizar la primera inserción a decision=null:
UPDATE Apply SET decision = null WHERE sID = 123;
Nos topamos con el mismo error:
ERROR: new row for relation "apply" violates check constraint "apply_decision_check"
Ejemplo 11
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 180 de 253
Supongamos que al agregar una nueva postulación en la tabla Apply, deseamos
verificar la existencia en la tabla Student a través del atributo sID, utilizando para ello,
subconsultas:
DROP TABLE Student; CREATE TABLE Student (sID INT, sName VARCHAR (50), Average INT); CREATE TABLE (sID INT, cName VARCHAR(50), Major VARCHAR(11), decision BOOL, CHECK( sID IN (SELECT sID FROM Student)));
Con las primeras 2 instrucciones no hay problemas, pero al intentar crear la
tabla Apply, el siguiente error aparece:
ERROR: cannot use subquery in check constraint
Eso es, utilizar subconsultas dentro de un CHECK no está permitido en PostgreSQL, de
hecho no se permite en la mayoría de motores de bases de datos.
Restricciones generales
Si bien son formas de restricción bastante poderosas, no están soportadas por casi
ningún sistema actual.
Ejemplo 12
Supongamos una Tabla T de atributo A. Deseamos forzar que este atributo sea llave
de T.
CREATE TABLE T (A INT); CREATE ASSERTION KEY CHECK ((SELECT COUNT (DISTICT A) FROM T)= (SELECT COUNT(*) FROM T));
La consulta de arriba busca forzar que por cada fila de la tabla T, el atributo A sea
distinto, lo que dejaría a A como clave.
No obstante la función assertion no está implementada en PostgreSQL:
CREATE ASSERTION is not yet implemented
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 181 de 253
Lección XXIII - Restricciones y triggers:
Integridad Referencial
Esta Lección presenta un tipo muy importante de restricción conocida como integridad
referencial.
Como un recordatorio de las Leccións anteriores, las restricciones de integridad de una
base de datos es imponer restricciones a los datos permitidos más allá de las impuestas
por la estructura y tipos de la base de datos. Ahora, el término de integridad
referencialse refiere a la integridad de referencias que aparecen en la base de datos.
A continuación se muestra de ejemplo una base de datos con las tablas
de Student, Apply y College.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 182 de 253
Supongamos por ejemplo, que se tiene un alumno, “1”, que había solicitado a la
universidad “UCHILE”, para una especialización en “CS” (ciencias), con una decisión de
aceptación “Y” (sí) en la tabla Apply. Al poseer estos datos en la tabla Apply, se puede
observar que los datos de esta tupla (o fila) deben estar referenciados de otras tablas
como es el caso del atributo sID y cName, en las que podremos obtener mayor
información, es por esto que aparece la tabla Student, que posee los datos de cada
estudiante que postula a alguna especialización en una universidad y la tabla College,
que entrega mayor información de la universidad a la que postula el estudiante.
En la tabla Student los atributos son: sID “1”, sName “Tom”, un cierto GPA y “HS”
(escuela secundaria) y en la tabla College los atributos
son: cName “UCHILE”, State y enr.
Entonces en este ejemplo se habla de integridad referencial al realizar las referencias
correspondientes en las otras tablas, como es el caso de sID en la
tabla Student y cName en la tabla College.
Específicamente si tenemos integridad referencial de un atributo A de una
relación R (R.A) en un atributo B de otra relación S (S.B).
A lo que se refiere es que cada valor que aparece en la columna A de la relación R debe
tener algún valor correspondiente en la columna B de la relación S. Así que, si
observamos el ejemplo anterior, podríamos decir que tendríamos integridad
referencial de la columna sID de Apply, a la columna sID de Student. Del mismo modo
se tiene que la integridad referencial de la columna cNamede Apply, a la
columna cName, en College.
En la siguiente imagen se muestra una violación de integridad referencial, por ejemplo,
si tuviéramos un sID “2”, cName “UCHILE”, un major y dec, en la tabla Apply y en la
tabla Student no existe este sID, por lo que sería considerado una violación de la
integridad referencial.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 183 de 253
Del mismo modo podríamos tener un sID “1”, lo cual es válido porque tenemos un
estudiante “1” en la tabla Student, pero si “1” se postulas a la universidad “PUC” y en la
tabla College no se encuentra “PUC”, de nuevo se tiene una violación de la integridad
referencial.
Ejemplo
Consideremos dos tablas:
Dorm(name, address) Student(name, dormName, roommateName)
Supongamos que algunos estudiantes viven en habitaciones individuales
(roommateName es nulo) y los dormitorios no están vacíos. ¿Cuál de las siguientes
restricciones de integridad referencial no se cumple?
a. Student.dormName a Dorm.name
b. Dorm.name a Student.dormName
c. Student.name a Student.roommateName
d. Student.roommateName a Student.name
La alternativa correcta es (c), puesto que la respuesta 1 dice que existe un estudiante
con dormitorio. Respuesta 2 dice que cada dormitorio tiene por lo menos un
estudiante. Respuesta 3 dice que cada estudiante es un compañero de dormitorio de un
estudiante (aunque puede ser NULL). Respuesta 4 dice que cada compañero de
dormitorio es un estudiante.
Ahora sólo se darán unos detalles de las restricciones de integridad referencial.
Las relaciones R.A a S.B tienen como características:
“A” es clave foránea
Y de hecho, la integridad referencial se refiere a menudo como restricciones de
claves foráneas. E incluso en la sintaxis SQL, veremos que la clave externa se
utiliza el término.
B se requiere generalmente para ser la clave primaria para la tabla S o por lo
menos único.
Múltiples atributos de claves foráneas son permitidos.
Por ejemplo, si el atributo cName y State de la tabla College fuesen claves
foráneas es necesario agregar una columna en la tabla Apply de State.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 184 de 253
Aplicación de la integridad referencial (R.A a R.B)
Modificaciones potencialmente violadas:
INSERT INTO R.
Si insertamos una tupla (o fila) en la relación Apply se puede haber
violado la integridad referencial si el valor insertado, por ejemplo un
nombre de sID o cName, no tienen valores coincidentes en las relaciones
de referencia como son: Student y College.
DELETE FROM R.
Si borramos de una relación de referencia, digamos que se borra un
estudiante de la tabla Student, entonces eso podría causar una violación
de integridad referencial, puesto que al borrar la tupla (o fila) de la
tabla Student el valor sID = “1”, se pierde la referencia que existía de este
estudiante en la tabla Apply.
UPDATE R.A.
UPDATE S.B.
Y por supuesto, si actualizamos el valor que hace referencia a cualquiera
de estas columnas podrían causar una violación de integridad referencial
si es que el nuevo valor no existe en la tabla de referencia, o si se
actualizaran los valores de referencia.
Ejemplo
Considere las tablas Dorm(name, address) y Student(name, dormName,
roommateName) con restricciones de integridad referencial:
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 185 de 253
1. Student.dormName a Dorm.name
2. Dorm.name a Student.dormName
3. Student.roommateName a Student.name
¿Cuál de las siguientes modificaciones no pueden causar una violación de la integridad
referencial?
a. Insertion into Student.
b. Deletion from Student.
c. Update Student.roommateName.
d. Todos ellos pueden causar violaciones.
La alternativa correcta es (d), puesto que al insertar un estudiante puede violar las
restricciones (1) y/o (3). Al eliminar un estudiante se pueden violar las restricciones (2)
y/o (3). Al actualizar un compañero de cuarto puede violar la restricción (3).
En el estándar SQL y en todas las implementaciones, si tenemos una inserción en la
tabla de referencia o una actualización de la tabla de referencia que cause una violación
a la restricción de integridad, entonces se genera un error, y que la modificación no es
permitida, al igual que la violación de otros tipos de restricciones.
Acciones especiales
DELETE FROM S.
Restrict(default):
SET NULL
CASCADE
UPDATE S.B.
Restrict(default)
SET NULL
CASCADE
Ahora se explicará con ejemplos en postgreSQL, para una mayor comprensión:
CREATE TABLE College(cName text PRIMARY KEY, state text, enrollment INT); CREATE TABLE Student(sID INT PRIMARY KEY, sName text, GPA REAL, sizeHS INT); CREATE TABLE Apply(sID INT REFERENCES Student(sID), cName text REFERENCES College(cName), major text, decision text);
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 186 de 253
En la tabla Apply se puede observar la integridad referencial con “REFERENCES” a la
tabla Student con el atributo sID y College con le atributo cName.
INSERT INTO Apply VALUES(1,'UCHILE','CS','Y'); INSERT INTO Apply VALUES(2,'PUC','biology','N');
Al querer ingresar estas tuplas (o filas), sale el siguiente error:
ERROR: insert or update on table "apply" violates foreign key constraint "apply_sid_fkey" DETAIL: Key (sid)=(1) is not present in table "student". ERROR: insert or update on table "apply" violates foreign key constraint "apply_sid_fkey" DETAIL: Key (sid)=(2) is not present in table "student".
Esto ocurre porque no se encuentran las referencias de estos datos en las
tablas Student y College.
Para solucionar este error es necesario primero insertar las tuplas en las tablas
de Student y College y finalmente insertar las tuplas en Apply.
INSERT INTO Student VALUES(1, 'Tom', 3.4, 1000); INSERT INTO Student VALUES(2, 'Brad', 3.8, 1500); INSERT INTO College VALUES('UCHILE', 'CA', 15000); INSERT INTO College VALUES('PUC', 'CA', 36000); INSERT INTO Apply VALUES(1,'UCHILE','CS','Y'); INSERT INTO Apply VALUES(2,'PUC','biology','N');
Ahora se quiere actualizar la tabla Apply.
UPDATE Apply SET sID=3 WHERE sID=1;
Retornando el siguiente error, puesto que intenta establecer la identificación del
estudiante a “3”, pero vamos a conseguir una violación de la integridad referencial
porque no hay estudiantes con ID = “3”.:
ERROR: insert or update on table "apply" violates foreign key constraint "apply_sid_fkey" DETAIL: Key (sid)=(3) is not present in table "student". UPDATE Apply SET sID=2 WHERE sID=1; UPDATE 1
Esta última actualización es satisfactoria, puesto que se actualizará la postulación del
estudiante “1” para tener un sID = “2”.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 187 de 253
Hasta ahora, hemos visto modificaciones a la tabla de referencia, pero también tenemos
que preocuparnos acerca de las modificaciones de las tablas de referencia.
Por ejemplo, supongamos que tratamos de eliminar de la tabla College, donde
el cName es “UCHILE”.
DELETE FROM College WHERE cName='UCHILE';
Pero retorna el siguiente error, puesto que el atributo cName posee una referencia al
atributo sName de la tabla Apply, por lo que es imposible borrar esta tupla (o fila).:
ERROR: update or delete on table "college" violates foreign key constraint "apply_cname_fkey" on table "apply" DETAIL: Key (cname)=(UCHILE) is still referenced from table "apply".
De la misma manera ocurre si se intenta eliminar la siguiente tupla (o fila) de la
tabla Student.
DELETE FROM Student WHERE sID=2;
Retornando el siguiente error, puesto que el atributo sID de la tabla Student posee una
referencia al atributo sID de la tabla Apply.:
ERROR: update or delete on table "student" violates foreign key constraint "apply_sid_fkey" on table "apply" DETAIL: Key (sid)=(2) is still referenced from table "apply".
Al querer eliminar la siguiente tupla (o fila), no retorna error, puesto que el
estudiante sID = “1”, no posee referencia en la tabla Apply.
DELETE FROM Student WHERE sID=1; DELETE 1
Si queremos actualizar el nombre de la universidad “UCHILE” por “USM” en la
tabla College.
UPDATE College SET cName='USM' WHERE cName='UCHILE';
Pero el resultado no es satisfactorio, puesto que si se modificara el atributo cName por
“USM” de la tabla College, se tendrá una referencia en la tabla Apply con el
atributo cName, pero que posee el valor de “UCHILE”, generándose una violación de
integridad.:
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 188 de 253
ERROR: update or delete on table "college" violates foreign key constraint "apply_cname_fkey" on table "apply" DETAIL: Key (cname)=(UCHILE) is still referenced from table "apply".
Ahora veremos la eliminación de tablas.
Por ejemplo, si tratamos de eliminar la tabla Student, de nuevo se tendría una
restricción de integridad referencial, ya que los datos de la tabla Apply estarían
referenciando a una tabla Student inexistente.
DROP TABLE Student;
retornando el siguiente error:
ERROR: cannot drop table student because other objects depend on it DETAIL: constraint apply_sid_fkey on table apply depends on table student HINT: Use DROP ... CASCADE to drop the dependent objects too.
A continuación vamos a configurar la tabla Apply con algunos de los mecanismos
automáticos para el manejo de violaciones de integridad referencial.
CREATE TABLE Apply(sID INT REFERENCES Student(sID) ON DELETE SET NULL, cName text REFERENCES College(cName) ON UPDATE CASCADE, major text, decision text); CREATE TABLE
Para la para la restricción de sID la integridad referencial que vamos a especificar es que
si un estudiante es eliminado, no vamos a establecer ninguna referencia a valores a
“null”, y lo hacemos con las palabras clave “ON DELETE” que nos dice qué hacer cuando
hay una eliminación de la tabla de referencia, se utiliza la opción SET NULL.
Para el atributo cName la integridad referencial que vamos a especificar es que si la
universidad se actualiza en la tabla College se utilizará la opción de cascada. Esto
quiere decir que si se modifica el valor de una tupla del atributo cName en la
tabla College, está también se modificará automáticamente en la tabla Apply.
Se podría haber especificado dos opciones más que hubiese sido una opción de
actualización para el sID de estudiante y una opción para borrar el cName, así que
podrían haber sido cuatro en total.
Vamos a generar ahora algunas modificaciones (comenzamos las tablas desde cero):
INSERT INTO Student VALUES(1, 'Tom', 3.4, 1000); INSERT INTO Student VALUES(2, 'Brad', 3.8, 1500); INSERT INTO Student VALUES(3, 'Lucy', 3.9, 3600);
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 189 de 253
INSERT INTO College VALUES('UCHILE', 'CA', 15000); INSERT INTO College VALUES('PUC', 'CA', 36000); INSERT INTO Apply VALUES(1,'UCHILE','CS','Y'); INSERT INTO Apply VALUES(2,'PUC','biology','N'); INSERT INTO Apply VALUES(1,'PUC','CS','Y'); INSERT INTO Apply VALUES(3,'UCHILE','history','Y'); INSERT INTO Apply VALUES(3,'UCHILE','CS','Y');
Cumpliendo todas las tuplas de la tabla Apply con la integridad referencial.
SELECT * FROM Student; sid | sname | gpa | sizehs -----+-------+-----+-------- 1 | Tom | 3.4 | 1000 2 | Brad | 3.8 | 1500 3 | Lucy | 3.9 | 3600 (3 rows) SELECT * FROM College; cname | state | enrollment -------+-------+------------ UCHILE | CA | 15000 PUC | CA | 36000 (2 rows) SELECT * FROM Apply; sid | cname | major | decision -----+-------+---------+---------- 1 | UCHILE | CS | Y 2 | PUC | biology | N 1 | PUC | CS | Y 3 | UCHILE | history | Y 3 | UCHILE | CS | Y (5 rows)
Ejemplo ON DELETE SET NULL
Ahora vamos a eliminar todos los estudiantes cuyo sID es mayor a 2:
DELETE FROM Student WHERE sID > 2; DELETE 1
Quedando como resultado las tablas Student y Apply
SELECT * FROM Student; sid | sname | gpa | sizehs -----+-------+-----+--------
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 190 de 253
1 | Tom | 3.4 | 1000 2 | Brad | 3.8 | 1500 (2 rows) SELECT * FROM Apply; sid | cname | major | decision -----+-------+---------+---------- 1 | UCHILE | CS | Y 2 | PUC | biology | N 1 | PUC | CS | Y | UCHILE | history | Y | UCHILE | CS | Y (5 rows)
Se observa que se eliminó a la estudiante “Lucy”, que tenía un sID = 3, de la
tabla Student y la tabla Apply dejando en esta última el valor del atributo sID = “null”,
cumpliéndose la restricción que se detalló en la creación de la
tabla ON DELETE SET NULL.
Ejemplo CASCADE
Se desea actualizar el cName de la tabla College el valor de “UCHILE” por “USM”.
UPDATE College SET cName='USM' WHERE cName='UCHILE'; UPDATE 1
Ahora no retornó ningún error como en el ejemplo anterior, esto se debe a la
restricción que se agregó en la creación de la tablaApply, en que se maneja
automáticamente las violaciones a la integración referencial.
Las tablas después de ejecutar el comando de actualización quedaron de la siguiente
manera:
SELECT * FROM College; cname | state | enrollment -------+-------+------------ PUC | CA | 36000 USM | CA | 15000 (2 rows) SELECT * FROM Apply; sid | cname | major | decision -----+-------+---------+---------- 2 | PUC | biology | N 1 | PUC | CS | Y 1 | USM | CS | Y | USM | history | Y
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 191 de 253
| USM | CS | Y (5 rows)
Observándose en las tablas College y Apply que se actualizó cName = ‘USM’, en ambas
tablas.
A continuación se mostrarán otras características que no se han visto en los ejemplos
anteriores:
CREATE TABLE T(A INT, B INT, C INT, PRIMARY KEY(A,B), FOREIGN KEY(B,C) REFERENCES T(A,B) ON DELETE CASCADE); INSERT INTO T VALUES(1,1,1); INSERT INTO T VALUES(2,1,1); INSERT INTO T VALUES(3,2,1); INSERT INTO T VALUES(4,3,2); INSERT INTO T VALUES(5,4,3); INSERT INTO T VALUES(6,5,4); INSERT INTO T VALUES(7,6,5); INSERT INTO T VALUES(8,7,6);
Este ejemplo es para demostrar la integridad referencial dentro de una sola tabla T.
SELECT * FROM T; a | b | c ---+---+--- 1 | 1 | 1 2 | 1 | 1 3 | 2 | 1 4 | 3 | 2 5 | 4 | 3 6 | 5 | 4 7 | 6 | 5 8 | 7 | 6 (8 rows)
Si queremos borrar de la tabla T, cuando A=1.
DELETE FROM T WHERE A=1;
Quedando la tabla como:
SELECT * FROM T; a | b | c ---+---+--- (0 rows)
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 192 de 253
Podemos observar que al dar la condición de borrar A=1, se eliminan todos los demás
valores, esto sucede por la definición que se dio como clave foránea de B y C en la
creación de la tabla T.
La integración referencial es muy común en las implementaciones de las bases de datos
relacionales. La forma natural de diseñar un esquema relacional suelen tener valores en
columnas de una tabla que se refieren a los valores de las columnas de otra tabla, y el
establecimiento de restricciones de integridad referencial, este sistema controlará la
base de datos y se asegurará de que se mantenga siempre constante.
Lección XXIV - Restricciones y Triggers:
Triggers introducción y demostración
Triggers (disparadores)
Durante la ejecución de una aplicación de base de datos, hay ocasiones que se requiere
realizar una o más acciones de forma automática, si se produce un evento en
específico. Es decir, que la primera acción provoca la ejecución de las siguientes
acciones. Los denominados Triggers o disparadores son el mecanismo de activación,
que posee SQL para entregar esta capacidad.
Definición
Un Trigger es una orden que el sistema ejecuta de manera automática como efecto
secundario de alguna modificación de la base de datos. Entonces los Triggers siguen en
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 193 de 253
orden la secuencia: evento->condición->acción. Se ejecutan mediante los
comandosINSERT, DELETE y UPDATE.
Para diseñar un mecanismo Trigger hay que cumplir algunos requisitos:
1. Procedimiento almacenado: Se debe crear la base de datos y las
relaciones, antes de definir el Trigger.
2. Especificar condiciones para ejecutar el Trigger: Se debe definir
un evento que causa la comprobación del Trigger y una condición que se
debe cumplir para ejecutar el Trigger.
3. Especificar las acciones: Se debe precisar qué acciones se van a realizar
cuando se ejecute el Trigger.
La base de datos almacena Trigger como si fuesen datos normales, por lo que son
persistentes y accesibles para todas las operaciones de la base de datos. Una vez se
almacena un Trigger en la base de datos, el sistema de base de datos asume la
responsabilidad de ejecutarlo cada vez que ocurra el evento especificado y se satisfaga
la condición correspondiente.
Algunas aplicaciones de Triggers
El Trigger es útil en una serie de situaciones diferentes. Un ejemplo es realizar una
función de registro. Algunas acciones críticas para la integridad de una base de datos,
tales como insertar, editar o eliminar una fila de la tabla, podrían desencadenar una
inscripción en un registro que documente la acción realizada. El registro podrían grabar
no sólo lo que se modificó, sino también cuando fue modificada y por quién.
Los Triggers también pueden ser usados para mantener una base de datos consistente.
Por ejemplo si se tiene una relación dePedidos, el pedido de un producto especifico
puede activar una sentencia que cambie el estado de ese producto en la
tabla Inventario, y pase de disponible a reservado. Del mismo modo, la eliminación de
una fila en la tabla de pedidos puede activar la acción para cambia el estado del
producto de reservado a disponible. Los Triggers ofrecen una flexibilidad aún mayor
que la que se ilustra en los ejemplos anteriores.
Creación de un disparo
1. Un Trigger se crea con la sentencia CREATE TRIGGER.
2. Después de que se crea, el Trigger se encuentra a la espera de que se
produzca el evento de activación.
3. Cuando el evento se produce desencadena una acción.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 194 de 253
Forma general:
(1)CREATE TRIGGER nombreTrigger (2)BEFORE|AFTER|INSTEAD OF AlgúnEvento ON nombreTabla (3)WHEN (condición) (3)Action
Variables especiales
Existen algunas palabras reservadas, que están disponibles para ser utilizadas por
Triggers. Algunas de estas variables especiales disponibles son las siguientes:
NEW: Variable que contiene la nueva fila de la tabla para las
operaciones INSERT/UPDATE.
OLD: Variable que contiene la antigua fila de la tabla para las
operaciones UPDATE/DELETE.
TG_NAME: Variable que contiene el nombre del Trigger que está usando la función
actualmente.
TG_RELID: identificador de objeto de la tabla que ha activado el Trigger.
TG_TABLE_NAME: nombre de la tabla que ha activado el Trigger.
Ejemplo :
Nota
El ejemplo a continuación es para explicar el funcionamiento de un Trigger, si se desea
probar en postgreSQL se debe crear la base de datos y la tabla Employee, más adelante se
verán un ejemplo práctico que podrá copiarse directamente en la consola.
El siguiente Trigger se “dispara” por cambios en el atributo salary. El efecto de este
Trigger es para frustrar cualquier intento de disminuir el valor de salary en la
tabla Employee.
Employee(cert−−−,name, address, salary)
(1) CREATE TRIGGER salaryTrigger (2) AFTER UPDATE OF salary ON Employee (3) REFERENCING (4) OLD ROW AS OldTuple, (5) NEW ROW AS NewTuple (6) FOR EACH ROW (7) WHEN (OldTuple.salary > NewTuple.salary)
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 195 de 253
(8) UPDATE Employee (9) SET salary = OldTuple.salary (10) WHERE cert = NewTuple.cert ;
(1) Se crea el Trigger: con las palabras claves CREATE TRIGGER y el nombre del
Trigger salaryTrigger.
(2) Evento de activación:, en este caso es la actualización del atributo salary de la
relación Employee.
(3) (4) y (5) Camino para la condición: a la tupla antigua (tupla antes de la
actualización) se le asigna el nombre OldTupley la nueva tupla (tupla después de
la actualización), se asigna como NewTuple. En la condición y la acción, estos
nombres se pueden utilizar como si fueran variables declaradas en la
cláusula FROM de una consulta SQL.
(6), La frase FOR EACH ROW, expresa la exigencia de que este Trigger se ejecute
una vez por cada tupla actualizada.
(7) Condición del Trigger: Se dice que sólo se realiza la acción cuando el
nuevo salary es menor que el salary antiguo.
(8) (9) y (10) Acción del Trigger Esta acción es una instrucción SQL de
actualización que tiene el efecto de restaurar el salarya lo que era antes de la
actualización. Tenga en cuenta que, en principio, cada tupla de Employee se
considera para la actualización, pero la cláusula WHERE de la línea (10) garantiza
que sólo la tupla actualizada (con el correcto cert) se verán afectados.
Funciones
Existe una forma de separar las acciones y las condiciones de un Trigger. Esto se logra
mediante el uso de funciones. Uno de los motivos de utilizar funciones es mantener la
lógica lejos de la aplicación, con esto se consigue consistencia entre aplicaciones y
reducción de funcionalidad duplicada. Además un acceso predefinido a objetos
restringidos.
SQL es un lenguaje declarativo, pero en ocasiones se requiere de otro tipo de lenguajes.
El manejo de funciones permite utilizar distintos de lenguajes, de manera que se puede
escoger la herramienta adecuada a cada caso. Para efecto de este curso se usará
unlenguaje imperativo, llamado PL/pgSQL (Procedural Language/PostgreSQL Structured
Query Language).
Nota
Un Lenguaje imperativo le ordena a la computadora cómo realizar una Práctica siguiendo
una serie de pasos o instrucciones. La ejecución de estos comandos se realiza, en la mayor
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 196 de 253
parte de ellos, secuencialmente, es decir, hasta que un comando no ha sido ejecutado no se
lee el siguiente. Aunque también existen los bucles controlados que se repiten hasta la
ocurrencia de algún evento.
PL/pgSQL dispone de estructuras condicionales y repetitivas. Se pueden realizar
cálculos complejos y crear nuevos tipos de datos de usuario. En PL/pgSQL se pueden
crear funciones. En esta sección se verá como dichas funciones pueden ser ejecutadas
en eventos de tipo Trigger.
Ejemplo Práctico 1:
Se crea una base de datos y se instala el lenguaje plpgsql.
postgres=# create database trggr2; CREATE DATABASE postgres=# \c trggr2 psql (8.4.11) Ahora está conectado a la base de datos «trggr2». trggr2=# CREATE PROCEDURAL LANGUAGE plpgsql; CREATE LANGUAGE
Se crea la relación numbers
CREATE TABLE numbers( number int NOT NULL, square int, squareroot real, PRIMARY KEY (number) );
Se define una función llamada save_data(), que será la encargada de llenar los datos, al
final del ejemplo se explica detalladamente su funcionamiento:
CREATE OR REPLACE FUNCTION save_data() RETURNS Trigger AS $save_data$ DECLARE BEGIN NEW.square := power(NEW.number,2); NEW.squareroot := sqrt(NEW.number); RETURN NEW; END; $save_data$ LANGUAGE plpgsql;
PostgreSQL retorna:
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 197 de 253
CREATE FUNCTION
Ahora ya se puede definir el Trigger que llamará a la
función save_data() automáticamente, cada vez que se inserte o actualice un dato.
CREATE TRIGGER save_data BEFORE INSERT OR UPDATE ON numbers FOR EACH ROW EXECUTE PROCEDURE save_data();
PostgreSQL retorna:
CREATE TRIGGER
Para ver cómo funciona el Trigger se insertan los números 4, 9 y 6.
trggr2=# INSERT INTO numbers (number) VALUES (4),(9),(6); INSERT 0 3
Y se realiza un select para ver los datos almacenados.
trggr2=# SELECT * FROM numbers; number | square | squareroot --------+--------+------------ 4 | 16 | 2 9 | 81 | 3 6 | 36 | 2.44949 (3 rows)
También se puede actualizar
trggr2=# UPDATE numbers SET number = 7 WHERE number = 6; UPDATE 1 trggr2=# SELECT * FROM numbers; number | square | squareroot --------+--------+------------ 4 | 16 | 2 9 | 81 | 3 7 | 49 | 2.64575 (3 rows)
Como se puede apreciar, solo se ha insertado o actualizado el valor number pero al
hacerlo automáticamente se llenaron los valores para los atributos square y squareroot.
Esto es debido a que el Trigger estaba definido para activarse al realizar
un INSERT o UPDATE. Por cada uno de estos comandos el Trigger ordenó la ejecución de
la función save_data(), una vez por cada fila involucrada. Es decir cuando realizamos el
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 198 de 253
primer INSERT (number = 4), el Trigger save_data llama a la función save_data() una
vez.
El valor de la variable NEW al empezar a
ejecutarse save_data() es: number=4, square=NULL, squareroot=NULL. La
tabla numbers aún está vacía.
A continuación se calcula el cuadrado y la raíz cuadrada de 4, estos valores se
asignan a NEW.square y NEW.squarerootrespectivamente. Ahora la variable NEW
contiene number=4, square=16, squareroot=2.
Para calcular el cuadrado de un número se utiliza la instrucción power, que recibe como
parámetros el número que se ingrese y el número al cual se eleva. Para calcular la raíz
cuadrara de un número se utiliza la instrucción sqrt que recibe como parámetro el
nuevo número.
Con la sentencia RETURN NEW, se retorna la fila RECORD almacenada en la
variable NEW, el sistema almacena entonces NEW en la tablanumbers.
Ejemplo Práctico 2:
Para este ejemplo se utiliza la misma relación numbers creada anteriormente, con los
valores ya insertados. La función protect_dataes usada para proteger datos en una
tabla. No se permitirá el borrado de filas, pues retorna NULL que, como se vio en
Leccións anteriores, es la inexistencia de valor.
CREATE OR REPLACE FUNCTION protect_data() RETURNS Trigger AS $Tprotect$ DECLARE BEGIN RETURN NULL; END; $Tprotect$ LANGUAGE plpgsql;
El siguiente Trigger llamado Tprotect se activa antes de realizar una eliminación de
datos de la tabla numbers, la acción que realiza es llamar a la función protect_data.
CREATE Trigger Tprotect BEFORE DELETE ON numbers FOR EACH ROW EXECUTE PROCEDURE protect_data();
Se intenta eliminar todos los datos de la tabla numbers con la siguiente sentencia:
trggr2=# DELETE FROM numbers; DELETE 0
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 199 de 253
Sin embargo no es posible borrar datos pues el Trigger acciona la
función protect_data, y ningún dato es eliminado.
trggr2=# SELECT * FROM numbers; number | square | squareroot --------+--------+------------ 4 | 16 | 2 9 | 81 | 3 7 | 49 | 2.64575 (3 rows)
Ejemplo Práctico 3:
Nuevamente se utiliza la relación numbers, las funciones y los Triggers ya creados.
La función que se verá a continuación busca evitar errores al calcular la raíz cuadrada
de un número negativo. Observe que ocurre al intentar insertar el valor -4:
trggr2=# INSERT INTO numbers (number) VALUES (-4); ERROR: cannot take square root of a negative number CONTEXTO: PL/pgSQL function "save_data" line 5 at assignment
La consola arroja un error en la función save_data, pues no puede calcular la raíz de un
número negativo.
La función invalid_root ocupa la sentencia IF para validar que el número sea mayor a 0.
La construcción IF sirve para ejecutar código sólo si una condición es cierta, dicha
condición debe ser una expresión booleana. La sentencia IF tiene la forma: si
(condición es cierta) entonces realizar sentencia, si la condición no se cumple la línea o
líneas se saltan y no son ejecutadas, se evalúan entonces sucesivamente las
condiciones ELSIF, que son una condición alternativa al IF, en este caso se especifica
que el nuevo número sea mayor o igual a 0.
Al ingresar a la sentencia IF se ejecuta la misma acción de la función protect_data, es
decir retorna NULL y no realiza ninguna acción sobre numbers. Si es mayor o igual a 0
se ejecuta la sentencia que está al interior de la instrucción ELSIF, esta sentencia es la
misma que emplea la función sabe_data, esto es, calcular el cuadrado y la raíz.
CREATE OR REPLACE FUNCTION invalid_root() RETURNS Trigger AS $invalid_root$ DECLARE BEGIN IF (NEW.number < 0) THEN RETURN NULL; ELSIF (NEW.number >= 0) THEN NEW.square := power(NEW.number,2);
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 200 de 253
NEW.squareroot := sqrt(NEW.number); RETURN NEW; END IF; END; $invalid_root$ LANGUAGE plpgsql;
Luego de tener la función se define el Trigger que detona la función. El
Trigger invalid_root se activa cuando se realiza una inserción o actualización de datos
en numbers.
CREATE TRIGGER invalid_root BEFORE INSERT OR UPDATE ON numbers FOR EACH ROW EXECUTE PROCEDURE invalid_root();
Ahora se vuelve a probar la inserción de un número negativo:
trggr2=# INSERT INTO numbers (number) VALUES (-4); INSERT 0 0
Esta vez no arroja error pues ingresa al IF que restringe valores negativos, y
simplemente no inserta el valor.
Y si se intenta ingresar un numero positivo, se consigue sin problemas:
trggr2=# INSERT INTO numbers (number) VALUES (5);INSERT 0 1 trggr2=# SELECT * FROM numbers; number | square | squareroot --------+--------+------------ 4 | 16 | 2 9 | 81 | 3 7 | 49 | 2.64575 5 | 25 | 2.23607 (4 filas)
Para borrar un Trigger y una función primero se elimina el Trigger:
trggr2=# DROP Trigger invalid_root ON numbers; DROP Trigger
Y luego se puede eliminar la función:
trggr2=# DROP FUNCTION invalid_root(); DROP FUNCTION
Cuándo no deben usarse los Triggers
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 201 de 253
Existen algunos casos que pueden ser manejados de mejor forma con otras técnicas:
Realizar resúmenes de datos: Muchos sistemas de bases de datos actuales
soportan las vistas materializadas, que proporcionan una forma mucho más
sencilla de mantener los datos de resumen.
Respaldo de las bases de datos: Anteriormente los diseñadores de sistemas,
usaban Triggers con la inserción, eliminación o actualización de las relaciones
para registrar los cambios. Un proceso separado copiaba los cambios al respaldo
de la base de datos, y el sistema ejecutaba los cambios sobre la réplica. Sin
embargo, los sistemas de bases de datos modernos proporcionan características
incorporadas para el respaldo de bases de datos, haciendo innecesarios a los
Triggers para la réplica en la mayoría de los casos.
Los Triggers se deberían escribir con sumo cuidado, dado que un error de un Trigger
detectado en tiempo de ejecución causa el fallo de la instrucción de inserción, borrado
o actualización que inició el Trigger. En el peor de los casos esto podría dar lugar a una
cadena infinita de Triggers. Generalmente, los sistemas de bases de datos limitan la
longitud de las cadenas de Triggers.
Lección XXV - Transacciones:
Introducción
En esta Lección se presentarán los conceptos de transacciones y acciones de interacción
con los sistemas de base de datos.
El concepto de transacciones está identificado por dos acepciones totalmente
independientes.
Uno, tiene que ver con el acceso concurrente de varios clientes a la base de datos; y el
otro, tiene relación con tener un sistema resistente a los fallos de sistema.
Primero, veremos como funciona la estructura de los sistemas de bases de datos y la
interacción con los clientes.
En la siguiente imagen podemos observar que los datos son almacenados en el disco,
quien se comunica con el sistema de gestión de base de datos, o DBMS, controlador de
las interacciones con los datos. A menudo hay software adicional por encima del DBMS;
tal vez un servidor de aplicaciones o servidor web, que luego interactúan con los que
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 202 de 253
podrían ser usuarios a través de comandos de selección, actualización, creación de
tablas, comandos de borrado, etc. Y es aquí finalmente donde ocurre el problema, que
es la interacción concurrente de múltiples usuarios.
Integridad de las transacciones
Una transacción es un conjunto de operaciones (u órdenes) que se ejecutan en
forma indivisible (atómica) sobre una base de datos.
El DBMS debe mantener la integridad de los datos, haciendo que
estas transacciones no puedan finalizar en un estado intermedio.
Si por algún motivo se debe cancelar la transacción, el DBMS empieza a deshacer
las órdenes ejecutadas hasta dejar la base de datos en su estado inicial (llamado
punto de integridad), como si la orden de la transacción nunca se hubiese
realizado.
Ahora se mostrarán ejemplos de dificultades que pueden ocurrir cuando múltiples
clientes están interactuando con la base de datos.
Nivel de Inconsistencia en Atributos
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 203 de 253
UPDATE College SET enrollment = enrollment + 500 WHERE cName = 'UCHILE';
concurrente con
UPDATE College SET enrollment = enrollment + 1000 WHERE cName = 'UCHILE';
En el ejemplo anterior se puede observar que tenemos 2 clientes; uno esta emitiendo
una declaración que aumenta las matriculas deUCHILE en 500, el segundo cliente, en el
mismo instante, está emitiendo una declaración que aumenta las matriculas en 1000.
El problema que se genera en este caso es que si el primer cliente modifica el valor de
la matricula de la universidad UCHILE en 500 y ahora el segundo cliente va a modificar
el valor de la matricula, sobre lo que ya modificó el primer cliente. A la base de datos se
le modificó dos veces el valor de la matricula.
Supongamos que el valor de la matricula está en 3000 y estas dos sentencias anteriores
se ejecutan al mismo tiempo, el valor final de la matricula será 4500 (500 + 1000 +
3000).
Nivel de Inconsistencia en Tuplas
UPDATE Apply SET major = 'history' WHERE sID = 1;
concurrente con
UPDATE Apply SET decision = 'Y' WHERE sID = 1;
En este ejemplo, al haber dos clientes que están realizando una modificación en una
tupla (o fila) sID = 1; el primero actualizando la especialidad a history y el segundo a
una decision con valor Y. Es posible que se vean ambas modificaciones reflejadas en la
base de datos, pero también existe la posibilidad de que sólo se visualice una.
Nivel de Inconsistencia en Tablas
UPDATE Apply SET decision = 'Y' WHERE sID IN (SELECT sID FROM Student WHERE GPA > 3.9);
concurrente con
UPDATE Student SET GPA = (1.1) * GPA WHERE sizeHS > 2500;
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 204 de 253
Tenemos el primer cliente trabajando en la tabla Apply, pero las condiciones que se
detallan en la tabla Apply, dependen de la tablaStudent. Mientras tanto el segundo
cliente esta modificando la tabla Student.
Así que lo que sucede en la tabla Apply, puede depender de si ocurre antes, después o
durante la modificación de la tabla Student.
Entonces los GPA se modifican y luego las aceptaciones se hacen o viceversa.
Objetivo de la Concurrencia
Tenemos múltiples clientes interactuando con la base de datos al mismo tiempo, y si en
realidad los comandos que se ejecutan en la base de datos fuesen intercalados, a
menudo los comandos de actualización e incluso los de selección, pueden generar un
comportamiento inconsistente o inesperado.
Lo que idealmente se busca es que el cliente ejecute comandos a las bases de datos y
no preocuparse de lo que están realizando otros clientes en ese mismo instante.
Objetivo Principal
Ejecutar secuencias de instrucciones SQL que parecen estar funcionando de manera
aislada.
Solución Simple: ejecutarlos de forma aislada.
Pero se desea habilitar la concurrencia siempre que sea seguro hacerlo.
Por lo general para poder hacer funcionar un ambiente con concurrencia es posible con
un sistema que posea:
Sistema multi-procesador.
Sistema multi-threads
A continuación se explicarán las fallas de sistema.
Resistencia a fallos del sistema
Una vez más, tenemos nuestro sistema de base de datos con los datos en el disco.
Supongamos que estamos en el proceso de una carga masiva de datos en la base de
datos.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 205 de 253
Quizás una gran cantidad de datos de una fuente externa, por ejemplo un conjunto de
archivos. Precisamente en el momento de una carga masiva de datos, tenemos una
caída del sistema o un fallo del sistema.
Esto podría deberse a un fallo de software o hardware, o algo tan simple como la salida
de energía.
Por lo tanto, si se cargaron la mitad de los datos que se debían cargar en la base de
datos
¿Qué sucede cuando el sistema vuelve?
Se queda en un estado inconsistente bastante desagradable.
Como ejemplo, vamos a suponer que estábamos realizando un montón de cambios en
la base de datos. Entonces los datos que se quieren actualizar son modificados en la
memoria y luego se escriben nuevamente en el disco. Así que, suponemos que en
medio de este proceso tenemos una caída del sistema.
Esto volvería a dejar a la base de datos en un estado inconsistente.
Así que el objetivo general frente a los fallos del sistema es que cuando queremos
hacer algo en la base de datos es indicarle al sistema que queremos garantizar la
ejecución de todo o nada para ese conjunto particular de operaciones en la base de
datos independientemente de los fallos que pudieran ocurrir durante la ejecución.
Solución para la concurrencia y fallos
Una transacción es una secuencia de una o más operaciones de SQL tratados como una
unidad.
Transacciones parecen funcionar de forma aislada.
Si el sistema falla, los cambios de cada transacción se reflejan en su totalidad.
Estándar SQL:
Una transacción comienza automáticamente en la primera sentencia SQL.
Cuando el comando “commit” (una palabra clave especial) se ejecuta, la
transacción actual termina y comienza una nueva.
La transacción actual, también termina cuando su período de sesiones termina
con la base de datos.
“Autocommit” cada sentencia SQL se ejecuta como una transacción.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 206 de 253
Lección XXVI - Transacciones:
Propiedades
En esta Lección se va a profundizar sobre las propiedades de las transacciones.
Como recordatorio, las transacciones son un concepto que ha sido introducido como
una solución tanto para el problema de control de concurrencia y fallos de sistemas en
las bases de datos.
Todo conocedor de bases de datos, sabe que las transacciones soportan lo que se
conoce como las propiedades ACID.
A: Atomicidad.
C: Consistencia.
I: Aislamiento.
D: Durabilidad.
A continuación se detallarán estas cuatro propiedades; primero aislamiento, segundo
durabilidad, tercero atomicidad y finalmente consistencia.
Aislamiento (I)
“Esta propiedad asegura que no sean afectadas entre sí las transacciones, en otras
palabras esto asegura que la realización de dos o más transacciones sobre la misma
información sean independientes y no generen ningún tipo de error” [1]
Podemos tener una gran cantidad de clientes que operan en una base de datos (como
se muestra en la imagen), en que cada cliente piensa que está operando por su cuenta.
Así como se comentó en la Lección anterior, cada cliente emite en el sistema de base de
datos una secuencia de transacciones. Así que un primer cliente podría emitir primero
la transacción T1, a continuación, T2, T3, y así sucesivamente. Un segundo cliente
podría emitir una transacción T9, T10, T11.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 207 de 253
Como recordatorio, cada transacción en sí puede ser una secuencia de instrucciones.
Por lo tanto estas transacciones, podrían ser una instrucción, dos instrucciones, tres
instrucciones y así sucesivamente, y finalmente estas instrucciones serán tratadas como
una unidad.
De manera que la propiedad aislante es implementada de una muy específica forma
normal llamada secuenciación.
La secuenciación quiere decir que las operaciones pueden ser intercaladas entre los
clientes, pero la ejecución debe ser equivalente a un orden secuencial (serial) de todas
las transacciones.
En base a la imagen anterior, el propio sistema puede ejecutar todas las instrucciones
dentro de cada operación y al mismo tiempo por cada cliente, pero tiene que garantizar
que el comportamiento de la base de datos es equivalente a una secuencia en orden.
Ejemplo
Supongamos cliente C1 emite T1, T2 transacciones y el cliente C2 T3, T4 transacciones
simultáneamente. ¿Cuántas “ordenes secuenciales equivalentes” distintas hay en estas 4
transacciones?
a. 2
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 208 de 253
b. 4
c. 6
d. 24
La alternativa correcta es (c), puesto que las combinaciones posibles son las
siguientes: T1,T2,T3,T4; T1,T3,T2,T4; T1,T3,T4,T2;T3,T1,T2,T4; T3,T1,T4,T2; T3,T4,T1
,T2.
Ahora, podemos preguntarnos cómo el sistema de base de datos podría garantizar este
nivel de coherencia manteniendo la “intercomunicación” de las operaciones. Esto se
logra con la utilización de protocolos que se basan en bloquear partes de la base de
datos.
Volveremos a un ejemplo de la Lección anterior.
UPDATE College SET enrollment = enrollment + 500 WHERE cName = 'UCHILE';
concurrente con
UPDATE College SET enrollment = enrollment + 1000 WHERE cName = 'UCHILE';
En este ejemplo dos clientes modifican la matricula a la universidad UCHILE.
Llamaremos a la primera instrucción T1 y a la segunda T2, así que cuando realizamos
estas transacciones en el sistema, la secuenciación esta garantizada, desde ahí
tendremos un comportamiento equivalente ya sea para T1 seguido por T2, o T2
seguido por T1.
Así que, en este caso, cuando empezamos con nuestra matrícula en 15.000, bien la
ejecución correcta tendrá una matricula final de 16.500, resolviendo nuestros
problemas de concurrencia.
Ahora se explicará otro ejemplo de la Lección anterior.
UPDATE Apply SET major = 'history' WHERE sID = 1;
concurrente con
UPDATE Apply SET decision = 'Y' WHERE sID = 1;
En este ejemplo, el primer cliente realizó la modificación de major del estudiante sID =
1 en la tabla Apply y el segundo fue la modificación de decision del estudiante sID = 1.
Y hemos visto que si permitimos que estas instrucciones se ejecuten de manera
intercalada, sería posible que sólo uno de las dos modificaciones se realicen. Una vez
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 209 de 253
más, con la secuenciación vamos a obtener un comportamiento que garantiza que es
equivalente a T1 seguido por T2 ó T2 seguido por T1.
Y en ambos casos, tanto los cambios se reflejarán en la base de datos que es lo que nos
gustaría.
Durabilidad (D)
“Es la propiedad de las transacciones que asegura que una vez finalizada su ejecución,
sus resultados son permanentes a pesar de otras consecuencias, como por ejemplo, si
falla el disco duro el sistema aún será capaz de recordar todas las transacciones que
han sido realizadas en el sistema” [1]
Aquí sólo debemos mirar un cliente y lo que está sucediendo.
Así que digamos que tenemos a nuestro cliente (siguiente imagen), que está emitiendo
una secuencia de instrucciones (S1, S2, ..., Sn) a la base de datos. Y cada transacción
(T1, T2, ..., Tn) que realiza el cliente, es una secuencia de instrucciones (S) y que al
finalizar cada instrucción (S) recibe un “commit” confirmación.
Si el sistema deja de funcionar después de las transacciones “commits”, todos los
efectos de las transacciones quedan en la base de datos.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 210 de 253
Entonces, específicamente, si en algún momento esto ocurre, si hay una falla por
cualquier razón, el cliente puede asegurarse que la base de datos ha sido afectada por
la transacción, y cuando el sistema vuelva a funcionar, los efectos seguirán ahí.
¿Es posible garantizar esto, siendo que los sistemas de base de datos mueven
información entre el disco duro y la memoria y una falla puede ocurrir en cualquier
momento?.
Son protocolos no tan complicados que son usados y están basados en el concepto
de logging.
Atomicidad (A)
“Cualquier cambio de estado que produce una transacción es atómico, es decir, ocurren
todos o no ocurre ninguno. En otras palabras, esta propiedad asegura que todas las
acciones de la transacción se realizan o ninguna de ellas se lleva a cabo; la atomicidad
requiere que si una transacción se interrumpe por una falla, sus resultados parciales
deben ser deshechos” [1]
De nuevo, sólo veremos un cliente que haya dado a conocer una serie de transacciones
a la base de datos. Y vamos a ver la transacción T2 que a su vez es una secuencia de
instrucciones seguidas por una confirmación (commit).
El caso que la atomicidad trabaja, es donde existe una falla durante la ejecución de la
transacción, después que se ha sido “enviado”.
Lo que la propiedad quiere decir que, incluso en presencia de fallos del sistema, cada
transacción se ejecuta todo o nada en la base de datos.
También se utiliza un mecanismo de log-in, específicamente, cuando el sistema se
recupera de un accidente y hay un proceso por el cual los efectos parciales de las
transacciones que se estaban ejecutando al momento de la falla, se
“deshacen/descartan”.
Ejemplo
Considere la posibilidad de una relación R (A) que contiene {(5), (6)} y dos
transacciones: T1: UPDATE R SET A = A + 1; T2: UPDATE R SET A = 2 * A. Supongamos
que ambas transacciones se presentan bajo la propiedad de aislamiento y atomicidad.
¿Cuál de los siguientes NO es un posible estado final de R?
a. {(10,12)}
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 211 de 253
b. {(11,13)}
c. {(11,12)}
d. {(12,14)}
La respuesta correcta es (c), puesto que la alternativa (a) se produce si no se completa
T1. La alternativa (b) se produce si T2 se realiza antes que T1. La alternativa (d) se
produce cuando T1 se realiza después que T2.
Deshacer (Rollback) Transacción
Deshace los efectos parciales de una transacción.
Puede ser iniciada por el sistema o por el cliente.
Ahora realizaremos un ejemplo práctico en postgreSQL.
Ejemplo
Tenemos la tabla colors, con sus respectivos atributos id y color, pero antes de
comenzar debemos definir algunos conceptos:
begin: Inicio de una transacción. Al ingresar esta clausula es posible recuperar
errores que puedan ocurrir.
savepoint: Con esta sentencia se realiza un commit hasta el punto que se está
seguro que no posee errores. La diferencia concommit es que no se finaliza la
transacción.
rollback: Deshace todos los cambios que se hayan realizado desde la
sentencia begin ó hasta donde se haya confirmado consavepoint.
commit: Confirma y termina la transacción con los cambios establecidos.
SELECT * FROM colors; id | color ----+-------- 1 | yellow 2 | blue 3 | red 4 | green (4 rows)
Ahora comenzamos la transacción con commit.
begin;
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 212 de 253
Retornando postgreSQL como resultado BEGIN.
Realizamos una modificación en los colores yellow por black.
UPDATE colors SET color='black' WHERE color='yellow'; SELECT * FROM colors; id | color ----+------- 2 | blue 3 | red 4 | green 1 | black (4 rows)
Ahora confirmaremos que hasta aquí está todo bien.
savepoint b;
Retornando postgreSQL como resultado SAVEPOINT.
Volvemos a modificar un color de la tabla blue por orange.
UPDATE colors SET color='orange' WHERE color='blue'; SELECT * FROM colors; id | color ----+-------- 3 | red 4 | green 1 | black 2 | orange (4 rows)
Pero nos damos cuenta nos equivocamos y no era orange el color que deseábamos,
entonces volvemos al punto que guardamos anteriormente.
rollback TO b;
Retornando postgreSQL como resultado ROLLBACK.
Volviendo al punto anterior.
SELECT * FROM colors; id | color ----+------- 2 | blue 3 | red
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 213 de 253
4 | green 1 | black (4 rows)
Consistencia (C)
“Esta propiedad establece que solo los valores o datos válidos serán escritos en la base
de datos; si por algún motivo una transacción que es ejecutada viola esta propiedad, se
aplicará un rollback a toda transacción dejando a las bases de datos en su estado de
consistencia anterior. En caso de que la transacción sea ejecutada con éxito, la base de
datos pasará de su estado de consistencia anterior a un nuevo estado de consistencia.”
La propiedad de consistencia habla de cómo las transacciones interactúan con las
restricciones de integridad que pueden existir en una base de datos.
En concreto, cuando tenemos varios clientes que interactúan con la base de datos de
manera concurrente, podemos tener una configuración en la que cada cliente puede
asumir que cuando comienza a operar sobre una base de datos, satisfaga todas las
restricciones de integridad.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 214 de 253
Lección XXVII – Vistas: Definición y usos
Las vistas se basan en una visión bases de datos de tres niveles, que lo componen:
Capa física: En el nivel inferior, se encuentran los datos reales almacenados en
un disco.
Capa conceptual: Es la abstracción de las relaciones (o tabla) de los datos
almacenados en un disco.
Capa de lógica: la última capa es una abstracción por encima de las relaciones
es lo que se conoce como vistas (views).
Definición
Una vista es una tabla virtual derivada de las tablas reales de una base de datos. Las
vistas no se almacenan en la base de datos, sólo se almacena una definición de
consulta, es decir una vista contiene la instrucción SELECT necesaria para crearla.
Resultado de la cual se produce una tabla cuyos datos proceden de la base de datos o
de otras vistas. Eso asegura que los datos sean coherentes al utilizar los datos
almacenados en las tablas. Si los datos de las relaciones cambian, los de la vista que
utiliza esos datos también cambia. Por todo ello, las vistas gastan muy poco espacio de
disco.
Como una vista se define como una consulta sobre las relaciones, aún pertenecen en el
modelo de datos relacional.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 215 de 253
Para definir una vista V, se especifica una consulta de Vista en SQL, a través de un
conjunto de tablas existentes (R1, R2,…Rn).
Vista V= ConsultaSQL(R1, R2, …, Rn)
La vista V, entonces, se puede pensar como una tabla de los resultados de la consulta.
Ahora supongamos que se desea ejecutar una consulta Q en la base de datos. Esta no
es una consulta de vista, es sólo una consulta como las vistas anteriormente en el
curso. La consulta Q hace referencia a V.
V := ViewQuery(R1,R2,…,Rn)
Evaluate Q
Lo que realmente hace Q es consultar o editar las relaciones R1, R2,…, Rn instanciadas
por V. El DBMS realiza automáticamente el proceso de rescritura sobre las relaciones.
Usos de las vistas
Las vistas se emplean para:
Realizar consultas complejas más fácilmente: Las vistas permiten dividir la
consulta en varias partes.
Proporcionar tablas con datos específicos: Las vistas permiten ser utilizadas
como tablas que resumen todos los datos, así como también permiten ocultar
ciertos datos. Cuando ese se requiere un detalle que no corresponde
precisamente a las relaciones.
Modularidad de acceso a base de datos: las vistas se pueden pensar en forma de
módulos que nos da acceso a partes de la base de datos. Cuando ese detalle que
se requiere no corresponde precisamente a las relaciones.
Las aplicaciones reales tienden a usar un muchas vistas, por lo que cuanto más grande
es la aplicación, más necesario es que haya modularidad, para facilitar determinadas
consultas o para ocultar los datos. Las vistas entonces son el mecanismo para alcanzar
dichos objetivos.
Creación de una vista
CREATE VIEW : Define una tabla lógica a partir de una o más tablas físicas o de
otras vistas.
DROP VIEW : Elimina una definición de vista (y cualquier vista definida a partir de
ella).
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 216 de 253
Create View Vname(A1,A2,…,An) As <QuerySQLstandar>
Vname es el nombre que se le asigna a la vista, A1, A2,…, An son los nuevos nombres
de los atributos que tendrá la vista.
Ejemplo 1
Se utiliza una base de datos con las siguientes relaciones:
Specie(sName−−−−−−,comName,family)
Esta tabla almacena los datos que caracterizan las especies animales. Almacena el
nombre científico en sName , el nombre común con el que se le conoce es guardado
en comName y la familia family a la que pertenece la especie.
Zoo(zID−−−,zooName,size, budget)
La relación Zoo almacena los datos de los zoológicos. Un zID que es la primary key, el
nombre en zooName, size es el tamaño en hectáreas y presupuesto budget en unidades
monetarias.
Animal(zID, sName, aName−−−−−−−−−−−−−−−,country)
La tabla animal guarda los datos de los animales que habitan cada zoológico. El
atributo zID es clave foránea a Zoo, se refiere al zoológico en el que se encuentra un
animal, sName es clave foránea a la Specie que pertenece, country es el país de
procedencia.
La creación de las relaciones y los valores que se utilizarán en este ejemplo se
encuentran en el siguiente archivo
Se crea una vista:
CREATE VIEW View1 AS SELECT zID, sName FROM Animal WHERE aName = 'Tony' and country = 'China';
Como ya se mencionó para crear una vista se usan las palabras
clave CREATE VIEW especificando el nombre de la vista view1 . Luego se declara la
consulta en SQL estándar. Dicha consulta selecciona zID y sName de los animales que
se llamen ‘Tony’ y procedan de ‘China’ .
PostgreSQL retorna:
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 217 de 253
CREATE VIEW
Al realizar un SELECT de la vista, PostgreSQL la despliega como si fuera una relación
cualquiera.
DBviews=# SELECT * FROM View1; zid | sname -----+------------------------ 5 | Ailuropoda melanoleuca 1 | Panthera leo 3 | Panthera tigris (3 rows)
Sin embargo la vista no almacena los datos, sino que estos siguen almacenados en la
relación Animal. Observe que ocurre cuando se insertan más datos en Animal
INSERT INTO Animal (zID, sName, aName, country) VALUES (4,'Ailuropoda melanoleuca', 'Tony', 'China'), (3,'Panthera leo', 'Tony', 'China'), (1,'Loxodonta africana', 'Tony', 'China');
La View1 se actualiza automáticamente:
DBviews=# SELECT * FROM View1; zid | sname -----+------------------------ 5 | Ailuropoda melanoleuca 1 | Panthera leo 3 | Panthera tigris 4 | Ailuropoda melanoleuca 3 | Panthera leo 1 | Loxodonta africana (6 rows)
Ejemplo 2
Si se desea renombrar los atributos de una vista, la sentencia debe ser:
CREATE VIEW Viewt(IDzoo,specieName) as SELECT zID, sName FROM Animal WHERE aName = 'Tony' and country = 'China';
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 218 de 253
PostgreSQL retorna:
CREATE VIEW
La vista Viewt fue definida igual que View1, pero esta vez los atributos que selecciona
son renombrados, zID se despliega como IDzooy sName como specieName
DBviews=# SELECT * FROM Viewt; idzoo | speciename -------+------------------------ 5 | Ailuropoda melanoleuca 1 | Panthera leo 3 | Panthera tigris 4 | Ailuropoda melanoleuca 3 | Panthera leo 1 | Loxodonta africana (6 rows)
Para seleccionar un atributo de Viewt debe hacerse con el nuevo nombre asignado:
DBviews=# SELECT zID FROM viewt; ERROR: column "zid" does not exist LÍNEA 1: select zid from viewt; DBviews=# SELECT idzoo FROM viewt; idzoo ------- 5 1 3 4 3 1 (6 rows)
Ejemplo 3
A pesar que la vista no almacena valores, solo los referencia, se puede trabajar como si
fuera una relación real. La siguiente consulta selecciona Zoo.zID, zooName y size de la
tabla Zoo y de la vista View1, donde zID de la tabla Zoo sea igual al zID de View1,
recordar que View1 y sName de View1 sea ‘Ailuropoda melanoleuca’ y
que size de Zoo sea menor a 10.
SELECT Zoo.zID, zooName, size FROM Zoo, View1 WHERE Zoo.zID = View1.zID and sName = 'Ailuropoda melanoleuca' and size < 10;
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 219 de 253
zid | zooname | size -----+------------+------ 4 | London Zoo | 9 (1 row)
Ejemplo 4
Una vista también puede referenciar a otra vista. Para ello se crea una vista
llamada View2 que referencia a la tabla Zoo y a la vista View1.
CREATE view View2 as SELECT Zoo.zID, zooName, size FROM Zoo, View1 WHERE Zoo.zID = View1.zID and sName = 'Panthera leo' and budget > 80;
La sentencia crea una vista que almacena datos de Zoo que poseen animales ‘Panthera
leo’, la búsqueda la hace dentro de los datos que posee View1, además
el budget de Zoo debe ser mayor a 80. Cabe mencionar que al ejecutar este comando
no muestra el resultado, sólo crea la vista.
Luego View2 puede ser utilizada en sentencias SELECT de la misma forma que las
tablas:
DBviews=# SELECT * FROM View2; zid | zooname | size -----+---------------+------ 1 | Metropolitano | 4 3 | San Diego | 14 (2 rows) DBviews=# SELECT * FROM View2 WHERE size > 5; zid | zooname | size -----+-----------+------ 3 | San Diego | 14 (1 row)
Finalmente se eliminan las vistas:
DROP VIEW View1; DROP VIEW View2; DROP VIEW View3;
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 220 de 253
Lección XXVIII - Vistas: Vistas y
modificaciones automáticas
Por lo general, las tablas son constituidas por un conjunto de definiciones y almacenan
datos físicos.
Por otra parte las vistas se encuentran en un nivel superior, es decir son constituidas
por un conjunto de definiciones, pero no almacenan datos, pues utilizan los datos que
están almacenadas en las tablas.
Es por ello que, podemos decir que las vistas son por un conjunto de definiciones, pero
no almacenan datos, pues utilizan los datos que están almacenadas en las tablas.
Es decir que las vistas se consideran “tablas virtuales”.
Su sintaxis es:
CREATE VIEW "view_name" AS "sql_instruction";
Donde:
1. “view_name” : corresponde al nombre de la vista.
2. “sql_instruction”: corresponde a alguna instrucción SQL vista hasta ahora, es
decir, operaciones de inserción y/o modificación.
Toda Base de Datos (BD), puede ser vista como un árbol de 3 niveles:
1. La raíz, compuesta por la parte física de la BD, es decir el(los) disco(s) duro(s).
2. El tronco, compuesto por las relaciones de dentro de la BD, es decir, su
parte conceptual.
3. Las ramas, que corresponde a la parte lógica, se refiere a las relaciones que
nacen desde las relaciones del tronco (tablas) y/o relaciones desde las ramas
(otras vistas).
Realizar modificaciones en una vista no tiene mucho sentido, pues al no almacenar
información,estos cambios simplemente se perderían. No obstante, si el objetivo de
estos cambios corresponde a modificar la(s) tabla(s), dicha modificación adquiere
sentido.
Nota
Por modificación se entienden operaciones de tipo INSERT, UPDATE y DELETE.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 221 de 253
Estas modificaciones en las vistas deben ser traducidas a modificaciones que afecten a
las tablas involucradas. Esta Lección está orientada a profundizar como se automatiza
este proceso.
Reglas
Dentro del estándar de SQL, existen 4 reglas para que una “vista sea modificable”, es
decir si se modifica la vista en cuestión, se modifica la relación/tabla desde donde nace
la vista. Estas reglas son:
1. Hacer un SELECT. de una tabla, no de una unión (JOIN). Además la tabla no
puede ser DISTINCT.
2. Si un atributo no esta en la vista, debe soportar valores NULL o uno por defecto.
3. Si la vista está sobre la relación/tabla T, las subconsultas no pueden referirse
a T, pero si a otras relaciones/tablas.
4. En una vista, no se puede usar GROUP BY o AGREGGATION.
Contexto
Supongamos que durante el primer semestre de clases, específicamente a un mes de
que se implementara el sistema de postulación a Establecimientos Educacionales,
postulan 4 estudiantes más. Es por ello que se decide realizar una mejora utilizando
vistas, debido a sus propiedades y simplificar complejas consultas sobre tablas, ya sea
seleccionando (SELECT.) y/o modificando(INSERT, UPDATE, DELETE) datos.
Además se utilizarán criterios más estrictos, pues en la versión del sistema, se permitió
la entrada a alumnos que no tenían promedio arriba de 50: se le denominará sistema
de postulación 2.0 (BETA).
Es por ello que, para esta Lección, se utilizará el sistema de Postulación de Estudiantes
a Establecimientos Educacionales:
CREATE TABLE College(cName VARCHAR(20), state VARCHAR(30), enrollment INTEGER, PRIMARY KEY(cName)); CREATE TABLE Student(sID SERIAL, sName VARCHAR(20), Average INTEGER, PRIMARY KEY(sID)); CREATE TABLE Apply(sID INTEGER, cName VARCHAR(20), major VARCHAR(30), decision BOOLEAN, PRIMARY KEY(sID, cName, major));
con los siguientes datos para la tabla College, Student y Apply respectivamente:
4 establecimientos:
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 222 de 253
INSERT INTO College VALUES ('Stanford','CA',15000); INSERT INTO College VALUES ('Berkeley','CA',36000); INSERT INTO College VALUES ('MIT', 'MA',10000); INSERT INTO College VALUES ('Harvard', 'CM',23000);
Nota
Estos datos no son necesariamente reales, ni se hicieron investigaciones para corroborar su
veracidad (estado o capacidad), pues se escapa al alcance de este curso. Sólo buscan ser
meras herramientas para el desarrollo de los ejemplos de esta Lección.
3 estudiantes:
INSERT INTO Student (sName, Average) VALUES ('Clark', 70); INSERT INTO Student (sName, Average) VALUES ('Marge', 85); INSERT INTO Student (sName, Average) VALUES ('Homer', 50);
8 postulaciones:
INSERT INTO Apply VALUES (1, 'Stanford', 'science' , True); INSERT INTO Apply VALUES (1, 'Berkeley', 'science' , False; INSERT INTO Apply VALUES (2, 'Harvard' , 'science' , False; INSERT INTO Apply VALUES (2, 'MIT' , 'engineering' , True); INSERT INTO Apply VALUES (2, 'Berkeley', 'science' , True); INSERT INTO Apply VALUES (3, 'MIT' , 'science' , True); INSERT INTO Apply VALUES (3, 'Harvard' , 'engineering' , True); INSERT INTO Apply VALUES (3, 'Harvard' , 'natural history' , True);
Nota
Estos datos no son necesariamente reales, ni se hicieron investigaciones para corroborar su
veracidad (mención académica), pues se escapa al alcance de este curso. Sólo buscan ser
meras herramientas para el desarrollo de los ejemplos de esta Lección.
Modificación automática de vistas y tablas
Supongamos que deseamos seleccionar a los Estudiantes que postularon y fueron
aceptados en en Ciencias, en cualquier Establecimiento Educacional, pero utilizando
vistas:
CREATE VIEW scAccepted as SELECT sid, sname FROM Apply WHERE major='science' and decision = true;
Esta vista cuenta con las 4 restricciones impuestas por el estándar SQL para que sea
considerada como “vista modificable”:
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 223 de 253
1. Se selecionan datos solamente de la tabla Apply.
2. Los atributos de dicha tabla no contienen alguna restricción de tipo NOT NULL.
3. No hay subconsultas que se refieran a la tabla Apply.
4. No se utiliza GROUP BY o AGREGGATION.
Si se seleccionan los datos de la vista:
SELECT * FROM scAccepted;
su salida es:
sid | cname ----+---------- 1 | Stanford 2 | Berkeley 3 | MIT
Ejemplo 1
Supongamos que se desea eliminar de la vista al estudiante con sID = 3 (Homer), pues
realizó trampa en esta prueba. La idea es eliminarlo de la vista y a la vez, de la tabla
Apply, para no tener que realizar 2 operaciones:
DELETE FROM scAccepted WHERE sid = 3;
No obstante:
ERROR: you cannot delete from view "scaccepted" HINT: You need a unconditional ON DELETE DO INSTEAD rule or INSTEAD OF DELETE trigger.
Pues MySQL es el único sistema, en relación a PostgreSQL o SQLite que permite un
manejo de datos de este tipo. Estos últimos permiten la modificación en base a reglas
y/o triggers solamente.
Advertencia
Si bien el motor de Base de Datos utilizado para este curso, no soporta el tópico de esta
Lección, se verán casos y consejos para utilizarlos en sistemas que funcionen. De todos
modos, los ejemplos se construyen utilizando PostgreSQL.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 224 de 253
Ejemplo 2
Supongamos que deseamos crear una vista que contenga a los Estudiantes que
postularon a Ciencias o Ingeniería.
CREATE VIEW sceng as SELECT sid, cname, major FROM Apply WHERE major = 'science' or major = 'engineering';
Verificando a través de una selección:
SELECT * FROM sceng;
la salida es:
sid | cname | major ----+----------+------------- 1 | Stanford | science 1 | Berkeley | science 2 | Harvard | science 2 | MIT | engineering 2 | Berkeley | science 3 | MIT | science 3 | Harvard | engineering
Si deseamos agregar una fila, digamos:
INSERT INTO sceng VALUES (1, 'MIT', 'science');
No hay problemas, pues cuenta con las 4 reglas de “vistas modificables”. El ejemplo
funciona en MySQL y en la teoría.
Ejemplo 3
Supongamos que deseamos agregar una fila a la vista scAccepted,
INSERT INTO scAccepted VALUES (2, 'MIT');
Si bien podría pensarse que, como la vista contiene valores determinados para el
atributo major y decision, bastaría con agregar sólo los restantes, es decir sID y cName.
Al momento de seleccionar todos los datos de la vista, no se verá esta nueva fila,
debido a que:
1. El hecho de que la vista cuente con valores de selección no quiere decir que ellos
sean de inserción.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 225 de 253
2. Al no tener los atributos major y decision con valores ‘science’ y ‘true’
respectivamente no pasan el filtro de la vista.
Sin embargo en la tabla (Apply en este caso), la nueva fila se agrega. Pero claro, no
tiene sentido, pues los campos major y decisionson NULL.
Ejemplo 4
En los sistemas que se permite el cambio automático, es posible evitar inconsistencias
como la que se generó en el ejemplo 3, agregando al final de la vista:
CREATE VIEW scAccepted2 as SELECT sid, sname FROM Apply WHERE major='science' and decision = true; WITH CHECK OPTION;
No obstante esta opción no está implementada en PostgreSQL, por lo que el siguiente
error aparece al ejecutar la consulta que está arriba:
ERROR: WITH CHECK OPTION is not implemented.
Conclusiones
1. Los cambios automáticos sólo se pueden realizar a “tablas modificables”, es
decir que cumplan con las 4 reglas.
2. PostgreSQL no soporta este tipo de modificación, sólo la permite a través de
reglas y/o triggers.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 226 de 253
Lección XXIX - Vistas: Vistas
materializadas
Introducción
En las Leccións anteriores se vio la vista virtual que es el tipo usual de vista que se
define como una consulta de la base de datos. En esta Lección se verán las vistas
materializadas, que almacena el resultado de la consulta en una tabla caché real. Es una
solución muy utilizada en entornos de almacenes de datos (datawarehousing), donde el
acceso frecuente a las tablas básicas resulta demasiado costoso.
Definición
Una vista materializada almacena físicamente los datos resultantes de ejecutar la
consulta definida en la vista. Inicialmente se almacenan los datos de las tablas base al
ejecutar la consulta y se actualiza periódicamente a partir de las tablas originales. Las
vistas materializadas constituyen datos redundantes, en el sentido de que su contenido
se puede deducir de la definición de la vista y del resto del contenido de la base de
datos.
Se define una vista especificando una consulta de Vista en SQL, a través de un conjunto
de tablas existentes (R1, R2,…Rn).
Vista V= ConsultaSQL(R1, R2, …, Rn)
De esta forma se crea en realidad una tabla física V con el esquema del resultado de la
consulta. Puede referirse a V como si fuese una relación, ya que en realidad es una tabla
almacenada en una base de datos.
Ventaja
Poseen las mismas ventajas de visitas virtuales. La diferencia radica en que las vistas
materializadas mejoran el rendimiento de consultas sobre la base de datos, pues
proporciona un acceso mucho más eficiente. Con la utilización de vistas materializadas
se logra aumentar el rendimiento de las consultas SQL además de ser un método de
optimización a nivel físico en modelos de datos muy complejos y/o con muchos datos.
Desventajas
Incrementa el tamaño de la base de datos
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 227 de 253
Posible falta de sincronía, es decir, que los datos de la vista pueden estar
potencialmente desfasados con respecto a los datos reales. Al contener
físicamente los datos de las tablas base, si cambian los datos de estas tablas no
se reflejarán en la vista materializada.
Mantenimiento de las vistas
Como se mencionó anteriormente un problema que poseen las vistas materializadas es
que hay que mantenerlas actualizadas cuando se modifican los datos de las tablas
bases que emplea la vista. La Práctica de actualizar una vista se
denomina mantenimiento de la vista materializada. También hay que tener presente
que al modificar una vista debe actualizarse la(s) tabla(s) de origen(es), pues las vistas y
las relaciones deben estar sincronizadas.
Una manera de realizar mantenimiento es utilizando Triggers para la inserción, la
eliminación y la actualización de cada relación de la definición de la vista.
Los Triggers deben modificar todo el contenido de la vista materializada.
Una mejor opción es editar sólo la parte modificada de la vista materializada, lo que se
conoce como mantenimiento incremental de la vista.
Los sistemas modernos de bases de datos proporcionan más soporte directo para el
mantenimiento incremental de las vistas. Los programadores de bases de datos ya no
necesitan definir Triggers para el mantenimiento de las vistas. Por el contrario, una vez
que se ha declarado materializada una vista, el sistema de bases de datos calcula su
contenido y actualiza de manera incremental el contenido cuando se modifican los
datos subyacentes.
Creación de una vista
En algunos sistemas de gestión de bases de datos poseen las palabras
reservadas CREATE MATERIALIZED VIEW que define una vista materializada a partir de
una o más tablas físicas.
Forma general:
CREATE MATERIALIZED VIEW viewName AS SELECT ... FROM ... WHERE ...
Sin embargo en esta Lección se utilizará otro método para tratar las vistas
materializada. Primero se crea la tabla matviews para guardar la información de una
vista materializada.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 228 de 253
CREATE TABLE matviews ( mv_name NAME NOT NULL PRIMARY KEY , v_name NAME NOT NULL , last_refresh TIMESTAMP WITH TIME ZONE );
Donde:
mv_name: es el nombre de la vista materializada representada por esta fila.
v_Name: es el nombre de la vista que se basa la vista materializada.
last_refresh: La hora de la última actualización de la vista materializada.
Ahora se crea una función create_matview escrita en PL/pgSQL. Dicha función inserta
una fila en la tabla matviews y crea la vista materializada. Recibe el nombre de la vista
materializada, y el nombre de la vista que se basa. Tenga en cuenta que se debe crear
la vista virtual en la que se basa, más adelante se explica cómo se crea y utiliza esta
vista. Esta función ve si una vista materializada con el nombre que recibe ya está
creada. Si es así, se produce una excepción. De lo contrario, se crea una nueva tabla
con la vista, e inserta una fila en la tabla matviews.
CREATE OR REPLACE FUNCTION create_matview(NAME, NAME) RETURNS VOID SECURITY DEFINER LANGUAGE plpgsql AS ' DECLARE matview ALIAS FOR $1; view_name ALIAS FOR $2; entry matviews%ROWTYPE; BEGIN SELECT * INTO entry FROM matviews WHERE mv_name = matview; IF FOUND THEN RAISE EXCEPTION ''Materialized view ''''%'''' already exists.'', matview; END IF; EXECUTE ''REVOKE ALL ON '' || view_name || '' FROM PUBLIC''; EXECUTE ''GRANT SELECT ON '' || view_name || '' TO PUBLIC''; EXECUTE ''CREATE TABLE '' || matview || '' AS SELECT * FROM '' || view_name; EXECUTE ''REVOKE ALL ON '' || matview || '' FROM PUBLIC''; EXECUTE ''GRANT SELECT ON '' || matview || '' TO PUBLIC'';
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 229 de 253
INSERT INTO matviews (mv_name, v_name, last_refresh) VALUES (matview, view_name, CURRENT_TIMESTAMP); RETURN; END ';
La función drop_matview elimina la vista materializada y la entrada de matviews ,
Dejando la vista virtual sola.
CREATE OR REPLACE FUNCTION drop_matview(NAME) RETURNS VOID SECURITY DEFINER LANGUAGE plpgsql AS ' DECLARE matview ALIAS FOR $1; entry matviews%ROWTYPE; BEGIN SELECT * INTO entry FROM matviews WHERE mv_name = matview; IF NOT FOUND THEN RAISE EXCEPTION ''Materialized view % does not exist.'', matview; END IF; EXECUTE ''DROP TABLE '' || matview; DELETE FROM matviews WHERE mv_name=matview; RETURN; END ';
La función refresh_matview actualiza las vistas materializadas de manera que los datos
no se convierten en obsoletos. Esta función sólo necesita el nombre de la matview. Se
utiliza un algoritmo que elimina todas las filas y vuelve a colocarlas en la vista.
CREATE OR REPLACE FUNCTION refresh_matview(name) RETURNS VOID SECURITY DEFINER LANGUAGE plpgsql AS ' DECLARE matview ALIAS FOR $1; entry matviews%ROWTYPE; BEGIN SELECT * INTO entry FROM matviews WHERE mv_name = matview; IF NOT FOUND THEN RAISE EXCEPTION ''Materialized view % does not exist.'', matview; END IF;
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 230 de 253
EXECUTE ''DELETE FROM '' || matview; EXECUTE ''INSERT INTO '' || matview || '' SELECT * FROM '' || entry.v_name; UPDATE matviews SET last_refresh=CURRENT_TIMESTAMP WHERE mv_name=matview; RETURN; END ';
Ejemplo
Para este ejemplo se utilizarán las funciones mostradas anteriormente, primero se
instala el lenguaje plpgsql:
viewm=# CREATE PROCEDURAL LANGUAGE plpgsql; CREATE LANGUAGE
Con el lenguaje ya instalado se crea la relación matviews y se agregar las
funciones create_matview, drop_matview y refresh_matview a la base de datos.
Se crea la relación game_score, también se crea la vista virtual player_total_score_v
CREATE TABLE game_score ( pname VARCHAR(255) NOT NULL, score INTEGER NOT NULL); CREATE VIEW player_total_score_v AS SELECT pname, sum(score) AS total_score FROM game_score GROUP BY pname;
Dado que muchos de los equipos juegan todos los días, y correr la vista es un poco
caro, se decide implementar una vista materializada en player_total_score_v . Para ello
se crea la vista invocando la función create_matview pasándole por parámetros el
nombre de la vista materializada player_total_score_mv y el nombre de la vista
virtual player_total_score_v.
viewm=# SELECT create_matview('player_total_score_mv', 'player_total_score_v'); create_matview ---------------- (1 row)
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 231 de 253
Al ejecutar un SELECT sobre la vista materializada se observa que está creada y vacía:
viewm=# SELECT * FROM player_total_score_mv; pname | total_score -------+------------- (0 row)
Los datos de la vista se almacena en la relación matviews
SELECT * FROM matviews; mv_name | v_name | last_refresh -----------------------+----------------------+------------------------------ player_total_score_mv | player_total_score_v | 2013-02-11 10:54:56.08571-03 (1 row)
Se insertan valores en la relación game_score:
viewm=# INSERT INTO game_score ( pname, score) VALUES ('UCH',2), ('SW',4); INSERT 0 2
Al ejecutar un SELECT se observa que la vista se mantiene vacía:
viewm=# SELECT * FROM player_total_score_mv; pname | total_score -------+------------- (0 row)
Para actualizar la vista materializada se debe ocupar la función refresh_matview:
viewm=# SELECT refresh_matview('player_total_score_mv'); refresh_matview ----------------- (1 row)
Esta vez al volver a seleccionar la vista materializada aparecen los valores insertados en
la relación game_score
viewm=# SELECT * FROM player_total_score_mv; pname | total_score -------+------------- SW | 4 UCH | 2 (2 rows)
Para eliminar la vista materializada se usa la función drop_matview:
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 232 de 253
viewm=# SELECT drop_matview('player_total_score_mv'); drop_matview -------------- (1 row)
Al hacer un SELECT a la vista materializada, aparece un error pues ya no existe.
viewm2=# SELECT * FROM player_total_score_mv; ERROR: relation "player_total_score_mv" does not exist LÍNEA 1: SELECT * from player_total_score_mv;
Se revisa la relación matviews y aquí también se eliminó la vista materializada:
viewm=# SELECT * from matviews; mv_name | v_name | last_refresh ---------+--------+-------------- (0 row)
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 233 de 253
Lección XXX – Mantenimiento de la Base
de Datos
Introducción
Una base de datos requiere de una mantención periódica, de lo contrario puede
desarrollar problemas en una o más áreas, lo cual a largo plazo puede provocar un mal
rendimiento de la aplicación, llegando incluso a perdidas de datos.
Existen actividades que el administrador del sistema gestor de bases de datos debe
realizar habitualmente. En el caso de PostgreSQL, mantenimiento de los identificadores
internos y de las estadísticas de planificación de las consultas, a una reindexación
periódica de las tablas, y al tratamiento de los ficheros de registro.
Rutinas de mantenimiento y monitoreo
Vacuum
VACUUM es el proceso que realiza una limpieza a la base de datos en PostgreSQL. Se
eliminan definitivamente tuplas marcadas para borrar y se efectúa una reorganización
de datos a nivel físico.
El VACUUM se realiza periódicamente se para:
Recuperar espacio en disco perdido por datos borrados o actualizados. En
operaciones normales de PostgreSQL, las tuplas que se eliminan o quedan
obsoletas por una actualización no se eliminan físicamente de su tabla, sino que
permanecen hasta se ejecuta un VACUUM. Por lo tanto es necesario
hacer VACUUM periódicamente, especialmente en las tablas frecuentemente
actualizadas.
Actualizar las estadísticas de datos utilizados por el planificador de consultas
SQL.
Protegerse ante la pérdida de datos por reutilización de identificadores de
transacción.
sintaxis
VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ table ] VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ]
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 234 de 253
VACUUM puede recibir ciertos parámetros para realizar los diferentes tipos de
vaciamiento:
FREEZE La opción FREEZE esta depreciada y será removida en liberaciones
futuras.
FULL Selecciona el vaciamiento “completo”, el cual recupera más espacio, pero
toma mucho más tiempo y bloquea exclusivamente la tabla.
VERBOSE Imprime un reporte detallado de la actividad de vaciamiento para cada
tabla.
ANALYZE Actualiza las estadísticas usadas por el planeador para determinar la
forma más eficiente de ejecutar una consulta.
tabla: El nombre de una tabla específica a vaciar. Por defecto se toman todas las
tablas de la base de datos actual.
columna: El nombre de una columna específica a analizar. Por defecto se toman
todas las columnas. Este comando es muy útil para automatizar vaciamientos a
través de cualquier sincronizador de Prácticas.
Asimismo, existe la opción del Autovacuum, cuya funcionalidad es ir realizando de
manera paulatina la mantención de nuestra base. Previamente y antes de activar esta
funcionalidad, es recomendable leer sobre las consideraciones a tener en cuenta, para
no degradar la performance de nuestro servidor.
Ejemplo:
Se ejecuta VACUUM sobre una base de datos existente.
demo=# VACUUM; VACUUM
Se ejecuta VACUUM con parámetro FULL sobre una base de datos existente
demo=# VACUUM FULL; VACUUM
Se realiza VACUUM sobre la relación game_score.
demo=# VACUUM game_score; VACUUM
En caso de que haya algún problema o acción adicional a realizar, el sistema lo indicará:
demo=# VACUUM;
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 235 de 253
WARNING: some databases have not been vacuumed in 1613770184 transactions HINT: Better vacuum them within 533713463 transactions, or you may have a wraparound failure.
Reindexación
Para facilitas la obtención de información de una tabla se utilizan índices. El índice de
una tabla permite encontrar datos rápidamente. Sin índice se debería recorrer
secuencialmente toda la tabla para encontrar un registro. Es muy útil para bases de
datos que posee mucha información.
Una tabla se indexa por un campo o varios. Es importante identificar el o los datos por
lo que sería útil crear un índice, aquellos campos por los cuales se realizan operaciones
de búsqueda con frecuencia.
Hay distintos tipos de índice:
primary key: como ya se explicó anteriormente es la clave primaria, los valores
deben ser únicos y además no pueden ser nulos.
index: crea un índice común, los valores no necesariamente son únicos y
aceptan valores nulos. Se le puede asignar un nombre, por defecto se coloca el
nombre “key”. Pueden ser varios por tabla.
unique: crea un índice para los cuales los valores deben ser únicos y diferentes,
aparece un mensaje de error si intentamos agregar un registro con un valor ya
existente. Permite valores nulos y pueden definirse varios por tabla.
La reindexación completa de la base de datos no es una Práctica muy habitual, pero
puede mejorar sustancialmente la velocidad de las consultas complejas en tablas con
mucha actividad.
Ejemplo:
Se ejecuta el comando sobre la base de datos utilizada en la Lección 29:
demo=# reindex database demo; NOTICE: table "pg_class" was reindexed NOTICE: table "pg_type" was reindexed NOTICE: table "pg_statistic" was reindexed NOTICE: table "sql_features" was reindexed NOTICE: table "sql_implementation_info" was reindexed NOTICE: table "sql_languages" was reindexed NOTICE: table "sql_packages" was reindexed
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 236 de 253
Se utiliza las palabras reservadas reindex database agregando el nombre de la base de
datos “demo”.
Ficheros de registro
Una buena práctica es mantener archivos de registro de la actividad del servidor, al
menos de los errores que origina. Durante el desarrollo de aplicaciones se puede
disponer de un registro de las consultas efectuadas, aunque disminuye el rendimiento
del gestor en bases de datos de mucha actividad, y puede no ser de mucha utilidad.
De igual modo es conveniente disponer de mecanismos de rotación de los ficheros de
registro; es decir, que periódicamente se mantenga un respaldo de estos ficheros y se
empiecen unos nuevos, lo que permite tener un historial.
PostgreSQL no proporciona directamente utilidades para realizar esta rotación, pero en
la mayoría de sistemas Unix vienen incluidas utilidades como logrotate que realizan
esta Práctica a partir de una planificación temporal.
VACUUM demo=# VACUUM VERBOSE ANALYZE; INFO: analyzing "pg_catalog.pg_operator" INFO: "pg_operator": scanned 13 of 13 pages, containing 704 live rows and 0 dead rows; 704 rows in sample, 704 estimated total rows INFO: vacuuming "pg_catalog.pg_opfamily" INFO: index "pg_opfamily_am_name_nsp_index" now contains 68 row versions in 2 pages DETALLE: 0 index row versions were removed. 0 index pages have been deleted, 0 are currently reusable. CPU 0.00s/0.00u sec elapsed 0.00 sec. VACUUM
Explain
Este comando muestra el plan de ejecución que el administrador del sistema gestor de
bases de datos Postgres genera para una consulta dada. El plan de ejecución muestra la
manera en que serán escaneadas las tablas referenciadas; ya sea escaneo secuencial
plano, escaneo por índice, etc. En el caso que se referencian varias tablas, los
algoritmos de unión que serán utilizados para agrupar las tuplas requeridas de cada
tabla de entrada.
Sintaxis
EXPLAIN [ VERBOSE ] consulta
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 237 de 253
La opción VERBOSE emite la representación interna completa del plan. Usualmente esta
opción es útil para la corrección de errores de Postgres.
Ejemplo 1.
Se emplea la misma tabla utilizada en la Lección 29:
demo=# SELECT * FROM game_score; pname | score -------+------- UCH | 2 SW | 4 (2 rows)
Para mostrar un plan de consulta para una consulta simple sobre una tabla con dos
columnas una del tipo INT y la otra VARCHAR :
EXPLAIN SELECT * FROM game_score; QUERY PLAN ---------------------------------------------------------- Seq Scan on game_score (cost=0.00..1.02 rows=2 width=7) (1 row)
Ejemplo 2.
Se crea una tabla con un índice INT y se insertan 4 valores:
demo=# CREATE TABLE score (num int); CREATE TABLE demo=# INSERT INTO score VALUES(1),(2),(5),(4); INSERT 0 4 EXPLAIN SELECT * FROM foo WHERE num = 4; QUERY PLAN ----------------------------------------------------- Seq Scan on foo (cost=0.00..40.00 rows=12 width=4) Filter: (num = 4) (2 rows)
EXPLAIN es la presentación del costo estimado de ejecución de la consulta, que es la
suposición del planificador sobre el tiempo que tomará correr la consulta (medido en
unidades de captura de páginas de disco). Se Muestra dos números: el tiempo inicial
que toma devolverse la primer tupla, y el tiempo total para devolver todas las tuplas.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 238 de 253
Lección XXXI - Servicios de Respaldo y
Recuperación para Bases de Datos (BD)
Vamos a comenzar esta Lección con algunas preguntas que a medida que avance la
Lección, serán respondidas:
1. ¿Por qué debemos respaldar una BD? ¿Es posible recuperar información? ¿Cuál es
la importancia de este tipo de servicios?
2. ¿Como funcionan?
3. ¿Son soportadas por los principales Sistemas de BD? ¿Cuál es el caso de
PostgreSQL?
Es de suma importancia tener algún sistema de respaldo/recuperación de datos, pues
esto permite:
1. Tener sistemas con cierto nivel de seguridad y estabilidad ante posibles fallos.
2. Poder volver a un punto seguro en el estado de la BD, debido a cambios
peligrosos.
Su funcionamiento está basado en estados. En cada momento la BD se encuentra en un
estado definido. Cuando realizamos operaciones de modificación, es decir:
1. INSERT
2. UPDATE
3. DELETE
Cambiamos su estado, llevándolo a uno nuevo.
Nota
No se considera SELECT, pues no provoca cambios. Recordemos que es una
operación de selección.
Al momento de realizar un respaldo, se guarda el estado en que se encuentra la BD al
momento de realizar dicha operación de respaldo.
Al momento de realizar la operación de recuperación, puede ser de varias formas, ya
sea a través de las operaciones (en orden) que han dejado la BD en el estado actual u
otras formas.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 239 de 253
La gran mayoría de Motores de BD cuentan con funciones de este tipo y PostgreSQL no
es la excepción.
Servicios en PostgreSQL
De forma nativa PostgreSQL cuenta con las siguientes funciones:
Advertencia
Algunos de los comandos que se verán a continuación, son ejecutados en terminales bajo
sistemas UNIX. No necesariamente dentro del entorno de PostgreSQL (psql).
SQL Dump
pg_dump
Esta función genera un archivo de texto con comandos SQL que, cuando son
reintroducidos (bajo cierto contexto ) al servidor, se deja a la BD en el mismo estado en
el que se encontraba al momento de ejecutar este comando.
Nota
Esto ocurre siempre y cuando la BD esté vacía, es decir, en el mismo estado inicial.
pg_dump guarda los comandos introducidos hasta el punto de control. El ejemplo 1
permitirá aclarar dudas.
su sintaxis es:
pg_dump dbname > archivo_salida
y se usa desde la linea de comandos.
Para realizar la restauración se utiliza:
psql dbname < archivo_entrada
Donde archivo_entrada corresponde al archivo_salida de la instrucción pg_dump.
Ejemplo 1
Supongamos que tenemos una BD llamada lecture31 y dentro de ella una única tabla
llamada Numbers con atributos Number YName, con datos:
1 One 2 Two
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 240 de 253
3 Three
Es decir:
CREATE DATABASE lecture31;
conectándose:
\c lecture31 CREATE TABLE Numbers(Number INTEGER, Name VARCHAR(20)); INSERT INTO Numbers VALUES (1, 'One' ); INSERT INTO Numbers VALUES (2, 'Two' ); INSERT INTO Numbers VALUES (3, 'Three' );
A través de un select:
number | name -------+------- 1 | One 2 | Two 3 | Three
Para realizar el respaldo, se utiliza pg_dump:
pg_dump lecture31 > resp.sql
Un posible problema a la hora de ejecutar pg_dump es:
pg_dump lecture31 > resp.sql (bash: permission denied)
Para evitar esto, es necesario considerar que el usuario de la BD debe tener permisos de
escritura en la carpeta donde se alojará el archivo.
Nota
Para los usuarios locales, basta con hacer “cd” en la linea de comandos (como usuario
postgres), para acceder a la carpeta de postgres. Si desea realizar pruebas desde el servidor
dedicado, puede crear BDs desde su sesión y alojar los archivos de respaldo en su capeta
home.
Nota
Es posible cambiar los permisos de Lección y escritura de las carpetas, dar accesos a
usuarios que no son dueños de las BD. No se profundiza esto, pues escapa a los alcances
de este curso.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 241 de 253
Supongamos que se comete un error, se borra información de seguridad nacional,
digamos la tupla “1, One”. Utilizando el archivo de respaldo es posible volver al estado
anterior:
psql lecture31 < resp.sql
Nota
Nótese que dentro de la salida del comando aparece: ERROR: relation “numbers” already
exists
Revisando la tabla a través de:
\c lecture31 SELECT * FROM Numbers;
La salida es:
number | name -------+------- 2 | Two 3 | Three 1 | One 2 | Two 3 | Three
Lo cual, claramente, no corresponde a la información inicial.
Antes de restaurar, es necesario recrear el contexto que tenía la BD. Específicamente
usuarios que poseían ciertos objetos o permisos. Si esto no calza con la BD, original, es
posible que la restauración no se realice correctamente.
En este caso el contexto inicial corresponde a una BD vacía, dentro de la cual se crea
una tabla y se agregan algunos datos Se invita al lector a borrar la tabla y realizar la
restauración.
Es necesario aclarar que se necesita una BD existente para hacer la restauración. Si ésta
no existe, por ejemplo utilizar lecture32 en lugar de 31, el siguiente error aparecerá:
psql: FATAL: database "lecture32" does not exist
Pero ¿Qué ocurre si utilizamos el atributo number como PK?, es decir modificar sólo la
linea (y seguir el resto de los pasos de la misma forma):
CREATE TABLE Numbers(Number INTEGER, Name VARCHAR(20), PRIMARY KEY (Number));
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 242 de 253
Al momento de borrar la tupla, digamos (3, ‘Three’), e intentar restaurar, dentro de la
salida del comando aparece:
ERROR: relation "numbers" already exists ERROR: duplicate key violates unique constraint "numbers_pkey" CONTEXT: COPY numbers, line 1: "1 One" ERROR: multiple primary keys for table "numbers" are not allowed
¿Qué ocurre si se elimina la primera tupla antes de restaurar?
Ejemplo 2
Este ejemplo es muy similar al anterior, sólo que, en lugar de trabajar con atributos
INTEGER, se trabajará con atributo serial es decir:
\c lecture31 DROP TABLE Numbers; CREATE TABLE Numbers2(Number SERIAL, Name VARCHAR(20)); INSERT INTO Numbers2 (name) VALUES ('One' ); INSERT INTO Numbers2 (name) VALUES ('Two' ); INSERT INTO Numbers2 (name) VALUES ('Three' );
Es decir que si se hace un select, se podrá ver:
number | name -------+------- 1 | One 2 | Two 3 | Three
Para poder realizar el respaldo, utilizando pg_dump:
pg_dump lecture31 > resp2.sql
Digamos que se agrega la tupla (4, ‘Four’) y borra la tupla (3, ‘Three’). Después de
realizar el respaldo:
number | name -------+------- 1 | One 2 | Two 4 | Four
Posteriormente se realiza la restauración:
psql lecture31 < resp.sql
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 243 de 253
Nota
Nótese que en la salida, es posible ver: setval 3
Revisando la tabla a través de:
\c lecture31 SELECT * FROM Numbers2;
La salida es:
number | name -------+------- 1 | One 2 | Two 4 | Four 1 | One 2 | Two 3 | Three
Lo cual es un problema, pues se trabaja con valores seriales. De hecho si en este estado
se agrega la tupla (4, Four) y se revisan los contenidos de la tabla, la salida es:
number | name -------+------- 1 | One 2 | Two 4 | Four 1 | One 2 | Two 3 | Three 4 | Four
Esto ocurre debido a que el contador serial vuelve a 3.
Ejercicio propuesto
Se deja en manos del lector ver que ocurre en caso de trabajar con atributo serial PK, es
decir:
CREATE TABLE Numbers2(Number SERIAL, Name VARCHAR(20), PRIMARY KEY (number));
y luego seguir los mismos pasos, es decir agregar las tuplas (1, ‘One’), (2, ‘Two’) y (3,
‘Three’). Luego realizar un respaldo, acceder a la BD, eliminar la última tupla, agregar
(4, ‘Four’), realizar la restauración, intentar agregar más tuplas (conectándose a la BD
primero) y los que desee hacer el lector.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 244 de 253
A modo de pista, si al agregar una tupla, aparece:
ERROR: duplicate key value violates unique constraint "numbers2_pkey"
Siga intentando, verá que es posible agregar más tuplas. Fíjese en el valor de la llave
primaria. ¿Cuántas veces tuvo que intentar?
¿Qué ocurre si en lugar de eliminar la última tupla, se elimina la primera?
pg_dumpall
Un pequeño inconveniente con pg_dump es que sólo puede hacer respaldos de una BD
a la vez. Además no respalda información acerca de roles de usuario e información por
el estilo
Para realizar un respaldo de la BD y el cluster de datos, existe el comando pg_dumpall.
su sintaxis es:
pg_dumpall > archivo_salida
y para realizar la restauración (utilizar el comando unix)
psql -f archivo_entrada postgres
Que trabaja emitiendo las consultas y comandos para recrear roles, tablespaces y Bases
de Datos vacíos. Posteriormente se invoca pg_dump por cada BD para corroborar
consistencia interna.
Advertencia
Es posible que el servidor dedicado no le permita restaurar, si se utiliza con el usuario
postgres. Por favor, utilice este comando sólo de manera local. Pruebe utilizando su propio
usuario.
Respaldo a nivel de archivos
Otra forma de realizar respaldos es a través del manejo directo de archivos, en lugar de
las sentencias utilizadas.
No obstante, existen 2 restricciones que hacen que este método sea menos práctico
que utilizar pg_dump:
1. El servidor debe ser apagado para poder obtener un respaldo utilizable.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 245 de 253
2. Cada vez que se realice un respaldo, el servidor debe estar apagado, para que
los cambios se guarden en su totalidad.
Advertencia
La mayor parte de las veces, se necesita acceso root, para poder realizar este tipo de
operación, pues es necesario configurar archivos de configuración de postgres. Es de suma
importancia que se realicen de forma correcta, pues ante algún fallo es posible destruir la
base de datos de forma completa. Por lo tanto, no se abordará de forma extensa este
apartado. No obstante es posible obtener información en internet.
Rsync
Rsync corresponde a un programa que sincroniza dos directorios a través de distintos
sistemas de archivos, incluso si están en distinto computadores, físicamente hablando.
A través del uso de SSH o Secure SHell por sus siglas en inglés, se pueden realizar
transferencias seguras y basadas en llaves de autenticación.
La principal ventaja de utilizar rsync a diferencia de otros comandos similares,
como scp, es que si el archivo que se encuentra en la fuente, es el mismo que, el que se
encuentra en el objetivo, no hay transmisión de datos; si el archivo que se encuentra en
el objetivo difiere del que se encuentra en la fuente, sólo aquellas partes que difieren
son transmitidas, en lugar de transmitir todo, por lo que el downtime de la BD, es decir,
el tiempo que debe permanecer apagada, es mucho menor.
Cabe destacar que es de suma importancia realizar una adecuada preparación de la BD,
para evitar posibles desastres. En [1] se explican con gran nivel de detalle. No obstante,
los cambios realizados son bajo su propio riesgo, y se recomienda fuertemente realizar
pruebas de manera local.
Conclusiones
Para finalizar, por lo general, los respaldos realizados a través de SQL Dump suelen ser
más livianos, en tamaño, que los realizados a través de respaldo de archivos, ya que,
por ejemplo en el caso de pg_dump no es necesario copiar índices de tablas o cosas
por el estilo; sino que sólo los comandos que los crean. Es por ello que, generalmente
estos últimos, son más rápidos.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 246 de 253
Lección XXXII – Querys al Catalogo de
PostgreSQL
Obtener objetos del servidor PostgreSQL.
En esta sección se especifican los objetos generales del servidor y se presentan
Algunas consultas útiles para el trabajo con PostgreSQL.
- Obtener las bases de datos disponibles
select datname from pg_database where datallowconn=true
- Obtener los Roles que se puede conectar al servidor
select rolname from pg_roles where rolcanlogin=true
- Obtener los Grupos que existes en el servidor
select rolname from pg_roles where rolcanlogin=false
- Obtener los tablespace del servidor
select spcname from pg_tablespace
- Obtener los lenguajes del servidor
select lanname from pg_language
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 247 de 253
Obtener objetos de las bases de datos. En esta sección se especifican los objetos dentro de una base de datos del
servidor y se presentan algunas consultas útiles para el trabajo con PostgreSQL.
- Obtener los esquemas.
Select * from information_schema.schemata where catalog_name='basedato' and schema_name not like 'pg_%' and schema_name<>'information_schema'
- Obtener las tablas.
Select * from information_schema.tables where table_catalog='basedato' and table_schema not like 'pg_%' and table_schema<>'information_schema' and table_type='BASE TABLE'
- Obtener las vistas.
select* from information_schema.tables where table_catalog='basedato' and table_schema not like 'pg_%' and table_schema<>'information_schema' and table_type='VIEW'
- Obtener las funciones.
select specific_schema,routine_name from information_schema.routines where specific_catalog='basedato' and specific_schema not like 'pg_%' and specific_schema<>'information_schema' and routine_type='FUNCTION'and dat a_type<>'trigger'
o SELECT n.nspname as "Schema", p.proname as "Name", u.rolname as "Propietario" FROM pg_catalog.pg_proc p LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 248 de 253
join pg_roles u on u.oid=p.proowner WHERE pg_cat alog.pg_function_is_visible(p.oid) AND n.nspname <> 'pg_catalog' AND n.nspname <> 'information_schema' AND p.prorettype<>'pg_catalog.trigger'::pg_catalog.regtype
- Obtener los trigger. select specific_schema,routine_name from informatio n_schema.routines where specific_catalog='basedato' and specific_schema not like 'pg_%' and specific_schema<>'information_schema' and routine_type='FUNCTION'and data_type='trigger'
o SELECT n.nspname as "Schema", p.proname as "Name", u.rolname as "Prop ietario" FROM pg_catalog.pg_proc p LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace join pg_roles u on u.oid=p.proowner WHERE pg_catalog.pg_function_is_visible(p.oid) AND n.nspname <> 'pg_catalog' AND n.nspname <> 'information_schema' AND p.prorettype='pg_catalog.trigger'::pg_catalog.regtype
- Obtener las secuencias. SELECT sequence_schema,sequence_name from information_schema.sequences where sequence_catalog='basedato'
o SELECT n.nspname as "Schema", c.relname as "Name", pg_catalog.pg_get_u serbyid(c.relowner) as "propietario" FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind ='S' AND n.nspname <> 'pg_catalog' AND n.nspname <> 'information_schema' AND n.nspname !~ '^pg_toast' AND pg_catalog.pg_table_is_visible(c.oid)
- Obtener los dominios.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 249 de 253
select * from information_schema.domains where domain_catalog='basedato' and domain_schema not like 'pg_%' and domain_schema<>'information_schema'
- Obtener las reglas.
select * from pg_rules where schemaname not like 'pg_%' and schemaname<>'information_schema'
- Obtener los tipos de datos.
select pg_type.typname,pg_namespace.nspname, case typcategory when 'N' then 'numerico' when 'B' then 'booleano' when 'C' then 'compuesto' when 'D' th en 'fecha/hora' when 'S' then 'string' when 'G' then 'geometrico' when 'E' then 'enumerativo' when 'I' then 'IP' when 'V' then 'string bit' ELSE 'otro' end as tipodedato from pg_type left join pg_namespace on (pg_type.typnamespace = pg_namespace.oid) where pg_type.typcategory<>'A' order by pg_namespace.nspname
- Obtener índices. select * from pg_indexes where schemaname not like 'pg_%' and schemaname<>'information_schema'
- Obtener detalles de los esquemas.
select pg_namespace.nspname,pg_roles.rolname,pg_namespace.nspacl from pg_namespace,pg_roles where pg_namespace.nspowner=pg_roles.oid and pg_namespace.nspname='equema'
- Obtener detalles de las tablas.
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 250 de 253
select ordinal_position, column_name,data_type from information_schema.columns where table_schema='equema' and table_name='tabla'
o SELECT a.attnum,a.attname as campos, pg_catalog.format_type(a.atttypid, a.atttypmod) as tipo, (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128) FROM pg_catalog.pg_attrdef d WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef) as pordefecto,a.attnotnull as NULO FROM pg_catalog.pg_attribute a WHERE a.attrelid = (select oid from pg_class where relname='tabla' ) AND a.attnum > 0 AND NOT a.attisdropped ORDER BY a.attnum SELECT pg_get_constraintdef(pg_constraint.oid), pg_class.relname AS tabla, pg_constraint.conname FROM pg_constraint, pg_class WHERE ((pg_constraint.contype = 'p'::"char") AND (pg_constraint.conrelid = pg_class.oid)) and relname='tabla' SELECT pg_constraint.conname as nombrellave , pg_get_constraintdef(pg_constraint.oid) as definicion, pg_class.relname AS tabla,(select a.relname from pg_class a where a.oid=pg_constraint.confrelid) as tablaforanea, case confmatchtype when 'u' then 'MATCH simple ' when 'f' then 'MATCH full' when 'p' then 'MATCH partial' end as tipo, case confupdtype when 'a' then 'no action ' when 'r' then 'restrict' when 'c' the n 'cascade' when 'n' then 'set null' else 'default' end as onupdate , case confdeltype when 'a' then 'no action '
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 251 de 253
when 'r' then 'restrict' when 'c' then 'cascade' when 'n' then 'set null' else 'default' end as ondelete FROM pg_constraint, pg_class WHERE ((pg_constraint.contype = 'f'::"char") AND (pg_constraint.conrelid = pg_class.oid) and relname='tabla')
- Obtener detalles de las vistas. select viewname as nombre ,viewowner as propietario,definition as definicion from pg_views where viewname='vista' and schemaname='esquema' o SELECT n.nspname AS schemaname, c.relname AS viewname, pg_get_userbyid(c.relowner) AS viewowner, pg_get_viewdef(c.oid) AS definition FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind = 'v'::"char" and n.nspname <> 'pg_catalog' AND n.nspname <> 'information_schema';
- Obtener detalles de las funciones.
SELECT n.nspname as "Schema", p.proname as "Name", pg_catalog.pg_get_functiondef(p.oid), pg_catalog.pg_get_function_result(p.oid) as "Result data type", pg_catalog.pg_get_function_arguments(p.oid) as "Argument data types", CASE WHEN p.proisagg THEN 'agg' WHEN p.proiswindow THEN 'window' ELS E 'normal' END as "Type", pg_language.lanname as lenguaje , p.prosecdef FROM pg_catalog.pg_proc p LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace join pg_language on ( p.prolang=pg_language.oid) WHERE pg_catalog.pg_function_is_ visible(p.oid) AND n.nspname <> 'pg_catalog'
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 252 de 253
AND n.nspname <> 'information_schema' AND p.prorettype<>'pg_catalog.trigger'::pg_catalog.regtype
- Obtener detalles de los trigger.
SELECT n.nspname as "Schema",p.proname as "Name",pg_catalog.pg_get_functiondef(p.oid), pg_catalog.pg_get_function_result(p.oid) as "Result data type", pg_catalog.pg_get_function_arguments(p.oid) as "Argument data types", pg_language.lanname as lenguaje ,p.prosecdef FROM pg_catalog.pg_proc p LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace join pg_language on ( p.prolang=pg_language.oid) WHERE pg_catalog.pg_function_is_visible(p.oid) AND n.nspname <> 'pg_catalog' AND n.nspname <> 'information_schema' AND p.pro rettype='pg_catalog.trigger'::pg_catalog.regtype ORDER BY 1, 2, 4;
Y
select distinct trigger_name , array_to_string( array (select event_manipulation::"text" from information_schema.triggers where trigger_name='cons' and trigger_schema='public' ),',') a s evento , event_object_table as tabla, action_orientation as modo,condition_timing as momento,action_statement as accion from information_schema.triggers where trigger_name='cons' and trigger_schema='public'
Curso SQL PostgreSQL – Profesor: Ing. Mario Soto Cordones – Página 253 de 253
Lección XXXIII. Consultas útiles de
monitoreo.
Usuarios conectados, IP y consulta select datname,usename,current_query,client_addr from pg_stat_activity
Peso de las base de datos del servidor SELECT distinct datname as "nombre de la base",pg_size_pretty(pg_database_size(datname)) as "Tamaño de la base" from pg_stat_activity ;
Peso de las tablas SELECT nspname, relname, pg_size_pretty(tablesize+indexsize+toastsize+toastindexsize) AS totalsize FROM (SELECT ns.nspname, cl.relname, pg_relation_size(cl.oid) AS tablesize, COALESCE((SELECT SUM(pg_relation_size(indexrelid))::bigint FROM pg_index WHERE cl.oid=indrelid), 0) AS i ndexsize, CASE WHEN reltoastrelid=0 THEN 0 ELSE pg_relation_size(reltoastrelid) END AS toastsize, CASE WHEN reltoastrelid=0 THEN 0 ELSE pg_relation_size((SELECT reltoastidxid FROM pg_class ct WHERE ct.oid = cl.reltoastrelid)) END AS toastindexsize FROM pg_ class cl, pg_namespace ns WHERE cl.relnamespace = ns.oid AND ns.nspname NOT IN ('pg_catalog', 'information_schema') AND cl.relname IN (SELECT table_name FROM information_schema.tables WHERE table_type = 'BASE TABLE')) ss ORDER BY tablesize+indexsize+toastsize+toastindexsize DESC;