Este documento resume los principales conceptos de programación en Oracle Forms 10g, incluyendo variables, sentencias de control y bucles, cursores, excepciones, la sentencia raise, funciones, procedimientos y paquetes. Cubre temas como declaración de variables, tipos de bucles como loop, while y for, uso de cursores explícitos e implícitos, manejo de excepciones, y creación de funciones y procedimientos definidos por el usuario.
Matriz de integración de tecnologías- Paola Carvajal.docx
Forms 10g procedimientos y cursores
1. Capacitación Oracle Forms 10g
Cuida de los minutos, que las horas se cuidan solas.- Lord Chesterfield
Instructor: Edwin Forms 10g Programación
ORACLE Developer Romero 1
2. Contenido
Variables
Sentencias de Control y Bucles
Cursores
Exceptions
Sentencia Raise
Funciones, procedimientos y paquetes
Triggers
ORACLE Developer Forms 10g Programación 2
3. Variables
Los principales tipos de variables escalares en Oracle PL/SQL son los siguientes:
VARCHAR2(tamaño)
NUMBER[(precisión,escala)]
DATE
CHAR(tamaño)
LONG
BOOLEAN
BINARY_INTEGER
Un ejemplo de declaración de tipos de variable
DECLARE
variable1 VARCHAR2(50);
variable2 BINARY_INTEGER:=0;
variable3 NUMBER(10,4);
ORACLE Developer Forms 10g Programación 3
4. Variables
Variables de tipo HOST
Las variables No-PL/SQL o de tipo HOST son variables globales que pueden usarse
tanto dentro como fuera de los bloques PL/SQL.
Las referencias a estas variables vienen precedidas por dos puntos (:)
VARIABLE total NUMBER(3,2);
:total := 10/2;
Atributo %TYPE
El atributo %TYPE sirve para declarar una variable a partir de otras declaradas
previamente, o a partir del tipo de una columna de la base de datos. Es decir, copiar
el tipo de otra variable.
El siguiente ejemplo asigna a la variable1 el mismo tipo que el campo de la base de
datos.
ver en popupcopiar a portapapelesimprimir
variable1 tabla.campo%TYPE;
ORACLE Developer Forms 10g Programación 4
5. Variables
Ejemplo:
DECLARE
v_cnt_emp number;
v_fecha date;
BEGIN
select sysdate() into v_fecha
from dual;
select count(*) into v_cnt_emp
from employee
where salary>1000;
BEGIN
dbms_output.put_line ('Empleados con salario>1000 : '||v_cnt_emp);
END;
END;
/
ORACLE Developer Forms 10g Programación 5
6. Sentencias de Control y Bucles
DECLARE
v_cnt_emp number;
v_tot_emp number;
BEGIN
select count(*) into v_tot_emp
from employee;
dbms_output.put_line ('Hay un total de '||v_tot_emp||' empleados.');
select count(*) into v_cnt_emp from employee
where salary>1000;
dbms_output.put_line ('Hay '||v_cnt_emp||' empleados que ganan mas de 1000 $.');
dbms_output.put_line ('Resultado de la analisis.');
IF (v_tot_emp=v_cnt_emp) then
dbms_output.put_line ('Los empleados ganan todos mas de 1000 $');
ELSIF (v_tot_emp<v_cnt_emp*2) then
dbms_output.put_line ('Mas de la mitad empleados ganan todos mas de 1000 $');
ELSE
dbms_output.put_line ('Menos de la mitad empleados ganan todos mas de 1000
$');
END IF;
END;
/
ORACLE Developer Forms 10g Programación 6
7. Sentencias de Control y Bucles
DECLARE
v_salary employee.salary%TYPE;
begin
select salary into v_salary from employee where emp_no=65;
dbms_output.put_line('Salario:'|| v_salary);
Case
when v_salary=0 THEN
dbms_output.put_line('Gratis!');
when v_salary<10000 then
dbms_output.put_line('Salado!');
when v_salary<90000 then
dbms_output.put_line('Mas o menos');
when v_salary>=90000 then
dbms_output.put_line('Correcto');
end case;
end;
/
ORACLE Developer Forms 10g Programación 7
8. Sentencias de Control y Bucles
DECLARE
v_job_grade employee.job_grade%TYPE;
begin
select job_grade into v_job_grade from employee where emp_no=2;
dbms_output.put_line('job_grade:'|| v_job_grade);
case v_job_grade
when 1 THEN
dbms_output.put_line('Jefe!');
when 2 then
dbms_output.put_line('Jefecito');
when 3 then
dbms_output.put_line('Empleado regular');
ELSE
dbms_output.put_line('Esclavo o dios');
end case;
end;
/
ORACLE Developer Forms 10g Programación 8
9. Bucles
En PL/SQL podemos utilizar bucles:
* LOOP
* WHILE
* FOR
LOOP
El bucle LOOP, se repite tantas veces como sea necesario hasta que se fuerza su salida con
la instrucción EXIT.
DECLARE
v_cnt PLS_INTEGER DEFAULT 0;
BEGIN
LOOP
v_cnt:=v_cnt+1; /*Suma 1 cada vuelta*/
dbms_output.put_line ('Contador = '||v_cnt);
IF (v_cnt>=10) then /*Ingresa al If cuando es >= a 10*/
dbms_output.put_line (‘Salí Pues!');
exit;
END IF;
END LOOP;
END;
ORACLE Developer Forms 10g Programación 9
10. Bucles
WHILE
El bucle WHILE, se repite mientras que se cumpla expresión.
Ejemplo:
DECLARE
v_cnt PLS_INTEGER DEFAULT 0;
BEGIN
v_cnt:=10;
WHILE (v_cnt>0) LOOP
dbms_output.put_line ('Contador = '||v_cnt);
v_cnt:=v_cnt-1; /*Cada vez que pasamos Restamos 1*/
END LOOP;
END;
/
ORACLE Developer Forms 10g Programación 10
11. Bucles
FOR
El bucle FOR, se repite tanta veces como le indiquemos en los identificadores inicio y final,
generalmente es usado para recorrer Cursores. En el caso de especificar REVERSE el bucle
se recorre en sentido inverso.
FOR contador IN [REVERSE] inicio..final LOOP
-- Instrucciones
END LOOP;
Ejemplo:
DECLARE
v_cnt PLS_INTEGER DEFAULT 0;
BEGIN
FOR v_cnt IN REVERSE 1..10 LOOP
dbms_output.put_line ('Contador = '||v_cnt);
END LOOP;
END;
/
ORACLE Developer Forms 10g Programación 11
12. Cursores
PL/SQL utiliza cursores para gestionar las instrucciones SELECT. Un cursor es un conjunto de
registros devuelto por una instrucción SQL. Técnicamente los cursores son fragmentos de
memoria que reservados para procesar los resultados de una consulta SELECT.
SQL%ISOPEN : True si el cursor esta abierto (entre open y close),
SQL%FOUND :
• NULL antes de ejecutar
• TRUE si uno o mas registros fueron inserted, merged, updated, o deleted o si solo 1
registro fue
seleccionado.
• FALSE si ningún registro fue seleccionado, merged, updated, inserted, o deleted.
SQL%NOTFOUND
• NULL antes de ejecutar
• TRUE si ningún registro fue seleccionado, merged, updated, inserted, o deleted.
• FALSE si uno o mas registros fueron inserted, merged, updated, deleted o seleccionado.
SQL%ROWCOUNT Cantidad de registros afectados por el cursor.
ORACLE Developer Forms 10g Programación 12
13. Cursores
Un Cursor Implícito:
DECLARE
v_nacionalidad varchar2(15);
BEGIN
SELECT nacionalidad INTO v_nacionalidad FROM persona WHERE pid=2;
dbms_output.put_line(La persona número 2 es de nacionalidad '|| v_nacionalidad );
end;
DECLARE
deptid employees.department_id%TYPE;
jobid employees.job_id%TYPE;
emp_rec employees%ROWTYPE;
TYPE emp_tab IS TABLE OF employees%ROWTYPE INDEX BY PLS_INTEGER;
all_emps emp_tab;
BEGIN
SELECT department_id, job_id INTO deptid, jobid
FROM employees WHERE employee_id = 140;
IF SQL%FOUND THEN
DBMS_OUTPUT.PUT_LINE('Dept Id: ' || deptid || ', Job Id: ' || jobid);
END IF;
SELECT * INTO emp_rec FROM employees WHERE employee_id = 105;
SELECT * BULK COLLECT INTO all_emps FROM employees;
DBMS_OUTPUT.PUT_LINE('Number of rows: ' || SQL%ROWCOUNT);
END;
ORACLE Developer Forms 10g Programación 13
14. Cursores
Ejemplo de cursor explicito:
DECLARE
CURSOR c_emp IS /*CURSOR*/
select ename, sal from employee;
BEGIN
FOR fila IN c_emp LOOP /*no es necesario definir la variable fila, será de tipo %ROW */
dbms_output.put_line(fila.ename||' tiene un salario de '||fila.sal);
END LOOP;
END;
/
ORACLE Developer Forms 10g Programación 14
15. Cursores
DECLARE
emp_rec employee%ROWTYPE; /*declaramos la variable igual a la fila de la tabla*/
cursor c_emp is select * from employee for update; /*La opción “For Update” bloquea los
registros */
BEGIN
OPEN c_emp; /*Abrimos el Cursor*/
LOOP
FETCH c_emp into emp_rec; /*Recuperamos una fila*/
EXIT WHEN c_emp%NOTFOUND OR c_emp%ROWCOUNT > 10;
UPDATE employee
SET salary = salary+5
where current of c_emp;
END LOOP;
CLOSE c_emp;
END;
ORACLE Developer Forms 10g Programación 15
16. Excepciones
Los bloques de excepciones permiten atrapar errores de ejecución y darles eventualmente
un tratamiento para evitar que termine el programa de manera anormal.
DECLARE
-- Declaraciones
BEGIN
-- Ejecución
EXCEPTION
WHEN NO_DATA_FOUND THEN
-- Se ejecuta cuando ocurre una excepción de tipo NO_DATA_FOUND
WHEN ZERO_DIVIDE THEN
-- Se ejecuta cuando ocurre una excepción de tipo ZERO_DIVIDE
WHEN OTHERS THEN
-- Se ejecuta cuando ocurre una excepción de un tipo no tratado
-- en los bloques anteriores
END;
ORACLE Developer Forms 10g Programación 16
17. Excepciones
Ejemplo:
DECLARE
v_sal NUMBER;
BEGIN
BEGIN
SELECT salary INTO v_sal FROM employee WHERE emp_no=1;
dbms_output.put_line('El empleado numero 1 tiene un salario de '||v_sal||' $');
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('El empleado numero 1 no existe!');
END;
BEGIN
SELECT emp_no INTO v_sal FROM employee WHERE salary>1000;
dbms_output.put_line('El empleado que tiene un salario>1000 $ es el empleado
numero'||v_sal);
EXCEPTION
WHEN too_many_rows THEN
dbms_output.put_line('HAY MAS DE UN EMPLEADO QUE GANA MAS DE 1000
$!');
END;
END;
ORACLE Developer Forms 10g Programación 17
18. Excepciones
ACCESS_INTO_NULL El programa intento asignar valores a los atributos de un objeto no
inicializado 6530
COLLECTION_IS_NULL El programa intento asignar valores a una tabla anidada aun no
inicializada 6531
CURSOR_ALREADY_OPEN El programa intento abrir un cursor que ya se encontraba abierto.
Recuerde que un cursor de ciclo FOR automáticamente lo abre y ello no se debe especificar
con la sentencia OPEN 6511
DUP_VAL_ON_INDEX El programa intento almacenar valores duplicados en una columna
que se mantiene con restriccion de integridad de un índice único (unique index) 1
INVALID_CURSOR El programa intento efectuar una operación no valida sobre un cursor
1001
INVALID_NUMBER En una sentencia SQL, la conversión de una cadena de caracteres hacia
un número falla cuando esa cadena no representa un numero valido 1722
LOGIN_DENIED El programa intento conectarse a Oracle con un nombre de usuario o
password invalido 1017
NO_DATA_FOUND Una sentencia SELECT INTO no devolvio valores o el programa referencio
un elemento no inicializado en una tabla indexada 100
NOT_LOGGED_ON El programa efectuo una llamada a Oracle sin estar conectado 1012
PROGRAM_ERROR PL/SQL tiene un problema interno 6501
ORACLE Developer Forms 10g Programación 18
19. Excepciones
ROWTYPE_MISMATCH Los elementos de una asignación (el valor a asignar y la variable que
lo contendra) tienen tipos incompatibles. También se presenta este error cuando un
parámetro pasado a un subprograma no es del tipo esperado 6504
SELF_IS_NULL El parámetro SELF (el primero que es pasado a un método MEMBER) es nulo
30625
STORAGE_ERROR La memoria se termino o esta corrupta 6500
SUBSCRIPT_BEYOND_COUNT El programa esta tratando de referenciar un elemento de un
arreglo indexado que se encuentra en una posición mas grande que el numero real de
elementos de la colección 6533
SUBSCRIPT_OUTSIDE_LIMIT El programa esta referenciando un elemento de un arreglo
utilizando un numero fuera del rango permitido (por ejemplo, el elemento “1”) 6532
SYS_INVALID_ROWID La conversión de una cadena de caracteres hacia un tipo rowid fallo
porque la cadena no representa un numero 1410
TIMEOUT_ON_RESOURCE Se excedió el tiempo máximo de espera por un recurso en Oracle
51
TOO_MANY_ROWS Una sentencia SELECT INTO devuelve mas de una fila 1422
VALUE_ERROR Ocurrió un error aritmético, de conversión o truncamiento. Por ejemplo,
sucede cuando se intenta calzar un valor muy grande dentro de una variable mas pequeña
6502
ZERO_DIVIDE El programa intento efectuar una división por cero 1476
ORACLE Developer Forms 10g Programación 19
20. Excepciones
DECLARE
err_num NUMBER;
err_msg VARCHAR2(255);
result NUMBER;
BEGIN
SELECT 1/0 INTO result
FROM DUAL;
EXCEPTION
WHEN OTHERS THEN
err_num := SQLCODE;
err_msg := SQLERRM;
DBMS_OUTPUT.put_line('Error:'||TO_CHAR(err_num));
DBMS_OUTPUT.put_line(err_msg);
END;
ORACLE Developer Forms 10g Programación 20
21. Sentencia Raise
La sentencia RAISE permite lanzar una excepción en forma explicita. Es posible utilizar esta
sentencia en cualquier lugar que se encuentre dentro del alcance de la excepción.
DECLARE
-- Declaramos una excepción identificada por VALOR_NEGATIVO
VALOR_NEGATIVO EXCEPTION;
valor NUMBER;
BEGIN
-- Ejecución
valor := -1;
IF valor < 0 THEN
RAISE VALOR_NEGATIVO;
END IF;
EXCEPTION
-- Excepción
WHEN VALOR_NEGATIVO THEN
dbms_output.put_line('El valor no puede ser negativo');
END;
ORACLE Developer Forms 10g Programación 21
22. Sentencia Raise
En ocasiones queremos enviar un mensaje de error personalizado al producirse una
excepcion PL/SQL.
Para ello es necesario utilizar la instruccion RAISE_APPLICATION_ERROR; La sintaxis
general es la siguiente:
RAISE_APPLICATION_ERROR(<error_num>,<mensaje>);
Siendo:
* error_num es un entero negativo comprendido entre 20001
y 20999
* mensaje la descripción del error
DECLARE
v_div NUMBER;
BEGIN
SELECT 1/0 INTO v_div FROM DUAL;
EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20001,'No se puede dividir por cero');
END;
ORACLE Developer Forms 10g Programación 22
24. Funciones, procedimientos y paquetes
Funciones definidas por el usuario
CREATE OR REPLACE /* Or replace es opcional */
FUNCTION fn_Obtener_Salario(p_empno NUMBER) RETURN NUMBER
IS
result NUMBER;
BEGIN
SELECT salary INTO result
FROM employee
WHERE emp_no = p_empno;
return(result);
EXCEPTION
WHEN NO_DATA_FOUND THEN
return 0;
END ;
ORACLE Developer Forms 10g Programación 24
25. Funciones, procedimientos y paquetes
Procedimientos
Debemos especificar el tipo de datos de cada parametro. Al especificar el tipo de dato del
parámetro no debemos especificar la longitud del tipo.
Los parámetros pueden ser de entrada (IN), de salida (OUT) o de entrada salida (IN OUT).
El valor por defecto es IN, y se toma ese valor en caso de que no especifiquemos nada.
Create or replace
PROCEDURE Actualiza_Salario(p_empno NUMBER,
p_new_salario NUMBER default 100)
/*podemos usar Default o :=*/
IS
-- Declaracion de variables locales
BEGIN
-- Sentencias
UPDATE employee
SET salary = p_new_salario,
hire_date = SYSDATE
WHERE emp_no = p_empno;
END Actualiza_Salario;
ORACLE Developer Forms 10g Programación 25
26. Funciones, procedimientos y paquetes
Paquetes
Un paquete es un conjunto de funciones y/o procedimiento. Permite facilitar la
administración de los códigos (agrupaciones), y la seguridad (a nivel de paquete en vez de
por función/procedimiento). En el paquete se pueden definir variable de alcance de todo
el paquete (global variables).
CREATE [OR REPLACE] PACKAGE <pkgName>
IS
-- Declaraciones de tipos y registros públicas
{[TYPE <TypeName> IS <Datatype>;]}
-- Declaraciones de variables y constantes publicas
-- También podemos declarar cursores
{[<ConstantName> CONSTANT <Datatype> := <valor>;]}
{[<VariableName> <Datatype>;]}
-- Declaraciones de procedimientos y funciones públicas
{[FUNCTION <FunctionName>(<Parameter> <Datatype>,...)
RETURN <Datatype>;]}
{[PROCEDURE <ProcedureName>(<Parameter> <Datatype>, ...);]}
END <pkgName>;
ORACLE Developer Forms 10g Programación 26
27. Funciones, procedimientos y paquetes
CREATE [OR REPLACE] PACKAGE BODY <pkgName> IS
-- Declaraciones de tipos y registros privados
{[TYPE <TypeName> IS <Datatype>;]}
-- Declaraciones de variables y constantes privadas
-- También podemos declarar cursores
{[<ConstantName> CONSTANT <Datatype> := <valor>;]}
{[<VariableName> <Datatype>;]}
-- Implementación de procedimientos y funciones
FUNCTION <FunctionName>(<Parameter> <Datatype>,...)
RETURN <Datatype>
IS
-- Variables locales de la función
BEGIN
-- Implementación de la función
return(<Result>);
[EXCEPTION]
-- Control de excepciones
END;
PROCEDURE <ProcedureName>(<Parameter> <Datatype>, ...)
IS
-- Variables locales de la función
BEGIN
-- Implementación de procedimiento
[EXCEPTION]
-- Control de excepciones
END;
END <pkgName>;
ORACLE Developer Forms 10g Programación 27
28. Triggers
Un trigger es un bloque PL/SQL asociado a una tabla, que se ejecuta como consecuencia de
una determinada instrucción SQL (una operación DML: INSERT, UPDATE o DELETE) sobre
dicha tabla.
CREATE [OR REPLACE] TRIGGER <nombre_trigger>
{BEFORE|AFTER}
{DELETE|INSERT|UPDATE [OF col1, col2, ..., colN]
[OR {DELETE|INSERT|UPDATE [OF col1, col2, ..., colN]...]}
ON <nombre_tabla>
[FOR EACH ROW [WHEN (<condicion>)]]
DECLARE
-- variables locales
BEGIN
-- Sentencias
[EXCEPTION]
-- Sentencias control de excepcion
END <nombre_trigger>;
ORACLE Developer Forms 10g Programación 28
29. Triggers
create or replace TRIGGER TR_EMP_AU
Curso de SQL avanzado y PL/SQL basico para Oracle 10g (10.2) Pagina 40 / 44
AFTER UPDATE ON EMPLOYEE
FOR EACH ROW
WHEN (OLD.salary<>NEW.salary)
DECLARE
-- local variables
BEGIN
INSERT INTO emp_audit
(emp_no,fecha,msg)
VALUES
(:NEW.emp_no,SYSDATE,'Salario modificado de '||:old.salary||' a '||:new.salary);
END TRIGGER TR_EMP_AU;
ORACLE Developer Forms 10g Programación 29
30. Cierre
Sitios Recomendados
http://www.oracle.com/technetwork/index.html Sitio Oficial de
Oracle
http://www.orasite.com/ Comunidad y foros de consulta sobre
Oracle todo en Español
http://es.scribd.com/ Libros con mucho información de varias
herramientas de desarrollo
Instructor: Edwin Alfredo Romero
Email: romero.espinoza@gmail.com
Blog: www.ejecucion.wordpress.com
Twitter: @Wirwin2009
Yo ruego a Dios, como si lo esperase todo de Él, pero trabajo como si lo esperase todo
de mí.- Santo Tomas de Aquino
ORACLE Developer Forms 10g Programación 30