geofox

Guia 5

Mar 2nd, 2012
2,003
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PL/SQL 30.25 KB | None | 0 0
  1. /* 1. Comprobacion de estado de  serveroutput */
  2.  
  3. SHOW SERVEROUTPUT ;
  4.  
  5. /* RESULTADO  */
  6. SERVEROUTPUT OFF ;
  7.  
  8. /* 2. Escribir un bloque anónimo PL/SQL que muestre por
  9. pantalla el nombre de usuario de sesión en Oracle (usar la pseudoconstante USER). */
  10.  
  11. DECLARE
  12. USUARIO VARCHAR2(100);
  13. BEGIN
  14.     SELECT USER INTO USUARIO FROM dual;
  15.     DBMS_OUTPUT.PUT_LINE('El usuario actual es :' ||  TO_CHAR(USUARIO));
  16. END;
  17. /
  18.  
  19.  
  20. /* 3. Activar SERVEROUTPUT e incluir esta activación en el archivo login.sql */
  21.  
  22. SET SERVEROUTPUT ON;
  23. @login.SQL;
  24.  
  25. /* 4. Compruebe lo que ocurre ejecutando de nuevo el bloque de código del Ejercicio 2 */
  26.  
  27. Se mostro la salida definida dentro del bloque PL/SQL:
  28. El usuario actual es : OWN_USUARIO
  29.  
  30. SERVEROUTPUT esta activo ya que se incluyo en el archivo login.SQL y cada vez que el usuario
  31. inicie sesion en oracle el estado de SERVEROUTPUT siempre será ON.
  32.  
  33.  
  34.  
  35.  
  36. /* 5. Escribe un bloque PL/SQL donde declare una variable, inicializada a la fecha actual,
  37.     que imprime su valor en pantalla  */
  38.  
  39.  
  40. DECLARE
  41. fecha DATE DEFAULT(SYSDATE);
  42. BEGIN
  43.    
  44.     DBMS_OUTPUT.PUT_LINE('La fecha actual es ' || TO_CHAR(fecha));
  45. END;
  46. /
  47.  
  48. /* 6.Escribe un boque PL/SQL que almacene en una variable numérica el año actual. Muestra
  49.    en pantalla el año. Puede usar las funciones to_number() y to_char(). */
  50.  
  51.  
  52. DECLARE
  53. YEAR NUMBER;
  54. BEGIN
  55.     SELECT TO_CHAR(SYSDATE, 'YYYY') INTO YEAR FROM DUAL;
  56.     DBMS_OUTPUT.PUT_LINE('La año actual es ' || TO_CHAR(YEAR));
  57. END;
  58. /
  59.  
  60.  
  61.  
  62. /* 7. Cree una tabla PRODUCTO(CODPROD, NOMPROD, PRECIO), usando SQL (no usar un bloque
  63. PL/SQL).*/
  64.  
  65. CREATE TABLE PRODUCTO(
  66. CODPROD INTEGER CONSTRAINT PK_CODPROD PRIMARY KEY,
  67. NOMPROD VARCHAR2(100) NOT NULL,
  68. PRECIO NUMBER (8,2) NOT NULL );
  69.  
  70. /* 8. Añadir un producto a la tabla usando una sentencia insert dentro de un bloque PL/SQL */
  71.  
  72. BEGIN
  73.       INSERT INTO PRODUCTO VALUES(1,'LAPTOP',71.50);
  74.  
  75. END;
  76. /
  77.  
  78. /* 9. Añadir otro producto, ahora utilizando una lista de variables en la sentencia insert.  */
  79.  
  80. DECLARE
  81. CODIGO INTEGER:=2;
  82. PRODUCTO VARCHAR2(100):='DVD ROM';
  83. PRECIO NUMBER(8,2):=25;
  84. BEGIN
  85.     INSERT INTO PRODUCTO VALUES(CODIGO,PRODUCTO,PRECIO);
  86.    
  87.  
  88. END;
  89. /
  90.  
  91. /* 10. Añadir, ahora usando un registro PL/SQL, dos productos mas. */
  92. DECLARE
  93. PD  PRODUCTO%ROWTYPE;
  94.  
  95. BEGIN
  96.               /* PRODUCTO 1 */
  97.                PD.CODPROD:=3;
  98.                PD.NOMPROD:= 'CD';
  99.                PD.PRECIO :=1;
  100.                
  101.                  INSERT INTO PRODUCTO VALUES PD;
  102.                  
  103.                    /* PRODUCTO 2 */
  104.                PD.CODPROD:=4;
  105.                PD.NOMPROD:= 'CD';
  106.                PD.PRECIO :=1;
  107.    
  108.                 INSERT INTO PRODUCTO VALUES PD;
  109.  
  110.    
  111. END;
  112. /
  113.  
  114. /*  11. Borrar el primer producto insertado, e incrementar el precio de los demás en un 5%  */
  115.  
  116. DECLARE
  117.     PORCENTAJE NUMBER(8,2):=0.05;
  118.      CALCULOP NUMBER(8,2);
  119.     INCREMENTO NUMBER(8,2);
  120.    
  121.     CURSOR C_ARTICULOS  IS SELECT CODPROD,PRECIO FROM PRODUCTO;
  122.    
  123.  
  124. BEGIN
  125.  
  126.       FOR i IN  C_ARTICULOS  LOOP
  127.      
  128.       IF i.CODPROD=1 THEN
  129.      
  130.       DELETE FROM PRODUCTO WHERE CODPROD=1;
  131.    
  132.      END IF;
  133.      
  134.        CALCULOP := i.PRECIO *  PORCENTAJE;
  135.        INCREMENTO:= i.PRECIO +  CALCULOP;
  136.      
  137.       UPDATE PRODUCTO SET PRECIO = INCREMENTO WHERE CODPROD=I.CODPROD;
  138.                
  139.        END LOOP;
  140.   END;
  141. /      
  142.  
  143. /* 12.   Obtener y mostrar en pantalla el número de productos que hay almacenados, usando
  144. select ... into y el mensaje “Hay n productos”.     */
  145.  
  146. DECLARE
  147.    N INTEGER;
  148.  
  149. BEGIN
  150.          SELECT COUNT(*) INTO N FROM  PRODUCTO;
  151.        
  152.          DBMS_OUTPUT.PUT_LINE(' Hay  ' || TO_CHAR(N) ||  ' PRODUCTOS ');
  153.  
  154. END;
  155. /
  156.  
  157. /* 13. Obtener y muestra todos los datos de un producto (buscar a partir de la clave primaria,
  158. escogiendo un código de producto existente. Usar select ... into y un registro PL/SQL. */
  159.  
  160. DECLARE
  161.  
  162.   PD PRODUCTO%ROWTYPE;
  163.  
  164.  
  165. BEGIN
  166.      SELECT CODPROD,NOMPROD,PRECIO INTO PD FROM PRODUCTO  WHERE CODPROD =3;
  167.      
  168.        DBMS_OUTPUT.PUT_LINE(' CODIGO :' || TO_CHAR(PD.CODPROD) || ' NOMBRE : ' || TO_CHAR(PD.NOMPROD) || ' PRECIO : '  || TO_CHAR(PD.PRECIO) );
  169.      
  170.    
  171. END;
  172. /
  173.  
  174. /* 14. Modificar el Ejercicio 13 de forma que busque un producto que no exista. */
  175. DECLARE
  176.  
  177.   PD PRODUCTO%ROWTYPE;
  178.  
  179.  
  180. BEGIN
  181.      SELECT CODPROD,NOMPROD,PRECIO INTO PD FROM PRODUCTO  WHERE CODPROD =6;
  182.      
  183.        DBMS_OUTPUT.PUT_LINE(' CODIGO :' || TO_CHAR(PD.CODPROD) || ' NOMBRE : ' || TO_CHAR(PD.NOMPROD) || ' PRECIO : '  || TO_CHAR(PD.PRECIO) );
  184.      
  185.      EXCEPTION
  186.      WHEN NO_DATA_FOUND THEN
  187.  
  188.        DBMS_OUTPUT.PUT_LINE(' NO EXISTE EL PRODUCTO ' );
  189. END;
  190.  
  191. /* 15 .  Modificar de nuevo el Ejercicio 13, ahora eliminando el where de la consulta, de forma que
  192. existan varios productos.   */    
  193.  
  194. DECLARE
  195.  
  196.  
  197.   CURSOR C_P  IS  SELECT CODPROD,NOMPROD,PRECIO  FROM PRODUCTO;
  198.  
  199. BEGIN
  200.    
  201.     FOR PD IN C_P  LOOP
  202.            
  203.       DBMS_OUTPUT.PUT_LINE(' CODIGO :' || TO_CHAR(PD.CODPROD) || ' NOMBRE : ' || TO_CHAR(PD.NOMPROD) || ' PRECIO : '  || TO_CHAR(PD.PRECIO));
  204.  
  205.      END LOOP;
  206. END;
  207. /
  208.    
  209. /*   16. Modificar el Ejercicio 12, que mostraba el número de productos, de forma que indique “No
  210. hay productos” en vez de “Hay 0 productos”                 */
  211.  
  212. DECLARE
  213.   N INTEGER;
  214.  
  215. BEGIN
  216.         SELECT COUNT(*) INTO N FROM  PRODUCTO;
  217.        
  218.     IF N = 0 THEN
  219.                  DBMS_OUTPUT.PUT_LINE(' NO HAY PRODUCTOS ');
  220.         ELSE
  221.                 DBMS_OUTPUT.PUT_LINE(' Hay  ' || TO_CHAR(N) ||  ' PRODUCTOS ');
  222.         END IF;
  223.        
  224. END;
  225. /
  226.  
  227. /*  17. Modificar de nuevo el bloque PL/SQL anterior, de forma que se indique que no hay
  228. produtos, que hay pocos (si hay entre 1 y 3) o el número exacto de productos existentes (si hay
  229. más de 3).  */
  230.  
  231. DECLARE
  232.     N INTEGER;
  233. BEGIN
  234.           SELECT COUNT(*) INTO N FROM  PRODUCTO;
  235.        
  236.         IF N  = 0 THEN
  237.                  DBMS_OUTPUT.PUT_LINE(' NO HAY PRODUCTOS ');
  238.        
  239.         ELSIF N  > 0 AND  N  <=3 THEN
  240.                   DBMS_OUTPUT.PUT_LINE(' HAY POCOS PRODUCTOS ');
  241.          
  242.         ELSIF N  > 3 THEN
  243.                      DBMS_OUTPUT.PUT_LINE(' Hay  ' || TO_CHAR(N ) ||  ' PRODUCTOS ');      
  244.            
  245.         END IF;
  246.        
  247. END;
  248. /
  249.  
  250. /*  18. Usar un bucle simple (LOOP ... END LOOP) para mostrar los números pares entre 1 y 10.
  251. Pueden usar la función mod(dividendo,divisor) para averiguar si el número es par o impar   */
  252. DECLARE
  253. CONTADOR INTEGER:=0;
  254. BEGIN
  255.  
  256.     LOOP
  257.     CONTADOR:= CONTADOR +1 ;
  258.     EXIT WHEN  CONTADOR > 10;
  259.      IF MOD(CONTADOR,2)=0 THEN
  260.             DBMS_OUTPUT.PUT_LINE(TO_CHAR(CONTADOR));
  261.            
  262.       END IF;
  263.     END LOOP;
  264. END;
  265. /
  266.  
  267. /* 19. Imprimir de nuevo los números pares entre 1 y 10, pero ahora usando un bucle WHILE */
  268. DECLARE
  269. CONTADOR  INTEGER:=1;
  270. BEGIN
  271.     WHILE (CONTADOR <=10)
  272.     LOOP
  273.    
  274.        IF MOD(CONTADOR,2)=0 THEN
  275.             DBMS_OUTPUT.PUT_LINE(TO_CHAR(CONTADOR));
  276.            
  277.       END IF;
  278.      
  279.       CONTADOR:= CONTADOR +1 ;
  280.     END LOOP;
  281.  
  282. END;
  283. /
  284.  
  285.  
  286. /* 20. Imprimir de nuevo los números pares entre 1 y 10, pero ahora usando un bucle FOR */
  287. BEGIN
  288.       FOR CONTADOR IN 1..10 LOOP
  289.            
  290.            IF MOD(CONTADOR,2)=0 THEN
  291.                   DBMS_OUTPUT.PUT_LINE(TO_CHAR(CONTADOR));
  292.            
  293.           END IF;
  294.    
  295.        
  296.       END LOOP;
  297. END;
  298. /
  299.  
  300. /* 21. Utilizar un cursor y un bucle LOOP simple para recuperar y mostrar los datos de todos Los productos.
  301. Indicar al final cuantos productos hay */
  302.  
  303. /* Esto Primero */
  304. SET serveroutput ON size 1000000;
  305.  
  306. DECLARE
  307. CURSOR C_ARTICULOS IS SELECT * FROM PRODUCTO;
  308. CODIGO INTEGER;
  309. PRODUCTO VARCHAR2(100) ;
  310. PRECIO NUMBER(8,2);
  311. BEGIN
  312.     OPEN C_ARTICULOS;
  313.     LOOP
  314.       FETCH C_ARTICULOS INTO CODIGO,PRODUCTO,PRECIO;
  315.       EXIT WHEN C_ARTICULOS%NOTFOUND;
  316.         DBMS_OUTPUT.PUT_LINE(' CODIGO :' || TO_CHAR(CODIGO) || ' NOMBRE : ' || TO_CHAR(PRODUCTO) || ' PRECIO : '  || TO_CHAR(PRECIO));
  317.   END LOOP;
  318.   DBMS_OUTPUT.PUT_LINE(' NUMERO DE PRODUCTOS : ' || C_ARTICULOS%ROWCOUNT);
  319.     CLOSE C_ARTICULOS;
  320.      
  321. END;
  322. /
  323.  
  324. /* 22. Mostrar los datos de todos los productos, pero ahora usando un bucle
  325. WHILE para recorrer el cursor, e indicar también el número de productos encontrados. */
  326. DECLARE
  327. CURSOR C_ARTICULOS IS SELECT * FROM PRODUCTO;
  328. CODIGO INTEGER;
  329. PRODUCTO VARCHAR2(100) ;
  330. PRECIO NUMBER(8,2);
  331. BEGIN
  332.        
  333.     OPEN C_ARTICULOS;
  334.     FETCH C_ARTICULOS INTO CODIGO,PRODUCTO,PRECIO;
  335.     WHILE  C_ARTICULOS%FOUND
  336.     LOOP
  337.           DBMS_OUTPUT.PUT_LINE(' CODIGO :' || TO_CHAR(CODIGO) || ' NOMBRE : ' || TO_CHAR(PRODUCTO) || ' PRECIO : '  || TO_CHAR(PRECIO));
  338.              FETCH C_ARTICULOS INTO CODIGO,PRODUCTO,PRECIO;
  339.     END LOOP;
  340.      DBMS_OUTPUT.PUT_LINE(' NUMERO DE PRODUCTOS : ' || C_ARTICULOS%ROWCOUNT);
  341.     CLOSE C_ARTICULOS;
  342.    
  343. END;
  344. /
  345.  
  346. /*   23. Recuperar e imprimir de nuevo los datos de todos los productos, y cuantos hay, pero ahora usa un bucle FOR        */
  347.  
  348. DECLARE
  349. CONTADOR  INTEGER:=0;
  350. CURSOR C_ARTICULOS IS SELECT * FROM PRODUCTO;
  351. BEGIN
  352.       FOR  PD IN C_ARTICULOS LOOP
  353.            DBMS_OUTPUT.PUT_LINE(' CODIGO :' || TO_CHAR(PD.CODPROD) || ' NOMBRE : ' || TO_CHAR(PD.NOMPROD) || ' PRECIO : '  || TO_CHAR(PD.PRECIO));
  354.             CONTADOR:= CONTADOR+1;    
  355.       END LOOP;
  356.      
  357.        DBMS_OUTPUT.PUT_LINE(' NUMERO DE PRODUCTOS : ' || TO_CHAR(CONTADOR));
  358.  
  359.  
  360.  
  361. END;
  362. /
  363.  
  364. /* 24. Modificar el Ejercicio 23, de forma que se utilice la consulta directamente
  365. en el bucle FOR en vez de declarar explícitamente el cursor.
  366. */
  367.  
  368. DECLARE
  369. CONTADOR  INTEGER:=0;
  370.  
  371. BEGIN
  372.       FOR  PD IN  (SELECT * FROM PRODUCTO)  LOOP
  373.            DBMS_OUTPUT.PUT_LINE(' CODIGO :' || TO_CHAR(PD.CODPROD) || ' NOMBRE : ' || TO_CHAR(PD.NOMPROD) || ' PRECIO : '  || TO_CHAR(PD.PRECIO));
  374.             CONTADOR:= CONTADOR+1;    
  375.       END LOOP;
  376.      
  377.        DBMS_OUTPUT.PUT_LINE(' NUMERO DE PRODUCTOS : ' || TO_CHAR(CONTADOR));
  378.  
  379.  
  380. END;
  381. /
  382.  
  383. /* 25. Modificar ahora el Ejercicio 24, de forma que se recuperen solo los códigos de los productos.
  384. Ya no es necesario indicar cuantos productos hay. */
  385.  
  386. BEGIN
  387.       FOR  PD IN  (SELECT CODPROD FROM PRODUCTO)  LOOP
  388.            DBMS_OUTPUT.PUT_LINE(' CODIGO :' || TO_CHAR(PD.CODPROD));
  389.            
  390.       END LOOP;
  391.      
  392.      
  393. END;
  394. /
  395.  
  396. /* 26. Recuperar ahora el doble del precio de los productos, usando el bucle FOR con la consulta directamente */
  397.  
  398. BEGIN
  399.       FOR  PD IN  (SELECT PRECIO * 2 AS P  FROM PRODUCTO)  LOOP
  400.            DBMS_OUTPUT.PUT_LINE(' PRECIO :' || TO_CHAR(PD.P));
  401.            
  402.       END LOOP;
  403.    
  404. END;
  405. /
  406.  
  407. /* 27. Escribir un bloque PL/SQL que modifique el producto 3, poniendo Monitor TFT 21'' como nombre del producto, y 497 como precio.
  408. Si no existe el producto con código 3, el bloque PL/SQL escrito debe insertar los valores indicados.
  409. El uso del cursor implícito SQL podría ayudar a resolver este ejercicio. */
  410.  
  411. DECLARE
  412. CODIGO INTEGER:=3;
  413. NOMBRE VARCHAR2(100):='Monitor TFT 21';
  414. PRICE NUMBER(8,2):=497;
  415. EXISTENCIA INTEGER;
  416. BEGIN
  417.       SELECT  COUNT(*) INTO EXISTENCIA FROM PRODUCTO WHERE CODPROD=CODIGO;
  418.        
  419.         IF EXISTENCIA=0  THEN
  420.                 INSERT INTO PRODUCTO VALUES(CODIGO,NOMBRE,PRICE);
  421.                   DBMS_OUTPUT.PUT_LINE(TO_CHAR(CODIGO) ||'   ' || TO_CHAR(NOMBRE) ||'  ' || '   '  ||TO_CHAR(PRICE) || '  PRODUCTO INSERTADO ');
  422.         ELSE
  423.                 UPDATE PRODUCTO SET NOMPROD=NOMBRE,PRECIO=PRICE WHERE CODPROD=CODIGO;
  424.                  DBMS_OUTPUT.PUT_LINE(TO_CHAR(CODIGO) ||'   ' || TO_CHAR(NOMBRE) ||'  ' || '   '  ||TO_CHAR(PRICE) || '  PRODUCTO ACTUALIZADO ');
  425.         END IF;
  426.    
  427. END;
  428. /
  429.  
  430. /* 28. En un bloque PL/SQL, intentar crear directamente una tabla T con un campo numérico C (fallara). */
  431. BEGIN
  432. CREATE TABLE T(
  433. C NUMBER
  434. );
  435.  
  436. END;
  437. /
  438.  
  439. /* 29. Crear la tabla usando SQL dinámico y EXECUTE IMMEDIATE dentro de un bloque PL/SQL.
  440. Comprobar que efectivamente la tabla fue creada, con una consulta simple sobre el catálogo de Oracle.
  441. Finalmente, eliminar (DROP) la tabla. */
  442.  
  443. DECLARE
  444. S_QL  VARCHAR2(255);
  445. TABLA  VARCHAR2(100);
  446. DROP_TABLA VARCHAR2(255);
  447. BEGIN
  448.   S_QL:='CREATE TABLE T(C NUMBER)';
  449.   EXECUTE IMMEDIATE S_QL;
  450.    
  451.     SELECT TABLE_NAME INTO TABLA  FROM USER_TABLES WHERE TABLE_NAME='T';
  452.       DBMS_OUTPUT.PUT_LINE(' TABLA : ' || TABLA || ' CREADA ' );
  453.      
  454.      DROP_TABLA:='DROP TABLE T';
  455.      EXECUTE IMMEDIATE DROP_TABLA;
  456.      
  457.        DBMS_OUTPUT.PUT_LINE(' TABLA : ' || TABLA || ' ELIMINADA ' );
  458.  
  459. END;
  460. /
  461.  
  462. /* 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. */
  463.  
  464. DECLARE
  465. S_QL  VARCHAR2(255);
  466. TABLA  VARCHAR2(100);
  467.  
  468. BEGIN
  469.   S_QL:='CREATE TABLE T2(S VARCHAR2(100))';
  470.   EXECUTE IMMEDIATE S_QL;
  471.  
  472.    SELECT TABLE_NAME INTO TABLA  FROM USER_TABLES WHERE TABLE_NAME='T2';
  473.       DBMS_OUTPUT.PUT_LINE(' TABLA : ' || TABLA || ' CREADA ' );
  474.      
  475.      EXECUTE IMMEDIATE  'INSERT INTO T2 VALUES(''B454'')';
  476.      DBMS_OUTPUT.PUT_LINE( SQL%ROWCOUNT || ' FILA INSERTADA ');
  477.    
  478.  
  479. END;
  480. /
  481.  
  482. /* 31. Recuperar e imprimir de nuevo los datos de todos los productos, ahora usando SQL dinámico. */
  483. DECLARE
  484.  TYPE C_REFERIDO IS REF CURSOR;
  485.  C_ARTICULOS C_REFERIDO;
  486.  CONSULTA VARCHAR2(255);
  487.  PD  PRODUCTO%ROWTYPE;
  488. BEGIN
  489.   CONSULTA:='SELECT * FROM PRODUCTO';
  490.  
  491.   OPEN C_ARTICULOS  FOR CONSULTA;
  492.   LOOP
  493.      FETCH C_ARTICULOS  INTO PD;
  494.       EXIT WHEN C_ARTICULOS%NOTFOUND;
  495.       DBMS_OUTPUT.PUT_LINE(' CODIGO :' || TO_CHAR(PD.CODPROD) || ' NOMBRE : ' || TO_CHAR(PD.NOMPROD) || ' PRECIO : '  || TO_CHAR(PD.PRECIO));
  496.             END LOOP;
  497.              CLOSE C_ARTICULOS;
  498. END;
  499. /
  500.  
  501.  
  502. /* 32. Alterar la tabla de productos,
  503. añadiendo una restricción c_precio_positivo que compruebe que el precio de un producto es mayor que cero.
  504. */
  505.  
  506. ALTER TABLE PRODUCTO
  507. ADD CONSTRAINT c_precio_positivo CHECK(PRECIO > 0);
  508.  
  509. /* 33. Averiguar como podría controlar el error de clave primaria (o restricción única) duplicada. */
  510.  
  511. USANDO LA EXCEPCIÓN  
  512. DUP_VAL_ON_INDEX
  513.  
  514. /* 34. Crear un bloque PL/SQL en el que se inserta un producto con código 3, ya existente. Haz el control de excepciones
  515. de forma que un error de clave primaria duplicada
  516. se ignore (no se inserta el producto pero el bloque PL/SQL se ejecuta correctamente).
  517. Si intentamos insertar un producto con precio negativo, debe aparecer un error.
  518. */
  519.  
  520. DECLARE
  521. CODIGO INTEGER:=3;
  522. PRODUCTO VARCHAR2(100):='HUB';
  523. PRECIO NUMBER(8,2):=1;
  524. BEGIN
  525.    
  526.     IF PRECIO > 0 THEN
  527.           INSERT INTO PRODUCTO VALUES(CODIGO,PRODUCTO,PRECIO);
  528.                  
  529.         ELSE
  530.            DBMS_OUTPUT.PUT_LINE(  ' PRECIO NO PUEDE SER NEGATIVO ');
  531.    
  532.         END IF;
  533.          
  534.       EXCEPTION
  535.      WHEN DUP_VAL_ON_INDEX THEN
  536.            DBMS_OUTPUT.PUT_LINE(  ' CLAVE  PRIMARIA DUPLICADA ');
  537.    
  538.    
  539.  
  540. END;
  541. /
  542.  
  543. /* 35. Eliminar la restricción c_precio_positivo creada en el Ejercicio 32.*/
  544.  
  545. ALTER TABLE PRODUCTO
  546. DROP CONSTRAINT  c_precio_positivo;
  547.  
  548. /* 36. Escribe un bloque PL/SQL donde usas un registro para almacenar los datos de un producto.
  549. El bloque insertará ese producto, pero si el precio no es positivo generar ´a una excepción de tipo precio_prod_invalido,
  550. que deberá declarar previamente, en vez de realizar la inserción */
  551.  
  552. DECLARE
  553. precio_prod_invalido EXCEPTION;
  554. PD PRODUCTO%ROWTYPE;
  555.  
  556.  
  557.  
  558. BEGIN
  559.          
  560.                PD.CODPROD:=10;
  561.                PD.NOMPROD:= 'CD';
  562.                PD.PRECIO :=-1;
  563.                
  564.                IF PD.PRECIO > 0 THEN
  565.                        INSERT INTO PRODUCTO VALUES PD;
  566.               ELSE
  567.                         RAISE precio_prod_invalido;
  568.               END IF;
  569.              
  570.               EXCEPTION
  571.               WHEN   precio_prod_invalido  THEN
  572.                   DBMS_OUTPUT.PUT_LINE(  ' PRECIO NO PUEDE SER NEGATIVO ');
  573.            
  574. END;
  575. /
  576.  
  577. /*  37. Modificar el Ejercicio 36, de forma que capture la excepción elevada.  */
  578.  
  579. DECLARE
  580. precio_prod_invalido EXCEPTION;
  581. PD  PRODUCTO%ROWTYPE;
  582.  
  583. BEGIN
  584.          
  585.                PD.CODPROD:=11;
  586.                PD.NOMPROD:= 'CD';
  587.                PD.PRECIO :=-1;
  588.                
  589.                IF PD.PRECIO > 0 THEN
  590.                        INSERT INTO PRODUCTO VALUES PD;
  591.               ELSE
  592.                         RAISE precio_prod_invalido;
  593.               END IF;
  594.              
  595.               EXCEPTION
  596.               WHEN   precio_prod_invalido  THEN
  597.                  RAISE_APPLICATION_ERROR(-20001,' PRECIO NO PUEDE SER NEGATIVO ');
  598.            
  599. END;
  600. /
  601.  
  602. /*   38. Modificar de nuevo el Ejercicio 36, de forma que ahora captures
  603. la excepción elevada y produces otra, con SQLCODE y mensaje de error especifico, usando RAISE_APPLICATION_ERROR */
  604.  
  605. DECLARE
  606. precio_prod_invalido EXCEPTION;
  607. PD  PRODUCTO%ROWTYPE;
  608. err_num NUMBER;
  609.  
  610.  
  611. BEGIN
  612.          
  613.                PD.CODPROD:=12;
  614.                PD.NOMPROD:= 'CD';
  615.                PD.PRECIO :=-1;
  616.                
  617.                IF PD.PRECIO > 0 THEN
  618.                       INSERT INTO PRODUCTO VALUES PD;
  619.               ELSE
  620.                         RAISE precio_prod_invalido;
  621.                    
  622.               END IF;
  623.              
  624.               EXCEPTION
  625.               WHEN   precio_prod_invalido  THEN
  626.                err_num := SQLCODE;
  627.                DBMS_OUTPUT.PUT_LINE(' ERROR PRECIO NEGATIVO :'||TO_CHAR(err_num));
  628.                RAISE_APPLICATION_ERROR(-20001,' PRECIO NO PUEDE SER NEGATIVO ');
  629.          
  630.      
  631. END;
  632. /
  633.  
  634.  
  635. /* 39. Crear un procedimiento InsertaProd para insertar un producto. Usar tres parámetros,
  636. uno para cada atributo (código, nombre, precio).
  637. */
  638.  
  639. CREATE OR REPLACE  PROCEDURE  InsertaProd (CODIGO INTEGER, NOMBRE VARCHAR2, PRECIO NUMBER)
  640. IS
  641. BEGIN
  642.  
  643.     INSERT INTO PRODUCTO VALUES(CODIGO,NOMBRE,PRECIO);
  644.  
  645.  
  646. END;
  647. /
  648.  
  649. /* 40. Revisar si hubo errores de compilación en la creación del procedimiento, y obtener la información sobre el procedimiento
  650. usando las tablas del catálogo USER_PROCEDURES y USER_OBJECTS (o su sinónimo OBJ). */
  651.  
  652. SHOW ERRORS;
  653.  
  654. No hay errores
  655.  
  656. /*OBTENIENDO INFORMACION DEL PROCEDIMIENTO DESDE USER_PROCEDURES */
  657. SELECT * FROM USER_PROCEDURES   WHERE   OBJECT_NAME='INSERTAPROD' ;
  658.  
  659.  
  660. /*OBTENIENDO INFORMACION DEL PROCEDIMIENTO DESDE USER_OBJECTS */
  661. SELECT * FROM USER_OBJECTS  WHERE OBJECT_TYPE='PROCEDURE' AND OBJECT_NAME='INSERTAPROD' ;
  662.  
  663.  
  664. /* 41. Examinar la estructura de la tabla USER_SOURCE y usarla para obtener el código fuente PL/SQL del procedimiento InsertaProd. */
  665.  
  666. /* Examinando Estructura */
  667. DESCRIBE USER_SOURCE;
  668. SELECT * FROM USER_SOURCE;
  669.  
  670.  
  671. /* obtener el código fuente PL/SQL del procedimiento InsertaProd. */
  672. SELECT LINE, TEXT  FROM USER_SOURCE WHERE  NAME='INSERTAPROD';
  673.  
  674.  
  675. /* 42. Ejecutar el procedimiento, insertando un producto mediante CALL y otro usando EXEC. */
  676.  
  677. /* Mediante CALL*/
  678. CALL  InsertaProd(5,'USB',10);
  679.  
  680. /*  MEDIANTE EXEC  */
  681. EXEC InsertaProd(7,'MEMORIA RAM 2GB',15);
  682.  
  683. /* 43. Averiguar que ocurre si creamos un bloque PL/SQL en el que insertamos varios productos llamando al procedimiento InsertaProd,
  684. pero una de las llamadas al procedimiento falla. Por ejemplo, trata de insertar la misma fila 2 veces. */
  685.  
  686. Se ejecuta el bloque PL/SQL y muestra  el siguiente error:
  687. ORA-00001: restricción única (OWN_USUARIO.PK_CODPROD)
  688.  
  689. 00001. 00000 -  "unique constraint (%s.%s) violated"
  690.  
  691. Se intento insertar la misma fila 2 veces en la tabla PRODUCTO la cual contiene
  692. una clave primaria CODPROD se activa el constraint correspondiante de manera que si se intenta
  693. insertar una fila  cuya clave primaria coincida con una existente se lanza el error de restricción unica,
  694. no se puede  realizar la insercion a la tabla PRODUCTO  en cada una de las llamadas al procedimiento
  695. InsertaProd, hasta que el valor del campo CODPROD no coincida con los existentes en la tabla.
  696.  
  697.  
  698. /* 44. Intentar crear otro procedimiento InsertaProd que inserte un
  699. producto tomando como único parámetro un registro de tipo producto.
  700. */
  701.  
  702. CREATE OR REPLACE PROCEDURE  InsertaProd(PD PRODUCTO%ROWTYPE)
  703. IS
  704.  
  705. BEGIN
  706.           INSERT INTO PRODUCTO VALUES(PD.CODPROD,PD.NOMPROD,PD.PRECIO);
  707.            
  708. END;
  709. /
  710.  
  711. /* COMO USARLO  -- TIP ! */
  712.  
  713. DECLARE
  714. ARTICULOS PRODUCTO%ROWTYPE;
  715.  
  716. BEGIN
  717.         ARTICULOS.CODPROD:=8;
  718.         ARTICULOS.NOMPROD:='USB 2.0';
  719.         ARTICULOS.PRECIO:=20;
  720.         InsertaProd(ARTICULOS);
  721.  
  722. END;
  723. /
  724.  
  725. /* 45. Crea un procedimiento ListaProds que toma como parámetro un valor numérico
  726. y lista todos los productos con precio mayor o igual a ese valor
  727. */
  728.  
  729. CREATE OR REPLACE PROCEDURE ListaProds(VALOR NUMBER)
  730. IS
  731. BEGIN
  732.        
  733.       FOR  PD IN  (SELECT  NOMPROD FROM PRODUCTO WHERE PRECIO >=VALOR)  LOOP
  734.            DBMS_OUTPUT.PUT_LINE( TO_CHAR(PD.NOMPROD) );
  735.            
  736.       END LOOP;
  737.  
  738. END;
  739. /
  740.  
  741.  
  742. /* 46. Crear una función triple que devuelva el triple del número que toma como argumento. */
  743.  
  744. CREATE OR REPLACE FUNCTION TRIPLE(NUMERO NUMBER)
  745. RETURN NUMBER
  746. IS RESULTADO NUMBER;
  747. BEGIN
  748.             RESULTADO:= (NUMERO * 3);
  749.             RETURN RESULTADO;
  750. END;
  751.  
  752. /* 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,
  753. que resulta de aplicarle a ese precio de coste un margen comercial del 20%. */
  754.  
  755. CREATE OR REPLACE FUNCTION PVP(PRECIO NUMBER)
  756. RETURN NUMBER
  757. IS
  758. PORCENTAJE NUMBER;
  759. P_VENTA_PUBLICO NUMBER;
  760. BEGIN
  761.           PORCENTAJE := (PRECIO * 0.20);
  762.           P_VENTA_PUBLICO:= PRECIO + PORCENTAJE;
  763.           RETURN P_VENTA_PUBLICO;
  764.  
  765. END;
  766. /
  767.  
  768. /* 48. Crea una vista VPRODUCTO que obtenga todos los datos de los productos más el precio de venta al público. */
  769.  
  770. CREATE VIEW VPRODUCTO AS
  771. SELECT CODPROD, NOMPROD, PRECIO, PVP(PRECIO) AS PRECIO_VENTA FROM PRODUCTO;
  772.  
  773. /* 49. Examinar los datos de la vista VPRODUCTO. Modificar la función PVP para que aplique un margen del 22%,
  774. y vuelve a examinar los datos de la vista. */
  775.  
  776. /* EXAMINANDO DATOS DE LA VISTA  */
  777. SELECT * FROM VPRODUCTO; /* PRECIO DE VENTA CON MARGEN DE 20% */
  778.  
  779. /* MODIFICANDO FUNCIÓN */
  780. CREATE OR REPLACE FUNCTION PVP(PRECIO NUMBER)
  781. RETURN NUMBER
  782. IS
  783. PORCENTAJE NUMBER;
  784. P_VENTA_PUBLICO NUMBER;
  785. BEGIN
  786.           PORCENTAJE := (PRECIO * 0.22);
  787.           P_VENTA_PUBLICO:= PRECIO + PORCENTAJE;
  788.           RETURN P_VENTA_PUBLICO;
  789.  
  790. END;
  791. /
  792.  
  793. /* EXAMINANDO DATOS DE LA VISTA  */
  794. SELECT * FROM VPRODUCTO;   /* PRECIO DE VENTA CON MARGEN DEL 22% */
  795.  
  796. /* 50. Crear un paquete (package) gestprod que usará para gestionar los productos. Debe incluir las signaturas de:
  797.  
  798. ? Dos procedimientos InsertaProd, uno que tome 3 parámetros (código, nombre y precio) y otro que tome
  799. solo un parámetro: un registro de tipo producto.
  800.  
  801. ? Una función BorraProd que borre un producto. Devolverá un valor booleano, indicando si borro el producto o no (porque no existía). */
  802.  
  803. CREATE OR REPLACE PACKAGE gestprod AS
  804. PROCEDURE  InsertaProd (CODIGO INTEGER, NOMBRE VARCHAR2, PRECIO   NUMBER);
  805. PROCEDURE InsertaProd(PD PRODUCTO%ROWTYPE);
  806. FUNCTION BorraProd(CODIGO INTEGER) RETURN BOOLEAN;
  807. END  gestprod;
  808.  
  809.  
  810. /* 51. Crea el cuerpo del paquete (package body) para el paquete gestprod. */
  811.  
  812. CREATE OR REPLACE PACKAGE BODY  gestprod AS
  813. PROCEDURE  InsertaProd (CODIGO INTEGER, NOMBRE VARCHAR2, PRECIO NUMBER)
  814. IS
  815. BEGIN
  816.  
  817.     INSERT INTO PRODUCTO VALUES(CODIGO,NOMBRE,PRECIO);
  818.  
  819.  
  820. END  InsertaProd ;
  821.  
  822. PROCEDURE  InsertaProd(PD PRODUCTO%ROWTYPE)
  823. IS
  824.  
  825. BEGIN
  826.           INSERT INTO PRODUCTO VALUES(PD.CODPROD,PD.NOMPROD,PD.PRECIO);
  827.            
  828. END InsertaProd ;
  829.  
  830.  FUNCTION BorraProd(CODIGO INTEGER)
  831. RETURN BOOLEAN
  832. IS
  833. ESTADO_ELIMINACION BOOLEAN;
  834. EXISTENCIA INTEGER;
  835. BEGIN
  836.           SELECT COUNT(*) INTO EXISTENCIA FROM PRODUCTO WHERE CODPROD=CODIGO;
  837.      
  838.           IF EXISTENCIA = 0 THEN
  839.           ESTADO_ELIMINACION:= FALSE;
  840.           ELSE
  841.                DELETE FROM PRODUCTO WHERE CODPROD=CODIGO;
  842.                ESTADO_ELIMINACION:= TRUE;
  843.           END IF;
  844.          
  845.           RETURN ESTADO_ELIMINACION;
  846. END BorraProd;
  847.  
  848. END  gestprod;
  849.  
  850. /* 52. Crear un trigger que fuerce a que los precios de los productos sean positivos. Controla solo las modificaciones (update) de datos. */
  851.  
  852. CREATE OR REPLACE TRIGGER TR_PRECIO_POSITIVO_UPDATE
  853.  BEFORE  UPDATE  ON PRODUCTO  
  854.   FOR EACH ROW
  855. DECLARE
  856. POSITIVO NUMBER(8,2);
  857. BEGIN
  858.         POSITIVO:=ABS(:NEW.PRECIO);
  859.         :NEW.PRECIO:=POSITIVO;
  860. END ;
  861. /
  862.  
  863. /* 53. Crear otro trigger que fuerce a que los precios de los productos sean positivos, pero en este caso controla solo las inserciones. */
  864.  
  865.  
  866. CREATE OR REPLACE TRIGGER TR_PRECIO_POSITIVO
  867.  BEFORE  INSERT ON PRODUCTO  
  868.   FOR EACH ROW
  869. DECLARE
  870. POSITIVO NUMBER(8,2);
  871. BEGIN
  872.         POSITIVO:=ABS(:NEW.PRECIO);
  873.         :NEW.PRECIO:=POSITIVO;
  874. END ;
  875. /
  876.  
  877.  
  878. /* 54. Repitir el Ejercicio 32, añadiendo de nuevo la restricción check que comprueba que los precios de los productos son positivos.
  879. Ahora compruebe que se activa antes, la restricción o el trigger. */
  880.  
  881. ALTER TABLE PRODUCTO
  882. ADD CONSTRAINT c_precio_positivo CHECK(PRECIO > 0);
  883.  
  884. Se activa antes el TRIGGER TR_PRECIO_POSITIVO  porque tiene el modificador BEFORE
  885. antes de realizar la insercion ejecuta lo que esta en el cuerpo del disparador, lo cual es en este caso
  886. forzar a que el precio del producto siempre sea positivo, luego se ejecuta la restricción CHECK
  887.  
  888.  
  889. /* 55. Comprobar que orden sigue Oracle en la activación de 2 triggers que comparten tabla, evento, granularidad y tiempo de activación.*/
  890.  
  891. Antes de comenzar a ejecutar la orden que provoca el disparo se ejecutaran los triggers del tipo before.... FOR each statement
  892.     Para cada fila afectada por la orden:
  893.     a) se ejecutan los triggers del tipo before … FOR each ROW
  894.     b) se ejecuta la actualización de la fila
  895.     c) se ejecutan los triggers after... FOR each ROW
  896.     Una vez realizada la operación se ejecuta el after … FOR each statement
  897.  
  898.    /* Comprobación : Se creo el trigger INCREMENTO  */
  899.    
  900. CREATE OR REPLACE TRIGGER INCREMENTO
  901.  BEFORE  INSERT ON PRODUCTO  
  902.   FOR EACH ROW
  903. DECLARE
  904. INCREMENTO NUMBER(8,2);
  905. RESULTADO NUMBER(8,2);
  906. BEGIN
  907.        INCREMENTO:=10;
  908.         RESULTADO:= :NEW.PRECIO+ INCREMENTO;
  909.         :NEW.PRECIO:=RESULTADO;
  910. END ;
  911. /
  912.  
  913.  
  914. Se insertaron datos en la tabla PRODUCTO y el TRIGGER que se ejecutaba
  915. era el TR_PRECIO_POSITIVO, se desactivo  con ALTER TRIGGER  TR_PRECIO_POSITIVO DISABLE  y se volvio activar
  916. ahora el TRIGGER que se ejecutaba antes era el  INCREMENTO posiblemente el orden de ejecucion de triggers
  917. del mismo tipo es  indeterminado
  918.  
  919.  
  920. /* 56. Cree las tablas para almacenar facturas y líneas de factura: */
  921.  
  922. /* CREANDO  TABLA FACTURAS */
  923. CREATE TABLE  FACTURAS(
  924. NUMERO INTEGER CONSTRAINT PK_NUM_FACTURA PRIMARY KEY,
  925. FECHA DATE NOT NULL,
  926. TOTAL NUMBER(8,2)
  927. );
  928.  
  929.  
  930. /* CREANDO TABLA LINEAS */
  931. CREATE TABLE LINEAS(
  932. NUMFAC INTEGER NOT NULL CONSTRAINT FK_NUM_FACTURA
  933. REFERENCES FACTURAS(NUMERO),
  934. NUMLI INTEGER NOT NULL,
  935. CODPROD INTEGER NOT NULL  CONSTRAINT FK_CODPROD
  936. REFERENCES PRODUCTO(CODPROD),
  937. CANTIDAD INTEGER NOT NULL,
  938. PRECIO NUMBER(8,2),
  939. SUBTOTAL NUMBER(8,2)
  940. );
  941.  
  942.  
  943.  
  944.  
  945. /* 57. Asegurar de que cuando se añade una factura el total sea 0. */
  946.  
  947. CREATE OR REPLACE TRIGGER TR_TOTAL_CERO
  948.  BEFORE  INSERT ON FACTURAS  
  949.   FOR EACH ROW
  950. BEGIN
  951.         :NEW.TOTAL:=0;
  952. END ;
  953. /
  954.  
  955.  
  956.  
  957. /* 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
  958. para que tanto el precio como el subtotal de esa línea se cubran automáticamente */
  959.  
  960. CREATE OR REPLACE TRIGGER t_subtotal_ins
  961.  BEFORE  INSERT ON LINEAS
  962.   FOR EACH ROW
  963. DECLARE
  964. CODIGO INTEGER;
  965. PRECIO_P  NUMBER(8,2);
  966. SUBTOTAL NUMBER(8,2);
  967. BEGIN
  968.      CODIGO :=  :NEW.CODPROD;
  969.      SELECT PRECIO INTO PRECIO_P  FROM PRODUCTO WHERE CODPROD=CODIGO;
  970.      
  971.      :NEW.PRECIO:=PRECIO_P;
  972.      SUBTOTAL:= (:NEW.CANTIDAD * PRECIO_P);
  973.      :NEW.SUBTOTAL:=SUBTOTAL;
  974.      
  975. END ;
  976. /
  977.  
  978. /* 59. Crea otro trigger t_subtotal_upd, similar al realizado para el Ejercicio 58, para realizar el mismo cometido
  979. cuando se modifica una línea de factura. */
  980.  
  981. CREATE OR REPLACE TRIGGER t_subtotal_upd
  982.  BEFORE  UPDATE ON LINEAS
  983.   FOR EACH ROW
  984. DECLARE
  985. CODIGO INTEGER;
  986. PRECIO_P  NUMBER(8,2);
  987. SUBTOTAL NUMBER(8,2);
  988. BEGIN
  989.      CODIGO :=  :NEW.CODPROD;
  990.      SELECT PRECIO INTO PRECIO_P  FROM PRODUCTO WHERE CODPROD=CODIGO;
  991.      
  992.      :NEW.PRECIO:=PRECIO_P;
  993.      SUBTOTAL:= (:NEW.CANTIDAD * PRECIO_P);
  994.      :NEW.SUBTOTAL:=SUBTOTAL;
  995.      
  996. END ;
  997. /
  998.  
  999. /* 60. Combina los triggers de los ejercicios 58 y 59 en un ´unico trigger t_subtotal. Decidir si se debe eliminar o deshabilitar
  1000. los triggers t_subtotal_ins y t_subtotal_upd una vez se haya creado.  */
  1001.  
  1002. /* Elimiando Triggers */
  1003. DROP TRIGGER  t_subtotal_ins;
  1004. DROP TRIGGER t_subtotal_upd;
  1005.  
  1006.  
  1007. CREATE OR REPLACE TRIGGER t_subtotal
  1008.  BEFORE  INSERT OR UPDATE ON LINEAS
  1009.   FOR EACH ROW
  1010. DECLARE
  1011. CODIGO INTEGER;
  1012. PRECIO_P  NUMBER(8,2);
  1013. SUBTOTAL NUMBER(8,2);
  1014. BEGIN
  1015.  
  1016.  
  1017.      CODIGO :=  :NEW.CODPROD;
  1018.      SELECT PRECIO INTO PRECIO_P  FROM PRODUCTO WHERE CODPROD=CODIGO;
  1019.      
  1020.      :NEW.PRECIO:=PRECIO_P;
  1021.      SUBTOTAL:= (:NEW.CANTIDAD * PRECIO_P);
  1022.      :NEW.SUBTOTAL:=SUBTOTAL;
  1023.      
  1024. END;
  1025. /
  1026.  
  1027. /* 61. Crear el(los) trigger(s) necesarios para mantener correctamente actualizado el total de la factura. */
  1028.  
  1029. DROP TRIGGER t_subtotal;
  1030.  
  1031. /* Me parece asi: 1 trigger para todo al mismo tiempo que se inserta se actualiza
  1032. 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 */
  1033.  
  1034. CREATE OR REPLACE TRIGGER FACTURA_TRANSACCION
  1035.  BEFORE  INSERT OR UPDATE ON LINEAS
  1036.   FOR EACH ROW
  1037. DECLARE
  1038. CODIGO INTEGER;
  1039. NUM_FACTURA NUMBER;
  1040. PRECIO_P  NUMBER(8,2);
  1041. SUBTOTAL NUMBER(8,2);
  1042. TOTAL_ACTUAL NUMBER(8,2);
  1043. TOTAL_ACUMULADO NUMBER(8,2);
  1044. TOTAL_ANTERIOR NUMBER(8,2);
  1045. BEGIN
  1046.  
  1047.     NUM_FACTURA:=:NEW.NUMFAC;
  1048.    
  1049.      CODIGO :=  :NEW.CODPROD;
  1050.      SELECT PRECIO INTO PRECIO_P  FROM PRODUCTO WHERE CODPROD=CODIGO;
  1051.      
  1052.      :NEW.PRECIO:=PRECIO_P;
  1053.      SUBTOTAL:= (:NEW.CANTIDAD * PRECIO_P);
  1054.      :NEW.SUBTOTAL:=SUBTOTAL;
  1055.      
  1056.      SELECT TOTAL INTO TOTAL_ACTUAL FROM   FACTURAS WHERE NUMERO=NUM_FACTURA;
  1057.      
  1058.       IF INSERTING THEN
  1059.                 TOTAL_ACUMULADO:= SUBTOTAL + TOTAL_ACTUAL;
  1060.                  UPDATE FACTURAS SET TOTAL=TOTAL_ACUMULADO  WHERE NUMERO=NUM_FACTURA;
  1061.                  
  1062.       ELSIF   UPDATING THEN
  1063.                   TOTAL_ANTERIOR := (TOTAL_ACTUAL - :OLD.SUBTOTAL);
  1064.                    TOTAL_ACUMULADO:= (SUBTOTAL + TOTAL_ANTERIOR);
  1065.                    UPDATE FACTURAS SET TOTAL=TOTAL_ACUMULADO  WHERE NUMERO=NUM_FACTURA;
  1066.      
  1067.       END IF;
  1068.          
  1069.        
  1070. END;
  1071. /
Advertisement
Add Comment
Please, Sign In to add comment