Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* 1. Comprobacion de estado de serveroutput */
- SHOW SERVEROUTPUT ;
- /* RESULTADO */
- SERVEROUTPUT OFF ;
- /* 2. Escribir un bloque anónimo PL/SQL que muestre por
- pantalla el nombre de usuario de sesión en Oracle (usar la pseudoconstante USER). */
- DECLARE
- USUARIO VARCHAR2(100);
- BEGIN
- SELECT USER INTO USUARIO FROM dual;
- DBMS_OUTPUT.PUT_LINE('El usuario actual es :' || TO_CHAR(USUARIO));
- END;
- /
- /* 3. Activar SERVEROUTPUT e incluir esta activación en el archivo login.sql */
- SET SERVEROUTPUT ON;
- @login.SQL;
- /* 4. Compruebe lo que ocurre ejecutando de nuevo el bloque de código del Ejercicio 2 */
- Se mostro la salida definida dentro del bloque PL/SQL:
- El usuario actual es : OWN_USUARIO
- SERVEROUTPUT esta activo ya que se incluyo en el archivo login.SQL y cada vez que el usuario
- inicie sesion en oracle el estado de SERVEROUTPUT siempre será ON.
- /* 5. Escribe un bloque PL/SQL donde declare una variable, inicializada a la fecha actual,
- que imprime su valor en pantalla */
- DECLARE
- fecha DATE DEFAULT(SYSDATE);
- BEGIN
- DBMS_OUTPUT.PUT_LINE('La fecha actual es ' || TO_CHAR(fecha));
- END;
- /
- /* 6.Escribe un boque PL/SQL que almacene en una variable numérica el año actual. Muestra
- en pantalla el año. Puede usar las funciones to_number() y to_char(). */
- DECLARE
- YEAR NUMBER;
- BEGIN
- SELECT TO_CHAR(SYSDATE, 'YYYY') INTO YEAR FROM DUAL;
- DBMS_OUTPUT.PUT_LINE('La año actual es ' || TO_CHAR(YEAR));
- END;
- /
- /* 7. Cree una tabla PRODUCTO(CODPROD, NOMPROD, PRECIO), usando SQL (no usar un bloque
- PL/SQL).*/
- CREATE TABLE PRODUCTO(
- CODPROD INTEGER CONSTRAINT PK_CODPROD PRIMARY KEY,
- NOMPROD VARCHAR2(100) NOT NULL,
- PRECIO NUMBER (8,2) NOT NULL );
- /* 8. Añadir un producto a la tabla usando una sentencia insert dentro de un bloque PL/SQL */
- BEGIN
- INSERT INTO PRODUCTO VALUES(1,'LAPTOP',71.50);
- END;
- /
- /* 9. Añadir otro producto, ahora utilizando una lista de variables en la sentencia insert. */
- DECLARE
- CODIGO INTEGER:=2;
- PRODUCTO VARCHAR2(100):='DVD ROM';
- PRECIO NUMBER(8,2):=25;
- BEGIN
- INSERT INTO PRODUCTO VALUES(CODIGO,PRODUCTO,PRECIO);
- END;
- /
- /* 10. Añadir, ahora usando un registro PL/SQL, dos productos mas. */
- DECLARE
- PD PRODUCTO%ROWTYPE;
- BEGIN
- /* PRODUCTO 1 */
- PD.CODPROD:=3;
- PD.NOMPROD:= 'CD';
- PD.PRECIO :=1;
- INSERT INTO PRODUCTO VALUES PD;
- /* PRODUCTO 2 */
- PD.CODPROD:=4;
- PD.NOMPROD:= 'CD';
- PD.PRECIO :=1;
- INSERT INTO PRODUCTO VALUES PD;
- END;
- /
- /* 11. Borrar el primer producto insertado, e incrementar el precio de los demás en un 5% */
- DECLARE
- PORCENTAJE NUMBER(8,2):=0.05;
- CALCULOP NUMBER(8,2);
- INCREMENTO NUMBER(8,2);
- CURSOR C_ARTICULOS IS SELECT CODPROD,PRECIO FROM PRODUCTO;
- BEGIN
- FOR i IN C_ARTICULOS LOOP
- IF i.CODPROD=1 THEN
- DELETE FROM PRODUCTO WHERE CODPROD=1;
- END IF;
- CALCULOP := i.PRECIO * PORCENTAJE;
- INCREMENTO:= i.PRECIO + CALCULOP;
- UPDATE PRODUCTO SET PRECIO = INCREMENTO WHERE CODPROD=I.CODPROD;
- END LOOP;
- END;
- /
- /* 12. Obtener y mostrar en pantalla el número de productos que hay almacenados, usando
- select ... into y el mensaje “Hay n productos”. */
- DECLARE
- N INTEGER;
- BEGIN
- SELECT COUNT(*) INTO N FROM PRODUCTO;
- DBMS_OUTPUT.PUT_LINE(' Hay ' || TO_CHAR(N) || ' PRODUCTOS ');
- END;
- /
- /* 13. Obtener y muestra todos los datos de un producto (buscar a partir de la clave primaria,
- escogiendo un código de producto existente. Usar select ... into y un registro PL/SQL. */
- DECLARE
- PD PRODUCTO%ROWTYPE;
- BEGIN
- SELECT CODPROD,NOMPROD,PRECIO INTO PD FROM PRODUCTO WHERE CODPROD =3;
- DBMS_OUTPUT.PUT_LINE(' CODIGO :' || TO_CHAR(PD.CODPROD) || ' NOMBRE : ' || TO_CHAR(PD.NOMPROD) || ' PRECIO : ' || TO_CHAR(PD.PRECIO) );
- END;
- /
- /* 14. Modificar el Ejercicio 13 de forma que busque un producto que no exista. */
- DECLARE
- PD PRODUCTO%ROWTYPE;
- BEGIN
- SELECT CODPROD,NOMPROD,PRECIO INTO PD FROM PRODUCTO WHERE CODPROD =6;
- DBMS_OUTPUT.PUT_LINE(' CODIGO :' || TO_CHAR(PD.CODPROD) || ' NOMBRE : ' || TO_CHAR(PD.NOMPROD) || ' PRECIO : ' || TO_CHAR(PD.PRECIO) );
- EXCEPTION
- WHEN NO_DATA_FOUND THEN
- DBMS_OUTPUT.PUT_LINE(' NO EXISTE EL PRODUCTO ' );
- END;
- /* 15 . Modificar de nuevo el Ejercicio 13, ahora eliminando el where de la consulta, de forma que
- existan varios productos. */
- DECLARE
- CURSOR C_P IS SELECT CODPROD,NOMPROD,PRECIO FROM PRODUCTO;
- BEGIN
- FOR PD IN C_P LOOP
- DBMS_OUTPUT.PUT_LINE(' CODIGO :' || TO_CHAR(PD.CODPROD) || ' NOMBRE : ' || TO_CHAR(PD.NOMPROD) || ' PRECIO : ' || TO_CHAR(PD.PRECIO));
- END LOOP;
- END;
- /
- /* 16. Modificar el Ejercicio 12, que mostraba el número de productos, de forma que indique “No
- hay productos” en vez de “Hay 0 productos” */
- DECLARE
- N INTEGER;
- BEGIN
- SELECT COUNT(*) INTO N FROM PRODUCTO;
- IF N = 0 THEN
- DBMS_OUTPUT.PUT_LINE(' NO HAY PRODUCTOS ');
- ELSE
- DBMS_OUTPUT.PUT_LINE(' Hay ' || TO_CHAR(N) || ' PRODUCTOS ');
- END IF;
- END;
- /
- /* 17. Modificar de nuevo el bloque PL/SQL anterior, de forma que se indique que no hay
- produtos, que hay pocos (si hay entre 1 y 3) o el número exacto de productos existentes (si hay
- más de 3). */
- DECLARE
- N INTEGER;
- BEGIN
- SELECT COUNT(*) INTO N FROM PRODUCTO;
- IF N = 0 THEN
- DBMS_OUTPUT.PUT_LINE(' NO HAY PRODUCTOS ');
- ELSIF N > 0 AND N <=3 THEN
- DBMS_OUTPUT.PUT_LINE(' HAY POCOS PRODUCTOS ');
- ELSIF N > 3 THEN
- DBMS_OUTPUT.PUT_LINE(' Hay ' || TO_CHAR(N ) || ' PRODUCTOS ');
- END IF;
- END;
- /
- /* 18. Usar un bucle simple (LOOP ... END LOOP) para mostrar los números pares entre 1 y 10.
- Pueden usar la función mod(dividendo,divisor) para averiguar si el número es par o impar */
- DECLARE
- CONTADOR INTEGER:=0;
- BEGIN
- LOOP
- CONTADOR:= CONTADOR +1 ;
- EXIT WHEN CONTADOR > 10;
- IF MOD(CONTADOR,2)=0 THEN
- DBMS_OUTPUT.PUT_LINE(TO_CHAR(CONTADOR));
- END IF;
- END LOOP;
- END;
- /
- /* 19. Imprimir de nuevo los números pares entre 1 y 10, pero ahora usando un bucle WHILE */
- DECLARE
- CONTADOR INTEGER:=1;
- BEGIN
- WHILE (CONTADOR <=10)
- LOOP
- IF MOD(CONTADOR,2)=0 THEN
- DBMS_OUTPUT.PUT_LINE(TO_CHAR(CONTADOR));
- END IF;
- CONTADOR:= CONTADOR +1 ;
- END LOOP;
- END;
- /
- /* 20. Imprimir de nuevo los números pares entre 1 y 10, pero ahora usando un bucle FOR */
- BEGIN
- FOR CONTADOR IN 1..10 LOOP
- IF MOD(CONTADOR,2)=0 THEN
- DBMS_OUTPUT.PUT_LINE(TO_CHAR(CONTADOR));
- END IF;
- END LOOP;
- END;
- /
- /* 21. Utilizar un cursor y un bucle LOOP simple para recuperar y mostrar los datos de todos Los productos.
- Indicar al final cuantos productos hay */
- /* Esto Primero */
- SET serveroutput ON size 1000000;
- DECLARE
- CURSOR C_ARTICULOS IS SELECT * FROM PRODUCTO;
- CODIGO INTEGER;
- PRODUCTO VARCHAR2(100) ;
- PRECIO NUMBER(8,2);
- BEGIN
- OPEN C_ARTICULOS;
- LOOP
- FETCH C_ARTICULOS INTO CODIGO,PRODUCTO,PRECIO;
- EXIT WHEN C_ARTICULOS%NOTFOUND;
- DBMS_OUTPUT.PUT_LINE(' CODIGO :' || TO_CHAR(CODIGO) || ' NOMBRE : ' || TO_CHAR(PRODUCTO) || ' PRECIO : ' || TO_CHAR(PRECIO));
- END LOOP;
- DBMS_OUTPUT.PUT_LINE(' NUMERO DE PRODUCTOS : ' || C_ARTICULOS%ROWCOUNT);
- CLOSE C_ARTICULOS;
- END;
- /
- /* 22. Mostrar los datos de todos los productos, pero ahora usando un bucle
- WHILE para recorrer el cursor, e indicar también el número de productos encontrados. */
- DECLARE
- CURSOR C_ARTICULOS IS SELECT * FROM PRODUCTO;
- CODIGO INTEGER;
- PRODUCTO VARCHAR2(100) ;
- PRECIO NUMBER(8,2);
- BEGIN
- OPEN C_ARTICULOS;
- FETCH C_ARTICULOS INTO CODIGO,PRODUCTO,PRECIO;
- WHILE C_ARTICULOS%FOUND
- LOOP
- DBMS_OUTPUT.PUT_LINE(' CODIGO :' || TO_CHAR(CODIGO) || ' NOMBRE : ' || TO_CHAR(PRODUCTO) || ' PRECIO : ' || TO_CHAR(PRECIO));
- FETCH C_ARTICULOS INTO CODIGO,PRODUCTO,PRECIO;
- END LOOP;
- DBMS_OUTPUT.PUT_LINE(' NUMERO DE PRODUCTOS : ' || C_ARTICULOS%ROWCOUNT);
- CLOSE C_ARTICULOS;
- END;
- /
- /* 23. Recuperar e imprimir de nuevo los datos de todos los productos, y cuantos hay, pero ahora usa un bucle FOR */
- DECLARE
- CONTADOR INTEGER:=0;
- CURSOR C_ARTICULOS IS SELECT * FROM PRODUCTO;
- BEGIN
- FOR PD IN C_ARTICULOS LOOP
- DBMS_OUTPUT.PUT_LINE(' CODIGO :' || TO_CHAR(PD.CODPROD) || ' NOMBRE : ' || TO_CHAR(PD.NOMPROD) || ' PRECIO : ' || TO_CHAR(PD.PRECIO));
- CONTADOR:= CONTADOR+1;
- END LOOP;
- DBMS_OUTPUT.PUT_LINE(' NUMERO DE PRODUCTOS : ' || TO_CHAR(CONTADOR));
- END;
- /
- /* 24. Modificar el Ejercicio 23, de forma que se utilice la consulta directamente
- en el bucle FOR en vez de declarar explícitamente el cursor.
- */
- DECLARE
- CONTADOR INTEGER:=0;
- BEGIN
- FOR PD IN (SELECT * FROM PRODUCTO) LOOP
- DBMS_OUTPUT.PUT_LINE(' CODIGO :' || TO_CHAR(PD.CODPROD) || ' NOMBRE : ' || TO_CHAR(PD.NOMPROD) || ' PRECIO : ' || TO_CHAR(PD.PRECIO));
- CONTADOR:= CONTADOR+1;
- END LOOP;
- DBMS_OUTPUT.PUT_LINE(' NUMERO DE PRODUCTOS : ' || TO_CHAR(CONTADOR));
- END;
- /
- /* 25. Modificar ahora el Ejercicio 24, de forma que se recuperen solo los códigos de los productos.
- Ya no es necesario indicar cuantos productos hay. */
- BEGIN
- FOR PD IN (SELECT CODPROD FROM PRODUCTO) LOOP
- DBMS_OUTPUT.PUT_LINE(' CODIGO :' || TO_CHAR(PD.CODPROD));
- END LOOP;
- END;
- /
- /* 26. Recuperar ahora el doble del precio de los productos, usando el bucle FOR con la consulta directamente */
- BEGIN
- FOR PD IN (SELECT PRECIO * 2 AS P FROM PRODUCTO) LOOP
- DBMS_OUTPUT.PUT_LINE(' PRECIO :' || TO_CHAR(PD.P));
- END LOOP;
- END;
- /
- /* 27. Escribir un bloque PL/SQL que modifique el producto 3, poniendo Monitor TFT 21'' como nombre del producto, y 497 como precio.
- Si no existe el producto con código 3, el bloque PL/SQL escrito debe insertar los valores indicados.
- El uso del cursor implícito SQL podría ayudar a resolver este ejercicio. */
- DECLARE
- CODIGO INTEGER:=3;
- NOMBRE VARCHAR2(100):='Monitor TFT 21';
- PRICE NUMBER(8,2):=497;
- EXISTENCIA INTEGER;
- BEGIN
- SELECT COUNT(*) INTO EXISTENCIA FROM PRODUCTO WHERE CODPROD=CODIGO;
- IF EXISTENCIA=0 THEN
- INSERT INTO PRODUCTO VALUES(CODIGO,NOMBRE,PRICE);
- DBMS_OUTPUT.PUT_LINE(TO_CHAR(CODIGO) ||' ' || TO_CHAR(NOMBRE) ||' ' || ' ' ||TO_CHAR(PRICE) || ' PRODUCTO INSERTADO ');
- ELSE
- UPDATE PRODUCTO SET NOMPROD=NOMBRE,PRECIO=PRICE WHERE CODPROD=CODIGO;
- DBMS_OUTPUT.PUT_LINE(TO_CHAR(CODIGO) ||' ' || TO_CHAR(NOMBRE) ||' ' || ' ' ||TO_CHAR(PRICE) || ' PRODUCTO ACTUALIZADO ');
- END IF;
- END;
- /
- /* 28. En un bloque PL/SQL, intentar crear directamente una tabla T con un campo numérico C (fallara). */
- BEGIN
- CREATE TABLE T(
- C NUMBER
- );
- END;
- /
- /* 29. Crear la tabla usando SQL dinámico y EXECUTE IMMEDIATE dentro de un bloque PL/SQL.
- Comprobar que efectivamente la tabla fue creada, con una consulta simple sobre el catálogo de Oracle.
- Finalmente, eliminar (DROP) la tabla. */
- DECLARE
- S_QL VARCHAR2(255);
- TABLA VARCHAR2(100);
- DROP_TABLA VARCHAR2(255);
- BEGIN
- S_QL:='CREATE TABLE T(C NUMBER)';
- EXECUTE IMMEDIATE S_QL;
- SELECT TABLE_NAME INTO TABLA FROM USER_TABLES WHERE TABLE_NAME='T';
- DBMS_OUTPUT.PUT_LINE(' TABLA : ' || TABLA || ' CREADA ' );
- DROP_TABLA:='DROP TABLE T';
- EXECUTE IMMEDIATE DROP_TABLA;
- DBMS_OUTPUT.PUT_LINE(' TABLA : ' || TABLA || ' ELIMINADA ' );
- END;
- /
- /* 30. De nuevo en un bloque PL/SQL, crear una tabla T2 con un campo S alfanumérico, e insertar una fila en esa tabla. */
- DECLARE
- S_QL VARCHAR2(255);
- TABLA VARCHAR2(100);
- BEGIN
- S_QL:='CREATE TABLE T2(S VARCHAR2(100))';
- EXECUTE IMMEDIATE S_QL;
- SELECT TABLE_NAME INTO TABLA FROM USER_TABLES WHERE TABLE_NAME='T2';
- DBMS_OUTPUT.PUT_LINE(' TABLA : ' || TABLA || ' CREADA ' );
- EXECUTE IMMEDIATE 'INSERT INTO T2 VALUES(''B454'')';
- DBMS_OUTPUT.PUT_LINE( SQL%ROWCOUNT || ' FILA INSERTADA ');
- END;
- /
- /* 31. Recuperar e imprimir de nuevo los datos de todos los productos, ahora usando SQL dinámico. */
- DECLARE
- TYPE C_REFERIDO IS REF CURSOR;
- C_ARTICULOS C_REFERIDO;
- CONSULTA VARCHAR2(255);
- PD PRODUCTO%ROWTYPE;
- BEGIN
- CONSULTA:='SELECT * FROM PRODUCTO';
- OPEN C_ARTICULOS FOR CONSULTA;
- LOOP
- FETCH C_ARTICULOS INTO PD;
- EXIT WHEN C_ARTICULOS%NOTFOUND;
- DBMS_OUTPUT.PUT_LINE(' CODIGO :' || TO_CHAR(PD.CODPROD) || ' NOMBRE : ' || TO_CHAR(PD.NOMPROD) || ' PRECIO : ' || TO_CHAR(PD.PRECIO));
- END LOOP;
- CLOSE C_ARTICULOS;
- END;
- /
- /* 32. Alterar la tabla de productos,
- añadiendo una restricción c_precio_positivo que compruebe que el precio de un producto es mayor que cero.
- */
- ALTER TABLE PRODUCTO
- ADD CONSTRAINT c_precio_positivo CHECK(PRECIO > 0);
- /* 33. Averiguar como podría controlar el error de clave primaria (o restricción única) duplicada. */
- USANDO LA EXCEPCIÓN
- DUP_VAL_ON_INDEX
- /* 34. Crear un bloque PL/SQL en el que se inserta un producto con código 3, ya existente. Haz el control de excepciones
- de forma que un error de clave primaria duplicada
- se ignore (no se inserta el producto pero el bloque PL/SQL se ejecuta correctamente).
- Si intentamos insertar un producto con precio negativo, debe aparecer un error.
- */
- DECLARE
- CODIGO INTEGER:=3;
- PRODUCTO VARCHAR2(100):='HUB';
- PRECIO NUMBER(8,2):=1;
- BEGIN
- IF PRECIO > 0 THEN
- INSERT INTO PRODUCTO VALUES(CODIGO,PRODUCTO,PRECIO);
- ELSE
- DBMS_OUTPUT.PUT_LINE( ' PRECIO NO PUEDE SER NEGATIVO ');
- END IF;
- EXCEPTION
- WHEN DUP_VAL_ON_INDEX THEN
- DBMS_OUTPUT.PUT_LINE( ' CLAVE PRIMARIA DUPLICADA ');
- END;
- /
- /* 35. Eliminar la restricción c_precio_positivo creada en el Ejercicio 32.*/
- ALTER TABLE PRODUCTO
- DROP CONSTRAINT c_precio_positivo;
- /* 36. Escribe un bloque PL/SQL donde usas un registro para almacenar los datos de un producto.
- El bloque insertará ese producto, pero si el precio no es positivo generar ´a una excepción de tipo precio_prod_invalido,
- que deberá declarar previamente, en vez de realizar la inserción */
- DECLARE
- precio_prod_invalido EXCEPTION;
- PD PRODUCTO%ROWTYPE;
- BEGIN
- PD.CODPROD:=10;
- PD.NOMPROD:= 'CD';
- PD.PRECIO :=-1;
- IF PD.PRECIO > 0 THEN
- INSERT INTO PRODUCTO VALUES PD;
- ELSE
- RAISE precio_prod_invalido;
- END IF;
- EXCEPTION
- WHEN precio_prod_invalido THEN
- DBMS_OUTPUT.PUT_LINE( ' PRECIO NO PUEDE SER NEGATIVO ');
- END;
- /
- /* 37. Modificar el Ejercicio 36, de forma que capture la excepción elevada. */
- DECLARE
- precio_prod_invalido EXCEPTION;
- PD PRODUCTO%ROWTYPE;
- BEGIN
- PD.CODPROD:=11;
- PD.NOMPROD:= 'CD';
- PD.PRECIO :=-1;
- IF PD.PRECIO > 0 THEN
- INSERT INTO PRODUCTO VALUES PD;
- ELSE
- RAISE precio_prod_invalido;
- END IF;
- EXCEPTION
- WHEN precio_prod_invalido THEN
- RAISE_APPLICATION_ERROR(-20001,' PRECIO NO PUEDE SER NEGATIVO ');
- END;
- /
- /* 38. Modificar de nuevo el Ejercicio 36, de forma que ahora captures
- la excepción elevada y produces otra, con SQLCODE y mensaje de error especifico, usando RAISE_APPLICATION_ERROR */
- DECLARE
- precio_prod_invalido EXCEPTION;
- PD PRODUCTO%ROWTYPE;
- err_num NUMBER;
- BEGIN
- PD.CODPROD:=12;
- PD.NOMPROD:= 'CD';
- PD.PRECIO :=-1;
- IF PD.PRECIO > 0 THEN
- INSERT INTO PRODUCTO VALUES PD;
- ELSE
- RAISE precio_prod_invalido;
- END IF;
- EXCEPTION
- WHEN precio_prod_invalido THEN
- err_num := SQLCODE;
- DBMS_OUTPUT.PUT_LINE(' ERROR PRECIO NEGATIVO :'||TO_CHAR(err_num));
- RAISE_APPLICATION_ERROR(-20001,' PRECIO NO PUEDE SER NEGATIVO ');
- END;
- /
- /* 39. Crear un procedimiento InsertaProd para insertar un producto. Usar tres parámetros,
- uno para cada atributo (código, nombre, precio).
- */
- CREATE OR REPLACE PROCEDURE InsertaProd (CODIGO INTEGER, NOMBRE VARCHAR2, PRECIO NUMBER)
- IS
- BEGIN
- INSERT INTO PRODUCTO VALUES(CODIGO,NOMBRE,PRECIO);
- END;
- /
- /* 40. Revisar si hubo errores de compilación en la creación del procedimiento, y obtener la información sobre el procedimiento
- usando las tablas del catálogo USER_PROCEDURES y USER_OBJECTS (o su sinónimo OBJ). */
- SHOW ERRORS;
- No hay errores
- /*OBTENIENDO INFORMACION DEL PROCEDIMIENTO DESDE USER_PROCEDURES */
- SELECT * FROM USER_PROCEDURES WHERE OBJECT_NAME='INSERTAPROD' ;
- /*OBTENIENDO INFORMACION DEL PROCEDIMIENTO DESDE USER_OBJECTS */
- SELECT * FROM USER_OBJECTS WHERE OBJECT_TYPE='PROCEDURE' AND OBJECT_NAME='INSERTAPROD' ;
- /* 41. Examinar la estructura de la tabla USER_SOURCE y usarla para obtener el código fuente PL/SQL del procedimiento InsertaProd. */
- /* Examinando Estructura */
- DESCRIBE USER_SOURCE;
- SELECT * FROM USER_SOURCE;
- /* obtener el código fuente PL/SQL del procedimiento InsertaProd. */
- SELECT LINE, TEXT FROM USER_SOURCE WHERE NAME='INSERTAPROD';
- /* 42. Ejecutar el procedimiento, insertando un producto mediante CALL y otro usando EXEC. */
- /* Mediante CALL*/
- CALL InsertaProd(5,'USB',10);
- /* MEDIANTE EXEC */
- EXEC InsertaProd(7,'MEMORIA RAM 2GB',15);
- /* 43. Averiguar que ocurre si creamos un bloque PL/SQL en el que insertamos varios productos llamando al procedimiento InsertaProd,
- pero una de las llamadas al procedimiento falla. Por ejemplo, trata de insertar la misma fila 2 veces. */
- Se ejecuta el bloque PL/SQL y muestra el siguiente error:
- ORA-00001: restricción única (OWN_USUARIO.PK_CODPROD)
- 00001. 00000 - "unique constraint (%s.%s) violated"
- Se intento insertar la misma fila 2 veces en la tabla PRODUCTO la cual contiene
- una clave primaria CODPROD se activa el constraint correspondiante de manera que si se intenta
- insertar una fila cuya clave primaria coincida con una existente se lanza el error de restricción unica,
- no se puede realizar la insercion a la tabla PRODUCTO en cada una de las llamadas al procedimiento
- InsertaProd, hasta que el valor del campo CODPROD no coincida con los existentes en la tabla.
- /* 44. Intentar crear otro procedimiento InsertaProd que inserte un
- producto tomando como único parámetro un registro de tipo producto.
- */
- CREATE OR REPLACE PROCEDURE InsertaProd(PD PRODUCTO%ROWTYPE)
- IS
- BEGIN
- INSERT INTO PRODUCTO VALUES(PD.CODPROD,PD.NOMPROD,PD.PRECIO);
- END;
- /
- /* COMO USARLO -- TIP ! */
- DECLARE
- ARTICULOS PRODUCTO%ROWTYPE;
- BEGIN
- ARTICULOS.CODPROD:=8;
- ARTICULOS.NOMPROD:='USB 2.0';
- ARTICULOS.PRECIO:=20;
- InsertaProd(ARTICULOS);
- END;
- /
- /* 45. Crea un procedimiento ListaProds que toma como parámetro un valor numérico
- y lista todos los productos con precio mayor o igual a ese valor
- */
- CREATE OR REPLACE PROCEDURE ListaProds(VALOR NUMBER)
- IS
- BEGIN
- FOR PD IN (SELECT NOMPROD FROM PRODUCTO WHERE PRECIO >=VALOR) LOOP
- DBMS_OUTPUT.PUT_LINE( TO_CHAR(PD.NOMPROD) );
- END LOOP;
- END;
- /
- /* 46. Crear una función triple que devuelva el triple del número que toma como argumento. */
- CREATE OR REPLACE FUNCTION TRIPLE(NUMERO NUMBER)
- RETURN NUMBER
- IS RESULTADO NUMBER;
- BEGIN
- RESULTADO:= (NUMERO * 3);
- RETURN RESULTADO;
- END;
- /* 47. Crear una función PVP que toma como argumento un precio (de coste) del producto y devuelve el precio de venta al público,
- que resulta de aplicarle a ese precio de coste un margen comercial del 20%. */
- CREATE OR REPLACE FUNCTION PVP(PRECIO NUMBER)
- RETURN NUMBER
- IS
- PORCENTAJE NUMBER;
- P_VENTA_PUBLICO NUMBER;
- BEGIN
- PORCENTAJE := (PRECIO * 0.20);
- P_VENTA_PUBLICO:= PRECIO + PORCENTAJE;
- RETURN P_VENTA_PUBLICO;
- END;
- /
- /* 48. Crea una vista VPRODUCTO que obtenga todos los datos de los productos más el precio de venta al público. */
- CREATE VIEW VPRODUCTO AS
- SELECT CODPROD, NOMPROD, PRECIO, PVP(PRECIO) AS PRECIO_VENTA FROM PRODUCTO;
- /* 49. Examinar los datos de la vista VPRODUCTO. Modificar la función PVP para que aplique un margen del 22%,
- y vuelve a examinar los datos de la vista. */
- /* EXAMINANDO DATOS DE LA VISTA */
- SELECT * FROM VPRODUCTO; /* PRECIO DE VENTA CON MARGEN DE 20% */
- /* MODIFICANDO FUNCIÓN */
- CREATE OR REPLACE FUNCTION PVP(PRECIO NUMBER)
- RETURN NUMBER
- IS
- PORCENTAJE NUMBER;
- P_VENTA_PUBLICO NUMBER;
- BEGIN
- PORCENTAJE := (PRECIO * 0.22);
- P_VENTA_PUBLICO:= PRECIO + PORCENTAJE;
- RETURN P_VENTA_PUBLICO;
- END;
- /
- /* EXAMINANDO DATOS DE LA VISTA */
- SELECT * FROM VPRODUCTO; /* PRECIO DE VENTA CON MARGEN DEL 22% */
- /* 50. Crear un paquete (package) gestprod que usará para gestionar los productos. Debe incluir las signaturas de:
- ? Dos procedimientos InsertaProd, uno que tome 3 parámetros (código, nombre y precio) y otro que tome
- solo un parámetro: un registro de tipo producto.
- ? Una función BorraProd que borre un producto. Devolverá un valor booleano, indicando si borro el producto o no (porque no existía). */
- CREATE OR REPLACE PACKAGE gestprod AS
- PROCEDURE InsertaProd (CODIGO INTEGER, NOMBRE VARCHAR2, PRECIO NUMBER);
- PROCEDURE InsertaProd(PD PRODUCTO%ROWTYPE);
- FUNCTION BorraProd(CODIGO INTEGER) RETURN BOOLEAN;
- END gestprod;
- /* 51. Crea el cuerpo del paquete (package body) para el paquete gestprod. */
- CREATE OR REPLACE PACKAGE BODY gestprod AS
- PROCEDURE InsertaProd (CODIGO INTEGER, NOMBRE VARCHAR2, PRECIO NUMBER)
- IS
- BEGIN
- INSERT INTO PRODUCTO VALUES(CODIGO,NOMBRE,PRECIO);
- END InsertaProd ;
- PROCEDURE InsertaProd(PD PRODUCTO%ROWTYPE)
- IS
- BEGIN
- INSERT INTO PRODUCTO VALUES(PD.CODPROD,PD.NOMPROD,PD.PRECIO);
- END InsertaProd ;
- FUNCTION BorraProd(CODIGO INTEGER)
- RETURN BOOLEAN
- IS
- ESTADO_ELIMINACION BOOLEAN;
- EXISTENCIA INTEGER;
- BEGIN
- SELECT COUNT(*) INTO EXISTENCIA FROM PRODUCTO WHERE CODPROD=CODIGO;
- IF EXISTENCIA = 0 THEN
- ESTADO_ELIMINACION:= FALSE;
- ELSE
- DELETE FROM PRODUCTO WHERE CODPROD=CODIGO;
- ESTADO_ELIMINACION:= TRUE;
- END IF;
- RETURN ESTADO_ELIMINACION;
- END BorraProd;
- END gestprod;
- /* 52. Crear un trigger que fuerce a que los precios de los productos sean positivos. Controla solo las modificaciones (update) de datos. */
- CREATE OR REPLACE TRIGGER TR_PRECIO_POSITIVO_UPDATE
- BEFORE UPDATE ON PRODUCTO
- FOR EACH ROW
- DECLARE
- POSITIVO NUMBER(8,2);
- BEGIN
- POSITIVO:=ABS(:NEW.PRECIO);
- :NEW.PRECIO:=POSITIVO;
- END ;
- /
- /* 53. Crear otro trigger que fuerce a que los precios de los productos sean positivos, pero en este caso controla solo las inserciones. */
- CREATE OR REPLACE TRIGGER TR_PRECIO_POSITIVO
- BEFORE INSERT ON PRODUCTO
- FOR EACH ROW
- DECLARE
- POSITIVO NUMBER(8,2);
- BEGIN
- POSITIVO:=ABS(:NEW.PRECIO);
- :NEW.PRECIO:=POSITIVO;
- END ;
- /
- /* 54. Repitir el Ejercicio 32, añadiendo de nuevo la restricción check que comprueba que los precios de los productos son positivos.
- Ahora compruebe que se activa antes, la restricción o el trigger. */
- ALTER TABLE PRODUCTO
- ADD CONSTRAINT c_precio_positivo CHECK(PRECIO > 0);
- Se activa antes el TRIGGER TR_PRECIO_POSITIVO porque tiene el modificador BEFORE
- antes de realizar la insercion ejecuta lo que esta en el cuerpo del disparador, lo cual es en este caso
- forzar a que el precio del producto siempre sea positivo, luego se ejecuta la restricción CHECK
- /* 55. Comprobar que orden sigue Oracle en la activación de 2 triggers que comparten tabla, evento, granularidad y tiempo de activación.*/
- Antes de comenzar a ejecutar la orden que provoca el disparo se ejecutaran los triggers del tipo before.... FOR each statement
- Para cada fila afectada por la orden:
- a) se ejecutan los triggers del tipo before … FOR each ROW
- b) se ejecuta la actualización de la fila
- c) se ejecutan los triggers after... FOR each ROW
- Una vez realizada la operación se ejecuta el after … FOR each statement
- /* Comprobación : Se creo el trigger INCREMENTO */
- CREATE OR REPLACE TRIGGER INCREMENTO
- BEFORE INSERT ON PRODUCTO
- FOR EACH ROW
- DECLARE
- INCREMENTO NUMBER(8,2);
- RESULTADO NUMBER(8,2);
- BEGIN
- INCREMENTO:=10;
- RESULTADO:= :NEW.PRECIO+ INCREMENTO;
- :NEW.PRECIO:=RESULTADO;
- END ;
- /
- Se insertaron datos en la tabla PRODUCTO y el TRIGGER que se ejecutaba
- era el TR_PRECIO_POSITIVO, se desactivo con ALTER TRIGGER TR_PRECIO_POSITIVO DISABLE y se volvio activar
- ahora el TRIGGER que se ejecutaba antes era el INCREMENTO posiblemente el orden de ejecucion de triggers
- del mismo tipo es indeterminado
- /* 56. Cree las tablas para almacenar facturas y líneas de factura: */
- /* CREANDO TABLA FACTURAS */
- CREATE TABLE FACTURAS(
- NUMERO INTEGER CONSTRAINT PK_NUM_FACTURA PRIMARY KEY,
- FECHA DATE NOT NULL,
- TOTAL NUMBER(8,2)
- );
- /* CREANDO TABLA LINEAS */
- CREATE TABLE LINEAS(
- NUMFAC INTEGER NOT NULL CONSTRAINT FK_NUM_FACTURA
- REFERENCES FACTURAS(NUMERO),
- NUMLI INTEGER NOT NULL,
- CODPROD INTEGER NOT NULL CONSTRAINT FK_CODPROD
- REFERENCES PRODUCTO(CODPROD),
- CANTIDAD INTEGER NOT NULL,
- PRECIO NUMBER(8,2),
- SUBTOTAL NUMBER(8,2)
- );
- /* 57. Asegurar de que cuando se añade una factura el total sea 0. */
- CREATE OR REPLACE TRIGGER TR_TOTAL_CERO
- BEFORE INSERT ON FACTURAS
- FOR EACH ROW
- BEGIN
- :NEW.TOTAL:=0;
- END ;
- /
- /* 58. Cuando se añade una línea de factura, debe especificarse (entre otras cosas) el código de producto y la cantidad. Crea un trigger t_subtotal_ins
- para que tanto el precio como el subtotal de esa línea se cubran automáticamente */
- CREATE OR REPLACE TRIGGER t_subtotal_ins
- BEFORE INSERT ON LINEAS
- FOR EACH ROW
- DECLARE
- CODIGO INTEGER;
- PRECIO_P NUMBER(8,2);
- SUBTOTAL NUMBER(8,2);
- BEGIN
- CODIGO := :NEW.CODPROD;
- SELECT PRECIO INTO PRECIO_P FROM PRODUCTO WHERE CODPROD=CODIGO;
- :NEW.PRECIO:=PRECIO_P;
- SUBTOTAL:= (:NEW.CANTIDAD * PRECIO_P);
- :NEW.SUBTOTAL:=SUBTOTAL;
- END ;
- /
- /* 59. Crea otro trigger t_subtotal_upd, similar al realizado para el Ejercicio 58, para realizar el mismo cometido
- cuando se modifica una línea de factura. */
- CREATE OR REPLACE TRIGGER t_subtotal_upd
- BEFORE UPDATE ON LINEAS
- FOR EACH ROW
- DECLARE
- CODIGO INTEGER;
- PRECIO_P NUMBER(8,2);
- SUBTOTAL NUMBER(8,2);
- BEGIN
- CODIGO := :NEW.CODPROD;
- SELECT PRECIO INTO PRECIO_P FROM PRODUCTO WHERE CODPROD=CODIGO;
- :NEW.PRECIO:=PRECIO_P;
- SUBTOTAL:= (:NEW.CANTIDAD * PRECIO_P);
- :NEW.SUBTOTAL:=SUBTOTAL;
- END ;
- /
- /* 60. Combina los triggers de los ejercicios 58 y 59 en un ´unico trigger t_subtotal. Decidir si se debe eliminar o deshabilitar
- los triggers t_subtotal_ins y t_subtotal_upd una vez se haya creado. */
- /* Elimiando Triggers */
- DROP TRIGGER t_subtotal_ins;
- DROP TRIGGER t_subtotal_upd;
- CREATE OR REPLACE TRIGGER t_subtotal
- BEFORE INSERT OR UPDATE ON LINEAS
- FOR EACH ROW
- DECLARE
- CODIGO INTEGER;
- PRECIO_P NUMBER(8,2);
- SUBTOTAL NUMBER(8,2);
- BEGIN
- CODIGO := :NEW.CODPROD;
- SELECT PRECIO INTO PRECIO_P FROM PRODUCTO WHERE CODPROD=CODIGO;
- :NEW.PRECIO:=PRECIO_P;
- SUBTOTAL:= (:NEW.CANTIDAD * PRECIO_P);
- :NEW.SUBTOTAL:=SUBTOTAL;
- END;
- /
- /* 61. Crear el(los) trigger(s) necesarios para mantener correctamente actualizado el total de la factura. */
- DROP TRIGGER t_subtotal;
- /* Me parece asi: 1 trigger para todo al mismo tiempo que se inserta se actualiza
- el total de la tabla factura, lo mismo cuando se hace el update se actualiza el total, además de eso se obtiene el precio y subtotal de la tabla lineas, asi que no es necesario el anterior asi que DROP TRIGGER */
- CREATE OR REPLACE TRIGGER FACTURA_TRANSACCION
- BEFORE INSERT OR UPDATE ON LINEAS
- FOR EACH ROW
- DECLARE
- CODIGO INTEGER;
- NUM_FACTURA NUMBER;
- PRECIO_P NUMBER(8,2);
- SUBTOTAL NUMBER(8,2);
- TOTAL_ACTUAL NUMBER(8,2);
- TOTAL_ACUMULADO NUMBER(8,2);
- TOTAL_ANTERIOR NUMBER(8,2);
- BEGIN
- NUM_FACTURA:=:NEW.NUMFAC;
- CODIGO := :NEW.CODPROD;
- SELECT PRECIO INTO PRECIO_P FROM PRODUCTO WHERE CODPROD=CODIGO;
- :NEW.PRECIO:=PRECIO_P;
- SUBTOTAL:= (:NEW.CANTIDAD * PRECIO_P);
- :NEW.SUBTOTAL:=SUBTOTAL;
- SELECT TOTAL INTO TOTAL_ACTUAL FROM FACTURAS WHERE NUMERO=NUM_FACTURA;
- IF INSERTING THEN
- TOTAL_ACUMULADO:= SUBTOTAL + TOTAL_ACTUAL;
- UPDATE FACTURAS SET TOTAL=TOTAL_ACUMULADO WHERE NUMERO=NUM_FACTURA;
- ELSIF UPDATING THEN
- TOTAL_ANTERIOR := (TOTAL_ACTUAL - :OLD.SUBTOTAL);
- TOTAL_ACUMULADO:= (SUBTOTAL + TOTAL_ANTERIOR);
- UPDATE FACTURAS SET TOTAL=TOTAL_ACUMULADO WHERE NUMERO=NUM_FACTURA;
- END IF;
- END;
- /
Advertisement
Add Comment
Please, Sign In to add comment