Sei sulla pagina 1di 76

DESARROLLO DE APLICACIONES EN ENTORNOS DE 4ª

GENERACIÓN Y CON HERRAMIENTAS CASE

EJER CICIO S

SELECT ... FROM WHERE...

a) Ejemplos de consultas simples con operadores aritméticos y relacionales.

1.- Selecionar los empleados con salario superior a 2000

SELECT APELLIDO FROM EMPLE WHERE SALARIO > 2000;

2.- Selecionar los empleados con salario superior a 2000 y con el trabajo de DIRECTOR

SELECT APELLIDO FROM EMPLE WHERE SALARIO > 2000 AND OFICIO LIKE ‘DIRECTOR’;

3.- Selecionar el nº de departamento que tengan distinto nombre

SELECT DISTINCT DNOMBRE, DEPT_NO FROM DEPART;

4.- Selecionar todos los empleados del departamento nº 20 y ademas debe de estar
ordenado por el apellido y tienen que aparecer en la consulta el nº del empleado, el
apellido, el oficio y el nº de departamento.

SELECT EMP_NO, APELLIDO, OFICIO, DEPT_NO FROM EMPLE WHERE DEPT_NO = 20


ORDER BY APELLIDO;

5.- Empleados cuyo oficio sea analista, ordenado por el número del empleado.

SELECT APELLIDO FROM EMPLE WHERE OFICIO LIKE ‘ANALISTA’ ORDER BY EMP_NO;

6.- Seleccionar las filas del departamento 10 cuyo oficio sea analista. La consulta debe
de estar ordenada descendentemente por el apellido y tambien descendentemente por
el nº empleado.

SELECT DEPT_NO FROM EMPLE WHERE (OFICIO LIKE 'ANALISTA' AND ORDER BY
EMP_NO DESC , ORDER BY APELLIDO DESC);

7.- Seleccionar los nombres de los alumnos y su nota de la tabla notas_alumnos.

SELECT NOMBRE_ALUMNO, NOTAS FROM NOTAS_ALUMNOS;


SELECT ... FROM WHERE...
b) Ejemplos de consultas simples con operadores aritméticos y relacionales.

8.- Seleccionar los nombres de los alumnos y su nota de la tabla notas_alumnos siendo
scott el propietario de la tabla.

SELECT NOMBRE_ALUMNO, NOTAS FROM SCOTT.NOTAS_ALUMNOS;

9.-Seleccionar la nota_media de los alumnos de la tabla notas_alumnos.

SELECT NOMBRE_ALUMNO, (NOTA1+NOTA2+NOTA3)/3 FROM NOTAS_ALUMNOS;

10.- Seleccionar los alumnos que de la nota1 hayan sacado un 7 y que la media de las 3
notas sea mayor que 6

SELECT NOTA_ALUMNO FROM NOTAS_ALUMNOS WHERE NOTA1=7 AND


(NOTA1+NOTA2+NOTA3)/3>6;

11.- Seleccionar los nombres de los alumnos y su nota siendo esta mayor o igual a 5 y
su curso primero.

SELECT NOMBRE_ALUMNO , NOTAS FROM NOTAS_ALUMNOS WHERE NOTA >=5 AND


CURSO LIKE 'PRIMERO';

12.- Seleccionar los empelados que sean analistas

SELECT APELLIDO FROM EMPLE WHERE OFICIO LIKE 'ANALISTA';

13.- Seleccionar los empleados cuyo apellido tenga una A en la 2ª posición.

SELECT APELLIDO FROM EMPLE WHERE APELLIDO LIKE '_A%';

14.- Seleccionar el apellido de los empleados cuyo oficio sea vendedor,analista o


empleado

SELECT APELLIDO FROM EMPLE WHERE OFICIO LIKE 'VENDEDOR' OR OFICIO LIKE
'ANALISTA' OR OFICIO LIKE 'EMPLEADO';

15.- Seleccionar el apellido, el salario y el nº de departamento de los empleados cuyo


salario sea mayor o igual a 125000 en los departamentos 10 o 20.

SELECT APELLIDO, SALARIO, DEPT_NO FROM EMPLE WHERE SALARIO > 125000 AND
DEPT_NO IN (10,20);
SELECT ... FROM WHERE...

c .- Ejemplos de consultas simples con operadores aritméticos y relacionales.

16.- Seleccionar la lista de empleados indicando para cada uno su apellido, oficio, fecha
de alta y el salario con un aumento del 16%.

SELECT APELLIDO, OFICIO, FECHA_ALT, SALARIO* 1.16 FROM EMPLE;

17.- De cada departamento saber el nombre y la localidad.

SELECT DNOMBRE , LOC FROM DEPART;

18.- seleccionar los departamentos agrupados por el nº departamento.

SELECT * FROM DEPART GROUP BY DEPART_NO ASC;

19.- seleccionar los empleados ordenados alfabeticamente por el nombre y por el


oficio.

SELECT * FROM EMPLE ORDER BY APELLIDO ASC, ORDER BY OFICIO ASC;

20.- seleccionar los empleados que no tienen comision.

SELECT APELLIDO FROM EMPLE WHERE COMISION = 0;

21.- Seleccionar los empleados de apellido muñoz.

SELECT APELLIDO FROM EMPLE WHERE APELLIDO LIKE 'MUÑOZ';

22.- Seleccionar los departamentos cuyo nombre acabe en 'on'

SELECT DNAME FROM DEPART WHERE DNAME LIKE '%ON';

23.- Seleccionar los empleados cuyo nº de departamento no sea ni 30, ni 20 ni 40.

a) SELECT APELLIDO FROM EMPLE WHERE DEPT_NO<>30, DEPT_NO<>20, DEPT_NO<>40;

b) SELECT APELLIDO FROM EMPLE WHERE DEPT_NO NOT IN(30,20,40)

24.- Seleccionar los departamentos cuya localidad no sea ni madrid ni bilbao.

SELECT DNOME FROM DEPART WHERE LOC LIKE NOT 'MADRID',LOC LIKE NOT 'BILBAO');

25.- Seleccionar los empleados cuya fecha de alta este entre entre el 8/9/61 y el
27/2/82.

SELECT APELLIDO FROM EMPLE WHERE FECHA_ALT BETWEEN '8/9/61' AND '27/2/82');
26.- seleccionar los departamentos que terminen en n y tengan una o en su interior.

SELECT DNOMBRE FROM DEPART WHERE DNOMBRE LIKE '%O%N' OR DNOMBRE LIKE 'O%N';

27.- Seleccionar los empleados que tengan una A en el apellido y una V en su oficio en
la posicion que sea.

SELECT APELLIDO FROM EMPLE WHERE APELLIDO LIKE '%A%' AND POBLACION LIKE '%V%';

28.- seleccionar los empelados cuyo salario sea mayor de 20000 y menor que 50000.

SELECT APELLIDO FROM EMPLE WHERE SALARIO>20000 AND SALARIO < 50000;

SELECT ... FROM WHERE...IN (SELECT...

a) Ejemplos de subconsultas con operadores aritméticos y relacionales.

1.- Seleccionar el apellido de los empleados que trabajen en madrid o barcelona.

SELECT APELLIDO FROM EMPLE WHERE DEPT_NO IN (SELECT DEPT_NO FROM DEPART
WHERE LOC IN ('MADRID','BARCELONA'));

2.- Seleccionar el apellido y el oficio de todos los empleados del departamento 20 cuyo
trabajo sea identico al de los empleados del departamento ventas.

SELECT APELLIDO,OFICIO FROM EMPLE WHERE DEPT_NO=20 AND OFICIO IN( SELECT
OFICIO FROM EMPLE WHERE DEPT_NO =(SELECT DEPT_NO FROM DEPART WHERE
DNOMBRE='VENTAS'));

3.- Obtener el departamento de los empleados con el mismo oficio y el salario de 'Gil'.

SELECT APELLIDO, SALARIO FROM EMPLE WHERE (OFICIO,SALARIO)= (SELECT OFICIO,


SALARIO FROM EMPLE WHERE APELLIDO='GIL');

4.- Obtener el nombre de alumno, su asignatura y su nota.

SELECT APENOM, NOMBRE, NOTA FROM ALUMNOS WHERE ALUMNOS.DNI


=NOTAS.DNI AND NOTAS.COD= ASIGNATURAS.COD;

5.- Nombre de los alumnos matriculados en FOL.

SELECT APENOM FROM ALUMNOS,ASIGNATURAS, NOTAS WHERE ALUMNOS.DNI =


NOTAS.DNI AND NOTAS.COD = ASIGNATURAS.COD AND NOMBRE='FOL';
SELECT ... FROM WHERE...IN(SELECT...

b) Ejemplos de subconsultas con operadores aritméticos y relacionales.

1.- seleccionar de la tabla emple aquellas filas cuyo apellido empiece por A y el oficio
tenga una e en cualquier posición.

SELECT APELLIDO,OFICIO FROM EMPLE WHERE APELLIDO LIKE '%A' OR OFICIO LIKE '%E%';

2.- Seleccionar el apellido, el oficio y la localidad de los departamentos donde trabajan


los analistas.

SELECT APELLIDO,OFICIO,LOC FROM EMPLE,DEPART WHERE OFICIO='ANALISTA';

3.- Mostrar los empleados (nombre, oficio, salario y fecha de alta) que desempeñen el
mismo oficio que JIMENEZ o que tengan el salario mayor o igual a FERNANDEZ.

SELECT APELLIDO,OFICIO,SALARIO,FECHA_ALT FROM EMPLE WHERE OFICIO = (SELECT


OFICIO FROM EMPLE WHERE APELLIDO = 'JIMENEZ') OR SALARIO >= (SELECT SALARIO
FROM EMPLE WHERE APELLIDO = 'FERNANDEZ');

4.- Mostar por pantalla el nombre, el oficio y el salario de los empleados del
departamento de FERNANDEZ que tengan su mismo salario.

SELECT APELLIDO,SALARIO,OFICIO FROM EMPLE WHERE (DEPT_NO, SALARIO) IN


(SELECT DEPT_NO,SALARIO FROM EMPLE WHERE APELLIDO = 'FERNANDEZ' );

5.- Presentar los nombres y oficios de los empleados que tienen el mismo trabajo que
JIMENEZ.

SELECT APELLIDO,OFICIO FROM EMPLE WHERE = (SELECT OFICIO FROM EMPLE WHERE
APELLIDO = 'JIMENEZ');

TABLA LIBRERÍA

6.- Visualizar el tema, estante y ejemplares de las filas de libreria de ejemplares


comprendidos entre 8 y 15.

SELECT * FROM LIBRERIA WHERE EJEMPLARES BETWEEN 8 AND 15;

7.- Visualizar las columnas tema, estante y ejemplares de las filas cuyo estante no este
comprendido entre la B y la D.

SELECT * FROM LIBRERIA WHERE ESTANTE NOT BETWEEN 'B' AND 'D';
8.- Visualizar con una sola orden select todos los temas de libreria cuyo numero de
ejemplares sea inferior a los que hay en medicina.

SELECT TEMA FROM LIBRERIA WHERE EJMEPLARES <(SELECT EJEMPLARES FROM


LIBRERIA WHERE TENA LIKE 'MEDICINA');

9.- Visualizar los temas de libreria cuyos numeros de ejemplares no este entre 15 y 20,
ambos incluidos.

SELECT TEMA FROM LIBRERIA WHERE EJEMPLARES NOT BETWEEN (15) AND (20);

SELECT ... FROM WHERE...IN(SELECT...

c) Ejemplos de subconsultas con operadores aritméticos y relacionales.

10.- Visualizar todas las asignaturas que contengan en su interior tres letras 'o' y
tengan alumnos matriculados en madrid.

SELECT NOMBRE FROM ASIGNATURAS, ALUMNOS,NOTAS WHERE NOMBRE LIKE '%O%O%O%'


AND POBLA ='MADRID' AND ALUMNOS.COD= NOTAS.COD AND NOTAS.DNI=ALUMNOS.DNI;

11.- Visualizar los nombres de los alumnos que tengan una nota entre 7 y 8 en la
asignatura de FOL.

SELECT APENOM,NOMBRE,NOTA FROM ALUMNOS ,ASIGNATURAS,NOTASWHERE


NOMBRE ='FOL' AND NOTA BETWEEN 7 AND 8 AND ALUMNOS.COD=NOTAS.COD AND
NOTAS.DNI=ALUMNOS.DNI;

12.- Visualizar los nombres de asignaturas que no tengan suspensos.

SELECT NOMBRE FROM ASIGNATURAS, NOTAS WHERE NOTA BETWEEN 5 AND 10;

13.- Visualizar los nombres de alumnos de madrid que tengan alguna asignatura
suspendida.

SELECT APENOM,DIREC,NOTA FROM ALUMNOS , NOTAS WHERE DIREC='MADRID' AND


NOTA BETWEEN 3 AND 4;

14.- Mostrar los nombres de alumnos que tengan la misma nota que tiene "Díaz
Fernández, María" en FOL en alguna asignatura.

SELECT APENOM FROM ALUMNOS WHERE DNI IN (SELECT DNI FROM NOTAS
WHERE NOTA =
(SELECT NOTA FROM NOTAS WHERE DNI = (SELECT DNI FROM ALUMNOS WHERE
APENOM = 'DÍAZ FERNÁNDEZ. MARÍA') AND COD = (SELECT COD FROM ASIGNATURAS
WHERE NOMBRE = 'FOL')));
SELECT ... FROM ...GROUP BY...HAVING...

a) Ejemplos de consultas simples con operadores aritméticos y relacionales.

1) Visualizar los departamentos en los que el salario medio es mayor o igual que la
media de todos los salarios;

SELECT DEPT_NO, AVG(SALARIO) FROM EMPLE GROUP BY DEPT_NO HAVING


AVG(SALARIO) >= (SELECT AVG(SALARIO) FROM EMPLE);

2) A partir de la tabla emple, visualizar el número de venderores del departamentos


'VENTAS';

SELECT COUNT(*) FROM EMPLE WHERE DEPT_NO = (SELECT DEPT_NO FROM DEPART
WHERE DNOMBRE ='VENTAS' AND OFICIO = 'VENDEDOR');

3) Partiendo de la tabla EMPLE, visualizar por cada oficio de los empleados del
departamento 'VENTAS' la suma de salarios.

SELECT SUM(SALARIO), OFICIO FROM EMPLE WHERE DEPT_NO IN (SELECT DEPT_NO


FROM DEPART WHERE DNOMBRE LIKE 'VENTAS') GROUP BY OFICIO;

4) seleccionar aquellos pedidos de la tabla EMPLE cuyo salario sea igual a la media de
su salario en su departamento.

SELECT APELLIDO, SALARIO FROM EMPLE WHERE (SALARIO,DEPT_NO) IN (SELECT


AVG(SALARIO),DEPT_NO FROM EMPLE GROUP BY DEPT_NO);

5) A partir de la tabla emple, visualizar el numero de empleados de cada departamento


cuyo oficio sea 'EMPLEADO'

SELECT DEPT_NO,COUNT(*) FROM EMPLE WHERE OFICIO LIKE 'EMPLEADO' GROUP BY DEPT_NO;

6) Desde la tabla EMPLE, visualizar el departamento que tenga más empleados cuyo
oficio sea 'EMPLEADO'

SELECT DEPT_NO, COUNT(*) FROM EMPLE WHERE OFICIO LIKE 'EMPLEADO' GROUP BY
DEPT_NO HAVING COUNT(*)=(SELECT MAX(COUNT(*)) FROM EMPLE WHERE OFICIO
LIKE 'EMPLEADO'GROUP BY DEPT_NO);

7) A partir de las tablas EMPLE y DEPART, visualizar el número de departamento y el


nombre de departamento que tenga más empleados cuyo oficio sea 'EMPLEADO'

SELECT DEPT_NO,DNOMBRE FROM DEPART WHERE DEPT_NO=(SELECT DEPT_NO FROM


EMPLE WHERE OFICIO= 'EMPLEADO' GROUP BY DEPT_NO HAVING COUNT(*)=(SELECT
MAX(COUNT(*)) FROM EMPLE WHERE OFICIO='EMPLEADO' GROUP BY DEPT_NO));
8) Buscar los departamentos que tienen más de dos personas trabajando en la misma
profesión

SELECT DEPT_NO,COUNT(*) FROM EMPLE GROUP BY DEPT_NO,OFICIO HAVING COUNT(*)>2;

9) Dada la tabla LIBRERIA, visualizar por cada estante la suma de los ejemplares.

SELECT ESTANTE, SUM(EJEMPLARES) FROM LIBRERIA GROUP BY ESTANTE;

10) Visualizar el estante con más ejemplares de la tabla libreria.

SELECT ESTANTE,SUM(EJEMPLARES) FROM LIBRERIA GROUP BY ESTANTE HAVING


SUM(EJEMPLARES)=(SELECT MAX(SUM(EJEMPLARES)) FROM LIBRERIA GROUP BY ESTANTE);

SELECT ... FROM ...GROUP BY...HAVING...

b) Ejemplos de consultas simples con operadores aritméticos y relacionales.

11) Visualizar los nombres de los alumnos de la tabla ALUM que aparezcan en alguna
de estas tablas: NUEVOS y ANTIGUOS.

SELECT NOMBRE FROM ALUM INTERSECT (SELECT NOMBRE FROM NUEVOS UNION
SELECT NOMBRE FROM ANTIGUOS);

12) Escribir las distintas formas en que se puede poner la consulta anterior llegando al
mismo resultado

SELECT NOMBRE FROM ALUM WHERE NOMBRE IN(SELECT NOMBRE FROM NUEVO)
UNION SELECT NOMBRE FROM ANTIGUO);

SELECT NOMBRE FROM ALUM WHERE NOMBRE IN (SELECT NOMBRE FROM NUEVO)
OR NOMBRE IN (SELECT NOMBRE FROM ANTIGUO);

13) Visualizar los nombres de los alumnos de la tabla alum que aparezcan en estas dos
tablas: antiguos y nuevos

SELECT NOMBRE FROM ALUM INTERSECT SELECT NOMBRE FROM ANTIGUOS


INTERSECT SELECT NOMBRE FROM NUEVOS;

14) Escribir las distintas formas en que se puede poner la consulta anterior llegando al
mismo resultado.

SELECT NOMBRE FROM ALUM WHERE NOMBRE IN(SELECT NOMBRE FROM


NUEVOS)AND NOMBRE IN(SELECT NOMBRE FROM ANTIGUOS);
15) Visualizar aquellos nombres de la tabla alum que no esten en la tabla antiguos ni
en la tabla nuevos

SELECT NOMBRE FROM ALUM MINUS SELECT NOMBRE FROM ANTIGUOS MINUS
SELECT NOMBRE FROM NUEVOS;

16) Realizar una consulta en la que aparezca por cada centro y en cada especialidad el
numero de profesores. Si el centro no tiene profesores debe aparecer un 0 en la
columna de profesores.

SELECT NOMBRE,ESPECIALIDAD,COUNT(*) FROM CENTROS,PROFESORES GROUP BY


COD_CENTRO,ESPECIALIDAD;

SELECT NOMBRE,ESPECIALIDAD,COUNT(DNI) FROM CENTROS,PROFESORES GROUP BY


COD_CENTRO HAVING (CENTROS.COD_CENTRO = PROFESORES.COD_CENTRO);

17) Obtener la especialidad con menos empleados

SELECT ESPECIALIDAD FROM PROFESORES WHERE APELLIDOS = (SELECT


MAX(APELLIDOS) FROM PROFESORES);

SELECT ... FROM ...GROUP BY...HAVING...

c) Ejemplos de consultas simples con operadores aritméticos y relacionales.

1.- mostrar el oficio y media de salarios de aquellos empleados cuya media de salario
sea mayor que 200000

SELECT AVG(SALARIO),OFICIO FROM EMPLE GROUP BY OFICIO HAVING AVG(SALARIO)>200000;

2.- mostrar el nombre y la comision de aquellos empleados que tengan una comision
mayor que la de sanchez

SELECT APELLIDO,COMISION FROM EMPLE WHERE COMISION > (SELECT COMISION


FROM EMPLE WHERE APELLIDO LIKE 'SÁNCHEZ');

3.- mostrar el nombre salario y nº de departamento de aquellos empleados que ganan


el salario maximo de su departamento

SELECT APELLIDO,SALARIO, DEPT_NO FROM EMPLE WHERE SALARIO IN (SELECT


MAX(SALARIO) FROM EMPLE GROUP BY DEPT_NO);
4.- mostrar el nombre del departamento que tanga más empleados cuyo oficio sea
presidente

SELECT DNOMBRE FROM DEPART GROUP BY DNOMBRE HAVING COUNT(*) = (SELECT


MAX(COUNT(*)) FROM EMPLE WHERE OFICIO
LIKE 'PRESIDENTE' GROUP BY DEPT_NO);

5.- mostrar el número de directores de la tabla emple que sean dep departamento
producción

SELECT COUNT(OFICIO) FROM EMPLE WHERE OFICIO = 'DIRECTOR' AND DEPT_NO =


(SELECT DEPT_NO FROM DEPART WHERE
DNOMBRE = 'PRODUCCIÓN');

SELECT ... FROM WHERE...FUNCION

a) Ejemplos de consultas con funciones numéricas y de caracteres.

2.- A partir de la tabla emple, visualizar cuantos apellidos de los empleados empiezan
por la letra ‘A’

SELECT COUNT (APELLIDO) EMPLE WHERE APELLIDO LIKE ‘A%’;

3.- Dada la tabla emple, obtener el sueldo medio, el número de comisiones no nulas , el
máximo sueldo y el minimo sueldo de los empleados del departamento 30.Emplear el
formato adecuado para la salida y las cantidades adecuadas.

SELECT AVG(SALARIO), COUNT(COMISION), MAX(SALARIO), MIN(SALARIO) FROM


EMPLE WHERE DEPT_NO= 30;

4.- Contar las filas de librería cuyo tema tenga por lo menos una ‘A’.

SELECT COUNT (TEMA) FROM LIBRERÍA WHERE TEMA LIKE ‘%A%’;

5.- Visualizar los temas con mayor número de ejemplares de la tabla librería y que
tengan al menos una ‘E’ (pueden ser un tema o varios).

SELECT TEMA FROM LIBRERIA WHERE EJEMPLARES =(SELECT MAX(EJEMPLARES) FROM


LIBRERÍA )AND TEMA LIKE (‘%E%’);

6.- Visualizar el número de estantes diferentes que hay en la tabla librería.

SELECT COUNT (DISTINCT ESTANTE ) FROM LIBRERÍA;


7.- Visualizar el número de estantes distintos que hay en la tabla librería de aquellos
temas que contienen al menos una ‘E’.

SELECT COUNT (DISTINCT ESTANTE ) FROM LIBRERIA WHERE TEMA LIKE (‘%E%’);

8.- ¿Qué sentencia select se debe ejecutar para tener el siguiente resultado?

SELECT RPAD(LTRIM (RTRIM(TITULO,’.’),’”’),45,’-1’)FROM LIBROS;

9.- Visualizar los titulos de la tabla MISTEXTOS sin los caracteres punto y comillas, y en
minusculas de dos formas conocidas.

SELECT LOWER (LTRIM (RTRIM(TITULO,’.”’),’”’) FROM MISTEXTOS;

10.- Escribir una sentencia select que visualice dos columnas, una con el autor y otra
con el apellido del autor.

SELECT AUTOR,SUBSTR(AUTOR,0,INSTR(AUTOR,',',1)-1) FROM LIBROS;

11.- Escribir la sentencia select que visualice las columnas de autor y otra columna con
el nombre del autor (sin el apellido) de la tabla libros.

SELECT AUTOR,SUBSTR(AUTOR,INSTR(AUTOR,',',1)+1) FROM LIBROS;

SELECT ... FROM WHERE...FUNCION

b) Ejemplos de consultas con funciones numéricas y de caracteres.

12.- A partir de la tabla libros, realizar una sentencia select que visualice en una
columna, primero el nombre del autor y luego el apellido.

SELECT SUBSTR(AUTOR,INSTR(AUTOR,',',1)+1), SUBSTR(AUTOR,0,INSTR(AUTOR,',',1)-1)


FROM LIBROS;

13.- A partir de la tabla libros , realizar una sentecia select que visualice los titulos
ordenados por su numero de caracteres.

SELECT TITULO FROM LIBROS ORDER BY LENGTH(TITULO);

14.- Realizar una select que obtenga el siguiente resultado:

SELECT NOMBRE, FECHANAC, TO_CHAR(FECHANAC, ‘”Nacio el”dd” de ”month” de


”yyyy’) from nacimientos;
15.- Dada la tabla librería, hacer una sentencia select que visualice el tema, el ultimo
carácter del tema que no sea blanco y el número de caracteres de tema (sin contar los
blancos de la derecha) ordenados por tema.

SELECT TEMA, SUBSTR(TEMA,INSTR(TEMA,’ ’)-1),INSTR(TEMA,’ ’)-1 FROM LIBRERIA


ORDER BY TEMA;

16.- a partir de la tabla nacimientos, visualizar en una columna el nombre seguido de


su fecha de nacimiento formateada (quitar blancos del nombre).

SELECT NOMBRE,TO_CHAR(FECHANAC,’DAY,DD MONTH YYYY’) FROM NACIMIENTOS;

17.- Convertir la cadena ‘01051998’ a fecha y visualizar su nombre de mes en


mayúsculas.

SELECT UPPER(TO_CHAR(TO_DATE(‘01051998’),’MONTH’)) FROM DUAL;

18.- A partir de la tabla emple, obtener el apellido de los empleados que lleven más de
19 años trabajando.

SELECT APELLIDO FROM EMPLE WHERE 2004-TO_NUMBER(


TO_CHAR(FECHA_ALT,’YYYY’) ) >19;

19.- Seleccionar el apellido de los empleados de la tabla emple que lleven mas de 18
años trabajando en el en el departamento ‘ventas’.

SELECT APELLIDO FROM EMPLE WHERE 2004 – TO_NUMBER (TO_CHAR


(FECHA_ALT,’YYYY’))>19 AND DEPT_NO = (SELECT DEPT_NO FROM DEPART WHERE
DNOMBRE = ‘VENTAS’);

20.- Visualizar el apellido, el salario y el número de departamento de aquellos


empleados de la tabla emple cuyo salario sea el mayor de su departamento.

SELECT APELLIDO, SALARIO , DEPT_NO FROM EMPLE E WHERE SALARIO IN (SELECT


MAX(SALARIO) FROM EMPLE DEPT_NO=E.DEPT_NO);

21.- Visualizar el apellido, el salario y el número de departamento de aquellos


empleados de la tabla emple cuyo salario supere a la media en su departamento.

SELECT APELLIDO, SALARIO, DEPT_NO FROM EMPLE E WHERE SALARIO >


(SELECT AVG(SALARIO) FROM EMPLE WHERE DEPT_NO=E.DEPT_NO);
SELECT ... FROM WHERE...FUNCION

c) Ejemplos de consultas con funciones numéricas y de caracteres.

1.- visualizar los departamentos con mayor número de empleados y que tengan un
salario mayor que 20000.

SELECT DNOMBRE FROM DEPART WHERE DEPT_NO = (SELECT DEPT_NO FROM EMPLE
WHERE EMP_NO = (SELECT MAX(EMP_NO) FROM EMPLE WHERE SALARIO = (SELECT
SALARIO FROM EMPLE WHERE SALARIO > 20000 )));

2.- visualizar los titulos de la tabla libros entre los caracteres * y en minuscula.Ejemplo:
*la colmena*

SELECT LOWER (CONCAT ('*',CONCAT (TITULO,'*'))) FROM LIBROS;

3.- visualizar los libros que comiencen por 'L' y sean de la editorial 'Planeta'.

SELECT TITULO FROM LIBROS WHERE TITULO LIKE 'L%' AND EDITORIAL = 'PLANETA';

4.- Si hoy es 22/03/2010 del lunes que dia sera el lunes de la semana que viene

SELECT NEXT_DAY (SYSDATE,'SÁBADO') FROM DUAL;

5.- Visualizar los autores que no sean de la editorial 'planeta'

SELECT AUTOR FROM LIBROS WHERE EDITORIAL NOT IN 'PLANETA';

6.- a partir de la tabla mis textos realizar una select para que aparezcan los autores
ordenados por el numero de caracteres de la columna titulo.

SELECT AUTOR FROM MIS TEXTOS ORDER BY LENGHT (TITULO);

7.- seleccionar los empleados que hayan trabajado más de 5 años y sumarles 10000 pts
a su salario.

SELECT APELLIDO, SALARIO + 10000 FROM EMPLE WHERE MONTHS_BETWEEN


(SYSDATE, FECHA_ALT)/12>5;

8.- obtener la fecha de hoy con el siguiente formato (en mayusculas) hoy es veintidós
de marzo de dosmil diez.

SELECT TO_CHAR (SYSDATE, "HOY ES" DAY, DD "DE" MONTHS "DE" YEAR) FROM DUAL;
9.- escribir una consultilla que visualice en una sola columna el nombre y apellido de las
personas de la tabla nacimiento y la fecha de nacimiento en un formato específico.

SELECT CONCAT (CONCAT(NOMBRE,APELLIDO), TO_CHAR (FECHANAC, 'DAY DD


MONTH YY')) FROM NACIMIENTO;

SELECT ... FROM WHERE...FUNCION

d) Ejemplos de consultas con funciones de fechas.

1.- Dada la tabla emple, sumar dos meses a la fecha de alta.

SELECT ADD_MONTHS(FECHA_ALT,2) FROM EMPLE;

2.- Dada la tabla emple, restar dos meses a la fecha de alta.

SELECT MONTHS_BETWEEN(FECHA_ALT,FECHA_ALT-2) FROM EMPLE;

3.- Obtener de la tabla emple el último dia del mes para cada uno de las fechas de alta.

SELECT LAST_DAY(FECHA_ALT) FROM EMPLE;

4.- Obtener la diferencia de meses que hay entre la fecha 5/5/200 y la fecha 1/1/2000.

SELECT MONTHS_BETWEEN(5/5/200 * 1/1/2000) FROM DUAL;

5. - Calcular vuestra edad.

SELECT MONTHS_BETWEEN(17/5/1981,SYSDATE)/12 FROM DUAL;

6.- Si hoy es domingo 25 de julio de 1999 (fecha del sistema "sysdate"). ¿Qué fecha será
el proximo jueves?

SELECT NEWT_DAY(SYSDATE,'JUEVES')FROM DUAL;

7.- A partir de la tabla emple, obtener la fecha de alta (columna FECHA_ALT)


fromateada, de manera que aparezca el nombre del mes con todas sus letras (month),
el numero del dia del mes(dd) y el año (yyyy).

SELECT TO_CHAR(FECHA_ALT,'MONTH,DDYYYY') FROM EMPLE;

8.- A partir de la tabla emple, obtener la fecha de lata de forma que aparezca el
nombre del mes con tres letras (month), el numero del dia del año (ddd), el ultimo
digito del año(y)y los tres digitos ultimos del año(yyy).

SELECT TO_CHAR(SECHA_ALT,'MON DDD Y YYY')FROM EMPLE;


9.- Obtener la fecha de hoy con el siguiente fromato: Hoy es NOMBRE_DIA,DIA_MES de
NOMBRE_MES de AÑO.

SELECT TO_CHAR(SYSDATE,'"HOY ES " DAY "," DD "DE" MONTH "DE" YYYY') FROM DUAL;

10.- Visualizar la suma de salarios de la tabla emple de manera formateada, tal que
aparezca el simbolo de la moneda local, el punto para los miles y la coma para los
decimales.

SELECT TO_CHAR(SUM(SALARIO),'L9,999,999.99') FROM EMPLE;

11.- Convertir la cadena 01012001 a tipo date.

SELECT TO_DATE('01012001')FROM DUAL;

12.- Obtener el nombre del mes a partir de la cadena '01012001'. Antes hay que
convertir la cadena a tipo fecha.

SELECT TO_CHAR(TO_DATE('01012001'),MONTH) FROM DUAL;

13.- Obtener el nombre del dia, el nombre del me, el dia y el año en ingles a partir de la
fecha '12121997'

SELECT TO_CHAR(TO_DATE('12121997')),'DAY,MONTH DD YYYY'FROM DUAL;

CREATE TABLE...

a) Creación de tablas depart y emple.

REM ******** TABLA DEPART: ***********

DROP TABLE DEPART cascade constraints;

CREATE TABLE DEPART (


DEPT_NO NUMBER(2) NOT NULL,
DNOMBRE VARCHAR2(14),
LOC VARCHAR2(14) ) ;
REM ******** TABLA EMPLE: *************

ALTER SESSION SET NLS_DATE_FORMAT='DD/MM/YYYY';

DROP TABLE EMPLE cascade constraints;

CREATE TABLE EMPLE (


EMP_NO NUMBER(4) NOT NULL,
APELLIDO VARCHAR2(10) ,
OFICIO VARCHAR2(10) ,
DIR NUMBER(4) ,
FECHA_ALT DATE ,
SALARIO NUMBER(10),
COMISION NUMBER(10),
DEPT_NO NUMBER(2) NOT NULL) ;

COMMIT;

CREATE TABLE...

b) Creación de tablas alumnos, asignaturas y notas.

REM ******** TABLA NOTAS_ALUMNOS: ***********

Drop table notas_alumnos cascade constraints;

create table notas_alumnos


(
NOMBRE_ALUMNO VARCHAR2(25) NOT NULL ,
nota1 number(2),
nota2 number(2),
nota3 number(2)
);

REM ******** TABLA LIBRERIA: *************

Drop table LIBRERIA cascade constraints;

create table LIBRERIA


(TEMA CHAR(15) NOT NULL ,
ESTANTE CHAR(1),
EJEMPLARES NUMBER(2)
);
REM ******** TABLAS ALUMNOS, ASIGNATURAS, NOTAS: ***********

DROP TABLE ALUMNOS cascade constraints;

CREATE TABLE ALUMNOS


(
DNI VARCHAR2(10) NOT NULL,
APENOM VARCHAR2(30),
DIREC VARCHAR2(30),
POBLA VARCHAR2(15),
TELEF VARCHAR2(10)
);

DROP TABLE ASIGNATURAS cascade constraints;

CREATE TABLE ASIGNATURAS


(
COD NUMBER(2) NOT NULL,
NOMBRE VARCHAR2(25)
);

DROP TABLE NOTAS cascade constraints;

CREATE TABLE NOTAS


(
DNI VARCHAR2(10) NOT NULL,
COD NUMBER(2) NOT NULL,
NOTA NUMBER(2)
);

commit;

CREATE TABLE...

c) Creación de tablas nombres, mistextos, libros y nacimientos.

REM ********** TABLA NOMBRES: ***********

DROP TABLE NOMBRES cascade constraints;


CREATE TABLE NOMBRES
(
NOMBRE VARCHAR2(15),
EDAD NUMBER(2)
);

COMMIT;
REM ********** TABLA MISTEXTOS: *************

DROP TABLE MISTEXTOS cascade constraints;

CREATE TABLE MISTEXTOS (


TITULO VARCHAR2(32),
AUTOR VARCHAR2(22),
EDITORIAL VARCHAR2(15),
PAGINA NUMBER(3)
);

COMMIT;

REM ********** TABLA LIBROS: *************

DROP TABLE LIBROS cascade constraints;

CREATE TABLE LIBROS (


TITULO VARCHAR2(32),
AUTOR VARCHAR2(22),
EDITORIAL VARCHAR2(15),
PAGINA NUMBER(3)
);

REM ********** TABLA NACIMIENTOS:******************

DROP TABLE NACIMIENTOS cascade constraints;

ALTER SESSION SET NLS_DATE_FORMAT='DD/MM/YYYY';

CREATE TABLE NACIMIENTOS (


NOMBRE CHAR(15),
APELLIDO CHAR(15),
FECHANAC DATE,
EDAD NUMBER
);

COMMIT;
CREATE TABLE...

d) Creación de tablas paraleer y leidos, alum, nuevos y antiguos, personal profesores


y centros.

REM ************ TABLAS PARALEER Y LEIDOS **************

DROP TABLE PARALEER cascade constraints;

CREATE TABLE PARALEER


(
COD_LIBRO NUMBER(3),
NOMBRE_LIBRO VARCHAR2(40)
);

DROP TABLE LEIDOS cascade constraints;

ALTER SESSION SET NLS_DATE_FORMAT='DD/MM/YYYY';

CREATE TABLE LEIDOS


(
COD_LIBRO NUMBER(3),
FECHA DATE
);

COMMIT;

REM ************ TABLA ALUM, NUEVOS, ANTIGUOS ************

DROP TABLE ALUM cascade constraints;


DROP TABLE NUEVOS cascade constraints;
DROP TABLE ANTIGUOS cascade constraints;

Create TABLE ALUM


(
NOMBRE VARCHAR2(20),
EDAD NUMBER(2),
LOCALIDAD VARCHAR2(15)
);

Create TABLE NUEVOS


(
NOMBRE VARCHAR2(20),
EDAD NUMBER(2),
LOCALIDAD VARCHAR2(15)
);
Create TABLE ANTIGUOS
(
NOMBRE VARCHAR2(20),
EDAD NUMBER(2),
LOCALIDAD VARCHAR2(15)
);

COMMIT;

REM ************ TABLA PERSONAL, PROFESORES, CENTROS ***********

DROP TABLE PERSONAL cascade constraints;

CREATE TABLE PERSONAL (


COD_CENTRO NUMBER(4) NOT NULL,
DNI NUMBER(10),
APELLIDOS VARCHAR2(30),
FUNCION VARCHAR2(15),
SALARIO NUMBER (10)
);

DROP TABLE PROFESORES cascade constraints;

CREATE TABLE PROFESORES (


COD_CENTRO NUMBER(4) NOT NULL,
DNI NUMBER(10), APELLIDOS
VARCHAR2(30), ESPECIALIDAD
VARCHAR2(16)
);

DROP TABLE CENTROS cascade constraints;

CREATE TABLE CENTROS (


COD_CENTRO NUMBER(4) NOT NULL,
TIPO_CENTRO CHAR(1),
NOMBRE VARCHAR2(30),
DIRECCION VARCHAR2(26),
TELEFONO VARCHAR2(10),
NUM_PLAZAS NUMBER(4)
);

commit;

REM ************ FIN ****************


CREATE TABLE...

e) Creación de tablas emple30 y coches, artículos, tiendas, fabricantes, pedidos y


ventas.

REM *************** TABLA EMPLE30: **************

DROP TABLE EMPLE30 cascade constraints;

CREATE TABLE EMPLE30 (


EMP_NO NUMBER(4) NOT NULL,
APELLIDO VARCHAR(10) ,
OFICIO VARCHAR(10) ,
DIR NUMBER(4) ,
FECHA_ALT DATE ,
SALARIO NUMBER(10),
COMISION NUMBER(10),
DEPT_NO NUMBER(2) NOT NULL) ;

REM *************** TABLA COCHES: *************

DROP TABLE COCHES cascade constraints;

CREATE TABLE COCHES (NOMBRE VARCHAR2(15)) TABLESPACE USER_DATA;

INSERT INTO COCHES VALUES('SEAT');

COMMIT;

REM *************** TABLAS ARTICULOS, TIENDAS, FABRICANTES, PEDIDOS y


VENTAS:********

DROP TABLE ARTICULOS cascade constraints;


DROP TABLE TIENDAS cascade constraints;
DROP TABLE FABRICANTES cascade constraints;
DROP TABLE PEDIDOS cascade constraints;
DROP TABLE VENTAS cascade constraints;

CREATE TABLE ARTICULOS( ARTICULO


VARCHAR2(20)NOT NULL,
COD_FABRICANTE NUMBER(3) NOT NULL,
PESO NUMBER(3) NOT NULL ,
CATEGORIA VARCHAR2(10) NOT NULL,
PRECIO_VENTA NUMBER (4),
PRECIO_COSTO NUMBER (4),
EXISTENCIAS NUMBER (5) );
CREATE TABLE FABRICANTES(
COD_FABRICANTE NUMBER(3) NOT NULL,
NOMBRE VARCHAR2(15),
PAIS VARCHAR2(15)) ;

CREATE TABLE TIENDAS(


NIF VARCHAR2(10) NOT NULL,
NOMBRE VARCHAR2(20),
DIRECCIÓN VARCHAR2(20),
POBLACIÓN VARCHAR2(20),
PROVINCIA VARCHAR2(20),
CODPOSTAL NUMBER(5) ) ;

CREATE TABLE PEDIDOS(


NIF VARCHAR2(10) NOT NULL, ARTICULO
VARCHAR2(20) NOT NULL,
COD_FABRICANTE NUMBER(3) NOT NULL,
PESO NUMBER(3) NOT NULL,
CATEGORIA VARCHAR2(10) NOT NULL,
FECHA_PEDIDO DATE NOT NULL,
UNIDADES_PEDIDAS NUMBER(4)
);

ALTER SESSION SET NLS_DATE_FORMAT='DD/MM/YYYY';

CREATE TABLE VENTAS(


NIF VARCHAR2(10) NOT NULL, ARTICULO
VARCHAR2(20) NOT NULL,
COD_FABRICANTE NUMBER(3) NOT NULL,
PESO NUMBER(3) NOT NULL,
CATEGORIA VARCHAR2(10) NOT NULL,
FECHA_VENTA DATE NOT NULL,
UNIDADES_VENDIDAS NUMBER(4)
);

commit;

REM *************** FIN *************************


INSERT INTO .... VALUES....

a) Ejemplos de inserción de datos en tablas.

INSERT INTO DEPART VALUES (10,'CONTABILIDAD','SEVILLA');


INSERT INTO DEPART VALUES (20,'INVESTIGACIÓON','MADRID');
INSERT INTO DEPART VALUES (30,'VENTAS','BARCELONA');
INSERT INTO DEPART VALUES (40,'PRODUCCIÓN','BILBAO');

INSERT INTO EMPLE VALUES (7369,'SÁNCHEZ','EMPLEADO',7902,'17/12/1980',


104000,NULL,20);
INSERT INTO EMPLE VALUES (7499,'ARROYO','VENDEDOR',7698,'20/02/1980',
208000,39000,30);
INSERT INTO EMPLE VALUES (7521,'SALA','VENDEDOR',7698,'22/02/1981',
162500,65000,30);
INSERT INTO EMPLE VALUES (7566,'JIMÉNEZ','DIRECTOR',7839,'02/04/1981',
386750,NULL,20);

insert into NOTAS_ALUMNOS VALUES ('Alcalde García, M. Luisa',5,5,5);


insert into NOTAS_ALUMNOS VALUES ('Benito Martín, Luis',7,6,8);
insert into NOTAS_ALUMNOS VALUES ('Casas Martínez, Manuel',7,5,5);
insert into NOTAS_ALUMNOS VALUES ('Corregidor Sánchez, Ana',6,9,8);
insert into NOTAS_ALUMNOS VALUES ('Díaz Sánchez, María',NULL,NULL,7);

INSERT INTO ASIGNATURAS VALUES (1,'Prog. Leng. Estr.');


INSERT INTO ASIGNATURAS VALUES (2,'Sist. Informáticos');
INSERT INTO ASIGNATURAS VALUES (3,'Análisis');
INSERT INTO ASIGNATURAS VALUES (4,'FOL');

INSERT INTO ALUMNOS VALUES


('12344345','Alcalde García, Elena', 'C/Las Matas, 24','Madrid','917766545');

INSERT INTO ALUMNOS VALUES


('4448242','Cerrato Vela, Luis', 'C/Mina 28 - 3A', 'Madrid','916566545');

INSERT INTO ALUMNOS VALUES


('56882942','Díaz Fernández, María', 'C/Luis Vives 25', 'Móstoles','915577545');

INSERT INTO NOTAS VALUES('12344345', 1,6);


INSERT INTO NOTAS VALUES('12344345', 2,5);
INSERT INTO NOTAS VALUES('12344345', 3,6);

INSERT INTO NOMBRES VALUES('PEDRO', 17);


INSERT INTO NOMBRES VALUES('JUAN', 17);
INSERT INTO NOMBRES VALUES('MARÍA', 16);
DROP TABLE... CASCADE CONSTRAINTS

b) Ejemplos de eliminación de tablas.

REM*** EJEMPLOS DE ELIMINACION DE TABLAS


REM=====================================

DROP TABLE DEPART cascade constraints;


DROP TABLE EMPLE cascade constraints;

Drop table notas_alumnos cascade constraints;


Drop table LIBRERIA cascade constraints;
DROP TABLE ALUMNOS cascade constraints;
DROP TABLE ASIGNATURAS cascade constraints;
DROP TABLE NOTAS cascade constraints;

DROP TABLE NOMBRES cascade constraints;


DROP TABLE MISTEXTOS cascade constraints;
DROP TABLE LIBROS cascade constraints;
DROP TABLE NACIMIENTOS cascade constraints;

DROP TABLE PARALEER cascade constraints;


DROP TABLE LEIDOS cascade constraints;

DROP TABLE ALUM cascade constraints;


DROP TABLE NUEVOS cascade constraints;
DROP TABLE ANTIGUOS cascade constraints;

DROP TABLE PERSONAL cascade constraints;


DROP TABLE PROFESORES cascade constraints;
DROP TABLE CENTROS cascade constraints;

DROP TABLE EMPLE30 cascade constraints;


DROP TABLE COCHES cascade constraints;
INSERT, DROP Y UPDATE MEDIANTE SELECT

c) Ejemplos de Inserción, eliminación y actualización mediante consultas.

1- Dadas las tablas ALUM y NUEVOS, insertar en la tabla ALUM los nuevos alumnos.

INSERT INTO ALUM (SELECT * FROM NUEVOS MINUS SELECT * FROM ALUM);

2- Borrar de la tabla ALUM los ANTIGUOS alumnos.

DELETE FROM ALUM WHERE NOMBRE IN (SELECT NOMBRE FROM ANTIGUOS);

3- Insertar a un empleado de apellido 'SAAVEDRA' con número 2000. La fecha de alta


será la actual, el SALARIO será el mismo salario de 'SALA' mas el 20 por 100 y el resto
de datos serán los mismos que los datos de 'SALA'.

INSERT INTO EMPLE (SELECT 2000,'SAAVEDRA',OFICIO,DIR,SYSDATE,SALARIO +


SALARIO*0.2,COMISION,DEPT_NO FROM EMPLE WHERE
APELLIDO LIKE 'SALA');

4- Modificar el número de departamentos de 'SAAVEDRA'. El nuevo departamento será


el departamento donde hay más empleados cuyo oficio sea 'EMPLEADO'

UPDATE EMPLE SET DEPT_NO = (SELECT DEPT_NO FROM EMPLE WHERE OFICIO LIKE
'EMPLEADO' GROUP BY DEPT_NO HAVING COUNT (*)
= (SELECT MAX(COUNT(*)) FROM EMPLE WHERE OFICIO LIKE 'EMPLEADO' GROUP BY
DEPT_NO)) WHERE APELLIDO LIKE 'SAAVEDRA';

5- Borrar todos los departamentos de la tabla DEPART para los cuales no existan
empleados en emple.

DELETE FROM DEPART WHERE DEPT_NO IN (SELECT DEPT_NO FROM DEPART MINUS
SELECT DEPT_NO FROM EMPLE);

6- Modificar el número de plazas con un valor igual a la mitad en aquellos centros con
menos de dos profesores.

UPDATE CENTROS SET NUM_PLAZAS = NUM_PLAZAS/2 WHERE COD_CENTRO IN


(SELECT COD_CENTRO FROM PROFESORES GROUP BY COD_CENTRO
HAVING COUNT(*)<2);

7- Eliminar los centros que no tengan personal.

DELETE CENTROS WHERE COD_CENTRO IN (SELECT COD_CENTRO FROM CENTROS


MINUS SELECT COD_CENTRO FROM PERSONAL);
8- Añadir un profesor en el centro o en los centros cuyo número de administrativos sea
2en la especialidad de 'IDIOMA', con DNI 8790055 y de nombre 'Clara Salas'.

INSERT INTO PROFESORES SELECT DISTINCT COD_CENTRO,


8790055,'SALAS,CLARA','IDIOMA' FROM PERSONAL WHERE COD_CENTRO IN
(SELECT COD_CENTRO FROM PERSONAL WHERE FUNCION = 'ADMINISTRATIVO'
GROUP BY COD_CENTRO HAVING COUNT(*) = 1);

9- Borrar al personal que esté en centros de menos de 300 plazas y con menos de dos
profesores.

DELETE PERSONAL WHERE COD_CENTRO IN (SELECT COD_CENTRO FROM CENTROS WHERE


NUM_PLAZAS<300) AND COD_CENTRO IN
(SELECT COD_CENTRO FROM PROFESORES GROUP BY COD_CENTRO HAVING COUNT(*)<2);

10- Borrar a los profesores que estén en la tabla PROFESORES y que no estén en la
tabal PERSONAL.

DELETE PROFESORES WHERE DNI NOT IN (SELECT DNI FROM PERSONAL);

11- Dar de alta un artículo de 'Primera' categoría para los fabricantes de 'Francia' y
abastecer con 5 unidades de ese artículo a todas las tiendas y en la fecha de hoy.

INSERT INTO ARTICULOS SELECT 'YOGUR FRESA', COD_FABRICANTE, 4, 'PRIMERA',


120,100,190 FROM FABRICANTES WHERE PAIS = 'FRANCIA';

SELECT NIF, 'YOGUR FRESA', COD_FABRICANTE, 4, 'PRIMERA', SYSDATE, 5 FROM


TIENDAS, FABRICANTES WHERE PAIS LIKE 'FRANCIA';

12- Insertar un pedido de 20 unidades en la tienda '111-A' con el artículo que mayor
número de ventas haya realizado.

INSERT INTO PEDIDOS SELECT DISTINCT '1111-A', ARTICULO, COD_FABRICANTE, PESO,


CATEGORIA, SYSDATE, 20 FROM VENTAS
WHERE (ARTICULO, COD_FABRICANTE,PESO,CATEGORIA) IN (SELECT
ARTICULO,COD_FABRICANTE,PESO,CATEGORIA FROM VENTAS GROUP BY
ARTICULO, COD_FABRICANTE, PESO, CATEGORIA HAVING COUNT (*) = (SELECT
MAX(COUNT(*)) FROM VENTAS GROUP BY ARTICULO,
COD_FABRICANTE, PESO, CATEGORIA));

13- Dar de alta una tienda en la provincia de 'MADRID' y abasteerla con 20 unidades de
cada uno de los artículos existentes.

INSERT INTO TIENDAS VALUES ('1010-C', 'LA CESTA', 'C/JUAN MAZO 30',
'ALCALA','MADRID',28809);

INSERT INTO PEDIDOS SELECT '1010-C',ARTICULO, COD_FABRICANTE, PESO,


CATEGORIA, SYSDATE, 20 FROM ARTICULOS;
14- Dar de alta dos tiendas en la provincia de 'SEVILLA' y abastecerlas con 30 unidades
de artículos de la marca 'GALLO'

INSERT INTO TIENDAS VALUES('4501-B','LA ECONÓMICA','C\SEVILLANAS 130','DOS


HEMANAS','SEVILLA',44003);

INSERT INTO TIENDAS VALUES('4501-B','COMETIBLES PETER','C\SEVILLANAS 130','DOS


HEMANAS','SEVILLA',44009);

INSERT INTO PEDIDOS SELECT


NIF,ARTICULO,A.COD_FABRICANTE,PESO,CATEGORIA,SYSDATE,30 FROM
TIENDAS,ARTICULOS A, FABRICANTES F
WHERE PROVINCIA='SEVILLA' AND F.NOMBRE='GALLO' AND
A.COD_FABRICANTE=F.COD_FABRICANTE;

15- Realizar una venta para todas las tiendas de 'TOLEDO' de 10 unidades en los
artículos de 'Primera' categoría.

INSERT INTO VENTAS SELECT


NIF,ARTICULO,COD_FABRICANTE,PESO,CATEGORIA,SYSDATE,10 FROM
TIENDAS,ARTICULOS WHERE PROVINCIA='TOLEDO' AND CATEGORIA='PRIMERA';

16- Para aquellos artículos de los que se hayan vendido más de 30 unidades, realizar un
pedido de 10 unidades para la tienda
con NIF '5555-B' con la fecha actual.

INSERT INTO PEDIDOS SELECT DISTINCT '5555-


B',ARTICULO,COD_FABRICANTE,PESO,CATEGORIA,SYSDATE,10FROM VENTAS WHERE
(ARTICULO,COD_FABRICANTE,PESO,CATEGORIA)IN (SELECT
ARTICULO,COD_FABRICANTE,PESO,CATEGORIA FROM VENTAS GROUP BY ARTICULO,
COD_FABRICANTE,PESO,CATEGORIA HAVING SUM(UNIDADES_VENDIDAS)<30);

17- Cambiar los datos de la tienda con NIF '1111-A' igualandolos a los de la tienda NIF
'2222-A'.

UPDATE TIENDAS
SET(NOMBRE,DIRECCIÓN,POBLACIÓN,PROVINCIA,CODPOSTAL)=(SELECT
NOMBRE,DIRECCIÓN,POBLACIÓN,PROVINCIA,
CODPOSTAL FROM TIENDAS WHERE PAIS='ITALIA');

18- Cambiar todos los artículos de 'Primera' categoria a 'Segunda' categoria del pais
'ITALIA'.

UPDATE ARTICULOS SET CATEGORIA='Segunda'


WHERE CATEGORIA='Primera'
AND COD_FABRICANTE = (SELECT COD_FABRICANTE FROM FABRICANTES
WHERE PAIS='ITALIA');
19- Modificar aquellos pedidos en los que la cantidad pedida sea superior a las
existencias del artículo, asignando el 20% de las existencias a la cantidad que se ha
pedido.

UPDATE PEDIDOS P
SET UNIDADES_PEDIDAS=
(SELECT EXISTENCIAS*0.2 FROM ARTICULOS WHERE
ARTICULO=P. ARTICULO AND
COD_FABRICANTE=P. COD_FABRICANTE AND
PESO=P. PESO AND
CATEGORIA=P. CATEGORIA )
WHERE UNIDADES_PEDIDAS >
(SELECT EXISTENCIAS FROM ARTICULOS WHERE
ARTICULO=P. ARTICULO AND
COD_FABRICANTE=P. COD_FABRICANTE AND
PESO=P. PESO AND
CATEGORIA=P. CATEGORIA);

20- Eliminar aquellas tiendas que no han realizado ventas.

DELETE TIENDAS
WHERE NIF NOT IN (SELECT DISTINCT NIF FROM VENTAS);

21- Eliminar los artículos que no hayan tenido ni compras ni ventas.

DELETE ARTICULOS
WHERE (ARTICULO, COD_FABRICANTE, PESO, CATEGORIA)
NOT IN (SELECT DISTINCT ARTICULO, COD_FABRICANTE, PESO,
CATEGORIA FROM VENTAS)
AND (ARTICULO, COD_FABRICANTE, PESO, CATEGORIA)
NOT IN (SELECT DISTINCT ARTICULO, COD_FABRICANTE, PESO,
CATEGORIA FROM PEDIDOS);

22- Borrar los pedidos de 'Primera' categoria cuyo pais de procedencia sea 'BELGICA'.

DELETE PEDIDOS
WHERE (ARTICULO, COD_FABRICANTE, PESO, CATEGORIA)
IN
(SELECT ARTICULO, COD_FABRICANTE, PESO, CATEGORIA
FROM ARTICULOS WHERE COD_FABRICANTE=
(SELECT COD_FABRICANTE FROM FABRICANTES WHERE PAIS ='BELGICA'))
AND CATEGORIA='Primera';

23- Borrar los pedidos que no tengan tienda.

DELETE PEDIDOS WHERE NIF NOT IN(SELECT NIF FROM TIENDAS);


24- Restar uno a las unidades de los últimos pedidos de la tienda con NIF '5555-B'.

UPDATE PEDIDOS SET UNIDADES_PEDIDAS=UNIDADES_PEDIDAS-1


WHERE NIF='5555-B' AND FECHA_PEDIDO=
(SELECT MAX(FECHA_PEDIDO) FROM PEDIDOS WHERE NIF='5555-B');

CREATE TABLE...,ALTER TABLE...

d) Ejemplos de creación de tablas y modificación de las tablas.

1. Crear la tabla fabricantes con las siguientes condiciones:


- la clave primaria es cod_fabricante
- las columnas nombre y pais han de almacenarse en mayuculas

CREATE TABLE FABRICANTES(


COD_FABRICANTE NUMBER(3) CONSTRAINT PK_FA PRIMARY KEY,
NOMBRE VARCHAR2(15)
CONSTRAINT CK_NO CHECK(NOMBRE=UPPER(NOMBRE)),
PAIS VARCHAR2(15)
CONSTRAINT CK_PA CHECK(PAIS=UPPER(PAIS))
);

2. Crear la tabla articulos con las siguientes condiciones:


- la clave primaria esta formada por las columnas: articulo, cod_fabricante,pero y
categoria.
- cod_fabricante es clave ajena que referencia a la tabla fabricantes.
- precio_venta, precio_costo han de ser >0.
- categoria ha de ser 'primera','segunda ' o 'tercera'.

CREATE TABLE ARTICULOS( ARTICULO


VARCHAR2(20)NOT NULL,
COD_FABRICANTE NUMBER(3) NOT NULL,
PESO NUMBER(3) NOT NULL
CONSTRAINT CK1_AR CHECK (PESO>0),
CATEGORIA VARCHAR2(10) NOT NULL,
PRECIO_VENTA NUMBER (4)
CONSTRAINT CK2_AR CHECK (PRECIO_VENTA>0),
PRECIO_COSTO NUMBER (4)
CONSTRAINT CK3_AR CHECK (PRECIO_COSTO>0),
EXISTENCIAS NUMBER (5),
CONSTRAINT PK_ART PRIMARY KEY
(ARTICULO, COD_FABRICANTE, PESO, CATEGORIA),
CONSTRAINT FK_ARFA FOREIGN KEY (COD_FABRICANTE) REFERENCES FABRICANTES,
CONSTRAINT CK_CAT CHECK(CATEGORIA IN('Primera','Segunda', 'Tercera'))
);
3. Crear la tabla tiendas con las siguientes condiciones:
- la clave primaria es NIF
- provincia ha de almacenarse en mayuculas.

CREATE TABLE TIENDAS(


NIF VARCHAR2(10) NOT NULL CONSTRAINT PK_TI PRIMARY KEY,
NOMBRE VARCHAR2(20),
DIRECCIÓN VARCHAR2(20),
POBLACIÓN VARCHAR2(20),
PROVINCIA VARCHAR2(20)
CONSTRAINT CK_PRO CHECK(PROVINCIA=UPPER(PROVINCIA)),
CODPOSTAL NUMBER(5)
);

4. Crear la tabla pedidos con las siguientes condiciones:


- la clave primaria esta formada por las columnas:NIF,
articulo,cod_fabricante,peso,categoria y fecha de pedido.
- cod_febricante es clave ajena que referencia a la tabla fabricantes.
- unidades pedidas ha de ser: >0
- categoria ha de ser 'primera','segunda ' o 'tercera'.
- las columnas articulo, cod_fabricante, peso y categoria son clave ajena y referencia a
la tabla articulos.Realizar un borrado en cascada.
- NIf es clave ajena y refencia a la tabla tiendas.

CREATE TABLE PEDIDOS(


NIF VARCHAR2(10) NOT NULL
CONSTRAINT FK_PETI REFERENCES TIENDAS,
ARTICULO VARCHAR2(20) NOT NULL,
COD_FABRICANTE NUMBER(3) NOT NULL
CONSTRAINT FK_PEFA REFERENCES FABRICANTES,
PESO NUMBER(3) NOT NULL,
CATEGORIA VARCHAR2(10) NOT NULL,
FECHA_PEDIDO DATE NOT NULL,
UNIDADES_PEDIDAS NUMBER(4)
CONSTRAINT CK_PEUP CHECK (UNIDADES_PEDIDAS>0),
CONSTRAINT PK_PED PRIMARY KEY
(NIF,ARTICULO, COD_FABRICANTE, PESO, CATEGORIA, FECHA_PEDIDO),
CONSTRAINT CK_CATPE CHECK(CATEGORIA IN('Primera','Segunda','Tercera')),
CONSTRAINT FK_PEAR FOREIGN KEY
(ARTICULO, COD_FABRICANTE, PESO, CATEGORIA) REFERENCES ARTICULOS
ON DELETE CASCADE
);
5. Crear la tabla ventas con las siguientes condiciones:
- la clave primaria esta formada por la por las columnas: nif,
articulo,cod_fabricantepeso,categoria y fecha venta.
- cod fabricante es clave ajena que referencia a la tabla fabricantes.
- unidades_vendidas ha de ser >0
- categoria ha de ser 'primera','segunda ' o 'tercera'.
- Las columnas articulo, cod_fabricante, peso, y categoria son clave ajena y referencia
de la tabla articulos. Realizar un borrado en cascada.
- NIF es clave ajena y referencia a la tabla tiendas

CREATE TABLE VENTAS(


NIF VARCHAR2(10) NOT NULL
CONSTRAINT FK_VETI REFERENCES TIENDAS,
ARTICULO VARCHAR2(20) NOT NULL,
COD_FABRICANTE NUMBER(3) NOT NULL
CONSTRAINT FK_VEFA REFERENCES FABRICANTES,
PESO NUMBER(3) NOT NULL,
CATEGORIA VARCHAR2(10) NOT NULL
CONSTRAINT CK_CATVE
CHECK(CATEGORIA IN('Primera','Segunda','Tercera')),
FECHA_VENTA DATE NOT NULL,
UNIDADES_VENDIDAS NUMBER(4)
CONSTRAINT CK_VEUV CHECK (UNIDADES_VENDIDAS>0),
CONSTRAINT PK_VEN PRIMARY KEY
(NIF,ARTICULO, COD_FABRICANTE, PESO, CATEGORIA, FECHA_VENTA),
CONSTRAINT FK_VEAR FOREIGN KEY
(ARTICULO, COD_FABRICANTE, PESO, CATEGORIA) REFERENCES ARTICULOS
ON DELETE CASCADE
);

6. Añadir una restricción a la tabla tiendas para que el nombre de la tienda sea de tipo
título

ALTER TABLE TIENDAS ADD CONSTRAINT


NOMBRETITU CHECK (NOMBRE=INITCAP(NOMBRE));

7. Visualizar las constraint definidas para las tablas anteriores.

SELECT TABLE_NAME, CONSTRAINT_NAME FROM USER_CONSTRAINTS


WHERE TABLE_NAME IN('ARTICULOS','TIENDAS', 'FABRICANTES', 'PEDIDOS'
,'VENTAS');

8. Modificar las columnas de las tablas pedidos y ventas para que las unidades
vendidas y las unidades pedidas puedan almacenar cantidades numericas de 6 dígitos.

ALTER TABLE PEDIDOS MODIFY (UNIDADES_PEDIDAS NUMBER(6));

ALTER TABLE VENTAS MODIFY (UNIDADES_VENDIDAS NUMBER(6));


9. Impedir que se den mas den de alta mas tiendas en la provindia de toledo.

ALTER TABLE TIENDAS ADD CONSTRAINT CK_TIENTO


CHECK (PROVINCIA !='TOLEDO');

10. Añadir a las tablas pedidos y ventas una nueva columna para que almacenen el pvp
del artículo.

ALTER TABLE PEDIDOS ADD(PVP NUMBER(4));

ALTER TABLE VENTAS ADD(PVP NUMBER(4));

TABLAS PERSONAL, PROFESORES y CENTROS:

11. Añadir a la tabla profesores una columna llamada cod_asig con dos posiciones
numéricas.

ALTER TABLE PROFESORES ADD(COD_ASIG NUMBER(2));

12. Crear la tabla tasig con las siguientes columnas: cod_asig numerico, 2 posiciones y
nom_asig cadena de 20 caracteres.

CREATE TABLE TASIG (


COD_ASIG NUMBER(2),
NOM_ASIG VARCHAR2(20) );

13. Añadir la restricción de clave primaria a la columna cod_asig de la tabla tasig.

ALTER TABLE TASIG


ADD CONSTRAINT PK_TASIG PRIMARY KEY (COD_ASIG);

14. Añadir la restricción de la clave ajena a la columna cod_asig de la tabla profesores.

ALTER TABLE PROFESORES


ADD CONSTRAINT FK_TASIG FOREIGN KEY (COD_ASIG) REFERENCES TASIG;

15. Visualizar los nombres de las constraint y las columnas afectadas de las tablas tasig
y profesores.

SELECT TABLE_NAME, CONSTRAINT_NAME, COLUMN_NAME


FROM USER_CONS_COLUMNS WHERE TABLE_NAME IN('TASIG','PROFESORES');

16. Cambiar los nombres de las tablas profesores y llamarlas profes

RENAME PROFESORES TO PROFES;


17. Borrar la tabla tasig

DROP TABLE TASIG CASCADE CONSTRAINTS;

18. Devolver la tabla profesores a su situación inicial

CREATE TABLE PROFESORES AS


SELECT COD_CENTRO, DNI, APELLIDOS, ESPECIALIDAD
FROM PROFES;

CREATE VIEW...AS...

a) Ejemplos de creación de vistas mediante consultas así como de sinónimos.

1º) Crear una vista que se llame conserjes que contenga el nombre del centro y el
nombre de sus conserjes.

CREATE VIEW CONSERJES AS


SELECT NOMBRE,APELLIDOS FROM CENTROS , PERSONAL
WHERE FUNCION='CONSERJE'
AND CENTROS.COD_CENTRO=PERSONAL.COD_CENTRO;

2º) Crear un sinonimo asociado a la vista creada anteriormente llamado conser


CREATE SYNONYM CONSER FOR CONSERJES;

CREATE VIEW...AS...

b) Ejemplos de operaciones sobre vistas.

1º) Crear una vista que se llame dep30 que contiene el apellido, oficio y el salario de los
empleados de la tabla emple del departamento 30.

CREATE VIEW DEP30 AS SELECT APELLIDO, OFICIO ,SALARIO FROM EMPLE WHERE
DEPT_NO=30;

2º) Hacer una descripción de la vista creada anteriormente.

DESC DEP30;

3º) Hacer una consulta que muestre el contenido de la vista dep30.

SELECT * FROM DEP30;


4º) Crear una vista o reemplazarla dando nombre a las columnas ape, ofi y sal:

CREATE OR REPLACE VIEW DEP30 (APE, OFI , SAL) AS SELECT APELLIDO, OFICIO
,SALARIO FROM EMPLE WHERE DEPT_NO=30;

5º) Hacer una consulta de las vistas creadas junto con sus textos:

SELECT VIEW_NAME, TEXT FROM USER_VIEWS;

DROP VIEW...UPDATE...SELECT...

c) Ejemplos borrados, inserciones y consultas sobre vistas.

1º) Borrar la vista dep30

DROP VIEW DEP30;

2º) consultar los apellidos de los vendedores dela vista dep30:

SELECT APE FROM DEP30 WHERE OFI='VENDEDOR';

3º) Modificar la vista dep30, modificamos el apellido 'MARTIN', almacenandolo


en minucuslas y cambiamos el salario a 200000;

UPDATE DEPT30 SET APE='MARTIN', SAL=200000 WHERE APE='MARTIN';

4º) Consultamos la vista y la tabla asocidad para comprobar los resultados.

SELECT APE, SAL FROM DEP30 WHERE APE='MARTIN';

SELECT APELLIDO, SALARIO FROM EMPLE WHERE APELLIDO='MARTIN';

5º) Crear una vista a partir de la tabla depart

CREATE VIEW VDEP AS SELECT DEPT_NO, DNOMBRE FROM DEPART;

6º) insertar valores en la vista vdep.

INSERT INTO VDEP VALUES (66,'DESARROLLO');

7º) borramos el departamento 66 y observamos como este departamento desaparece


de la tabla depart.

DELETE VDEP WHERE DEPT_NO = 66;


8º) A partir de las tablas depart y emple creamos una vista que contenga el emp_no,
apellido, dept_no y dnombre.

CREATE VIEW DEPT_EMP(EMP_NO, APELLIDO, DEPT_NO ,DNOMBRE)


AS SELECT EMP_NO, APELLIDO, EMPLE.DEPT_NO, DNOMBRE FROM EMPLE , DEPART
WHERE EMPLE.DEPT_NO=DEPART.DEPT_NO;

9º) Insertar una fila en la vista creada

INSERT INTO DEPT_EMP VALUES(2222,'SUELA',20,'INVESTIGACIÓN');

LISTADOS

1.- Ejemplos de creación informes.

A partir de las tablas emple y depart, hacer un listado en el que se produzca una suma
de salarios por localidad y dentro de la localidad una suma de salarios por oficios.
- el titulo superios de la lista es: LISTADO DE LOS EMPLEADOS DE LA TABLA EMPLE
- El titulo inferior del listado es:Con ruptura por departamento y por oficio calculando
totales
- La cabecera estara formada por los siguientes titulos: Localidad, apellidos, Nº de
empleado, oficio, salario y comisión.

ALTER SESSION SET NLS_NUMERIC_CHARACTERS=',.';


REM Nombre : LISTADO3.SQL
REM Descripción: Listado de Empleados.

TTITLE 'LISTADO DE LOS EMPLEADOS DE LA TABLA EMPLE' skip 2


BTITLE 'Con ruptura por departamento y por oficio calculando totales' skip 2

COLUMN LOC HEADING 'Localidad' COLUMN


APELLIDO HEADING 'Apellidos' COLUMN
EMP_NO HEADING 'Nº de empleado' COLUMN
OFICIO HEADING 'Oficio'
COLUMN SALARIO HEADING 'Salario' FORMAT 9G999G999
COLUMN COMISION HEADING 'Comisión' FORMAT 9G999G999

BREAK ON LOC SKIP 2 ON OFICIO SKIP 1


COMPUTE SUM LABEL'Suma por loc.' OF SALARIO ON LOC
COMPUTE SUM LABEL'Sum por ofi.' OF SALARIO ON oficio

SET LINESIZE 79
SET PAGESIZE 45
SET NEWPAGE 0

SPOOL LISTADO3.LST
SELECT LOC, APELLIDO, EMP_NO, OFICIO, SALARIO, COMISION
FROM EMPLE, DEPART
WHERE EMPLE.DEPT_NO=DEPART.DEPT_NO
ORDER BY LOC, OFICIO;

TTITLE OFF
BTITLE OFF
CLEAR BREAKS
CLEAR COMPUTES
CLEAR COLUMNS
SPOOL OFF

FORMATEAR LISTADOS

2 .- Ejemplos de creación de informes dando formatos.

Realizar un informe en el que aparezca por cada departamento el


salario maximo, el minimo, el total junto con la media y el numero
de empleados.
- el titulo superios de la lista es: RESUMEN DEPARTAMENTAL

REM Nombre : LISTADO5.SQL


REM Descripción: RESUMEN DEPARTAMENTAL

SET HEADSEP |
TTITLE CENTER 'RESUMEN DEPARTAMENTAL' skip 2

COLUMN DNOMBRE HEADING 'Nombre|Departamento'


COLUMN MAXIMO HEADING 'Máximo|Salario' FORMAT 9,999,999
COLUMN MINIMO HEADING 'Mínimo|Salario' FORMAT 9,999,999
COLUMN SUMA HEADING 'Suma|Salarios' FORMAT 9,999,999
COLUMN MEDIO HEADING 'Salario|Medio' FORMAT 9,999,999
COLUMN CUENTA HEADING 'Número|Empleados' FORMAT 9,999

SET LINESIZE 79
SET PAGESIZE 60
SET NEWPAGE 0

SPOOL LISTADO5.LST

SELECT DNOMBRE, max(salario) MAXIMO, min(salario) MINIMO, sum(salario) SUMA,


avg(salario) MEDIO, count(*) CUENTA
FROM EMPLE, DEPART
WHERE EMPLE.DEPT_NO=DEPART.DEPT_NO
GROUP BY DNOMBRE;
TTITLE OFF
BTITLE OFF
CLEAR BREAKS
CLEAR COMPUTES
CLEAR COLUMNS
SPOOL OFF

ACCEPT...PROMPT

3 .- Ejemplosde creación de informes introduciendo parámetros de entrada para


generar el informe

Obtener el listado anterior formateando las salidas numericas de


tal forma que el punto represente los miles y la coma los decimales.

ALTER SESSION SET NLS_NUMERIC_CHARACTERS=',.';

REM Nombre : LISTADO6.SQL


REM Descripción: RESUMEN DEPARTAMENTAL

SET HEADSEP |
TTITLE CENTER 'RESUMEN DEPARTAMENTAL' skip 2

COLUMN DNOMBRE HEADING 'Nombre|Departamento'


COLUMN MAXIMO HEADING 'Máximo|Salario' FORMAT 9G999G999D99
COLUMN MINIMO HEADING 'Mínimo|Salario' FORMAT 9G999G999D99
COLUMN SUMA HEADING 'Suma|Salarios' FORMAT 9G999G999D99
COLUMN MEDIO HEADING 'Salario|Medio' FORMAT 9G999G999D99
COLUMN CUENTA HEADING 'Número|Empleados' FORMAT 9G999
SET LINESIZE 90
SET PAGESIZE 60
SET NEWPAGE 0
SPOOL LISTADO6.LST
SELECT DNOMBRE, max(salario) MAXIMO, min(salario) MINIMO, sum(salario) SUMA,
avg(salario) MEDIO, count(*) CUENTA
FROM EMPLE, DEPART
WHERE EMPLE.DEPT_NO=DEPART.DEPT_NO
GROUP BY DNOMBRE;

TTITLE OFF
BTITLE OFF
CLEAR COMPUTES
CLEAR COLUMNS
SPOOL OFF
Hacer el mismo informe que se pide en el ejercicio 2, con la diferencia
que nos pida introducir por teclado el nombre del departamento que se va a listar.
No se han de obtener los calculos por report ni imprimir el titulo inferior.

REM Nombre : LISTADO7.SQL


REM Descripción: Listado de SALARIOS - INTRODUCIMOS DEPARTAMENTO
SET HEADSEP |
TTITLE CENTER 'LISTADO DE LOS SALARIOS DE LOS EMPLEADOS' skip 2
COLUMN DNOMBRE HEADING 'Nombre|Departamento'
COLUMN APELLIDO HEADING 'Apellido'
COLUMN SALARIO HEADING 'Salario' FORMAT 9,999,999

BREAK ON DNOMBRE SKIP 1


COMPUTE SUM MAX MIN AVG OF SALARIO ON DNOMBRE
SET LINESIZE 79
SET PAGESIZE 30
SET NEWPAGE 0
SPOOL LISTADO7.LST

ACCEPT NOM PROMPT "Nombre de departamento a listar:"


SELECT DNOMBRE, APELLIDO, SALARIO FROM EMPLE, DEPART
WHERE EMPLE.DEPT_NO=DEPART.DEPT_NO AND DNOMBRE='&NOM'
ORDER BY DNOMBRE;

TTITLE OFF
BTITLE OFF
CLEAR BREAKS
CLEAR COMPUTES
CLEAR COLUMNS
SPOOL OFF
CREATE TABLESPACE...

a) Ejemplos de creación de tablespaces.

1º) Crear un tablespace de nombre COMPRAS asociandole un fichero en disco llamado


COMPRAS.ORA de 5 Mb.

CREATE TABLESPACE COMPRAS DATAFILE 'COMPRAS.ORA' SIZE 5M;

2º) Modificar el tablespace del ejercicio1 para que pueda autoextenderse


automaticamente sin limite de espacio en el disco.

ALTER TABLESPACE COMPRAS ADD DATAFILE 'COMPRAS1.ORA' SIZE 1M


AUTOEXTEND ON NEXT 1M MAXSIZE UNLIMITED;

CREATE USER...

b) Ejemplos de creación de usuarios.

3º) Crear un rol que tenga los siguientes privilegios, insert select
en depart y emple, create session, create database link, create table
y create view.

CREATE ROLE UN_ROL;


GRANT INSERT, SELECT ON DEPART TO UN_ROL;
GRANT INSERT, SELECT ON EMPLE TO UN_ROL;
GRANT CREATE SESSION, CREATE DATABASE LINK,CREATE TABLE, CREATE VIEW TO
UN_ROL;

4º) Crea un usuario llamado 'COMPRADOR'. El tableespace por defecto es 'COMPRAS'


y se le asigna un mega en el tableespace COMPRAS y 0 de cuota en el tablespace
SYSTEM. El tablespace temporl sera TEMPORARY_DATA. Se le asigna un rol anterior.

CREATE USER COMPRADOR IDENTIFIED BY COMPRADOR


DEFAULT TABLESPACE COMPRAS TEMPORARY TABLESPACE TEMPORARY_DATA
QUOTA 1M ON COMPRAS QUOTA 0 ON SYSTEM;

GRANT UN_ROL TO COMPRADOR;


GRANT... CONNECT... CREATE ROLE...

c) Ejemplos de usuarios con derechos de administración, roles...

5º)Realiza la siguiente secuencia de instrucciones en el orden indicado:


- Crear un usuario de la BD que tenga funciones de administrador

CREATE USER ADMINISTRADOR IDENTIFIED BY ADMINISTRADOR;

GRANT DBA TO ADMINISTRADOR;

- conectarse con el nombre del usuario creado

CONNECT ADMINISTRADOR@DAINT

- crear varias tablas en el propio esquema

CREATE TABLE TABLA1 (N NUMBER(10));


CREATE TABLE TABLA2 (N NUMBER(10));
CREATE TABLE TABLA3 (N NUMBER(10));

- Crear 5 usuarios nuevos asignandoles un tablespace por defecto y cuota en


(USU1,USU2, USU3...5).

CREATE USER USU1 IDENTIFIED BY USU1 DEFAULT TABLESPACE COMPRAS


QUOTA 2M ON COMPRAS;

CREATE USER USU2 IDENTIFIED BY USU2 DEFAULT TABLESPACE COMPRAS


QUOTA 2M ON COMPRAS;

CREATE USER USU3 IDENTIFIED BY USU3 DEFAULT TABLESPACE COMPRAS


QUOTA 2M ON COMPRAS;

CREATE USER USU4 IDENTIFIED BY USU4 DEFAULT TABLESPACE COMPRAS


QUOTA 2M ON COMPRAS;

CREATE USER USU5 IDENTIFIED BY USU5 DEFAULT TABLESPACE COMPRAS


QUOTA 2M ON COMPRAS;

- Dar permiso al usuario USU1 solo para q pueda conectarse a la BD.

GRANT CREATE SESSION TO USU1;


- Crear un rol q permita conectarse a la bd y hacer SELECT sobre algunas tablas.

CREATE ROLE ROL_USU;


GRANT CREATE SESSION TO ROL_USU;
GRANT SELECT ON TABLA1 TO ROL_USU;
GRANT SELECT ON TABLA2 TO ROL_USU;
GRANT SELECT ON TABLA3 TO ROL_USU;

- Conceder al USU4 privilegios sobre qalgunas tablas con la opción de poder


concederselos a otros usuarios.

GRANT ROL_USU TO USU2, USU3;

- Conceder al usuario USU5 cuatro privilegios del sistema, dos de ellos, con la opción de
poder concederselos a otros usuarios.

GRANT INSERT, DELETE ON TABLA1 TO USU4 WITH GRANT OPTION;


GRANT INSERT, DELETE ON TABLA2 TO USU4 WITH GRANT OPTION;

- Conceder a todos los usuarios de la BD privilegios para q puedan modificar ciertas


columnas de algunas tablas.

GRANT CREATE ANY TABLE,CREATE USER TO USU5 WITH ADMIN OPTION;


GRANT ALTER TABLESPACE, CREATE TABLESPACE TO USU5;

GRANT UPDATE(N) ON TABLA1 TO PUBLIC;


GRANT UPDATE(N) ON TABLA2 TO PUBLIC;

- Quitar a los usuarios USU3 y USU4 todos los privilegios q tenían asignados.

REVOKE ROL_USU FROM USU3;


REVOKE ALL ON TABLA1 FROM USU4;
REVOKE ALL ON TABLA2 FROM USU4;

- Hacer q USU5 solo pueda conectarse en dos sesiones concurrentes a la vez.

CREATE PROFILE LIM_SESION LIMIT SESSIONS_PER_USER 2;


ALTER USER USU5 IDENTIFIED BY USU5 PROFILE LIM_SESION;

- Limitar el tiempo de conexión a la BD a 5 minutos a los usuarios USU2 y USU3.

CREATE PROFILE TIEMPOLIMITE LIMIT CONNECT_TIME 5;


ALTER USER USU2 IDENTIFIED BY USU2 PROFILE TIEMPOLIMITE;
ALTER USER USU3 IDENTIFIED BY USU3 PROFILE TIEMPOLIMITE;
DECLARE...BEGIN...END

a) Ejemplos de creación de un bloque PL/SQL.

1.- Escribir un bloque PL/SQL que escriba el texto ‘Hola’

SQL> BEGIN
2 DBMS_OUTPUT.PUT_LINE('HOLA');
3 END;
4/

SAVE...

b) Ejemplos de como guardar un bloque PL/SQL.

2.- Escribir un bloque PL/SQL que cuente el número de filas que hay en la tabla
productos, deposita el resultado en la variable v_num, y visualiza su contenido.

SQL>DECLARE
2 v_num NUMBER;
3 BEGIN
4 SELECT count(*) INTO v_num
5 FROM productos;
6 DBMS_OUTPUT.PUT_LINE(v_num);
7 END;
8/

START...,GET...,RUN

c) Ejemplos como ejecutar o arrancar un bloque PL/SQL.

3.- Cargar y ejecutar el bloque guardado en el archivo PROG01.SQL de la unidad A.

SQL> START A:\PROG01.SQL

O bien:
SQL> GET A:\PROG01.SQL
SQL> RUN
CREATE OR REPLACE PROCEDURE...

1.- Ejemplos de creación procedimientos.

1) Escribir un procedimiento que reciba dos números y visualice su suma.

CREATE OR REPLACE PROCEDURE sumar_numeros (


num1 NUMBER,
num2 NUMBER)
IS
suma NUMBER(6);
BEGIN
suma := num1 + num2;
DBMS_OUTPUT.PUT_LINE('Suma: '|| suma);
END sumar_numeros;

2) Codificar un procedimiento que reciba una cadena y la visualice al revés.

CREATE OR REPLACE PROCEDURE cadena_reves(


vcadena VARCHAR2)
AS
vcad_reves VARCHAR2(80);
BEGIN
FOR i IN REVERSE 1..LENGTH(vcadena) LOOP
vcad_reves := vcad_reves || SUBSTR(vcadena,i,1);
END LOOP;
DBMS_OUTPUT.PUT_LINE(vcad_reves);
END cadena_reves;

3) Escribir una función que reciba una fecha y devuelva el año, en número,
correspondiente a esa fecha.

CREATE OR REPLACE FUNCTION anio (


fecha DATE)
RETURN NUMBER
AS
v_anio NUMBER(4);
BEGIN
v_anio := TO_NUMBER(TO_CHAR(fecha, 'YYYY'));
RETURN v_anio;
END anio;
CREATE OR REPLACE FUNCTION....

2 .- Ejemplos de creación de funciones.

4) Escribir un bloque PL/SQL que haga uso de la función anterior.

DECLARE
n NUMBER(4);
BEGIN
n := anio(SYSDATE);
DBMS_OUTPUT.PUT_LINE('AÑO : '|| n);
END;

5) Dado el siguiente procedimiento:

CREATE OR REPLACE PROCEDURE crear_depart (


v_num_dept depart.dept_no%TYPE,
v_dnombre depart.dnombre%TYPE DEFAULT 'PROVISIONAL',
v_loc depart.loc%TYPE DEFAULT ‘PROVISIONAL’)
IS
BEGIN
INSERT INTO depart
VALUES (v_num_dept, v_dnombre, v_loc);
END crear_depart;

Indicar cuáles de las siguientes llamadas son correctas y cuáles incorrectas, en este
último caso escribir la llamada correcta usando la notación posicional (en los casos que
se pueda):

1º. crear_depart;
2º. crear_depart(50);
3º. crear_depart('COMPRAS');
4º. crear_depart(50,'COMPRAS');
5º. crear_depart('COMPRAS', 50);
6º. crear_depart('COMPRAS', 'VALENCIA');
7º. crear_depart(50, 'COMPRAS', 'VALENCIA');
8º. crear_depart('COMPRAS', 50, 'VALENCIA');
9º. crear_depart('VALENCIA', ‘COMPRAS’);
10º. crear_depart('VALENCIA', 50);

1º Incorrecta: hay que pasar al menos el número de departamento.

2º Correcta.

3º Incorrecta: hay que pasar también el número de departamento.

4º Correcta.
5º Incorrecta: los argumentos están en orden inverso. Solución:

crear_depart(50, 'COMPRAS');

6º Incorrecta: hay que pasar también el número.

7º Correcta.

8º Incorrecta: el orden de los argumentos es incorrecto.Solución:

crear_depart(50, 'COMPRAS', 'VALENCIA');

9º Incorrecta: hay que pasar también el número de departamento.

10º Incorrecta: los argumentos están en orden inverso.Solución:

crear_depart(50, NULL, 'VALENCIA');

6) Desarrollar una función que devuelva el número de años completos que hay entre
dos fechas que se pasan como argumentos.

CREATE OR REPLACE FUNCTION anios_dif (


fecha1 DATE,
fecha2 DATE)
RETURN NUMBER
AS
v_anios_dif NUMBER(6);
BEGIN
v_anios_dif := ABS(TRUNC(MONTHS_BETWEEN(fecha2,fecha1)
/ 12));
RETURN v_anios_dif;
END anios_dif;

7) Escribir una función que, haciendo uso de la función anterior devuelva los trienios
que hay entre dos fechas. (Un trienio son tres años completos).

CREATE OR REPLACE FUNCTION trienios (


fecha1 DATE,
fecha2 DATE)
RETURN NUMBER
AS
v_trienios NUMBER(6);
BEGIN
v_trienios := TRUNC(anios_dif(fecha1,fecha2) / 3);
RETURN v_trienios;
END;
PROCEDIMIENTOS Y FUNCIONES

3 .- Ejemplos de procedimientos y funciones.

8) Codificar un procedimiento que reciba una lista de hasta 5 números y visualice su


suma.

CREATE OR REPLACE PROCEDURE sumar_5numeros (


Num1 NUMBER DEFAULT 0,
Num2 NUMBER DEFAULT 0,
Num3 NUMBER DEFAULT 0,
Num4 NUMBER DEFAULT 0,
Num5 NUMBER DEFAULT 0)
AS
BEGIN
DBMS_OUTPUT.PUT_LINE(Num1 + Num2 + Num3 + Num4 + Num5);
END sumar_5numeros;

9) Escribir una función que devuelva solamente caracteres alfabéticos sustituyendo


cualquier otro carácter por blancos a partir de una cadena que se pasará en la llamada.

CREATE OR REPLACE FUNCTION sust_por_blancos(


cad VARCHAR2)
RETURN VARCHAR2
AS
nueva_cad VARCHAR2(30);
car CHARACTER;
BEGIN
FOR i IN 1..LENGTH(cad) LOOP
car:=SUBSTR(cad,i,1);
IF (ASCII(car) NOT BETWEEN 65 AND 90)
AND (ASCII(car) NOT BETWEEN 97 AND 122) THEN
car :=' ';
END IF;
nueva_cad := nueva_cad || car;
END LOOP;
RETURN nueva_cad;
END sust_por_blancos;
10) Implementar un procedimiento que reciba un importe y visualice el desglose del
cambio en unidades monetarias de 1, 5, 10, 25, 50, 100, 200, 500, 1000, 2000, 5000
Ptas. en orden inverso al que aparecen aquí enumeradas.

CREATE OR REPLACE PROCEDURE desglose_cambio(


importe NUMBER)
AS
cambio NATURAL := importe;
moneda NATURAL;
v_uni_moneda NATURAL;
BEGIN
DBMS_OUTPUT.PUT_LINE('***** DESGLOSE DE: ' || importe );
WHILE cambio > 0 LOOP
IF cambio >= 5000 THEN
moneda := 5000;
ELSIF cambio >= 2000 THEN
moneda := 2000;
ELSIF cambio >= 1000 THEN
moneda := 1000;
ELSIF cambio >= 500 THEN
moneda := 500;
ELSIF cambio >= 200 THEN
moneda := 200;
ELSIF cambio >= 100 THEN
moneda := 100;
ELSIF cambio >= 50 THEN
moneda := 50;
ELSIF cambio >= 25 THEN
moneda := 25;
ELSIF cambio >= 10 THEN
moneda := 10;
ELSIF cambio >= 5 THEN
moneda := 5;
ELSE
moneda := 1;
END IF;
v_uni_moneda := TRUNC(cambio / moneda);
DBMS_OUTPUT.PUT_LINE(v_uni_moneda ||
' Unidades de: ' || moneda || ' Ptas. ');
cambio := MOD(cambio, moneda);
END LOOP;
END desglose_cambio;
11) Codificar un procedimiento que permita borrar un empleado cuyo número se
pasará en la llamada.

CREATE OR REPLACE PROCEDURE borrar_emple(


num_emple emple.emp_no%TYPE)
AS
BEGIN
DELETE FROM emple WHERE emp_no = num_emple;
END borrar_emple;

Nota: El procedimiento anterior devolverá el mensaje


<< Procedimiento PL/SQL terminado con éxito >> aunque no exista el número y, por
tanto, no se borre el empleado. Para evitarlo se puede escribir:

CREATE OR REPLACE PROCEDURE borrar_emple(


num_emple emple.emp_no%TYPE)
AS
v_row ROWID;
BEGIN
SELECT ROWID INTO v_row FROM emple
WHERE emp_no = num_emple;
DELETE FROM emple WHERE ROWID = v_row;
END borrar_emple;

12) Escribir un procedimiento que modifique la localidad de un departamento. El


procedimiento recibirá como parámetros el número del departamento y la localidad
nueva.

CREATE OR REPLACE
PROCEDURE modificar_localidad(
num_depart NUMBER,
localidad VARCHAR2)
AS
BEGIN
UPDATE depart SET loc = localidad
WHERE dept_no = num_depart;
END modificar_localidad;

Nota: Lo indicado en la nota del ejercicio anterior se puede aplicar también a este.

13) Visualizar todos los procedimientos y funciones del usuario almacenados en la base
de datos y su situación (valid o invalid).

SELECT OBJECT_NAME, OBJECT_TYPE, STATUS


FROM USER_OBJECTS
WHERE OBJECT_TYPE IN ('PROCEDURE','FUNCTION');

Nota: También se puede utilizar la vista ALL_OBJECTS.


CURSOR...IS...

1.- Ejemplos de creación de procedimientos con cursores.

1) Desarrollar un procedimiento que visualice el apellido y la fecha de alta de todos los


empleados ordenados por apellido.

CREATE OR REPLACE PROCEDURE ver_emple


AS
CURSOR c_emple IS
SELECT APELLIDO, FECHA_ALT
FROM EMPLE
ORDER BY APELLIDO;
v_apellido VARCHAR2(10);
v_fecha DATE;
BEGIN
OPEN c_emple;
FETCH c_emple into v_apellido, v_fecha; WHILE
c_emple%FOUND LOOP DBMS_OUTPUT.PUT_LINE(
v_apellido||' * '||v_fecha); FETCH c_emple into
v_apellido,v_fecha;
END LOOP;
CLOSE c_emple;
END ver_emple;

2) Codificar un procedimiento que muestre el nombre de cada departamento y el


número de empleados que tiene.

CREATE OR REPLACE PROCEDURE ver_emple_depart


AS
CURSOR c_emple IS
SELECT dnombre, COUNT(emp_no)
FROM emple e, depart d
WHERE d.dept_no = e.dept_no(+)
GROUP BY dnombre;
v_dnombre depart.dnombre%TYPE;
v_num_emple BINARY_INTEGER;
BEGIN
OPEN c_emple;
FETCH c_emple into v_dnombre, v_num_emple; WHILE
c_emple%FOUND LOOP
DBMS_OUTPUT.PUT_LINE(v_dnombre||' * '||v_num_emple);
FETCH c_emple into v_dnombre,v_num_emple;
END LOOP;
CLOSE c_emple;
END ver_emple_depart;
3) Escribir un procedimiento que reciba una cadena y visualice el apellido y el número de
empleado de todos los empleados cuyo apellido contenga la cadena especificada. Al
finalizar visualizar el número de empleados mostrados.

CREATE OR REPLACE PROCEDURE ver_emple_apell(


cadena VARCHAR2)
AS
cad VARCHAR2(10);
CURSOR c_emple IS
SELECT apellido, emp_no FROM emple
WHERE apellido LIKE cad;
vr_emple c_emple%ROWTYPE;
BEGIN
cad :='%'||cadena||'%';
OPEN c_emple;
FETCH c_emple INTO vr_emple; WHILE (c_emple%FOUND) LOOP
DBMS_OUTPUT.PUT_LINE(vr_emple.emp_no||' * '||vr_emple.apellido);
FETCH c_emple INTO vr_emple;
END LOOP;
DBMS_OUTPUT.PUT_LINE('NUMERO DE EMPLEADOS: '|| c_emple%ROWCOUNT);
CLOSE c_emple;
END ver_emple_apell;

4) Escribir un programa que visualice el apellido y el salario de los cinco empleados que
tienen el salario más alto.

CREATE OR REPLACE PROCEDURE emp_5maxsal


AS
CURSOR c_emp IS
SELECT apellido, salario FROM emple
ORDER BY salario DESC;
vr_emp c_emp%ROWTYPE;
i NUMBER;
BEGIN
i:=1;
OPEN c_emp;
FETCH c_emp INTO vr_emp;
WHILE c_emp%FOUND AND i<=5 LOOP
DBMS_OUTPUT.PUT_LINE(vr_emp.apellido ||' * '|| vr_emp.salario);
FETCH c_emp INTO vr_emp;
i:=I+1;
END LOOP;
CLOSE c_emp;
END emp_5maxsal;
OPEN...FETCH...

2 .- Ejemplos de como como recorrer un cursor.

5) Codificar un programa que visualice los dos empleados que ganan menos de cada
oficio.

CREATE OR REPLACE PROCEDURE emp_2minsal


AS
CURSOR c_emp IS
SELECT apellido, oficio, salario FROM emple
ORDER BY oficio, salario; vr_emp
c_emp%ROWTYPE; oficio_ant
EMPLE.OFICIO%TYPE; i NUMBER;
BEGIN
OPEN c_emp;
oficio_ant:='*';
FETCH c_emp INTO vr_emp;
WHILE c_emp%FOUND LOOP
IF oficio_ant <> vr_emp.oficio THEN
oficio_ant := vr_emp.oficio;
i := 1;
END IF;
IF i <= 2 THEN
DBMS_OUTPUT.PUT_LINE(vr_emp.oficio||' * '
||vr_emp.apellido||' * '
||vr_emp.salario);
END IF;
FETCH c_emp INTO vr_emp;
i:=I+1;
END LOOP;
CLOSE c_emp;
END emp_2minsal;
6) Escribir un programa que muestre, en formato similar a las rupturas de control o
secuencia vistas en SQL*plus los siguientes datos:
- Para cada empleado: apellido y salario.
- Para cada departamento: Número de empleados y suma de los salarios del
departamento.
- Al final del listado: Número total de empleados y suma de todos los salarios.

CREATE OR REPLACE PROCEDURE listar_emple


AS
CURSOR c1 IS
SELECT apellido, salario, dept_no FROM emple
ORDER BY dept_no, apellido;
vr_emp c1%ROWTYPE;
dep_ant EMPLE.DEPT_NO%TYPE;
cont_emple NUMBER(4) DEFAULT 0;
sum_sal NUMBER(9) DEFAULT 0;
tot_emple NUMBER(4) DEFAULT 0;
tot_sal NUMBER(10) DEFAULT 0;
BEGIN
OPEN c1;
FETCH c1 INTO vr_emp;
IF c1%FOUND THEN
dep_ant := vr_emp.dept_no;
END IF;
WHILE c1%FOUND LOOP

/* Comprobación nuevo departamento y resumen */ IF


dep_ant <> vr_emp.dept_no THEN
DBMS_OUTPUT.PUT_LINE('*** DEPTO: ' || dep_ant ||
' NUM. EMPLEADOS: '||cont_emple ||
' SUM. SALARIOS: '||sum_sal);
dep_ant := vr_emp.dept_no;
tot_emple := tot_emple + cont_emple;
tot_sal:= tot_sal + sum_sal;
cont_emple:=0;
sum_sal:=0;
END IF;

/* Líneas de detalle */
DBMS_OUTPUT.PUT_LINE(RPAD(vr_emp.apellido,10)|| ' * '
||LPAD(TO_CHAR(vr_emp.salario,'9,999,999'),12));
/* Incrementar y acumular */
cont_emple := cont_emple + 1;
sum_sal:=sum_sal + vr_emp.salario;

FETCH c1 INTO vr_emp;


END LOOP;
CLOSE c1;

IF cont_emple > 0 THEN

/* Escribir datos del último departamento */


DBMS_OUTPUT.PUT_LINE('*** DEPTO: ' || dep_ant ||
' NUM EMPLEADOS: '|| cont_emple ||
' SUM. SALARIOS: '||sum_sal);
dep_ant := vr_emp.dept_no;
tot_emple := tot_emple + cont_emple;
tot_sal:= tot_sal + sum_sal;
cont_emple:=0;
sum_sal:=0;

/* Escribir totales informe */


DBMS_OUTPUT.PUT_LINE(' ****** NUMERO TOTAL EMPLEADOS: '
||tot_emple ||
' TOTAL SALARIOS: '|| tot_sal);
END IF;
END listar_emple;

/* Nota: este procedimiento puede escribirse de forma que la visualización de los


resultados resulte mas clara incluyendo líneas de separación, cabeceras de columnas,
etcétera. Por razones didácticas no se han incluido estos elementos ya que pueden
distraer y dificultar la comprensión del código. */

7) Desarrollar un procedimiento que permita insertar nuevos departamentos según las


siguientes especificaciones:
Se pasará al procedimiento el nombre del departamento y la localidad.
El procedimiento insertará la fila nueva asignando como número de departamento la
decena siguiente al número mayor de la tabla.
Se incluirá gestión de posibles errores.

CREATE OR REPLACE PROCEDURE insertar_depart(


nombre_dep VARCHAR2,
loc VARCHAR2)
AS
CURSOR c_dep IS SELECT dnombre
FROM depart WHERE dnombre = nombre_dep;
v_dummy DEPART.DNOMBRE%TYPE DEFAULT NULL;
v_ulti_num DEPART.DEPT_NO%TYPE;
nombre_duplicado EXCEPTION;
BEGIN
/* Comprobación de que el departamento no está duplicado */
OPEN c_dep;
FETCH c_dep INTO v_dummy;
CLOSE c_dep;
IF v_dummy IS NOT NULL THEN
RAISE nombre_duplicado;
END IF;

/* Captura del último número y cálculo del siguiente */


SELECT MAX(dept_no) INTO v_ulti_num FROM depart;

/* Inserción de la nueva fila */


INSERT INTO depart VALUES ((TRUNC(v_ulti_num, -1)+10)
, nombre_dep, loc);
EXCEPTION
WHEN nombre_duplicado THEN
DBMS_OUTPUT.PUT_LINE('Err. departamento duplicado');
RAISE;
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20005,'Err. Operación cancelada’);
END insertar_depart;

8) Escribir un procedimiento que reciba todos los datos de un nuevo empleado procese
la transacción de alta, gestionando posibles errores.

CREATE OR REPLACE PROCEDURE alta_emp(


num emple.emp_no%TYPE,
ape emple.apellido%TYPE,
ofi emple.oficio%TYPE,
jef emple.dir%TYPE,
fec emple.fecha_alt%TYPE,
sal emple.salario%TYPE,
com emple.comision%TYPE DEFAULT NULL,
dep emple.dept_no%TYPE)
AS
v_dummy_jef EMPLE.DIR%TYPE DEFAULT NULL;
v_dummy_dep DEPART.DEPT_NO%TYPE DEFAULT NULL;
BEGIN
/* Comprobación de que existe el departamento */
SELECT dept_no INTO v_dummy_dep
FROM depart WHERE dept_no = dep;

/* Comprobación de que existe el jefe del empleado */


SELECT emp_no INTO v_dummy_jef
FROM emple WHERE emp_no = jef;
/* Inserción de la fila */
INSERT INTO EMPLE VALUES
(num, ape, ofi, jef, fec, sal, com, dep);

EXCEPTION
WHEN NO_DATA_FOUND THEN IF
v_dummy_dep IS NULL THEN
RAISE_APPLICATION_ERROR(-20005,
'Err. Departamento inexistente');
ELSIF v_dummy_jef IS NULL THEN
RAISE_APPLICATION_ERROR(-20005,
'Err. No existe el jefe');
ELSE
RAISE_APPLICATION_ERROR(-20005,
'Err. Datos no encontrados(*)');
END IF;
WHEN DUP_VAL_ON_INDEX THEN
DBMS_OUTPUT.PUT_LINE
('Err.numero de empleado duplicado');
RAISE;
END alta_emp;

WHILE...FOUND...LOOP...

3 .- Ejemplos como procedimientos con cursores y parámetros de entrada.

9) Codificar un procedimiento reciba como parámetros un numero de departamento, un


importe y un porcentaje; y suba el salario a todos los empleados del departamento
indicado en la llamada. La subida será el porcentaje o el importe indicado en la llamada
(el que sea más beneficioso para el empleado en cada caso empleado).

CREATE OR REPLACE PROCEDURE subida_sal1(


num_depar emple.dept_no%TYPE,
importe NUMBER,
porcentaje NUMBER)
AS
CURSOR c_sal IS SELECT salario,ROWID
FROM emple WHERE dept_no = num_depar;
vr_sal c_sal%ROWTYPE;
v_imp_pct NUMBER(10);
BEGIN
OPEN c_sal;
FETCH c_sal INTO vr_sal;
WHILE c_sal%FOUND LOOP

/* Guardar en v_imp_pct el importe mayor */


v_imp_pct :=
GREATEST((vr_sal.salario/100)*porcentaje,
v_imp_pct);

/* Actualizar */
UPDATE EMPLE SET SALARIO=SALARIO + v_imp_pct
WHERE ROWID = vr_sal.rowid;

FETCH c_sal INTO vr_sal;


END LOOP;
CLOSE c_sal;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Err. ninguna fila actualizada');
END subida_sal1;

10) Escribir un procedimiento que suba el sueldo de todos los empleados que ganen
menos que el salario medio de su oficio. La subida será del 50% de la diferencia entre el
salario del empleado y la media de su oficio. Se deberá asegurar que la transacción no
se quede a medias, y se gestionarán los posibles errores.

CREATE OR REPLACE PROCEDURE subida_50pct


AS
CURSOR c_ofi_sal IS
SELECT oficio, AVG(salario) salario FROM emple
GROUP BY oficio;
CURSOR c_emp_sal IS
SELECT oficio, salario FROM emple E1
WHERE salario <
(SELECT AVG(salario) FROM emple E2
WHERE E2.oficio = E1.oficio)
ORDER BY oficio, salario FOR UPDATE OF salario;

vr_ofi_sal c_ofi_sal%ROWTYPE;
vr_emp_sal c_emp_sal%ROWTYPE;
v_incremento emple.salario%TYPE;
BEGIN
COMMIT;
OPEN c_emp_sal;
FETCH c_emp_sal INTO vr_emp_sal;
OPEN c_ofi_sal;
FETCH c_ofi_sal INTO vr_ofi_sal;
WHILE c_ofi_sal%FOUND AND c_emp_sal%FOUND LOOP

/* calcular incremento */
v_incremento :=
(vr_ofi_sal.salario - vr_emp_sal.salario) / 2;

/* actualizar */
UPDATE emple SET salario = salario + v_incremento
WHERE CURRENT OF c_emp_sal;

/* siguiente empleado */
FETCH c_emp_sal INTO vr_emp_sal;

/* comprobar si es otro oficio */


IF c_ofi_sal%FOUND and
vr_ofi_sal.oficio <> vr_emp_sal.oficio THEN
FETCH c_ofi_sal INTO vr_ofi_sal;
END IF;
END LOOP;
CLOSE c_emp_sal;
CLOSE c_ofi_sal;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK WORK;
RAISE;
END subida_50pct;
11) Diseñar una aplicación que simule un listado de liquidación de los empleados según
las siguientes especificaciones:

- El listado tendrá el siguiente formato para cada empleado:

**********************************************************************
Liquidación del empleado:...................(1)
Dpto:.................(2) Oficio:...........(3)

Salario : ............(4)
Trienios :.............(5)
Comp. Responsabil :.............(6)
Comisión :.............(7)
------------
Total :.............(8)
**********************************************************************

Donde:

 1 ,2, 3 y 4 Corresponden al apellido, departamento, oficio y salario del


empleado.
 5 Es el importe en concepto de trienios. Cada trienio son tres años completos
desde la fecha de alta hasta la de emisión y supone 50€.
 6 Es el complemento por responsabilidad. Será de 100€ por cada empleado que
se encuentre directamente a cargo del empleado en cuestión.
 7 Es la comisión. Los valores nulos serán sustituidos por ceros.
 8 Suma de todos los conceptos anteriores.

El listado irá ordenado por Apellido.

CREATE OR REPLACE PROCEDURE liquidar


AS
CURSOR c_emp IS
SELECT apellido, emp_no, oficio, salario,
NVL(comision,0) comision, dept_no, fecha_alt
FROM emple
ORDER BY apellido;
vr_emp c_emp%ROWTYPE;
v_trien NUMBER(9) DEFAULT 0;
v_comp_r NUMBER(9);
v_total NUMBER(10);
BEGIN
FOR vr_emp in c_emp LOOP

/* Calcular trienios. Llama a la función trienios


creada en el ejercicio 11.8 */
v_trien := trienios(vr_emp.fecha_alt,SYSDATE)*50;

/* Calcular complemento de responsabilidad. Se


encierra en un bloque pues levantará NO_DATA_FOUND*/
BEGIN
SELECT COUNT(*) INTO v_comp_r
FROM EMPLE WHERE DIR = vr_emp.emp_no;
v_comp_r := v_comp_r *100;
EXCEPTION
WHEN NO_DATA_FOUND THEN
v_comp_r:=0;
END;

/* Calcular el total del empleado */


v_total := vr_emp.salario + vr_emp. comision +
v_trien + v_comp_r;

/* Visualizar datos del empleado */


DBMS_OUTPUT.PUT_LINE('*************************************');
DBMS_OUTPUT.PUT_LINE(' Liquidacion de : '|| vr_emp.apellido
||' Dpto: ' || vr_emp.dept_no
|| ' Oficio: ' || vr_emp.oficio);
DBMS_OUTPUT.PUT_LINE(RPAD('Salario:',16)
||LPAD(TO_CHAR(vr_emp.salario,'9,999,999'),12));
DBMS_OUTPUT.PUT_LINE(RPAD('Trienios: ',16)
|| LPAD(TO_CHAR(v_trien,'9,999,999'),12));
DBMS_OUTPUT.PUT_LINE('Comp. Respons: '
||LPAD(TO_CHAR(v_comp_r,'9,999,999'),12));
DBMS_OUTPUT.PUT_LINE(RPAD('Comision: ' ,16)
||LPAD(TO_CHAR(vr_emp.comision,'9,999,999'),12));
DBMS_OUTPUT.PUT_LINE('------------------');
DBMS_OUTPUT.PUT_LINE(RPAD(' Total : ',16)
||LPAD(TO_CHAR(v_total,'9,999,999') ,12));
DBMS_OUTPUT.PUT_LINE('**************************************');
END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('No se ha encontrado ninguna fila');
END liquidar;
/* Nota: También se puede utilizar una cláusula SELECT más compleja:

CURSOR c_emp IS
SELECT APELLIDO, EMP_NO, OFICIO, (EMP_CARGO *
10000) COM_RESPONSABILIDAD, SALARIO,
NVL(COMISION, 0) COMISION, DEPT_NO,
TRIENIOS(FECHA_ALT, SYSDATE) * 5000 TOT_TRIENIOS
FROM EMPLE,(SELECT DIR,COUNT(*) EMP_CARGO FROM EMPLE
GROUP BY DIR) DIREC
WHERE EMPLE.EMP_NO = DIREC.DIR(+)
ORDER BY APELLIDO;

de esta forma se simplifica el programa y se evita la utilización de variables de trabajo.


*/

12) Crear la tabla T_liquidacion con las columnas apellido, departamento, oficio,
salario, trienios, comp_responsabilidad, comisión y total; y modificar la aplicación
anterior para que en lugar de realizar el listado directamente en pantalla, guarde los
datos en la tabla. Se controlarán todas las posibles incidencias que puedan ocurrir
durante el proceso.

CREATE TABLE t_liquidacion (


APELLIDO VARCHAR2(10),
DEPARTAMENTO NUMBER(2),
OFICIO VARCHAR2(10),
SALARIO NUMBER(10),
TRIENIOS NUMBER(10),
COMP_RESPONSABILIDAD NUMBER(10),
COMISION NUMBER(10),
TOTAL NUMBER(10)
);

CREATE OR REPLACE PROCEDURE liquidar2


AS
CURSOR c_emp IS
SELECT apellido, emp_no, oficio, salario,
NVL(comision,0) comision, dept_no, fecha_alt
FROM emple
ORDER BY apellido;
vr_emp c_emp%ROWTYPE;
v_trien NUMBER(9) DEFAULT 0;
v_comp_r NUMBER(9);
v_total NUMBER(10);
BEGIN
COMMIT WORK;
FOR vr_emp in c_emp LOOP

/* Calcular trienios. Llama a la función trienios


creada en el ejercicio 11.8 */
v_trien := trienios(vr_emp.fecha_alt,SYSDATE)*5000;

/* Calcular complemento de responsabilidad. Se


encierra en un bloque pues levantará NO_DATA_FOUND*/
BEGIN
SELECT COUNT(*) INTO v_comp_r
FROM EMPLE WHERE DIR = vr_emp.emp_no;
v_comp_r := v_comp_r *10000;
EXCEPTION
WHEN NO_DATA_FOUND THEN
v_comp_r:=0;
END;

/* Calcular el total del empleado */


v_total := vr_emp.salario + vr_emp. comision +
v_trien + v_comp_r;

/* Insertar los datos en la tabla T_liquidacion */


INSERT INTO t_liquidacion
(APELLIDO, OFICIO, SALARIO, TRIENIOS,
COMP_RESPONSABILIDAD, COMISION, TOTAL)
VALUES
(vr_emp.apellido, vr_emp.oficio, vr_emp.salario,
v_trien, v_comp_r, vr_emp.comision, v_total);
END LOOP;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK WORK;
END liquidar2;
CREATE OR REPLACE TRIGGER...

a) Ejemplo de como crear un trigger.

1.- Construir un disparador de base de datos que permita auditar las operaciones de
inserción o borrado de datos que se realicen en la tabla emple según las siguientes
especificaciones:
- En primer lugar se creará desde SQL*Plus la tabla auditaremple con la columna col1
VARCHAR2(200).
- Cuando se produzca cualquier manipulación se insertará una fila en dicha tabla que
contendrá:
- Fecha y hora
- Número de empleado
- Apellido
- La operación de actualización INSERCIÓN o BORRADO

CREATE TABLE auditaremple (


col1 VARCHAR2(200)
);

CREATE OR REPLACE TRIGGER auditar_act_emp


BEFORE INSERT OR DELETE
ON EMPLE
FOR EACH ROW
BEGIN
IF DELETING THEN
INSERT INTO AUDITAREMPLE
VALUES(TO_CHAR(sysdate,'DD/MM/YY*HH24:MI*')
|| :OLD.EMP_NO|| '*' || :OLD.APELLIDO || '* BORRADO ');
ELSIF INSERTING THEN
INSERT INTO AUDITAREMPLE
VALUES(TO_CHAR(sysdate,'DD/MM/YY*HH24:MI*')
|| :NEW.EMP_NO || '*' || :NEW.APELLIDO||'* INSERCION ');
END IF;
END;
CREATE OR REPLACE TRIGGER....

b) Ejemplo de como crear un trigger cuando actualizamos en la tabla datos.

2.- Escribir un trigger de base de datos un que permita auditar las modificaciones en la
tabla empleados insertado en la tabla auditaremple los siguientes datos:
- Fecha y hora
- Número de empleado
- Apellido
- La operación de actualización: MODIFICACIÓN.
- El valor anterior y el valor nuevo de cada columna modificada. (solo las columnas
modificadas)

CREATE OR REPLACE TRIGGER audit_modif


BEFORE UPDATE ON EMPLE
FOR EACH ROW
DECLARE
v_cad_inser auditaremple.col1%TYPE;
BEGIN
v_cad_inser := TO_CHAR(sysdate,'DD/MM/YY*HH24:MI*') ||:OLD.EMP_NO ||'*
MODIFICACION *';

IF UPDATING ('EMP_NO') THEN


v_cad_inser := v_cad_inser
||:OLD.EMP_NO|| '*'|| :NEW.EMP_NO;
END IF;

IF UPDATING ('APELLIDO') THEN


v_cad_inser := v_cad_inser
||:OLD.APELLIDO|| '*'||:NEW.APELLIDO;
END IF;

IF UPDATING ('OFICIO') THEN


v_cad_inser := v_cad_inser
||:OLD.OFICIO|| '*'||:NEW.OFICIO;
END IF;

IF UPDATING ('DIR') THEN


v_cad_inser := v_cad_inser
||:OLD.DIR|| '*'||:NEW.DIR;
END IF;

IF UPDATING ('FECHA_ALT') THEN


v_cad_inser := v_cad_inser
||:OLD.FECHA_ALT||:NEW.FECHA_ALT;
END IF;
IF UPDATING ('SALARIO') THEN
v_cad_inser := v_cad_inser
||:OLD.SALARIO|| '*'||:NEW.SALARIO;
END IF;

IF UPDATING ('COMISION') THEN


v_cad_inser := v_cad_inser
||:OLD.COMISION|| '*'||:NEW.COMISION;
END IF;

IF UPDATING ('DEPT_NO') THEN


v_cad_inser := v_cad_inser
||:OLD.DEPT_NO|| '*'||:NEW.DEPT_NO;
END IF;

INSERT INTO AUDITAREMPLE VALUES(v_cad_inser);


END;

3.- Escribir un disparador de base de datos que haga fallar cualquier operación de
modificación del apellido o del número de un empleado, o que suponga una subida de
sueldo superior al 10%.

CREATE OR REPLACE TRIGGER fallo_modif


BEFORE UPDATE OF apellido, emp_no, salario
ON emple
FOR EACH ROW
BEGIN
IF UPDATING('emp_no') OR UPDATING('apellido')
OR (UPDATING ('salario') AND
:new.salario>:old.salario*1.1)
THEN
RAISE_APPLICATION_ERROR
(-20001,'Err. Modificacion no permitida');
END IF;
END;
CREATE OR REPLACE TRIGGER...

c) Ejemplo de como crear un trigger a partir de una vista.

4.- Suponiendo que disponemos de la vista

CREATE VIEW DEPARTAM AS


SELECT DEPART.DEPT_NO, DNOMBRE, LOC, COUNT(EMP_NO) TOT_EMPLE
FROM EMPLE, DEPART
WHERE EMPLE.DEPT_NO (+) = DEPART.DEPT_NO
GROUP BY DEPART.DEPT_NO, DNOMBRE, LOC;

Construir un disparador que permita realizar operaciones de actualización en la tabla


depart a partir de la vista dptos, de forma similar al ejemplo del trigger
t_ges_emplead. Se contemplarán las siguientes operaciones:
- Insertar departamento.
- Borrar departamento.
- Modificar la localidad de un departamento.

CREATE OR REPLACE TRIGGER ges_depart


INSTEAD OF DELETE OR INSERT OR UPDATE
ON DEPARTAM
FOR EACH ROW
BEGIN
IF DELETING THEN
DELETE FROM depart WHERE dept_no = :old.dept_no;
ELSIF INSERTING THEN
INSERT INTO depart
VALUES(:new.dept_no, :new.dnombre, :new.loc);
ELSIF UPDATING('loc') THEN
UPDATE depart SET loc = :new.loc
WHERE dept_no = :old.dept_no;
ELSE
RAISE_APPLICATION_ERROR
(-20001,'Error en la actualización');
END IF;
END;
CREATE OR REPLACE PACKAGE...

1.- Ejemplo de cómo crear un paquete.

Escribir un paquete completo para gestionar los departamentos. El paquete se llamará


gest_depart y deberá incluir, al menos, los siguientes subprogramas:

- insertar_nuevo_depart: permite insertar un departamento nuevo. El procedimiento


recibe el nombre y la localidad del nuevo departamento. Creará el nuevo departamento
comprobando que el nombre no se duplique y le asignará como número de
departamento la decena siguiente al último número de departamento utilizado.
- borrar_depart: permite borrar un departamento. El procedimiento recibirá dos
números de departamento de los cuales el primero corresponde al departamento que
queremos borrar y el segundo al departamento al que pasarán los empleados del
departamento que se va eliminar. El procedimiento se encargará de realizar los
cambios oportunos en los números de departamento de los empleados
correspondientes.
- modificar_loc_depart: modifica la localidad del departamento. El procedimiento
recibirá el número del departamento a modificar y la nueva localidad, y realizará el
cambio solicitado.
- visualizar_datos_depart: visualizará los datos de un departamento cuyo número se
pasará en la llamada. Además de los datos relativos al departamento, se visualizará el
número de empleados que pertenecen actualmente al departamento.
- visualizar_datos_depart: versión sobrecargada del procedimiento anterior que, en
lugar del número del departamento, recibirá el nombre del departamento. Realizará
una llamada a la función buscar_depart_por_nombre que se indica en el apartado
siguiente.
- buscar_depart_por_nombre: función local al paquete. Recibe el nombre de un
departamento y devuelve el número del mismo.

/************* Cabecera o especificación del paquete **********/


CREATE OR REPLACE PACKAGE gest_depart AS
PROCEDURE insert_depart
(v_nom_dep VARCHAR2,
v_loc VARCHAR2);
PROCEDURE borrar_depar
(v_dep_borrar NUMBER,
v_dep_nue NUMBER);
PROCEDURE cambiar_localidad
(v_num_dep NUMBER,
v_loc VARCHAR2);
PROCEDURE visualizar_datos_depart
(v_num_dep NUMBER);
PROCEDURE visualizar_datos_depart
(v_nom_dep VARCHAR2);
END gest_depart;
/
/******************* Cuerpo del paquete **********************/
CREATE OR REPLACE PACKAGE BODY gest_depart AS
FUNCTION buscar_depart_por_nombre /* Función privada */
(v_nom_dep VARCHAR2)
RETURN NUMBER;
/*************************************************************/

PROCEDURE insert_depart(
v_nom_dep VARCHAR2,
v_loc VARCHAR2)
AS
ultimo_dep DEPART.DEPT_NO%TYPE;
nombre_repetido EXCEPTION;
BEGIN

/*Comprobar dpt repetido(Puede levantar NO_DATA_FOUND)*/


DECLARE
nom_dep depart.DNOMBRE%TYPE;
nombre_repetido EXCEPTION;
BEGIN
SELECT dnombre INTO nom_dep FROM depart
WHERE dnombre = v_nom_dep;
RAISE insert_depart.nombre_repetido;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
WHEN TOO_MANY_ROWS THEN
RAISE insert_Depart.nombre_repetido;
END; /* Fin del bloque de comprobación
de departamento repetido */

/* Calcular el número de departamento e insertar */ SELECT


MAX(DEPT_NO) INTO ultimo_dep FROM DEPART; INSERT
INTO DEPART VALUES ((TRUNC(ultimo_dep, -1) +10),
v_nom_dep,v_loc);
EXCEPTION
WHEN nombre_repetido THEN
DBMS_OUTPUT.PUT_LINE
('Err. Nombre de departamento duplicado');
WHEN NO_DATA_FOUND THEN /* Si no había ningún departamento */
INSERT INTO DEPART VALUES (10,v_nom_dep,v_loc);
END insert_depart;
/**************************************************************/
PROCEDURE borrar_depar
(v_dep_borrar NUMBER,
v_dep_nue NUMBER)
AS
BEGIN
UPDATE emple SET dept_no = v_dep_nue
WHERE DEPT_NO=v_dep_borrar;
DELETE FROM depart WHERE dept_no = v_dep_borrar;
END borrar_depar;
/*************************************************************/

PROCEDURE visualizar_datos_depart
(v_num_dep NUMBER)
AS
vr_dep depart%ROWTYPE;
v_num_empleados NUMBER(4);
BEGIN
SELECT * INTO vr_dep FROM depart
WHERE DEPT_NO=v_num_dep;
SELECT COUNT(*) INTO v_num_empleados FROM
EMPLE WHERE DEPT_NO=v_num_dep;

DBMS_OUTPUT.PUT_LINE
('Número de departamento: '||vr_dep.dept_no);
DBMS_OUTPUT.PUT_LINE
('Nombre del departamento: '||vr_dep.dnombre);
DBMS_OUTPUT.PUT_LINE
('Localidad : '||vr_dep.loc);
DBMS_OUTPUT.PUT_LINE
('Numero de empleados : '||v_num_empleados);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Err departamento no encontrado');
END visualizar_datos_depart;
/*************************************************************/

PROCEDURE visualizar_datos_depart /* Versión sobrecargada */


(v_nom_dep VARCHAR2)
AS
v_num_dep depart.dept_no%TYPE;
vr_dep depart%ROWTYPE;
v_num_empleados NUMBER(4);
BEGIN
v_num_dep:=buscar_depart_por_nombre(v_nom_dep);
SELECT * INTO vr_dep FROM depart
WHERE dept_no=v_num_dep;
SELECT COUNT(*) INTO v_num_empleados FROM EMPLE
WHERE dept_no=v_num_dep;

DBMS_OUTPUT.PUT_LINE
('Número de departamento: '||vr_dep.dept_no);
DBMS_OUTPUT.PUT_LINE
('Nombre del departamento: '||vr_dep.dnombre);
DBMS_OUTPUT.PUT_LINE
('Localidad : '||vr_dep.loc);
DBMS_OUTPUT.PUT_LINE
('Numero de empleados : '||v_num_empleados);

EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Err departamento no encontrado');
END visualizar_datos_depart;
/*************************************************************/

FUNCTION buscar_depart_por_nombre
(v_nom_dep VARCHAR2)
RETURN NUMBER
AS
v_num_dep depart.dept_no%TYPE;
BEGIN
SELECT dept_no INTO v_num_dep FROM depart
WHERE DNOMBRE = v_nom_dep;
RETURN v_num_dep;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Err departamento no encontrado');
END buscar_depart_por_nombre;
/*************************************************************/

PROCEDURE cambiar_localidad(
v_num_dep NUMBER,
v_loc VARCHAR2)
AS
BEGIN
UPDATE depart
SET LOC=v_loc
WHERE dept_no=v_num_dep;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Err departamento no encontrado');
END cambiar_localidad;
END gest_depart;
CREATE OR REPLACE PACKAGE BODY....

2 .- Ejemplo de como crear un paquete.

Escribir un paquete completo para gestionar los empleados. El paquete se llamará


gest_emple e incluirá, al menos los siguientes subprogramas:

- insertar_nuevo_emple
- borrar_emple. Cuando se borra un empleado todos los empleados que dependían de
él pasarán a depender del director del empleado borrado.
- modificar_oficio_emple
- modificar_dept_emple
- modificar_dir_emple
- modificar_salario_emple
- modificar_comision_emple
- visualizar_datos_emple. También se incluirá una versión sobrecargada del
procedimiento que recibirá el nombre del empleado.
- buscar_emple_por_nombre. Función local que recibe el nombre y devuelve el
número.

Todos los procedimientos recibirán el número del empleado seguido de los demás
datos necesarios. También se incluirán en el paquete cursores y declaraciones de tipo
registro, así como siguientes procedimientos que afectarán a todos los empleados:

- subida_salario_pct: incrementará el salario de todos los empleados el porcentaje


indicado en la llamada que no podrá ser superior al 25%.
- subida_salario_imp: sumará al salario de todos los empleados el importe indicado en
la llamada. Antes de proceder a la incrementar los salarios se comprobará que el
importe indicado no supera el 25% del salario medio.

/****************** Cabecera del paquete *********************/


CREATE OR REPLACE PACKAGE gest_emple AS

CURSOR c_sal RETURN EMPLE%ROWTYPE;

PROCEDURE insertar_nuevo_emple(
v_num_emp EMPLE.EMP_NO%TYPE,
v_apell EMPLE.APELLIDO%TYPE,
v_oficio EMPLE.OFICIO%TYPE,
v_dir EMPLE.DIR%TYPE,
v_fecha_al EMPLE.FECHA_ALT%TYPE,
v_sal EMPLE.SALARIO%TYPE,
v_comision EMPLE.COMISION%TYPE DEFAULT NULL,
v_num_dep EMPLE.DEPT_NO%TYPE);

PROCEDURE borrar_emple(
v_num_emple NUMBER);
PROCEDURE modificar_oficio_emple(
v_num_emp EMPLE.EMP_NO%TYPE,
v_oficio EMPLE.OFICIO%TYPE);

PROCEDURE modificar_dept_emple(
v_num_emp EMPLE.EMP_NO%TYPE,
v_dept EMPLE.DEPT_NO%TYPE);

PROCEDURE modificar_dir_emple(
v_num_emp EMPLE.EMP_NO%TYPE,
v_direccion EMPLE.DIR%TYPE);

PROCEDURE modificar_salario_emple(
v_num_emp EMPLE.EMP_NO%TYPE,
v_salario EMPLE.SALARIO%TYPE);

PROCEDURE modificar_comision_emple(
v_num_emp EMPLE.EMP_NO%TYPE,
v_comis EMPLE.COMISION%TYPE);

PROCEDURE visualizar_datos_emple(
v_num_emp EMPLE.EMP_NO%TYPE);

PROCEDURE visualizar_datos_emple(
v_nombre_emp EMPLE.APELLIDO%TYPE);

PROCEDURE subida_salario_pct(
v_pct_subida NUMBER);

PROCEDURE subida_salario_imp(
v_imp_subida NUMBER);
END gest_emple;

/******************** Cuerpo del paquete *********************/

CREATE OR REPLACE PACKAGE BODY gest_emple AS

CURSOR c_sal RETURN EMPLE%ROWTYPE


IS SELECT * FROM EMPLE;

FUNCTION buscar_emple_por_nombre
(n_emp VARCHAR2)
RETURN NUMBER;
/*************************************************************/
PROCEDURE insertar_nuevo_emple(
v_num_emp EMPLE.EMP_NO%TYPE,
v_apell EMPLE.APELLIDO%TYPE,
v_oficio EMPLE.OFICIO%TYPE,
v_dir EMPLE.DIR%TYPE,
v_fecha_al EMPLE.FECHA_ALT%TYPE,
v_sal EMPLE.SALARIO%TYPE,
v_comision EMPLE.COMISION%TYPE DEFAULT NULL,
v_num_dep EMPLE.DEPT_NO%TYPE)
IS
dir_no_existe EXCEPTION;
BEGIN
DECLARE
v_num_emple EMPLE.EMP_NO%TYPE;
BEGIN
SELECT EMP_NO INTO v_num_emple FROM EMPLE
WHERE EMP_NO=v_dir;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE insertar_nuevo_emple.dir_no_existe;
END;
INSERT INTO EMPLE VALUES (v_num_emp, v_apell, v_oficio,
v_dir, v_fecha_al, v_sal, v_comision, v_num_dep);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
DBMS_OUTPUT.PUT_LINE('Err. Número de empleado duplicado');
WHEN dir_no_existe THEN
DBMS_OUTPUT.PUT_LINE('Err. No existe el director');
END insertar_nuevo_emple;

/*************************************************************/
PROCEDURE borrar_emple(
v_num_emple NUMBER)
IS
emp_dir EMPLE.DIR%TYPE;
BEGIN
SELECT DIR INTO emp_dir FROM EMPLE
WHERE EMP_NO = v_num_emple;
DELETE FROM EMPLE WHERE EMP_NO = v_num_emple;
UPDATE EMPLE SET DIR = emp_dir WHERE DIR = v_num_emple;
END borrar_emple;

/*************************************************************/
DESARROLLO DE APLICACIONES EN ENTORNOS DE 4ª GENERACIÓN Y CON HERRAMIENTAS CASE

PROCEDURE modificar_oficio_emple(
v_num_emp EMPLE.EMP_NO%TYPE,
v_oficio EMPLE.OFICIO%TYPE)
IS
BEGIN
UPDATE EMPLE SET OFICIO = v_oficio
WHERE EMP_NO = v_num_emp;
END modificar_oficio_emple;

/*************************************************************/
PROCEDURE modificar_dept_emple(
v_num_emp EMPLE.EMP_NO%TYPE,
v_dept EMPLE.DEPT_NO%TYPE)
IS
BEGIN
UPDATE EMPLE SET DEPT_NO = v_dept WHERE EMP_NO = v_num_emp;
END modificar_dept_emple;

/*************************************************************/
PROCEDURE modificar_dir_emple(
v_num_emp EMPLE.EMP_NO%TYPE,
v_direccion EMPLE.DIR%TYPE)
IS
BEGIN
UPDATE EMPLE SET DIR = v_direccion WHERE EMP_NO = v_num_emp;
END modificar_dir_emple;

/*************************************************************/
PROCEDURE modificar_salario_emple(
v_num_emp EMPLE.EMP_NO%TYPE,
v_salario EMPLE.SALARIO%TYPE)
IS
BEGIN
UPDATE EMPLE SET SALARIO = v_salario WHERE EMP_NO = v_num_emp;
END modificar_salario_emple;

/*************************************************************/
PROCEDURE modificar_comision_emple(
v_num_emp EMPLE.EMP_NO%TYPE,
v_comis EMPLE.COMISION%TYPE)
IS
BEGIN
UPDATE EMPLE SET COMISION = v_comis WHERE EMP_NO = v_num_emp;
END modificar_comision_emple;
/*************************************************************/
DESARROLLO DE APLICACIONES EN ENTORNOS DE 4ª GENERACIÓN Y CON HERRAMIENTAS CASE

PROCEDURE visualizar_datos_emple(
v_num_emp EMPLE.EMP_NO%TYPE)
IS
reg_emple EMPLE%ROWTYPE;
BEGIN
SELECT * INTO reg_emple FROM EMPLE WHERE EMP_NO = v_num_emp;
DBMS_OUTPUT.PUT_LINE('NUMERO EMPLEADO: '||reg_emple.EMP_NO);
DBMS_OUTPUT.PUT_LINE('APELLIDO: '||reg_emple.APELLIDO);
DBMS_OUTPUT.PUT_LINE('OFICIO: '||reg_emple.OFICIO);
DBMS_OUTPUT.PUT_LINE('DIRECTOR: '||reg_emple.DIR);
DBMS_OUTPUT.PUT_LINE('FECHA ALTA): '||reg_emple.FECHA_ALT);
DBMS_OUTPUT.PUT_LINE('SALARIO: '||reg_emple.SALARIO);
DBMS_OUTPUT.PUT_LINE('COMISION: '||reg_emple.COMISION);
DBMS_OUTPUT.PUT_LINE('NUMERO DEPARTAMENTO: '||reg_emple.DEPT_NO);
END visualizar_datos_emple;
/*************************************************************/

PROCEDURE visualizar_datos_emple(
v_nombre_emp EMPLE.APELLIDO%TYPE)
IS
v_num_emp EMPLE.EMP_NO%TYPE;
reg_emple EMPLE%ROWTYPE; BEGIN
v_num_emp:=buscar_emple_por_nombre(v_nombre_emp);
SELECT * INTO reg_emple FROM EMPLE WHERE EMP_NO = v_num_emp;
DBMS_OUTPUT.PUT_LINE('NUMERO EMPLEADO: '||reg_emple.EMP_NO);
DBMS_OUTPUT.PUT_LINE('APELLIDO : '||reg_emple.APELLIDO);
DBMS_OUTPUT.PUT_LINE('OFICIO : '||reg_emple.OFICIO);
DBMS_OUTPUT.PUT_LINE('DIRECTOR : '||reg_emple.DIR);
DBMS_OUTPUT.PUT_LINE('FECHA ALTA: '||reg_emple.FECHA_ALT);
DBMS_OUTPUT.PUT_LINE('SALARIO : '||reg_emple.SALARIO);
DBMS_OUTPUT.PUT_LINE('COMISION : '||reg_emple.COMISION);
DBMS_OUTPUT.PUT_LINE('NUM DEPART: '||reg_emple.DEPT_NO);
END visualizar_datos_emple;
/*************************************************************/

FUNCTION buscar_emple_por_nombre(
n_emp VARCHAR2)
RETURN NUMBER
IS
numero EMPLE.EMP_NO%TYPE;
BEGIN
SELECT EMP_NO INTO numero FROM EMPLE WHERE APELLIDO = n_emp;
RETURN numero;
END buscar_emple_por_nombre;
/*************************************************************/
DESARROLLO DE APLICACIONES EN ENTORNOS DE 4ª GENERACIÓN Y CON HERRAMIENTAS CASE

PROCEDURE subida_salario_pct(
v_pct_subida NUMBER)
IS
subida_mayor EXCEPTION;
BEGIN
IF v_pct_subida > 25 THEN
RAISE subida_mayor;
END IF;
FOR vr_c_sal IN c_sal LOOP
UPDATE EMPLE SET SALARIO = SALARIO +
(SALARIO * v_pct_subida / 100)
WHERE EMP_NO = vr_c_sal.emp_no;
END LOOP;
EXCEPTION
WHEN subida_mayor THEN
DBMS_OUTPUT.PUT_LINE('Subida superior a la permitida');
END subida_salario_pct;
/*************************************************************/

PROCEDURE subida_salario_imp(
v_imp_subida NUMBER)
IS
subida_mayor EXCEPTION;
sueldo_medio NUMBER(10);
BEGIN
SELECT AVG(SALARIO) INTO sueldo_medio FROM EMPLE;
IF v_imp_subida>sueldo_medio THEN
RAISE subida_mayor;
END IF;
FOR vr_c_sal in c_sal LOOP
UPDATE EMPLE SET SALARIO = SALARIO + v_imp_subida
WHERE EMP_NO = vr_c_sal.emp_no;
END LOOP;
EXCEPTION
WHEN subida_mayor THEN
DBMS_OUTPUT.PUT_LINE('Subida superior a la permitida');
END subida_salario_imp;
END gest_emple;
DESARROLLO DE APLICACIONES EN ENTORNOS DE 4ª GENERACIÓN Y CON HERRAMIENTAS CASE

SQL DINÁMICO – Paquete DBMS.SQL

1.- Crear un procedimiento que permita consultar todos los datos de la tabla depart a
partir de una condición que se indicará en la llamada al procedimiento.

CREATE OR REPLACE PROCEDURE consultar_depart


(condicion VARCHAR2,
valor VARCHAR2)
AS
id_cursor INTEGER;
v_comando VARCHAR2(2000);
v_dummy NUMBER;
v_dept_no depart.dept_no%TYPE;
v_dnombre depart.dnombre%TYPE;
v_loc depart.loc%TYPE;
BEGIN
id_cursor := DBMS_SQL.OPEN_CURSOR;
v_comando := ‘ SELECT dept_no, dnombre, loc
FROM depart
WHERE ‘ || condicion || ‘:val_1’;
DBMS_OUTPUT.PUT_LINE(v_comando);
DBMS_SQL.PARSE(id_cursor, v_comando, DBMS_SQL.V7);
DBMS_SQL.BIND_VARIABLE(id_cursor, ‘:val_1’, valor);
/* A continuación se especifican las variables que recibirán los valores de la selección*/
DBMS_SQL.DEFINE_COLUMN(id_cursor, 1, v_dept_no);
DBMS_SQL.DEFINE_COLUMN(id_cursor, 2, v_dnombre,14);
DBMS_SQL.DEFINE_COLUMN(id_cursor, 3, v_loc, 14);
v_dummy := DBMS_SQL.EXECUTE(id_cursor);
/* La función FETCH_ROWS recupera filas y retorna el número de filas que quedan */
WHILE DBMS_SQL.FETCH_ROWS(id_cursor)>0 LOOP
/* A continuación se depositarán los valores recuperados en las variables PL/SQL */
DBMS_SQL.COLUMN_VALUE(id_cursor, 1, v_dept_no);
DBMS_SQL.COLUMN_VALUE(id_cursor, 2, v_dnombre);
DBMS_SQL.COLUMN_VALUE(id_cursor, 3, v_loc);
DBMS_OUTPUT.PUT_LINE(v_dept_no || ’*’ || v_dnombre
|| ’*’ || v_loc); END LOOP;
DBMS_SQL.CLOSE_CURSOR(id_cursor);
EXCEPTION
WHEN OTHERS THEN
DBMS_SQL.CLOSE_CURSOR(id_cursor);
RAISE;
END consultar_depart;

Potrebbero piacerti anche