CONSULTAS SQL
CONSULTAS SQL
CONSULTAS SQL
4.1 Introducción
Las consultas, las sentencias SELECT se apoyan sobre dos conceptos matemáticos denominados
Algebra relacional
Cálculo relacional
La sentencia SELECT permite extraer datos de las tablas en base a condiciones muy diversas.
La operación más básica que podemos hacer es extraer todo lo que hay en una tabla.
select * from proveedores;
select * from partes;
select * from proyectos;
select * from suministra;
4.3 Condiciones
Muy a menudo no necesitaremos mostrar todos los datos de la tabla, sino solo algunos que se especifi-
carán mediante condiciones.
Si por ejemplo, deseáramos mostrar solo los proveedores cuya ciudad sede está en París haríamos algo
como esto.
select * from proveedores
where ciudad="Paris";
Otra posible consulta sería “mostrar todos los proveedores cuyo estado tiene el codigo 10”
select * from proveedores
where estado=10;
39
Bases de datos, Versión 1.1
Las condiciones pueden ser muy complejas, y se pueden construir utilizando los operadores AND y OR.
Por ejemplo, “mostrar todos los proveedores cuya ciudad es Londres y su estado es 10”.
select * from proveedores
where ciudad="Londres"
and estado=10;
No es obligatorio mostrar todos los campos, se pueden mostrar solamente algunos de ellos indicando su
nombre. Por ejemplo, “mostrar el nombre de proveedor y la ciudad de los proveedores cuyo estado sea
20”.
select nombreprov, ciudad
from proveedores
where estado=20;
La respuesta es que no se muestra nada. La condición está mal escrita ya que no puede haber un número
que sea menor de 10 y a la vez mayor de 20.
Mostrar los nombres de proveedores cuyo estado sea 10 y su ciudad Paris o Londres.
Un primer intento sería este .. code-block:: mysql
select nombreprov from proveedores where estado=10 and (ciudad=”Paris” or ciu-
dad=”Londres”);
Sin embargo, no funciona correctamente. La propia pregunta es ambigua
Una posibilidad es que la pregunta fuera así “Mostrar los nombres de proveedores cuyo estado sea
10 y (su ciudad Paris o Londres).”
La otra posibilidad es que la pregunta fuera así “Mostrar los nombres de proveedores cuyo (estado
sea 10 y su ciudad Paris) o Londres.”
Es importante recordar que cuando en una condición hay tres o más elementos de comparación puede
que sea necesario utilizar paréntesis.
Mostrar las partes rojas o verdes que pesen 17 o más.
Esta pregunta debe aclararse antes de resolverse.
Mostrar las partes siempre que pesen 17 o más y que luego cumplan una de estas dos: tener color
rojo o tener color verde.
“Mostrar las partes (rojas o verdes) que pesen 17 o más.”
Mostrar las partes que siendo verdes pesen 17 o más o si no que simplemente sean rojas.
Se denomina agregado a alguna función de tipo estadístico aplicada a un subconjunto de los datos de
una tabla.
4.4.1 Recuento
La función COUNT nos dice cuantas filas cumplen una cierta condición. No es obligatorio poner dicha
condición.
select count(*) from partes;
Si deseáramos una condición como por ejemplo “hacer el recuento de partes cuyo color sea Azul”
select count(*) from partes
where color="Azul";
4.4.2 Promedio
Esta función calcula la media aritmética de las filas que cumplan una cierta condición. Tampoco es
obligatorio poner la condición. La función promedio en SQL es AVG(*)
¿Cual es el peso medio de las partes?
select avg(peso) from partes;
Son operaciones que nos devuelven el valor más grande o más pequeño de entre los que cumplan una
condición.
Estas funciones en SQL son
MAX(campo-numérico)
MIN(campo-numérico)
¿Cual es peso más grande de alguna parte?
select max(peso) from partes;
4.4.4 Sumas
La operación SUM(campo-numérico) efectúa la suma de ese campo para las filas que cumplan una cierta
condición.
¿Cuantas partes en total ha suministrado el proveedor v1?
select sum(cantidad)
from suministra
where numprov="v1";
A veces no se hará una sola operación matemática sino muchas. En ese caso es muy importante indicar
a SQL en base a qué debe hacer los resultados, o lo que es lo mismo como agrupar antes de hacer las
operaciones.
En SQL se indicarán los grupos sobre los cuales se va a hacer cada operación mediante la cláusula
GROUP BY (campo). Además, al hacer un “group by” es obligatorio también seleccionar el campo por
el que se hacen los grupos.
La respuesta a una pregunta como:”¿Cual es la media de peso de las partes por color?”
select avg(peso), color
from partes
group by (color);
Si ahora deseamos mostrar solo aquellos cuyo recuento sea mayor o igual que 2 debemos añadir una
cláusula HAVING como esta
select count(*), ciudad
from proveedores
group by (ciudad)
having count(*)>=2;
El WHERE es una condición que se aplica antes de hacer los cálculos. Sin embargo, si una vez hechos
los cálculos no deseamos mostrarlos todos deberemos utilizar el HAVING.
“Mostrar cuantos tornillos hay en total”
Al hacer esta consulta se pueden cometer varios errores, como por ejemplo este, que muestra todas las
partes
select count(*), nombreparte from partes
group by nombreparte;
Esto no es exactamente un error, sino más bien una trampa: se hizo el recuento a mano y se hizo trampa
Error: En este caso se ha confundido el where con el having
select count(*), nombreparte from partes
group by nombreparte having nombreparte="Tornillo";
Pregunta: ¿Podríamos quitar el group by? Respuesta: aunque en este caso sí podríamos no se debe hacer.
Cuando nos pidan una operación matemática por grupos, debemos poner group by
select count(*), nombreparte from partes
where nombreparte="Tornillo"
group by nombreparte
En ocasiones la información que nos pidan puede que esté dispersa por distintas tablas. SQL ofrece un
mecanismo para “conectar” tablas y así poder hacer las comparaciones que nos pidan.
Por ejemplo, si nos piden el nombre de las partes suministradas en una cantidad >=500 descubriremos
que
El nombreparte está en la tabla partes
La cantidad esta en la tabla suministra
Las tablas partes y suministra tienen un campo en común, el campo numparte
Utilizando una cláusula denominada “inner join” SQL puede establecer las correspondencias correctas
entre dos o más tablas.
Cruce de datos entre las tablas partes y suministra basándonos en que el campo numparte de suministra
debe ser igual que el numparte de suministra
De aqui sacamos solamente los campos que nos piden
2. Deseamos saber los numeros de proveedor que realizan suministros pero sin que se muestren
repetidos
select distinct numprov from suministra;
3. Sumar las cantidades que se han suministrado (¿cuantas piezas se han suministrado?)
select sum(cantidad) from suministra;
7. Mostrar los numeros de parte suministrados en una cantidad total mayor o igual que 1000
select sum(cantidad), numparte
from suministra
group by (numparte)
having sum(cantidad)>=1000;
8. Mostrar la suma de las partes suministradas por v1, v2, o v3 en una cantidad mayor de 550
select sum(cantidad),numparte
from suministra
where numprov=’v1’ or numprov=’v2’ or numprov=’v3’
group by (numparte)
having sum(cantidad)>550;
4.7 Subconsultas
Al hacer consultas hemos observado que hay cláusulas que permiten establecer condiciones.
Al hacer las condiciones es posible que necesitemos hacer una “subpregunta” y que la sentencia SE-
LECT quede algo así
select ....
from ...
where campo>(select max(cantidad) from suministra)
Supongamos una pregunta como la siguiente: “¿Cuales son los nombres de parte que pesan lo mismo
que la parte más pesada?”
Podemos sacar el peso maximo con esta consulta
select max(peso) from partes;
Dentro de las subconsultas, aparte de las comparaciones típicas como >, >=, <>, <=, <, etc... existen
otros elementos para hacer comparaciones
EXISTS: nos dará las filas donde exista alguna fila que cumpla la condición
ALL: la condición deben cumplirla todas las filas
12. ¿Qué nombres de parte corresponden a una pieza azul o almacenada en París?
select nombreparte from partes
where color="Azul" or ciudad="Paris"
13. ¿Qué colores tienen las distintas partes que no sean tornillos?
select * from partes
where nombreparte<>"Tornillo";
15. ¿Qué nombres de parte se suministran en una cantidad mayor o igual de 400?
select nombreparte,cantidad
from partes inner join suministra
on partes.numparte=suministra.numparte
where cantidad>=400;
4.7. Subconsultas 47
Bases de datos, Versión 1.1
Cuyo resultado es que se cruzan los datos correctamente y se obtiene una tabla como esta
numprov numparte numproyecto cantidad numprov nombreprov estado ciudad
v1 p1 y1 200 v1 Smith 20 Londres
v1 p1 y4 700 v1 Smith 20 Londres
v2 p3 y1 400 v2 Jones 10 Paris
v2 p3 y2 200 v2 Jones 10 Paris
v2 p3 y3 300 v2 Jones 10 Paris
v2 p3 y4 500 v2 Jones 10 Paris
v2 p3 y5 600 v2 Jones 10 Paris
v2 p3 y6 400 v2 Jones 10 Paris
v2 p3 y7 600 v2 Jones 10 Paris
v2 p5 y2 100 v2 Jones 10 Paris
v3 p3 y1 200 v3 Blake 30 Paris
v3 p4 y2 500 v3 Blake 30 Paris
v4 p6 y3 300 v4 Clarke 20 Londres
v4 p6 y7 300 v4 Clarke 20 Londres
v5 p1 y4 100 v5 Adams 30 Atenas
v5 p2 y2 200 v5 Adams 30 Atenas
v5 p2 y4 100 v5 Adams 30 Atenas
v5 p3 y4 200 v5 Adams 30 Atenas
v5 p4 y4 800 v5 Adams 30 Atenas
v5 p5 y4 400 v5 Adams 30 Atenas
v5 p5 y5 500 v5 Adams 30 Atenas
v5 p6 y2 200 v5 Adams 30 Atenas
v5 p6 y4 500 v5 Adams 30 Atenas
Si ponemos la condición que nos falta el ejercicio se resuelve correctamente
select nombreprov,cantidad
from proveedores inner join suministra
on proveedores.numprov=suministra.numprov
where cantidad<300
order by nombreprov desc;
select count(numprov)
from suministra
where cantidad<300;
18. ¿Qué nombre tienen las partes suministradas en una cantidad total de 550 o más?
select sum(cantidad), partes.numparte,nombreparte
from suministra
inner join partes
on suministra.numparte=partes.numparte
group by (partes.numparte)
having sum(cantidad)>=550;
20. Queremos saber los proveedores que están ubicados en el mismo sitio que alguna parte.
Examinemos la tabla partes
numparte nombreparte color peso ciudad
p1 Tuerca Rojo 12 Londres
p2 Perno Verde 17 Paris
p3 Tornillo Azul 17 Roma
p4 Tornillo Rojo 14 Londres
p5 Leva Azul 12 Paris
p6 Engranaje Rojo 19 Londres
Examinemos la tabla proveedores
numprov nombreprov estado ciudad
v1 Smith 20 Londres
v2 Jones 10 Paris
v3 Blake 30 Paris
v4 Clarke 20 Londres
v5 Adams 30 Atenas
Se puede comprobar que no nos piden para nada datos de la tabla suministra. Lo único que se necesita
es emparejar las filas donde las ciudades sean iguales.
select nombreprov,nombreparte,partes.ciudad
from partes
inner join proveedores
on partes.ciudad=proveedores.ciudad;
4.7. Subconsultas 49
Bases de datos, Versión 1.1
25. Obtener el nombre de los provedores, el nombre de parte que suministran y la cantidad en que
suministran
select nombreprov, nombreparte,cantidad
from proveedores
inner join suministra
on
suministra.numprov=proveedores.numprov
inner join partes
on
suministra.numparte=partes.numparte
27. Mostrar suministros donde el proveedor y la parte hayan resultado ser de una ciudad distinta
select suministra.numprov, suministra.numparte,
proveedores.ciudad, partes.ciudad
from suministra
inner join proveedores
on proveedores.numprov=suministra.numprov
inner join partes
on partes.numparte=suministra.numparte
where
proveedores.ciudad<>partes.ciudad;
28. ¿Cuantos proveedores suministran partes rojas o que pesen 12 gramos o más?
Trozo 1: partes rojas
select numparte from partes where color="Rojo"
30. ¿De qué ciudad de proveedor ha salido la cantidad más grande de suministros?.
Esta pregunta podría entenderse de dos formas “Obtener la cantidad más grande suministrada y la ciudad
del proveedor correspondiente”
En primer lugar necesitamos cruzar “proveedores” y suministra
4.7. Subconsultas 51
Bases de datos, Versión 1.1
Sin embargo esto no funciona porque cualquier operación de agregado no involucra a ninguna fila. De
hecho esa consulta nos devuelve un máximo correcto pero no nos devuelve la ciudad asociada, sino la
primera que encuentra.
Hay que encontrar otra forma de expresar esta consulta
select ciudad
from proveedores inner join suministra
on
suministra.numprov=proveedores.numprov
where cantidad=
(
select max(cantidad) from suministra
);
having sum(cantidad)>=
ALL
(
select sum(cantidad)
from suministra
group by (numprov)
)
;
33. Obtener todos los detalles de todos los proyectos ubicados en Londres.
select nombreprov, nombreparte,nombreproyecto,cantidad
from suministra
inner join proyectos
on
suministra.numproyecto=proyectos.numproyecto
4.7. Subconsultas 53
Bases de datos, Versión 1.1
35. Obtener los datos de los proyectos que usan partes en cantidades comprendidas entre 300 y 750.
select distinct proyectos.*
from suministra
inner join proyectos
on
suministra.numproyecto=proyectos.numproyecto
where
( cantidad>=300 ) and ( cantidad<=750 )
order by proyectos.numproyecto
;
37. Obtener los colores de las partes que se han suministrado por V1.
select partes.color from suministra
inner join
partes
on partes.numparte=suministra.numparte
where numprov=’v1’;
39. Obtener las parejas de nombres de ciudad tales que un proveedor ubicado en la primera ciudad
suministra a algún proyecto ubicado en la segunda ciudad.
select proveedores.ciudad, proyectos.ciudad
from suministra
inner join proveedores
on
suministra.numprov=proveedores.numprov
inner join proyectos
on
suministra.numproyecto=proyectos.numproyecto;
40. Obtener los códigos de parte suministrados a los proyectos ubicados en la misma ciudad del
proveedor.
select suministra.numparte
from suministra
inner join proyectos
on
suministra.numproyecto=proyectos.numproyecto
inner join proveedores
on
suministra.numprov=proveedores.numprov
where
proveedores.ciudad=proyectos.ciudad;
41. Obtener los códigos de proyecto a los que suministra un proveedor que no está en la misma ciudad.
select suministra.numproyecto
from suministra
inner join proveedores
on
proveedores.numprov=suministra.numprov
inner join proyectos
on
proyectos.numproyecto=suministra.numproyecto
where
proyectos.ciudad<>proveedores.ciudad;
43. Obtener los códigos de parte suministrados a cualquier proyecto que esté ubicado en Londres
select numparte from suministra
inner join proyectos
on
suministra.numproyecto=proyectos.numproyecto
where
proyectos.ciudad="Londres";
44. Obtener los códigos de proyecto que usan al menos una parte suministrada por el proveedor V1
4.7. Subconsultas 55
Bases de datos, Versión 1.1
En segundo lugar queremos saber los proyectos cuyas partes sean alguna de las que hemos extraído
antes.
select numproyecto from suministra
where numparte in
(
select numparte from suministra
where numprov=’v1’
);
45. Obtener los códigos de proveedor que suministran al menos una parte roja.
Seleccionamos las partes cuyo color es rojo
select numparte from partes where color="Rojo";
Ahora, en la tabla suministra sacamos las filas donde la parte sea alguna de las extraídas antes
select numprov from suministra
where numparte in
(
select numparte from partes
where color="Rojo"
);
46. Obtener los códigos de proyecto cuya ciudad es la primera en la lista de ciudades.
Seleccionamos la ciudad más pequeña
select min(ciudad) from proyectos;
47. Obtener los códigos de proyecto a los que se suministra la parte P1 en una cantidad promedio
igual o superior a la cantidad más grande que se suministra al proyecto Y1.
Extraemos la cantidad más grande del proyecto “y1”
select max(cantidad) from suministra
where numproyecto="y1";
Al haber una condición para el promedio deberemos poner algo como esto
select numproyecto,avg(cantidad) from suministra
where numparte=’p1’
group by numproyecto
having avg(cantidad)>=
(
select max(cantidad) from suministra
where numproyecto="y1"
);
48. Obtener los códigos de proveedor de los que suministran la parte P1 a algún proyecto en una
cantidad superior a la cantidad promedio de la parte P1 para ese proyecto.
Podemos empezar intentando sacar la media de partes p1 para cada proyecto
select numproyecto, avg(cantidad) from suministra
where numparte=’p1’
group by numproyecto;
49. Obtener los códigos de proyecto a los que ningún proveedor de Londres suministra una parte roja.
Primero averiguamos los proveedores de Londres que suministran partes rojas.
select suministra.numprov
from suministra
inner join partes
on partes.numparte=suministra.numparte
inner join proveedores
on proveedores.numprov=suministra.numprov
where
proveedores.ciudad="Londres"
and
partes.color="Rojo";
Ahora examinamos la tabla suministra y comprobamos que el proveedor no esté en el conjunto devuelto
por la consulta anterior
4.7. Subconsultas 57
Bases de datos, Versión 1.1
50. ¿Hay algún proveedor que suministre la misma parte a TODOS los proyectos?
Para conseguir la solución a este problema se deben utilizar algunas características de los cuantifi-
cadores.
Replanteamos la pregunta
“se desea saber los proveedores donde para todos los proyectos existe una misma parte suministrada”
o más desarrollado
“proveedores (de la tabla suministra) donde para todo proyecto (de la tabla proyectos) existe un sumin-
istro donde el codigo de proveedor es dicho proveedor y la parte es la misma parte que mirábamos en
suministra”
select numprov from suministra as s1
where not exists
(
select numproyecto from proyectos
where numproyecto not in
(
select numproyecto from suministra as s2
where
s1.numparte=s2.numparte
and
s1.numprov=s2.numprov
);
51. Obtener los códigos de proyecto que usan todas las partes suministradas por el proveedor v1
“Obtener los códigos de proyecto donde para toda parte de la tabla suministra existe una parte sumin-
istrada por v1”
Obtener el conjunto de parte suministradas por v1.
select numparte from suministra
where numprov=’v1’;
Las filas de la tabla suministra donde para toda parte de v1 existe alguna fila asociada
52. (Para nota) Obtener los pares de proveedores V1 y V2 que suministren EXACTAMENTE el mis-
mo conjunto de partes.
La pregunta podría replantearse como
“obtener parejas de proveedores donde para toda parte de un proveedor de la primera tabla existe otro
proveedor distinto tal que la parte es la misma que la parte del primero”.
Una vez que se han insertado datos, estos no son inmutables. Pueden cambiarse valores de las filas o
incluso pueden borrarse las filas.
Estas operaciones se hacen con las sentencias UPDATE y DELETE.
Para cambiar valores se hace lo siguiente
UPDATE <TABLA> SET <CAMPO>=VALOR WHERE <CONDICION>
Por ejemplo, si quisiéramos hacer que en la tabla partes se cambiara la ciudad Londres por Madrid
haríamos algo como esto
UPDATE partes SET ciudad="Madrid"
WHERE ciudad="Londres";
Poner en la tabla partes el peso a 30 en todas las partes cuyo peso sea mayor que 16;
update partes set peso=30
where peso>16;
Programación
5.1 Introducción
Los elementos de los lenguajes de programación son muy similares entre sí y el cambio de lenguaje
solamente supone la modificación de ciertos hábitos.
En el entorno de las bases de datos se pueden encontrar programas que actúen mediante dos mecanismos
distintos. Estos dos mecanismos se definen como
Procedimientos almacenados: residen en el propio servidor de bases de datos.
Programas externos: utilizando algún mecanismo los programas externos se comunican con el
servidor para intercambiar datos mediante un lenguaje de programación cualquiera.
Entre los mecanismos de comunicación más utilizados encontramos ODBC (Open DataBases Commu-
nication). Este estándar especifica claramente a servidores y cliente como tienen que dar o pedir datos.
Una versión modificada de ODBC es JDBC que ha modernizado el estándar pero solo sirve para pro-
gramas Java.
5.2.2 Variables
Una variable es una posición de memoria con nombre. Normalmente las variables conllevan un tipo que
restringe lo que podemos almacenar en ella.
En MySQL las variables se declaran con la palabra clave DECLARE.
Los tipos utilizables con las variables son los mismos que tiene MySQL.
61
Bases de datos, Versión 1.1
Los procedimientos en MySQL actúan igual que las funciones en Java con las diferencias en la sintaxis.
El primer problema que aparece en los procedimientos MySQL viene dado por el hecho de que los
procedimientos a veces interfieren con el delimitador ”;”. Para evitarlo, debemos avisar a MySQL de
que durante un tiempo cambiaremos de delimitador, para ello se usa la siguiente sentencia
Dentro de “código” podrán ir sentencias que terminarán de forma normal, con el punto y coma ”;”
El problema viene dado porque el intérprete de MySQL intenta procesar todo lo que haya hasta llegar
a un punto y coma. Si no cambiásemos el delimitador, se ejecutaría la definición del procedimiento sin
haber encontrado un “end” y todo fallaría.
Ejercicio: crear un procedimiento que acepte una cantidad c y que seleccione todos los suministros cuyo
campo cantidad sea mayor que c
delimiter //
//
delimiter ;
Ejercicio: crear un programa que acepte un color co y una ciudad ci y que busque todas las partes cuyo
color sea ese co pasado y la ciudad ese ci pasado. Co y ci son parámetros y NO LLEVAN COMILLAS
delimiter //
create procedure Color_parte
(color_pasado varchar(20),
ciudad_pasada varchar(20) )
begin
select * from partes
where color=color_pasado
and
ciudad=ciudad_pasada;
end
//
delimiter ;
Ejercicio: crear un procedimiento que permita sumar la cantidad de partes suministradas cuyo color sea
el mismo que un cierto color pasado
drop procedure suministradas_color;
delimiter //
begin
select sum(cantidad)
62 Capítulo 5. Programación
Bases de datos, Versión 1.1
from suministra
inner join partes
on
suministra.numparte=partes.numparte
where color=color_pasado;
end
//
delimiter ;
call suministradas_color("Rojo");
call suministradas_color("Gris");
begin
select * from suministra inner join partes
on suministra.numparte=partes.numparte
where
nombreparte=nombre_parte_pasada
and
cantidad>cantidad_pasada;
end
//
delimiter ;
IF (<comparacion>) THEN
BEGIN
<sentencias>
END
ELSE
BEGIN
END
END IF;
Ejemplo: crear un procedimiento que extraiga las filas de la tabla suministra que cumplan cierta condi-
cion sobre la cantidad. Si el usuario pasa un simbolo “>” el procedimiento nos devuelve las filas mayores
que cierta cantidad. Si no pasa un “<” nos devuelve las filas con una cantidad menor que la pasada
drop procedure selector_v2;
delimiter //
//
delimiter ;
Ejercicio:crear un procedimiento que dados los parámetros siguientes compruebe cuantas partes con un
cierto nombre tienen una cantidad menor o mayor que una cierta cantidad pasada
nombre_parte_pasado
cantidad_pasada
operacion
drop procedure selector_v3;
delimiter //
64 Capítulo 5. Programación
Bases de datos, Versión 1.1
suministra.numparte=partes.numparte
where
nombreparte=nombre_parte_pasada
and
cantidad>cantidad_pasada;
end;
else
begin
select * from suministra inner join
partes on
suministra.numparte=partes.numparte
where
nombreparte=nombre_parte_pasada
and
cantidad<cantidad_pasada;
end;
end if;
end;
//
delimiter ;
Ejercicio: ampliar el programa anterior para que soporte búsquedas utilizando los comparadores “<”,
“>”, “>=”, “<=”, “=” y “<>”.
El programa anterior puede resolverse utilizando sentencias if-then-else anidadas, sin embargo es poco
práctico y difícil de ampliar.
La sintaxis de la sentencia case es la siguiente
CASE <variable>
WHEN ">" THEN
BEGIN
END;
WHEN ">=" THEN
BEGIN
END;
WHEN "<" THEN
BEGIN
END;
...
ELSE
BEGIN
END;
END CASE;
Basándonos en esta sintaxis, una posible solución al problema anterior sería esta
drop procedure selector_v4;
delimiter //
create procedure selector_v4
( nombre_parte_pasada varchar(11),
cantidad_pasada int,
operacion varchar(1) )
begin
case operacion
when ">" then
begin
select * from suministra
inner join partes
on
suministra.numparte=partes.numparte
where
nombreparte=nombre_parte_pasada
and cantidad>cantidad_pasada;
end;
when ">=" then
begin
select * from suministra
inner join partes
on
suministra.numparte=partes.numparte
where
nombreparte=nombre_parte_pasada
and cantidad>=cantidad_pasada;
end;
when "<>" then
begin
select * from suministra
inner join partes
on
suministra.numparte=partes.numparte
where
nombreparte=nombre_parte_pasada
and cantidad<>cantidad_pasada;
end;
when "<" then
begin
select * from suministra
inner join partes
on
suministra.numparte=partes.numparte
where
nombreparte=nombre_parte_pasada
and cantidad<cantidad_pasada;
end;
when "<=" then
begin
select * from suministra
inner join partes
on
suministra.numparte=partes.numparte
where
nombreparte=nombre_parte_pasada
and cantidad<=cantidad_pasada;
end;
when "=" then
begin
select * from suministra
inner join partes
on
66 Capítulo 5. Programación
Bases de datos, Versión 1.1
suministra.numparte=partes.numparte
where
nombreparte=nombre_parte_pasada
and cantidad=cantidad_pasada;
end;
else
begin
select ("Operacion no reconocida");
end;
end case;
end;
//
delimiter ;
Ejercicio: crear un programa que acepte un nombre de parte,luego dos ciudades C1 y C2 y luego un
comparador que puede ser “AND” o “OR”. El programa debe decirnos las partes que pertenecen a las
dos ciudades o a una de ellas.
drop procedure comparador;
delimiter //
case operador
when "AND" then
begin
select * from partes as p1, partes as p2
where p1.nombreparte=nombre_parte_pasada
and
p2.nombreparte=nombre_parte_pasada
and (p1.ciudad=c1_pasada
and p2.ciudad=c2_pasada);
end;
when "OR" then
begin
select * from partes as p1, partes as p2
where p1.nombreparte=nombre_parte_pasada
and
p2.nombreparte=nombre_parte_pasada
and (p1.ciudad=c1_pasada
or p2.ciudad=c2_pasada);
end;
else
begin
select ("Escriba OR o AND (mayúsculas)");
end;
end case;
end
//
delimiter ;
Utilizando la sentencia WHILE podemos repetir una tarea que se repita un cierto número de veces por
medio de una variable.
La sintaxis de WHILE es la siguiente
set variable_control=0;
WHILE (<condicion>) DO
...
<sentencias>
..
set variable_control=variable_control+1;
END WHILE;
Ejercicio resuelto: hacer un programa MySQL que imprima los 10 primeros números pares.
drop procedure pares;
delimiter //
//
delimiter ;
5.3.4 Cursores
Un cursor es un puntero que apunta a la primera fila del resultado de una consulta. Podemos ir ha-
ciendo avanzar el puntero y procesar cada fila por separado. Podemos dejar de procesar filas cuando lo
deseemos, sin que sea obligatorio examinar todos los resultados.
No se puede declarar variables nuevas despues de un cursor. Es decir, esto no es válido
declare un_cursor cursor for...
declare contador int;
Esto sí es válido
declare contador int;
declare un_cursor cursor for...
68 Capítulo 5. Programación
Bases de datos, Versión 1.1
CLOSE nombre_cursor;
Ejercicio: extraer los proveedores que han recibido las 5 cantidades más grandes de suministros.
drop procedure mejores_clientes;
delimiter //
open cur1;
set contador=0;
while (contador<5) do
fetch cur1 into num_prov_sacado, cantidad_sacada;
select (num_prov_sacado);
select (cantidad_sacada);
set contador=contador+1;
end while;
close cur1;
end;
//
delimiter ;
Ejercicio: hacer un programa que saque las 2 partes de más peso de la tabla partes.
La consulta para este ejercicio sería:
select * from partes order by peso desc;
Y el procedimiento sería
drop procedure mayores_pesos;
delimiter //
create procedure mayores_pesos()
begin
declare contador int;
declare peso_extraido int;
declare ciudad_extraida varchar(15);
declare cur1 cursor for
select ciudad,peso from partes order by peso desc;
open cur1;
set contador=0;
while (contador<2) do
begin
fetch cur1 into ciudad_extraida,
select (ciudad_extraida),(peso_extraido);
set contador=contador+1;
end;
end while;
close cur1;
end;
//
delimiter ;
Y la solución sería
drop procedure suma_filas;
delimiter //
create procedure suma_filas()
begin
declare contador int;
declare suma int;
declare cantidad_extraida int;
declare cur1 cursor for
select cantidad from suministra
order by cantidad asc;
open cur1;
set suma=0;
set contador=0;
while contador<5 do
fetch cur1 into cantidad_extraida;
set suma=suma+cantidad_extraida;
set contador=contador+1;
end while;
close cur1;
select suma;
end;
//
delimiter ;
Si un procedimiento tiene que devolver cosas puede hacerlo utilizando parámetros en la cabecera que
hayan sido etiquetados como “out”.
drop procedure suma_filas;
delimiter //
create procedure suma_filas(out suma_devuelta int)
begin
declare contador int;
declare suma int;
declare cantidad_extraida int;
declare cur1 cursor for
select cantidad from suministra
order by cantidad asc;
open cur1;
set suma=0;
set contador=0;
while contador<5 do
fetch cur1 into cantidad_extraida;
70 Capítulo 5. Programación
Bases de datos, Versión 1.1
set suma=suma+cantidad_extraida;
set contador=contador+1;
end while;
close cur1;
set suma_devuelta=suma;
end;
//
delimiter ;
Ejercicio: realizar un procedimiento que devuelva en una variable la ciudad del proveedor con una
cantidad total (sumar) de suministros mayor.
La consulta sería algo así
select sum(cantidad),suministra.numprov,
ciudad from suministra
inner join proveedores
on suministra.numprov=proveedores.numprov
group by numprov
having sum(cantidad)>=ALL
(
select sum(cantidad)
from suministra
group by numprov
);
open cur1;
fetch cur1 into suma, num_proveedor,c_devuelta;
set ciudad_devuelta=c_devuelta;
close cur1;
end;
//
5.4 Funciones
//
delimiter ;
Ejercicio: construir una función que devuelva la suma total de cantidades de la tabla suministra
La consulta sería así:
select sum(cantidad) from suministra;
Y la función
drop function suma_suministra;
delimiter //
create function suma_suministra() returns int
begin
declare suma int;
declare cur1 cursor for
select sum(cantidad) from suministra;
open cur1;
fetch cur1 into suma;
close cur1;
return suma;
end;
//
delimiter ;
set @s=suma_suministra();
103