consultas multitabl1 sql

29
Consultas multitabla La unión de tablas Esta operación se utiliza cuando tenemos dos tablas con las mismas columnas y queremosobtener una nueva tabla con las filas de la primera y las filas de la segunda. En este caso la tablaresultante tiene las mismas columnas que la primera tabla (que son las mismas que las de lasegunda tabla).Por ejemplo tenemos una tabla de libros nuevos y una tabla de libros antiguos y queremos unalista con todos los libros que tenemos. En este caso las dos tablas tienen las mismas columnas,lo único que varía son las filas, además queremos obtener una lista de libros (las columnas deuna de las tablas) con las filas que están tanto en libros nuevos como las que están en librosantiguos, en este caso utilizaremos este tipo de operación.Cuando hablamos de tablas pueden ser tablas reales almacenadas en la base de datos o tablaslógicas (resultados de una consulta), esto nos permite utilizar la operación con más frecuencia yaque pocas veces tenemos en una base de datos tablas idénticas en cuanto a columnas. Elresultado es siempre una tabla lógica. La composición de tablas La composición de tablas consiste en concatenar filas de una tabla con filas de otra. En este casoobtenemos una tabla con las columnas de la primera tabla unidas a las columnas de la segundatabla, y las filas de la tabla resultante son concatenaciones de filas de la primera tabla con filas dela segunda tabla.A diferencia de la unión la composición permite obtener una fila con datos de las dos tablas, estoes muy útil cuando queremos visualizar filas cuyos datos se encuentran en dos tablas.Por ejemplo queremos listar los pedidos con el nombre del representante que ha hecho el pedido,pues los datos del pedido los tenemos en la tabla de pedidos pero el nombre del representanteestá en la tabla de empleados y además queremos que aparezcan en la misma línea; en estecaso necesitamos componer las dos tablas (Nota: en el ejemplo expuesto a continuación, hemosseleccionado las filas que nos interesan).Existen distintos tipos de composición, aprenderemos a utilizarlos todos y a elegir el tipo másapropiado a cada caso.Los tipos de composición de tablas son:. El producto cartesiano. El INNER JOIN El LEFT / RIGHT JOIN El operador UNION El operador UNION sirve para obtener a partir de dos tablas con las mismas columnas, unanueva tabla con las filas de la primera y las filas de la segunda.La sintaxis es la siguiente: El INNER JOIN El INNER JOIN es otro tipo de composición de tablas, permite emparejar filas de distintas tablasde forma más eficiente que con el producto cartesiano cuando una de las columnas

Upload: amilcarsequen

Post on 26-Jun-2015

95 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Consultas multitabl1 sql

Consultas multitablaLa unión de tablasEsta operación se util iza cuando tenemos dos tablas con las mismas columnas y queremosobtener una nueva tabla con las filas de la primera y las filas de la segunda. En este caso la tablaresultante tiene las mismas columnas que la primera tabla (que son las mismas que las de lasegunda tabla).Por ejemplo tenemos una tabla de libros nuevos y una tabla de libros antiguos y queremos una lista con todos los libros que tenemos. En este caso las dos tablas tienen las mismas columnas,lo único que varía son las fi las, además queremos obtener una lista de libros (las columnas deuna de las tablas) con las fi las que están tanto en libros nuevos como las que están en librosantiguos, en este caso utilizaremos este tipo de operación.Cuando hablamos de tablas pueden ser tablas reales almacenadas en la base de datos o tablaslógicas (resultados de una consulta), esto nos permite utilizar la operación con más frecuencia yaq u e p o c a s v e c e s t e n e m o s e n u n a b a s e d e d a t o s t a b l a s i d é n t i c a s e n c u a n t o a c o l u m n a s . E l resultado es siempre una tabla lógica.La composición de tablasLa composición de tablas consiste en concatenar filas de una tabla con filas de otra. En este casoobtenemos una tabla con las columnas de la primera tabla unidas a las columnas de la segundatabla, y las filas de la tabla resultante son concatenaciones de filas de la primera tabla con filas dela segunda tabla.A diferencia de la unión la composición permite obtener una fila con datos de las dos tablas, estoes muy útil cuando queremos visualizar filas cuyos datos se encuentran en dos tablas.Por ejemplo queremos listar los pedidos con el nombre del representante que ha hecho el pedido,pues los datos del pedido los tenemos en la tabla de pedidos pero el nombre del representanteestá en la tabla de empleados y además queremos que aparezcan en la misma línea; en estecaso necesitamos componer las dos tablas (Nota: en el ejemplo expuesto a continuación, hemosseleccionado las filas que nos interesan).Existen distintos tipos de composición, aprenderemos a util izarlos todos y a elegir el tipo másapropiado a cada caso.Los tipos de composición de tablas son:. El producto cartesiano. El INNER JOIN

El LEFT / RIGHT JOINEl operador UNIONE l operador UN ION s i rve pa ra ob tener a pa r t i r de dos tab las con l as m ismas co lumnas , una nueva tabla con las filas de la primera y las filas de la segunda.La sintaxis es la siguiente:El INNER JOINEl INNER JOIN es otro tipo de composición de tablas, permite emparejar filas de distintas tablasd e f o r m a m á s e f i c i e n t e q u e c o n e l p r o d u c t o c a r t e s i a n o c u a n d o u n a d e l a s c o l u m n a s d e emparejamiento está indexada. Ya que en vez de hacer el producto cartesiano completo y luegoseleccionar la filas que cumplen la condición de emparejamiento, para cada fila de una de lastab las busca d i rec tamente en l a o t ra tab la l a s f i l a s que cump len l a cond i c i ón , con l o cua l se emparejan sólo las filas que luego aparecen en el resultado.La sintaxis es la siguiente:Ejemplo:SELECT *FROM pedidos INNER JOIN clientes ON pedidos.clie = clientes.numclieEjemplo:SELECT *FROM pedidos INNER JOIN clientes ON pedidos.clie = clientes.numclietabla1ytabla2 son especificaciones de tabla (nombre de tabla con alias o no, nombre deconsulta guardada), de las tablas cuyos registros se van a combinar.Pueden ser las dos la misma tabla, en este caso es obligatorio definir al menos un alias de tabla.col1, col2 

Page 2: Consultas multitabl1 sql

son las columnas de emparejamiento.Observar que dentro de la cláusula ON los nombres de columna deben ser nombres cualificados(llevan delante el nombre de la tabla y un punto).Las columnas de emparejamiento deben contener la misma clase de datos, las dos de tipo texto,de tipo fecha etc... los campos numéricos deben ser de tipos similares. Por ejemplo, se puede

Page 3: Consultas multitabl1 sql
Page 4: Consultas multitabl1 sql
Page 5: Consultas multitabl1 sql

  combinar campos AutoNumérico y Long puesto que son tipos similares, sin embargo, no sepuede combinar campos de tipo Simple y Doble. Además las columnas no pueden ser de tipoMemo ni OLE.comp representa cualquier operador de comparación ( =, <, >, <=, >=, o <> ) y se utiliza paraestablecer la condición de emparejamiento.Se pueden definir varias condiciones de emparejamiento unidas por los operadores AND y ORponiendo cada condición entre paréntesis. Ejemplo:SELECT * FROM pedidos INNER JOIN productos ON (pedidos.fab = productos.idfab) AND(pedidos.producto = productos.idproducto)Se pueden combinar más de dos tablasEn este caso hay que sustituir en la sintaxis una tabla por un INNER JOIN completoEl LEFT JOIN y RIGHT JOINE l LEFT JO IN y R IGHT JO IN son o t ro t i po de compos i c i ón de tab las , t amb ién denominada composición externa. Son una extensión del INNER JOIN.L a s c o m p o s i c i o n e s v i s t a s h a s t a a h o r a ( e l p r o d u c t o c a r t e s i a n o y e l I N N E R J O I N ) s o n composiciones internas ya que todos los valores de las filas del resultado son valores que estánen las tablas que se combinan.Con una composición interna sólo se obtienen las filas que tienen al menos una fila de la otratabla que cumpla la condición, veamos un ejemplo:Queremos combinar los empleados con las oficinas para saber la ciudad de la oficina dondetrabaja cada empleado, si utilizamos un producto cartesiano tenemos:SELECT empleados.*,ciudadFROM empleados, oficinasWHERE empleados.oficina = oficinas.oficinaConsultas SumariasSubconsultasUna subconsulta es una sentencia SELECT que aparece dentro de otra sentencia SELECT quellamaremos consulta principal.

Page 6: Consultas multitabl1 sql

Se puede encontrar en la lista de selección, en la cláusula WHERE o en la cláusula HAVING dela consulta principal.Una subconsulta tiene la misma sintaxis que una sentencia SELECT normal exceptuando queaparece encerrada entre paréntesis, no puede contener la cláusula ORDER BY, ni puede ser laUNION de varias sentencias SELECT, además tiene algunas restricciones en cuanto a númerode columnas según el lugar donde aparece en la consulta principal. Estas restricciones las iremosdescribiendo en cada caso.Cuando se ejecuta una consulta que contiene una subconsulta, la subconsulta se ejecuta por  cada fila de la consulta principal.Se aconseja no utilizar campos calculados en las subconsultas, ralentizan la consulta.Las consultas que utilizan subconsultas suelen ser más fáciles de interpretar por el usuario.Referencias externasA menudo, es necesario, dentro del cuerpo de una subconsulta, hacer referencia al valor de unacolumna en la fila actual de la consulta principal, ese nombre de columna se denomina referenciaexterna.Una referencia externa es un nombre de columna que estando en la subconsulta, no se refiere aninguna columna de las tablas designadas en la FROM de la subconsulta sino a una columna delas tablas designadas en la FROM de la consulta principal. Como la subconsulta se ejecuta por  cada fila de la consulta principal, el valor de la referencia externa irá cambiando.Ejemplo:SELECT numemp, nombre, (SELECT MIN(fechapedido) FROM pedidos WHERE rep = numemp)FROM empleados;En este ejemplo la consulta principal es SELECT... FROM empleados.La subconsulta es ( SELECT MIN(fechapedido) FROM pedidos WHERE rep = numemp ).En esta subconsulta tenemos una referencia externa (numemp) es un campo de la tablaempleados (origen de la consulta principal).Si quitamos la cláusula WHERE de la subconsulta obtenemos la fecha del primer pedido de todoslos pedidos no del empleado correspondiente.Anidar subconsultasLas subconsultas pueden anidarse de forma que una subconsulta aparezca en la cláusulaWHERE (por ejemplo) de otra subconsulta que a su vez forma parte de otra consulta principal. Enla práctica, una consulta consume mucho más tiempo y memoria cuando se incrementa elnúmero de niveles de anidamiento. La consulta resulta también más difícil de leer , comprender ymantener cuando contiene más de uno o dos niveles de subconsultas.Ejemplo:SELECT numemp, nombreFROM empleadosWHERE numemp = (SELECT rep FROM pedidos WHERE clie = (SELECT numclie FROMclientes WHERE nombre = 'Julia Antequera'))  En este ejemplo, por cada linea de pedido se calcula la subconsulta de clientes, y esto se repitepor cada empleado, en el caso de tener 10 filas de empleados y 200 filas de pedidos (tablasrealmente pequeñas), la subconsulta más interna se ejecutaría 2000 veces (10 x 200).Subconsulta en la lista de selecciónCuando la subconsulta aparece en la lista de selección de la consulta principal, en este caso lasubconsulta, no puede devolver varias filas ni varias columnas, de lo contrario se da un mensajede error.Muchos SQLs no permiten que una subconsulta aparezca en la lista de selección de la consultaprincipal pero eso no es ningún problema ya que normalmente se puede obtener lo mismoutilizando como origen de datos las dos tablas. El ejemplo anterior se puede obtener de lasiguiente

Page 7: Consultas multitabl1 sql

forma:SELECT numemp, nombre, MIN(fechapedido)FROM empleados LEFT JOIN pedidos ON empleados.numemp = pedidos.repGROUP BY numemp, nombreEn la cláusula FROMEn la cláusula FROM se puede encontrar una sentencia SELECT encerrada entre paréntesispero más que subconsulta sería una consulta ya que no se ejecuta para cada fila de la tablaorigen sino que se ejecuta una sola vez al principio, su resultado se combina con las filas de laotra tabla para formar las filas origen de la SELECT primera y no admite referencias externas.En la cláusula FROM vimos que se podía poner un nombre de tabla o un nombre de consulta,pues en vez de poner un nombre de consulta se puede poner directamente la sentencia SELECTcorrespondiente a esa consulta encerrada entre paréntesis.Subconsulta en las cláusulas WHERE y HAVINGSe suele utilizar subconsultas en las cláusulas WHERE o HAVING cuando los datos quequeremos visualizar están en una tabla pero para seleccionar las filas de esa tabla necesitamosun dato que está en otra tabla.Ejemplo:SELECT numemp, nombreFROM empleadosWHERE contrato = (SELECT MIN(fechapedido) FROM pedidos)En este ejemplo listamos el número y nombre de los empleados cuya fecha de contrato sea iguala la primera fecha de todos los pedidos de la empresa.En una cláusula WHERE / HAVING tenemos siempre una condición y la subconsulta actúa deoperando dentro de esa condición.ANY.La subconsulta debe devolver una única columna sino se produce un error.Se evalúa la comparación con cada valor devuelto por la subconsulta.Si alguna de las comparaciones individuales produce el resultado verdadero, el test ANYdevuelve el resultado verdadero.Si la subconsulta no devuelve ningún valor, el test ANY devuelve falso.

Si el test de comparación es falso para todos los valores de la columna, ANY devuelve falso.Si el test de comparación no es verdadero para ningún valor de la columna, y es nulo para almenos alguno de los valores, ANY devuelve nulo.ALL.La subconsulta debe devolver una única columna sino se produce un error.Se evalúa la comparación con cada valor devuelto por la subconsulta.Si todas las comparaciones individuales, producen un resultado verdadero, el test devuelve elvalor verdadero.Si la subconsulta no devuelve ningún valor el test ALL devuelve el valor verdadero. (¡Ojo conesto!)Si el test de comparación es falso para algún valor de la columna, el resultado es falso.Si el test de comparación no es falso para ningún valor de la columna, pero es nulo para algunode esos valores, el test ALL devuelve valor nulo.EXISTS.Examina si la subconsulta produce alguna fila de resultados.Si la subconsulta contiene filas, el test adopta el valor verdadero, si la subconsulta no contieneninguna fila, el test toma el valor falso, nunca puede tomar el valor nulo.Con este test la subconsulta puede tener varias columnas, no importa ya que el test se fija no enlos valores devueltos sino en si hay o no fila en la tabla resultado de la subconsulta.Cuando se utiliza el test de existencia en la mayoría de los casos habrá que utilizar unareferenciaexterna.Si no se utiliza una referencia externa la subconsulta devuelta siempre será la misma para todaslas f i l a s de l a consu l ta p r inc ipa l y en es te caso se se lecc ionan todas l as f i l a s de l a consu l ta principal (si la subconsulta genera filas) o ninguna (si la subconsulta no devuelve ningunaActualización de datosLa actualización de esos datos, es decir insertar nuevas filas, borrar filas o cambiar el contenidode las filas de una tabla. Estas operaciones modifican los datos almacenados en las tablas perono su estructura, ni su definición.

Page 8: Consultas multitabl1 sql

Insertar una fila INSERT INTO...VALUESLa inserción de nuevos datos en una tabla se realiza añadiendo filas enteras a la tabla, laLa i nse rc ión de nuevos da tos en una tab la se rea l i za añad iendo f i l a s en te ras a l a tab la , l a sentencia SQL que lo permite es la orden INSERT INTO.La inserción se puede realizar de una fila o de varias filas de golpe, veremos las dos opciones por separado y empezaremos por la inserción de una fila.La sintaxis es la siguiente:

  Esta sintaxis se utiliza para insertar una sola fila cuyos valores indicamos después de la palabrareservada VALUES. En castellano la sentencia se leería: INSERTA EN destino...VALORES ....Los registros se agregan siempre al final de la tabla.Destino es el nombre de la tabla donde vamos a insertar la fila también se puede utilizar unnombre de consulta, consulta que tenga como origen de datos una única tabla. Al nombre de latabla se le puede añadir la cláusula IN si la tabla se encuentra en otra base de datos (en unabase de datos externa).La palabra reservada VALUES se puede sustituir por la palabra SELECT ( en otros SQLs seemplea únicamente VALUES).A continuación de la palabra VALUES, entre paréntesis se escriben los valores que queremosañadir. Estos valores se tienen que escribir de acuerdo al tipo de dato de la columna donde sevan a insertar (encerrados entre comillas simples ' ' para valores de tipo texto, entre # # paravalores de fecha...) la asignación de valores se realiza por posición, el primer valor lo asigna a laprimera columna, el segundo valor a la segunda columna, así sucesivamente...Cuando la tabla tiene una columna de tipo contador (AutoNumber), lo normal es no asignar valor a esa columna para que el sistema le asigne el valor que le toque según el contador, si por elcontrario queremos que la columna tenga un valor concreto, lo indicamos en la lista de valores.Cuando no se indica ninguna lista de columnas después del destino, se asume por El mismo orden que las columnas que enunciamos. Como no enunciamos las columnas oficina ydirector se rellenarán con el valor nulo (porque es el valor que tienen esas columnas como valor predeterminado).El utilizar la opción de poner una lista de columnas podría parecer peor ya que se tiene queescribir más pero realmente tiene ventajas sobre todo cuando la sentencia la vamos a almacenar y reutilizar:Integridad de datosEl primer paso de la especificación de los dominios de una tabla consiste en determinar los tipos dedatos de las columnas. Un dominio es el conjunto de todos los valores permitidos en una columna.El dominio no sólo incluye el concepto del tipo de datos aplicables, sino también los valorespermitidos en la columna. Por ejemplo, el dominio de la columnaColor de la tablaProduction.Productincluye el tipo de datosnvarchar y un límite de tamaño de 15 caracteres. El dominiotambién podría especificar las cadenas de caracteres admitidas en la columna, como Red, Blue,Green, Yellow, Brown, Black, White, Teal, Gray y Silver. Para obtener más información, veaTipos de datos (motor de base de datos).Dos pasos importantes en el diseño de las tablas son la identificación de valores válidos para unacolumna y la determinación de cómo forzar la integridad de los datos en la columna. La integridadde datos pertenece a una de las siguientes categorías:•Integridad de entidad

Page 9: Consultas multitabl1 sql

Las restricciones le permiten definir la manera en que Database Engine (Motor de base de datos)exigirá automáticamente la integridad de una base de datos. Las restricciones definen reglasrelativas a los valores permitidos en las columnas y constituyen el mecanismo estándar para exigir la integridad. El uso de restricciones es preferible al uso deDesencadenadores DML, reglasy valores predeterminados.El optimizador de consultas también utiliza definiciones de restriccionespara generar planes de ejecución de consultas de alto rendimiento.Clases de restriccionesSQL Server admite las siguientes clases de restricciones:•NOT NULL especifica que la columna no acepta valores NULL. Para obtener másinformación, veaPermitir valores NULL.•Las restricciones CHECK exigen la integridad del dominio mediante la limitación de losvalores que se pueden asignar a una columna. Para obtener más información, veaRestricciones CHECK.Una restricción CHECK especifica una condición de búsqueda booleana (se evalúa comoTRUE, FALSE o desconocido) que se aplica a todos los valores que se indican en lacolumna. Se rechazan todos los valores que se evalúan como FALSE. En una mismacolumna se pueden especificar varias restricciones CHECK. En el siguiente ejemplo semuestra la creación de la restricción chk_id. Esta restricción aumenta las exigencias deldominio de la clave principal asegurándose de que se indiquen para la clave solamente losnúmeros comprendidos en un intervalo especificado.CREATE TABLE cust_sample(cust_id int PRIMARY KEY,cust_name char(50),cust_address char(50),cust_credit_limit money,CONSTRAINT chk_id CHECK (cust_id BETWEEN 0 and 10000 ))Las restricciones UNIQUE exigen la unicidad de los valores de un conjunto de columnas.En una restricción UNIQUE, dos filas de la tabla no pueden tener el mismo valor en las columnas.Las claves principales también exigen exclusividad, pero no aceptan NULL como uno de losvalores exclusivos. Para obtener más información, veaRestricciones UNIQUE.Las restricciones PRIMARY KEY identifican la columna o el conjunto de columnas cuyos valoresidentifican de forma exclusiva cada una de las filas de una tabla. Para obtener más información,veaRestricciones PRIMARY KEY.Dos filas de la tabla no pueden tener el mismo valor de clave principal. No se pueden asignar valores NULL a ninguna de las columnas de una clave principal. Se recomienda utilizar unacolumna pequeña de tipo entero como clave principal. Todas las tablas tienen que tener una claveprincipal. Una columna o combinación de columnas certificada como valor de clave principal sedenomina clave candidata.En el siguiente ejemplo se crea la tabla part_sample y especifica el campo part_nmbr como clave

SQL embebido

Un feo ejemplo (no escribas un programa como este ...esto es sólo con propósitos educativos)

 /* - Para verlo, aquí tienes un programa ejemplo que usa SQL embebido. SQL embebido permite a los programadores conectar con una base de datos e incluir código SQL en su programa, y poder usar, manipular y procesar datos de la base de datos..

Page 10: Consultas multitabl1 sql

- Este ejemplo de programa en C (usando SQL embebido) imprimirá un informe. - Este programa deberá ser precompilado para las sentencias SQL, antes de la compilación normal. - Las partes EXEC SQL son las mismas (estándar), pero el código C restante deberá ser cambiado, incluyendo la declaración de variables si estás usando un lenguaje diferente. -SQL embebido cambia de sistema a sistema, así que, una vez más, comprueba la documentación, especialmente la declaración de variables y procedimientos, en donde las consideraciones del DBMS y el sistema operativo son cruciales. */ /* ***************************************************/ /* ESTE PROGRAMA NO ES COMPILABLE O EJECUTABLE */ /* SU PROPOSITO ES SÓLO DE SEVIR DE EJEMPLO             */ /****************************************************/ #include <stdio.h>

/* Esta sección declara las variables locales, estas deberán ser las variables que tu programa use, pero también

las variables SQL podrán ser utilizadas para tomar o dar valores */

EXEC SQL BEGIN DECLARE SECTION;     int ID_comprador;     char Nombre[100], Apellidos[100], Producto[100]; EXEC SQL END DECLARE SECTION;

/* Esto incluye la variable SQLCA , aquí puede haber algún error si se compilase. */

EXEC SQL INCLUDE SQLCA; main() {

/* Este es un posible camino para conectarse con la base de datos */

EXEC SQL CONNECT UserID/Password;

/* Este código informa si estás conectado a la base de datos o si ha habido algún error durante la conexión*/

if(sqlca.sqlcode) {     printf(Printer, "Error conectando al servidor de la base de datos.\n");     exit();  } printf("Conectado al servidor de la base de datos.\n");

/* Esto declara un "Cursor". Éste es usado cuando una consulta devuelve más de una fila, y una operación va a ser realizada en cada fila resultante de la consulta. Con cada fila establecida por esta consulta, lo usare en el informe. Después "Fetch" será usado para sacar cada fila, una a una, pero para la consulta que está actualmente ejecutada, se usará el estamento "Open". El "Declare" simplemente establece la consulta.*/

EXEC SQL DECLARE ProductoCursor CURSOR FOR         SELECT PRODUCTO, ID_COMPRADOR         FROM ANTIGÜEDADES         ORDER BY PRODUCTO;

EXEC SQL OPEN ProductoCursor;

Page 11: Consultas multitabl1 sql

 /* +-- Podrías desear poner un bloque de chequeo de errores aquí. --+ */

/* Fetch pone los valores de la "siguiente" fila de la consulta en las variables locales, respectivamente. Sin embargo, un "priming fetch" (tecnica de programación) debe ser hecha antes. Cuando el cursor está fuera de los datos, un código SQL debe de ser generado para permitirnos salir del bucle. Para simplificar, el bucle será dejado cuando ocurra cualquier código SQL, incluso si es una código de error. De otra manera, un código de chequeo específico debería de ser preparado*/

EXEC SQL FETCH ProductoCursor INTO :Producto, :ID_comprador;

while(!sqlca.sqlcode) {

/* Con cada fila, además hacemos un par de cosas. Primero, aumentamos el precio $5 (honorarios por tramitaciones) y extraemos el nombre del comprador para ponerlo en el informe. Para hacer esto, usaremos Update y Select, antes de imprimir la línea en la pantalla. La actuaclización, sin embargo, asume que un comprador dado sólo ha comprado uno de todos los productos dados, o sino, el precio será incrementado demasiadas veces. Por otra parte, una "FilaID" podría haber sido utilizada (ver documentación). Además observa los dos puntos antes de los nombres de las variables locales cuando son usada dentro de sentencias de SQL.*/

    EXEC SQL UPDATE ANTIGÜEDADES     SET PRECIO = PRECIO + 5     WHERE PRODUCTO = :Producto AND ID_COMPRADOR = :ID_comprador;

    EXEC SQL SELECT NOMBREPROPIETARIO, APELLIDOPROPIETARIO     INTO :Nombre, :Apellidos     FROM PROPIETARIOS_ANTIGÜEDADES     WHERE ID_COMPRADOR = :ID_comprador;

    printf("%25s %25s %25s", Nombre, Apellidos, Producto); /* Feo informe- sólo para propositos de ejemplo!. Veamos la siguiente fila */     EXEC SQL FETCH ProductoCursor INTO :Producto, :ID_comprador; } /* Cierra el cursor, entrega los cambios (ver debajo), y sale del programa */ EXEC SQL CLOSE ProductoCursor; EXEC SQL COMMIT RELEASE; exit(); }

El Lenguaje SQL

Como en el caso de los más modernos lenguajes relacionales, SQL está basado en el cálculo relacional de tuplas. Como resultado, toda consulta formulada utilizando el cálculo relacional de tuplas ( o su equivalente, el álgebra relacional) se pude formular también utilizando SQL. Hay, sin embargo, capacidades que van más allá del cálculo o del álgebra relaciona. Aquí tenemos una lista de algunas características proporcionadas por SQL que no forman parte del álgebra y del cálculo relacionales:

Comandos para inserción, borrado o modificación de datos.

Page 12: Consultas multitabl1 sql

Capacidades aritméticas: En SQL es posible incluir operaciones aritméticas así como comparaciones, por ejemplo A < B + 3. Nótese que ni + ni otros operadores aritméticos aparecían en el álgebra relacional ni en cálculo relacional.

Asignación y comandos de impresión: es posible imprimir una relación construida por una consulta y asignar una relación calculada a un nombre de relación.

Funciones agregadas: Operaciones tales como promedio (average), suma (sum), máximo (max), etc. se pueden aplicar a las columnas de una relación para obtener una cantidad única.

Select

El comando más usado en SQL es la instrucción SELECT, que se utiliza para recuperar datos. La sintaxis es:

SELECT [ALL|DISTINCT] { * | expr_1 [AS c_alias_1] [, ... [, expr_k [AS c_alias_k]]]} FROM table_name_1 [t_alias_1] [, ... [, table_name_n [t_alias_n]]] [WHERE condition] [GROUP BY name_of_attr_i [,... [, name_of_attr_j]] [HAVING condition]] [{UNION [ALL] | INTERSECT | EXCEPT} SELECT ...] [ORDER BY name_of_attr_i [ASC|DESC] [, ... [, name_of_attr_j [ASC|DESC]]]];

Ilustraremos ahora la compleja sintaxis de la instrucción SELECT con varios ejemplos. Las tablas utilizadas para los ejemplos se definen en: La Base de Datos de Proveedores y Artículos.

Select sencillas

Aquí tenemos algunos ejemplos sencillos utilizando la instrucción SELECT:

Ejemplo 4. Query sencilla con cualificación

Para recuperar todas las tuplas de la tabla PART donde el atributo PRICE es mayor que 10, formularemos la siguiente consulta:

SELECT * FROM PART WHERE PRICE > 10;

y obtenemos la siguiente tabla:

PNO | PNAME | PRICE -----+-------------+-------- 3 | Cerrojos | 15 4 | Levas | 25

Utilizando "*" en la instrucción SELECT solicitaremos todos los atributos de la tabla. Si queremos recuperar sólo los atributos PNAME y PRICE de la tabla PART utilizaremos la instrucción:

SELECT PNAME, PRICE

Page 13: Consultas multitabl1 sql

FROM PART WHERE PRICE > 10;

En este caso el resultado es:

PNAME | PRICE ------------+-------- Cerrojos | 15 Levas | 25

Nótese que la SELECT SQL corresponde a la "proyección" en álgebra relaciona, no a la "selección" (vea Álgebra Relacional para más detalles).

Las cualificaciones en la clausula WHERE pueden también conectarse lógicamente utilizando las palabras claves OR, AND, y NOT:

SELECT PNAME, PRICE FROM PART WHERE PNAME = 'Cerrojos' AND (PRICE = 0 OR PRICE < 15);

dará como resultado:

PNAME | PRICE ------------+-------- Cerrojos | 15

Las operaciones aritméticas se pueden utilizar en la lista de objetivos y en la clausula WHERE. Por ejemplo, si queremos conocer cuanto cuestan si tomamos dos piezas de un artículo, podríamos utilizar la siguiente consulta:

SELECT PNAME, PRICE * 2 AS DOUBLE FROM PART WHERE PRICE * 2 < 50;

y obtenemos:

PNAME | DOUBLE ------------+--------- Tornillos | 20 Tuercas | 16 Cerrojos | 30

Nótese que la palabra DOBLE tras la palabra clave AS es el nuevo título de la segunda columna. Esta técnica puede utilizarse para cada elemento de la lista objetivo para asignar un nuevo título a la columna resultante. Este nuevo título recibe el calificativo de "un alias". El alias no puede utilizarse en todo el resto de la consulta.

Page 14: Consultas multitabl1 sql

Joins (Cruces)

El siguiente ejemplo muestra como las joins (cruces) se realizan en SQL.

Para cruzar tres tablas SUPPLIER, PART y SELLS a través de sus atributos comunes, formularemos la siguiente instrucción:

SELECT S.SNAME, P.PNAME FROM SUPPLIER S, PART P, SELLS SE WHERE S.SNO = SE.SNO AND P.PNO = SE.PNO;

y obtendremos la siguiente tabla como resultado:

SNAME | PNAME -------+------- Smith | Tornillos Smith | Tuercas Jones | Levas Adams | Tornillos Adams | Cerrojos Blake | Tuercas Blake | Cerrojos Blake | Levas

En la clausula FROM hemos introducido un alias al nombre para cada relación porque hay atributos con nombre común (SNO y PNO) en las relaciones. Ahora podemos distinguir entre los atributos con nombre común simplificando la adicción de un prefijo al nombre del atributo con el nombre del alias seguido de un punto. La join se calcula de la misma forma, tal como se muestra en Una Inner Join (Una Join Interna). Primero el producto cartesiano: SUPPLIER × PART × SELLS Ahora seleccionamos únicamente aquellas tuplas que satisfagan las condiciones dadas en la clausula WHERE (es decir, los atributos con nombre común deben ser iguales). Finalmente eliminamos las columnas repetidas (S.SNAME, P.PNAME).

Operadores Agregados

SQL proporciona operadores agregados (como son AVG, COUNT, SUM, MIN, MAX) que toman el nombre de un atributo como argumento. El valor del operador agregado se calcula sobre todos los valores de la columna especificada en la tabla completa. Si se especifican grupos en la consulta, el cálculo se hace sólo sobre los valores de cada grupo (vean la siguiente sección).

Ejemplo 5. Aggregates

Si queremos conocer el coste promedio de todos los artículos de la tabla PART, utilizaremos la siguiente consulta:

SELECT AVG(PRICE) AS AVG_PRICE FROM PART;

El resultado es:

Page 15: Consultas multitabl1 sql

AVG_PRICE ----------- 14.5

Si queremos conocer cuantos artículos se recogen en la tabla PART, utilizaremos la instrucción:

SELECT COUNT(PNO) FROM PART;

y obtendremos:

COUNT ------- 4

Agregación por Grupos

SQL nos permite particionar las tuplas de una tabla en grupos. En estas condiciones, los operadores agregados descritos antes pueden aplicarse a los grupos (es decir, el valor del operador agregado no se calculan sobre todos los valores de la columna especificada, sino sobre todos los valores de un grupo. El operador agregado se calcula individualmente para cada grupo).

El particionamiento de las tuplas en grupos se hace utilizando las palabras clave GROUP BY seguidas de una lista de atributos que definen los grupos. Si tenemos GROUP BY A1, ⃛, Ak habremos particionado la relación en grupos, de tal modo que dos tuplas son del mismo grupo si y sólo si tienen el mismo valor en sus atributos A1, ⃛, Ak.

Ejemplo 6. Agregados

Si queremos conocer cuántos artículos han sido vendidos por cada proveedor formularemos la consulta:

SELECT S.SNO, S.SNAME, COUNT(SE.PNO) FROM SUPPLIER S, SELLS SE WHERE S.SNO = SE.SNO GROUP BY S.SNO, S.SNAME;

y obtendremos:

SNO | SNAME | COUNT -----+-------+------- 1 | Smith | 2 2 | Jones | 1 3 | Adams | 2 4 | Blake | 3

Demos ahora una mirada a lo que está ocurriendo aquí. Primero, la join de las tablas SUPPLIER y SELLS:

Page 16: Consultas multitabl1 sql

S.SNO | S.SNAME | SE.PNO -------+---------+-------- 1 | Smith | 1 1 | Smith | 2 2 | Jones | 4 3 | Adams | 1 3 | Adams | 3 4 | Blake | 2 4 | Blake | 3 4 | Blake | 4

Ahora particionamos las tuplas en grupos reuniendo todas las tuplas que tiene el mismo atributo en S.SNO y S.SNAME:

S.SNO | S.SNAME | SE.PNO -------+---------+-------- 1 | Smith | 1 | 2 -------------------------- 2 | Jones | 4 -------------------------- 3 | Adams | 1 | 3 -------------------------- 4 | Blake | 2 | 3 | 4

En nuestro ejemplo, obtenemos cuatro grupos y ahora podemos aplicar el operador agregado COUNT para cada grupo, obteniendo el resultado total de la consulta dada anteriormente.

Nótese que para el resultado de una consulta utilizando GROUP BY y operadores agregados para dar sentido a los atributos agrupados, debemos primero obtener la lista objetivo. Los demás atributos que no aparecen en la clausula GROUP BY se seleccionarán utilizando una función agregada. Por otro lado, no se pueden utilizar funciones agregadas en atributos que aparecen en la clausula GROUP BY.

Having

La clausula HAVING trabaja de forma muy parecida a la clausula WHERE, y se utiliza para considerar sólo aquellos grupos que satisfagan la cualificación dada en la misma. Las expresiones permitidas en la clausula HAVING deben involucrar funcionen agregadas. Cada expresión que utilice sólo atributos planos deberá recogerse en la clausula WHERE. Por otro lado, toda expresión que involucre funciones agregadas debe aparecer en la clausula HAVING.

Ejemplo 7. Having

Si queremos solamente los proveedores que venden más de un artículo, utilizaremos la consulta:

SELECT S.SNO, S.SNAME, COUNT(SE.PNO) FROM SUPPLIER S, SELLS SE WHERE S.SNO = SE.SNO GROUP BY S.SNO, S.SNAME

Page 17: Consultas multitabl1 sql

HAVING COUNT(SE.PNO) > 1;

y obtendremos:

SNO | SNAME | COUNT -----+-------+------- 1 | Smith | 2 3 | Adams | 2 4 | Blake | 3

Subconsultas

En las clausulas WHERE y HAVING se permite el uso de subconsultas (subselects) en cualquier lugar donde se espere un valor. En este caso, el valor debe derivar de la evaluación previa de la subconsulta. El uso de subconsultas amplía el poder expresivo de SQL.

Ejemplo 8. Subselect

Si queremos conocer los artículos que tienen mayor precio que el artículo llamado 'Tornillos', utilizaremos la consulta:

SELECT * FROM PART WHERE PRICE > (SELECT PRICE FROM PART WHERE PNAME='Tornillos');

El resultado será:

PNO | PNAME | PRICE -----+-------------+-------- 3 | Cerrojos | 15 4 | Levas | 25

Cuando revisamos la consulta anterior, podemos ver la palabra clave SELECT dos veces. La primera al principio de la consulta - a la que nos referiremos como la SELECT externa - y la segunda en la clausula WHERE, donde empieza una consulta anidada - nos referiremos a ella como la SELECT interna. Para cada tupla de la SELECT externa, la SELECT interna deberá ser evaluada. Tras cada evaluación, conoceremos el precio de la tupla llamada 'Tornillos', y podremos chequear si el precio de la tupla actual es mayor.

Si queremos conocer todos los proveedores que no venden ningún artículo (por ejemplo, para poderlos eliminar de la base de datos), utilizaremos:

SELECT * FROM SUPPLIER S WHERE NOT EXISTS (SELECT * FROM SELLS SE WHERE SE.SNO = S.SNO);

Page 18: Consultas multitabl1 sql

En nuestro ejemplo, obtendremos un resultado vacío, porque cada proveedor vende al menos un artículo. Nótese que utilizamos S.SNO de la SELECT externa en la clausula WHERE de la SELECT interna. Como hemos descrito antes, la subconsulta se evalúa para cada tupla de la consulta externa, es decir, el valor de S.SNO se toma siempre de la tupla actual de la SELECT externa.

Unión, Intersección, Excepción

Estas operaciones calculan la unión, la intersección y la diferencia de la teoría de conjuntos de las tuplas derivadas de dos subconsultas.

Ejemplo 9. Union, Intersect, Except

La siguiente consulta es un ejemplo de UNION:

SELECT S.SNO, S.SNAME, S.CITY FROM SUPPLIER S WHERE S.SNAME = 'Jones' UNION SELECT S.SNO, S.SNAME, S.CITY FROM SUPPLIER S WHERE S.SNAME = 'Adams';

Dará el resultado:

SNO | SNAME | CITY -----+-------+-------- 2 | Jones | Paris 3 | Adams | Vienna

Aquí tenemos un ejemplo para INTERSECT:

SELECT S.SNO, S.SNAME, S.CITY FROM SUPPLIER S WHERE S.SNO > 1 INTERSECT SELECT S.SNO, S.SNAME, S.CITY FROM SUPPLIER S WHERE S.SNO > 2;

que dará como resultado:

SNO | SNAME | CITY -----+-------+-------- 2 | Jones | Paris La única tupla devuelta por ambas partes de la consulta es la única que tiene $SNO=2$.

Finalmente, un ejemplo de EXCEPT:

Page 19: Consultas multitabl1 sql

SELECT S.SNO, S.SNAME, S.CITY FROM SUPPLIER S WHERE S.SNO > 1 EXCEPT SELECT S.SNO, S.SNAME, S.CITY FROM SUPPLIER S WHERE S.SNO > 3;

que dará como resultado:

SNO | SNAME | CITY -----+-------+-------- 2 | Jones | Paris 3 | Adams | Vienna

Definición de Datos

El lenguaje SQL incluye un conjunto de comandos para definición de datos.

Create Table

El comando fundamental para definir datos es el que crea una nueva relación (una nueva tabla). La sintaxis del comando CREATE TABLE es:

CREATE TABLE table_name (name_of_attr_1 type_of_attr_1 [, name_of_attr_2 type_of_attr_2 [, ...]]);

Ejemplo 10. Creación de una tabla

Para crear las tablas definidas en La Base de Datos de Proveedores y Artículos se utilizaron las siguientes instrucciones de SQL:

CREATE TABLE SUPPLIER (SNO INTEGER, SNAME VARCHAR(20), CITY VARCHAR(20));

CREATE TABLE PART (PNO INTEGER, PNAME VARCHAR(20), PRICE DECIMAL(4 , 2));

CREATE TABLE SELLS (SNO INTEGER, PNO INTEGER);

Tipos de Datos en SQL

Page 20: Consultas multitabl1 sql

A continuación sigue una lista de algunos tipos de datos soportados por SQL:

INTEGER: entero binario con signo de palabra completa (31 bits de precisión). SMALLINT: entero binario con signo de media palabra (15 bits de precisión). DECIMAL (p[,q]): número decimal con signo de p dígitos de precisión, asumiendo q a la derecha

para el punto decimal. (15 ≥ p ≥ qq ≥ 0). Si q se omite, se asume que vale 0. FLOAT: numérico con signo de doble palabra y coma flotante. CHAR(n): cadena de caracteres de longitud fija, de longitud n. VARCHAR(n): cadena de caracteres de longitud variable, de longitud máxima n.

Create Index

Se utilizan los índices para acelerar el acceso a una relación. Si una relación R tiene un índice en el atributo A podremos recuperar todas la tuplas t que tienen t(A) = a en un tiempo aproximadamente proporcional al número de tales tuplas t más que en un tiempo proporcional al tamaño de R.

Para crear un índice en SQL se utiliza el comando CREATE INDEX. La sintaxis es:

CREATE INDEX index_name ON table_name ( name_of_attribute );

Ejemplo 11. Create Index

Para crear un índice llamado I sobre el atributo SNAME de la relación SUPPLIER, utilizaremos la siguiente instrucción:

CREATE INDEX I ON SUPPLIER (SNAME);

El índice creado se mantiene automáticamente. es decir, cada vez que una nueva tupla se inserte en la relación SUPPLIER, se adaptará el índice I. Nótese que el único cambio que un usuario puede percibir cuando se crea un índice es un incremento en la velocidad.

Create View

Se puede ver una vista como una tabla virtual, es decir, una tabla que no existe físicamente en la base de datos, pero aparece al usuario como si existiese. Por contra, cuando hablamos de una tabla base, hay realmente un equivalente almacenado para cada fila en la tabla en algún sitio del almacenamiento físico.

Las vistas no tienen datos almacenados propios, distinguibles y físicamente almacenados. En su lugar, el sistema almacena la definición de la vista (es decir, las reglas para acceder a las tablas base físicamente almacenadas para materializar la vista) en algún lugar de los catálogos del sistema (vea System Catalogs). Para una discusión de las diferentes técnicas para implementar vistas, refiérase a SIM98.

En SQL se utiliza el comando CREATE VIEW para definir una vista. La sintaxis es:

CREATE VIEW view_name AS select_stmt

Page 21: Consultas multitabl1 sql

donde select_stmt es una instrucción select válida, como se definió en Select. Nótese que select_stmt no se ejecuta cuando se crea la vista. Simplemente se almacena en los catálogos del sistema y se ejecuta cada vez que se realiza una consulta contra la vista.

Sea la siguiente definición de una vista (utilizamos de nuevo las tablas de La Base de Datos de Proveedores y Artículos ):

CREATE VIEW London_Suppliers AS SELECT S.SNAME, P.PNAME FROM SUPPLIER S, PART P, SELLS SE WHERE S.SNO = SE.SNO AND P.PNO = SE.PNO AND S.CITY = 'London';

Ahora podemos utilizar esta relación virtual London_Suppliers como si se tratase de otra tabla base:

SELECT * FROM London_Suppliers WHERE P.PNAME = 'Tornillos';

Lo cual nos devolverá la siguiente tabla:

SNAME | PNAME -------+---------- Smith | Tornillos

Para calcular este resultado, el sistema de base de datos ha realizado previamente un acceso oculto a las tablas de la base SUPPLIER, SELLS y PART. Hace esto ejecutando la consulta dada en la definición de la vista contra aquellas tablas base. Tras eso, las cualificaciones adicionales (dadas en la consulta contra la vista) se podrán aplicar para obtener la tabla resultante.

Drop Table, Drop Index, Drop View

Se utiliza el comando DROP TABLE para eliminar una tabla (incluyendo todas las tuplas almacenadas en ella):

DROP TABLE table_name;

Para eliminar la tabla SUPPLIER, utilizaremos la instrucción:

DROP TABLE SUPPLIER;

Se utiliza el comando DROP INDEX para eliminar un índice:

DROP INDEX index_name;

Page 22: Consultas multitabl1 sql

Finalmente, eliminaremos una vista dada utilizando el comando DROP VIEW:

DROP VIEW view_name;

Manipulación de Datos

Insert Into

Una vez que se crea una tabla (vea Create Table), puede ser llenada con tuplas mediante el comando INSERT INTO. La sintaxis es:

INSERT INTO table_name (name_of_attr_1 [, name_of_attr_2 [,...]]) VALUES (val_attr_1 [, val_attr_2 [, ...]]);

Para insertar la primera tupla en la relación SUPPLIER (de La Base de Datos de Proveedores y Artículos) utilizamos la siguiente instrucción:

INSERT INTO SUPPLIER (SNO, SNAME, CITY) VALUES (1, 'Smith', 'London');

Para insertar la primera tupla en la relación SELLS, utilizamos:

INSERT INTO SELLS (SNO, PNO) VALUES (1, 1);

Update

Para cambiar uno o más valores de atributos de tuplas en una relación, se utiliza el comando UPDATE. La sintaxis es:

UPDATE table_name SET name_of_attr_1 = value_1 [, ... [, name_of_attr_k = value_k]] WHERE condition;

Para cambiar el valor del atributo PRICE en el artículo 'Tornillos' de la relación PART, utilizamos:

UPDATE PART SET PRICE = 15 WHERE PNAME = 'Tornillos';

El nuevo valor del atributo PRICE de la tupla cuyo nombre es 'Tornillos' es ahora 15.

Delete

Page 23: Consultas multitabl1 sql

Para borrar una tupla de una tabla particular, utilizamos el comando DELETE FROM. La sintaxis es:

DELETE FROM table_name WHERE condition;

Para borrar el proveedor llamado 'Smith' de la tabla SUPPLIER, utilizamos la siguiente instrucción:

DELETE FROM SUPPLIER WHERE SNAME = 'Smith';

System Catalogs

En todo sistema de base de datos SQL se emplean catálogos de sistema para mantener el control de qué tablas, vistas, índices, etc están definidas en la base de datos. Estos catálogos del sistema se pueden investigar como si de cualquier otra relación normal se tratase. Por ejemplo, hay un catálogo utilizado para la definición de vistas. Este catálogo almacena la consulta de la definición de la vista. Siempre que se hace una consulta contra la vista, el sistema toma primero la consulta de definición de la vista del catálogo y materializa la vista antes de proceder con la consulta del usuario (vea SIM98 para obtener una descripción más detallada). Diríjase aDATE para obtener más información sobre los catálogos del sistema.

SQL Embebido

En esta sección revisaremos como se puede embeber SQL en un lenguaje de host (p.e. C). Hay dos razones principales por las que podríamos querer utilizar SQLdesde un lenguaje de host:

Hay consultas que no se pueden formular utilizando SQL puro (por ejemplo, las consultas recursivas). Para ser capaz de realizar esas consultas necesitamos un lenguaje de host de mayor poder expresivo que SQL.

Simplemente queremos acceder a una base de datos desde una aplicación que está escrita en el lenguaje del host (p.e. un sistema de reserva de billetes con una interface gráfica escrita en C, y la información sobre los billetes está almacenada en una base de datos que puede accederse utilizando SQL embebido).

Un programa que utiliza SQL embebido en un lenguaje de host consiste en instrucciones del lenguaje del host e instrucciones de SQL embebido (ESQL). Cada instrucción de ESQL empieza con las palabras claves EXEC SQL. Las instrucciones ESQL se transforman en instrucciones del lenguaje del host mediante un precompilador (que habitualmente inserta llamadas a rutinas de librerías que ejecutan los variados comandos de SQL).

Cuando vemos los ejemplos de Select observamos que el resultado de las consultas es algo muy próximo a un conjunto de tuplas. La mayoría de los lenguajes de host no están diseñados para operar con conjuntos, de modo que necesitamos un mecanismo para acceder a cada tupla única del conjunto de tuplas devueltas por una instrucción SELECT. Este mecanismo puede ser proporcionado declarando un cursor. Tras ello, podemos utilizar el comando FETCH para recuperar una tupla y apuntar el cursor hacia la siguiente tupla