Diferència entre revisions de la pàgina «M2 - Bases de dades / Exercicis UF3: Llenguatges SQL / Solucions PL-SQL T8»

De wikiserver
Dreceres ràpides: navegació, cerca
 
(Hi ha 12 revisions intermèdies del mateix usuari que no es mostren)
Línia 1: Línia 1:
==T8- Cursors explícits ==
+
==Solución 8-1: Manejo de Excepciones Predefinidas==
  
*'''Exercici 1'''
+
En esta práctica, escribirá un bloque PL/SQL que aplique una excepción predefinida para procesar un único registro a la vez. El bloque PL/SQL seleccionará el nombre del empleado con un valor de salario determinado.
  
Previ: buida la taula TOP_DOGS.
+
1) Ejecute el comando en el archivo lab_05_01.sql para volver a crear la tabla messages.
  
::SQL> DELETE
+
2) En la sección de declaraciones, declare dos variables: v_ename del tipo employees.last_name y v_emp_sal del tipo employees.salary.
:: 2  FROM TOP_DOGS;
+
Inicialice la última en 6000.
 +
<pre>
 +
DECLARE
 +
  v_ename employees.last_name%TYPE;
 +
  v_emp_sal employees.salary%TYPE := 6000;
 +
</pre>
 +
3) En la sección ejecutable, recupere los apellidos de los empleados cuyos salarios son iguales al valor de v_emp_sal. Si el salario introducido devuelve sólo una fila, inserte en la tabla messages el nombre y el importe del salario del empleado.
  
Crea un bloc pl/sql que determini els n empleats amb sous més alts (suposeu que no hi ha dos empleats o més amb el mateix sou):
+
'''Nota:''' no utilice cursores explícitos.
 +
<pre>
 +
BEGIN
 +
  SELECT last_name INTO v_ename
 +
  FROM employees
 +
  WHERE salary = v_emp_sal;
 +
  INSERT INTO messages (results)
 +
  VALUES (v_ename || ' - ' || v_emp_sal);
 +
</pre>
 +
4) Si el salario introducido no devuelve ninguna fila, maneje la excepción con un manejador de excepciones adecuado e inserte en la tabla messages el mensaje “No employee with a salary of ''<salary>''”.
 +
<pre>
 +
EXCEPTION
 +
  WHEN no_data_found THEN
 +
    INSERT INTO messages (results)
 +
    VALUES ('No employee with a salary of '|| TO_CHAR(v_emp_sal));
 +
</pre>
 +
5) Si el salario introducido devuelve varias filas, maneje la excepción con un manejador de excepciones adecuado e inserte en la tabla messages el mensaje “More than one employee with a salary of ''<salary>''”.
 +
<pre>
 +
WHEN too_many_rows THEN
 +
  INSERT INTO messages (results)
 +
  VALUES ('More than one employee with a salary of '|| TO_CHAR(v_emp_sal));
 +
</pre>
 +
6) Maneje cualquier otra excepción con un manejador de excepciones adecuado e inserte en la tabla messages el mensaje “Some other error occurred”.
 +
<pre>
 +
WHEN others THEN
 +
  INSERT INTO messages (results)
 +
  VALUES ('Some other error occurred.');
 +
END;
 +
</pre>
 +
7) Muestre las filas de la tabla messages para comprobar si el bloque PL/SQL se ha ejecutado correctamente.
 +
<pre>
 +
/
 +
SELECT * FROM messages;
 +
</pre>
 +
La salida es la siguiente:
 +
[[Imatge:M2UF3_MEP_1.png |400px|center| Manejo de Excepciones Predefinidas]]
  
a. obtenir un numero "n" entrat per teclat per l'usuari amb un paràmetre de substitució.
+
8) Cambie el valor inicializado de v_emp_sal a 2000 y vuelva a ejecutar. La salida es la siguiente:
 +
[[Imatge:M2UF3_MEP_2.png |400px|center| Manejo de Excepciones Predefinidas]]
  
b. en un bucle, obtenir els cognoms  i sous d'aquests "n" empleats de la taula EMP
+
<source lang="java">
 +
DECLARE
 +
  v_ename employees.last_name%TYPE;
 +
  v_emp_sal employees.salary%TYPE := 6000;
 +
BEGIN
 +
  SELECT last_name INTO v_ename
 +
  FROM employees
 +
  WHERE salary = v_emp_sal;
 +
  INSERT INTO messages (results)
 +
  VALUES (v_ename || ' - ' || v_emp_sal);
 +
EXCEPTION
 +
  WHEN no_data_found THEN
 +
    INSERT INTO messages (results)
 +
    VALUES ('No employee with a salary of '|| TO_CHAR(v_emp_sal));
 +
  WHEN too_many_rows THEN
 +
    INSERT INTO messages (results)
 +
    VALUES ('More than one employee with a salary of '|| TO_CHAR(v_emp_sal));
 +
  WHEN others THEN
 +
    INSERT INTO messages (results)
 +
    VALUES ('Some other error occurred.');
 +
END;
 +
/
 +
SELECT * FROM messages;
 +
</source>
  
c. guarda aquestes dades en la taula TOP_DOGS.
+
==Solución 8-2: Manejo de Excepciones de Oracle Server Estándar==
  
d. Suposa que no hi ha dos empleats amb al mateix sou.
+
En esta práctica, escribirá un bloque PL/SQL que declare una excepción para el error de Oracle Server ORA-02292 (integrity constraint violated – child record found). El bloque comprobará la excepción y mostrará el mensaje de error.
  
e. comprova varis casos: n=0 i n més gran que el número màxim d'empleats.
+
1) En la sección de declaraciones, declare una excepción e_childrecord_exists.
 +
Asocie la excepción declarada al error de Oracle Server estándar –02292.
 +
<pre>
 +
SET SERVEROUTPUT ON
 +
DECLARE
 +
  e_childrecord_exists EXCEPTION;
 +
  PRAGMA EXCEPTION_INIT(e_childrecord_exists, -02292);
 +
</pre>
 +
2) En la sección ejecutable, muestre “Deleting department 40....” Incluya una sentencia DELETE para suprimir el departamento con department_id 40.
 +
<pre>
 +
BEGIN
 +
  DBMS_OUTPUT.PUT_LINE(' Deleting department 40........');
 +
  delete from departments where department_id=40;
 +
</pre>
 +
3) Incluya una sección de excepciones para manejar la excepción e_childrecord_exists y muestre el mensaje adecuado.
 +
<pre>
 +
EXCEPTION
 +
  WHEN e_childrecord_exists THEN
 +
  DBMS_OUTPUT.PUT_LINE(' Cannot delete this department. There are employees in this department (child records exist.) ');
 +
END;
 +
</pre>
 +
La salida de ejemplo es la siguiente:
 +
[[Imatge:M2UF3_MEP_3.png |600px|center| Manejo de Excepciones Estándar]]
  
 
+
<source lang="java">
::SET SERVEROUTPUT ON;
+
SET SERVEROUTPUT ON
 
+
DECLARE
::SET VERIFY OFF;
+
  e_childrecord_exists EXCEPTION;
 
+
   PRAGMA EXCEPTION_INIT(e_childrecord_exists, -02292);
::ACCEPT p_num PROMPT  'Introdueixi el número de empleats amb sou més alt:  '
+
BEGIN
 
+
  DBMS_OUTPUT.PUT_LINE(' Deleting department 40........');
::DECLARE
+
   delete from departments where department_id=40;
    
+
EXCEPTION
:::v_num NUMBER(3) :=&p_num;
+
  WHEN e_childrecord_exists THEN
 
+
  DBMS_OUTPUT.PUT_LINE(' Cannot delete this department. There are employees in this department (child records exist.) ');
:::v_ename emp.ename%TYPE;
+
END;
 
+
</source>
:::v_sal emp.sal%TYPE;   
 
 
 
:::--declarem un cursor que guardarà totes les dades de la taula empleats
 
:::CURSOR emp_cursor IS
 
::::SELECT ename, sal
 
::::FROM emp
 
::::WHERE sal IS NOT NULL
 
::::ORDER BY sal DESC;
 
 
 
::BEGIN
 
 
 
:::OPEN emp_cursor; --obrim el cursor, aquest es posiciona apuntant el primer registre del cursor
 
 
 
:::FETCH emp_cursor INTO v_ename, v_sal; --carreguem el valor de la primera fila en les variables v_ename i v_sal, el cursor se situa en el següent registre
 
 
 
:::WHILE emp.cursor%ROWCOUNT <= v_num AND emp_curosr%FOUND LOOP -- mentre recuperem menys registres dels demanats i quedin registres
 
   
 
::::INSERT INTO top_dogs VALUES (v_ename,v_sal); --inserim una nova fila amb el valors carregats
 
       
 
::::FETCH emp_cursor INTO v_ename, v_sal; --fem que el cursor carregui de nou i passi al següent registre
 
   
 
:::END LOOP;
 
   
 
:::CLOSE emp_cursor;--tanquem el cursor, alliberem memòria
 
 
 
:::COMMIT;
 
 
 
::END;
 
 
 
::/
 
 
 
::SQL> SELECT *
 
:: 2  FROM TOP_DOGS;
 
 
 
 
 
*'''Exercici 2'''
 
 
 
Considera el cas de que varis empleats tinguin el mateix salari. Al igual que l'exercici anterior crea un bloc pl/sql que determini els n empleats amb sous més alts, però en aquest cas si se cal mostrar totes les persones que tinguin un mateix sou.
 
 
 
a. Si l'usuari introdueix n=2 han d'aparèixer tres registres (king, ford i scott, aquest últims tenen el mateix sou.
 
 
 
b. Si l'usuari introdueix n=3 han d'aparèixer 4 registres (king, ford i scott i jones).
 
 
 
c. Buida totes les files de la taula TOP_DOGS abans de prova l'exercici.
 
 
 
::SET SERVEROUTPUT ON;
 
 
 
::SET VERIFY OFF;
 
 
 
::ACCEPT p_num PROMPT  'Introdueixi el número de empleats amb sou més alt:  '
 
 
 
::DECLARE
 
    
 
:::v_num NUMBER(3) :=&p_num;
 
 
 
:::v_ename emp.ename%TYPE;
 
 
 
:::v_current_sal emp.sal%TYPE;   
 
 
 
:::v_last_sal emp.sal%TYPE := -1;
 
 
 
:::CURSOR emp_cursor IS
 
::::SELECT ename, sal
 
::::FROM emp
 
::::WHERE sal IS NOT NULL
 
::::ORDER BY sal DESC;
 
 
 
::BEGIN
 
 
 
:::OPEN emp_cursor;
 
 
 
:::FETCH emp_cursor INTO v_ename, v_current_sal;
 
 
 
:::WHILE (emp.cursor%ROWCOUNT <= v_num OR v_current_sal = v_last_sal) AND emp_curosr%FOUND LOOP
 
   
 
::::INSERT INTO top_dogs VALUES (v_ename,v_sal);  
 
       
 
::::FETCH emp_cursor INTO v_ename, v_current_sal;
 
   
 
:::END LOOP;
 
   
 
:::CLOSE emp_cursor;
 
 
 
:::COMMIT;
 
 
 
::END;
 
 
 
::/
 
 
 
::SQL> SELECT *
 
:: 2  FROM TOP_DOGS;:::OPEN emp_cursor; --obrim el cursor, aquest es posiciona apuntant el primer registre del cursor
 

Revisió de 16:13, 19 març 2018

Solución 8-1: Manejo de Excepciones Predefinidas

En esta práctica, escribirá un bloque PL/SQL que aplique una excepción predefinida para procesar un único registro a la vez. El bloque PL/SQL seleccionará el nombre del empleado con un valor de salario determinado.

1) Ejecute el comando en el archivo lab_05_01.sql para volver a crear la tabla messages.

2) En la sección de declaraciones, declare dos variables: v_ename del tipo employees.last_name y v_emp_sal del tipo employees.salary. Inicialice la última en 6000.

DECLARE
  v_ename employees.last_name%TYPE;
  v_emp_sal employees.salary%TYPE := 6000;

3) En la sección ejecutable, recupere los apellidos de los empleados cuyos salarios son iguales al valor de v_emp_sal. Si el salario introducido devuelve sólo una fila, inserte en la tabla messages el nombre y el importe del salario del empleado.

Nota: no utilice cursores explícitos.

BEGIN
  SELECT last_name INTO v_ename
  FROM employees
  WHERE salary = v_emp_sal;
  INSERT INTO messages (results)
  VALUES (v_ename || ' - ' || v_emp_sal);

4) Si el salario introducido no devuelve ninguna fila, maneje la excepción con un manejador de excepciones adecuado e inserte en la tabla messages el mensaje “No employee with a salary of <salary>”.

EXCEPTION
  WHEN no_data_found THEN
    INSERT INTO messages (results)
    VALUES ('No employee with a salary of '|| TO_CHAR(v_emp_sal));

5) Si el salario introducido devuelve varias filas, maneje la excepción con un manejador de excepciones adecuado e inserte en la tabla messages el mensaje “More than one employee with a salary of <salary>”.

WHEN too_many_rows THEN
  INSERT INTO messages (results)
  VALUES ('More than one employee with a salary of '|| TO_CHAR(v_emp_sal));

6) Maneje cualquier otra excepción con un manejador de excepciones adecuado e inserte en la tabla messages el mensaje “Some other error occurred”.

WHEN others THEN
  INSERT INTO messages (results)
  VALUES ('Some other error occurred.');
END;

7) Muestre las filas de la tabla messages para comprobar si el bloque PL/SQL se ha ejecutado correctamente.

/
SELECT * FROM messages;

La salida es la siguiente:

Manejo de Excepciones Predefinidas

8) Cambie el valor inicializado de v_emp_sal a 2000 y vuelva a ejecutar. La salida es la siguiente:

Manejo de Excepciones Predefinidas
DECLARE
  v_ename employees.last_name%TYPE;
  v_emp_sal employees.salary%TYPE := 6000;
BEGIN
  SELECT last_name INTO v_ename
  FROM employees
  WHERE salary = v_emp_sal;
  INSERT INTO messages (results)
  VALUES (v_ename || ' - ' || v_emp_sal);
EXCEPTION
  WHEN no_data_found THEN
    INSERT INTO messages (results)
    VALUES ('No employee with a salary of '|| TO_CHAR(v_emp_sal));
  WHEN too_many_rows THEN
    INSERT INTO messages (results)
    VALUES ('More than one employee with a salary of '|| TO_CHAR(v_emp_sal));
  WHEN others THEN
    INSERT INTO messages (results)
    VALUES ('Some other error occurred.');
END;
/
SELECT * FROM messages;

Solución 8-2: Manejo de Excepciones de Oracle Server Estándar

En esta práctica, escribirá un bloque PL/SQL que declare una excepción para el error de Oracle Server ORA-02292 (integrity constraint violated – child record found). El bloque comprobará la excepción y mostrará el mensaje de error.

1) En la sección de declaraciones, declare una excepción e_childrecord_exists. Asocie la excepción declarada al error de Oracle Server estándar –02292.

SET SERVEROUTPUT ON
DECLARE
  e_childrecord_exists EXCEPTION;
  PRAGMA EXCEPTION_INIT(e_childrecord_exists, -02292);

2) En la sección ejecutable, muestre “Deleting department 40....” Incluya una sentencia DELETE para suprimir el departamento con department_id 40.

BEGIN
  DBMS_OUTPUT.PUT_LINE(' Deleting department 40........');
  delete from departments where department_id=40;

3) Incluya una sección de excepciones para manejar la excepción e_childrecord_exists y muestre el mensaje adecuado.

EXCEPTION
  WHEN e_childrecord_exists THEN
  DBMS_OUTPUT.PUT_LINE(' Cannot delete this department. There are employees in this department (child records exist.) ');
END;

La salida de ejemplo es la siguiente:

Manejo de Excepciones Estándar
SET SERVEROUTPUT ON
DECLARE
  e_childrecord_exists EXCEPTION;
  PRAGMA EXCEPTION_INIT(e_childrecord_exists, -02292);
BEGIN
  DBMS_OUTPUT.PUT_LINE(' Deleting department 40........');
  delete from departments where department_id=40;
EXCEPTION
  WHEN e_childrecord_exists THEN
  DBMS_OUTPUT.PUT_LINE(' Cannot delete this department. There are employees in this department (child records exist.) ');
END;