Está en la página 1de 27

Programación en Oracle PL/SQL

Estructura
Ejemplo
REM Inicializar el parámetro de SQL*Plus por substitución P_SAL
ACCEPT p_sal PROMPT ‘Ingresar el salario mensual:’

REM Inicializar la variable global SQL*Plus g_year_sal


VARIABLE g_year_sal NUMBER

DECLARE
v_sal NUMBER(9,2) := &p_sal: -- Inicializar con valor ingresado
BEGIN
/* Calculo del salario anual */
:g_year_sal := v_sal * 12;
END;
/
REM Imprimir el salario anual en la pantalla
PRINT g_year_sal
Declaración de variables
Sintaxis
Identificador [CONSTANT] tipo_de_dato [NOT NULL][:= | DEFAULT expresion_plsql]

Notas
• EL nombre de los identificadores están de acuerdo a las mismas reglas de los objetos de
SQL*Plus

• Se restringe a un identificador a no pueda cambiar su valor mediante la palabra


CONSTANT. Las constantes deben ser inicializadas.

• Se puede restringir las variables para que no puedan contener nulos mediante la palabra
NOT NULL. Las variables de este tipo deben ser inicializadas.

• Inicializar una variable con una expresión PL/SQL con el operador de asignación := o con
la palabra reservada DEFAULT; de lo contrario las variables son inicializadas con NULL.
Tipos de datos
TIPO DESCRIPCION
BINARY_INTEGER Tipo base para enteros entre -2E31 a 2E31 -1
POSITIVE Subtipo para enteros mayores que cero
NATURAL Subtipo para enteros mayores o iguales a 0

Tipo base para numeros de punto fijo y flotante


NUMBER de cualquier tamaño
FLOAT,DECIMAL,REAL,INTEGER, SMALLINT Subtipos de NUMBER

Tipo de datos carácter con longitud variable.


VARCHAR2 Longitud máxima de 2000

Tipo de datos carácter de longitud variable de


LONG hasta 2 GigaBytes

Tipo de datos carácter de longitud fija. Longitud


CHAR máxima de 255

Subtipo CHAR para representar el tipo de la


ROWID pseudo columna ROWID
DATE Tipo para Fecha
RAW Tipo para binarios de hasta 255 bytes

Tipo para almacenar tres posibles valores, TRUE,


BOOLEAN FALSE o NULL
EJEMPLOS
V_COUNT BINARY_INTEGER := 0;

V_INGRESO NUMBER(9,2)

V_TOTAL_SAL NUMBER(9,2) DEFAULT 0;

V_NAME VARCHAR2(25);

V_GENERO CHAR(1);

C_COMPANY_NAME CONSTANT VARCHAR2(12) := ‘Mikoyan’;

V_FECHA_ORDEN DATE NOT NULL := SYSDATE;

V_SHIP_DATE DATE NOT NULL := SYSDATE + 7;

V_FLAG BOOLEAN NOT NULL DEFAULT FALSE;


Declaración de variables
complejas
Declaración de variables basado en otra variable

DECLARE
v_balance NUMBER(7,2);
v_minimun_balance v_balance%TYPE := 10;

Declaración de variables basado en una columna de una tabla

DECLARE
v_apellido S_EMP.LAST_NAME%TYPE;
v_nombre S_EMP.NAME%TYPE;
Etiquetar bloques
Se deben etiquetar los bloques externos para evitar reglas de ámbito donde las
variables declaradas en el no sean visibles.

Sintaxis

<<nombre_etiqueta>>
[DECLARE]
BEGIN

END nombre_etiqueta;
Ejemplo de bloques etiquetados
<<bloque_externo>>
DECLARE
v_n NUMBER;
BEGIN
v_n := 5;
/* Aquí empieza el sub-bloque */
DECLARE
v_x NUMBER := 10;
v_n VARCHAR2(10) := ‘FIFTEEN’;
BEGIN
INSERT INTO temp(col1,col2,message)
VALUES (bloque_externo.v_n,v_x,v_n);
COMMIT;
END; /* Fin de sub-bloque */
END bloque_externo;
Ejercicio
DECLARE
v_weight VARCHAR2(3) := ‘600’;
v_message VARCHAR2(255);
BEGIN
DECLARE
v_weight NUMBER(3) := 1;
v_message VARCHAR2(255);
v_new_locn VARCHAR2(50) := ‘Europe’;
BEGIN
v_weight := v_weight + 1; 7.
v_message := v_weight || ‘is overweight’; 8.
v_new_locn := ‘Western ‘|| v_new_locn; 9.
END;
v_weight := v_weight + 1; 10.
v_message := v_weight || ‘is overweight’; 11.
v_new_locn := ‘Western ‘|| v_new_locn; 12.

END;

Determine el valor que se asigna a las variables de los puntos 7 al 12.


Flujos de ejecución
Sentencia IF – THEN - ELSE
IF <condición> THEN
instrucción1;
instrucción2;
...
[ELSIF <condición> THEN
instrucción1;
instrucción2;
...]
[ELSE
instrucción1;
instrucción2;
...]
END IF;
Ejemplo
Poner el tipo de pago para una orden específica dependiendo del rating de crédito
para el cliente.

DECLARE
v_credit_rating s_customer.credit_rating%TYPE
BEGIN
SELECT s_customer.credit_rating INTO v_credit_rating
FROM s_customer.s_ord
WHERE s_customer.id = s_ord.customer_id
AND s_ord.id = &p_ord_id;
IF (v_credit_rating = ‘GOOD’ OR v_credit_rating = ‘EXCELLENT’)
THEN
UPDATE s_ord SET payment_type = ‘CREDIT’
WHERE id = &p_ord_id;
ELSIF (v_credit_rating = ‘POOR’)
THEN
UPDATE s_ord SET payment_type = ‘POOR’
WHERE id = &p_ord_id;
ELSE
UPDATE s_ord SET payment_type = ‘POOR’
WHERE id = &p_ord_id;
END IF;
COMMIT WORK;
END;
Construyendo condiciones lógicas
Se pueden construir condiciones lógicas combinando números, caracteres,
expresiones con fechas con operadores de comparación. Los valores NULL se
operan con el operador IS NULL.

• Cualquier expresión que contenga un NULL, avalúa a NULL, con la excepción


de la operación de concatenación, la cual maneja el NULL como una cadena
vacía.
• Cualquier comparación con el operador IS NULL evalúa a TRUE o FALSE.
Ciclos
FOR índice IN [REVERSE] limite_inf .. Limite_sup LOOP
instrucción1;
instrucción2;
...
END LOOP;

WHILE <condicion> LOOP


instrucción1;
instrucción2;
...
END LOOP;

<<nombre_etiqueta>>
LOOP
instrucción1;
instrucción2;
...
END LOOP nombre_etiqueta;
Ejemplo LOOP anidados
<<outer_loop>>
WHILE a > b LOOP
b := b + 1;
<<inner_loop>>
WHILE b > 1 LOOP
c := c + 2;
EXIT outer_loop WHEN c > 200
END LOOP inner_loop;
END LOOP outer_loop;
Procesando múltiples filas
Pasos para declarar y manipular un cursor

1. Declarar el cursor
2. Abrir el cursor (OPEN)
3. Acceder los datos del cursor (FETCH)
4. Cerrar el cursos (CLOSE)

Declaración
DECLARE
CURSOR nombre_cursor IS
instrucción_SELECT
Ejemplo
DECLARE
v_ord_id s_item.ord_id%TYPE;
v_product_id s_item.product_id%TYPE;
v_item_total NUMBER(11,2)
CURSOR item_cursor IS
SELECT product_id,price*quantity
FROM s_item
WHERE ord_id = v_ord_id;
BEGIN
...
END;

Nota:
• No incluir la clausula INTO en la declaración del cursor ya que aparece después
dentro de la instrucción FETCH.
• Si la instrucción SELECT hace referencia a cualquier variable, se debe asegurar
que ésta variable esté declarada anteriormente en la declaración del cursor.
Procesando múltiples filas
Abrir Cursor:
Abrir el cursor antes de especificar las variables de ingreso de
datos.

Sintaxis:

OPEN nombre_cursor nombre del cursor previamente definido

DECLARE
v_ord_id s_item.ord_id%TYPE;
v_product_id s_item.product_id%TYPE;
v_item_total NUMBER(11,2)
CURSOR item_cursor IS
SELECT product_id,price*quantity
FROM s_item
WHERE ord_id = v_ord_id;
BEGIN
v_ord_id := &p_ord_id;
OPEN item_cursor;
END;
Procesando múltiples filas
Abrir Cursor:
Para acceder los datos del cursor, se pueden almacenar en
variables locales.

Sintaxis:

FETCH nombre_cursor INTO variable1 , variable2;

Ejemplo:

FETCH item_cursor INTO v_product_id, v_item_total

Nota:

• Incluir el mismo número de variables dentro de la clausula INTO de la


instrucción FETCH como columnas retorne la instrucción SELECT, y
además deben ser tipo compatible.
• Las variables deben corresponder a las columnas por la posición.
Procesando múltiples filas
Cerrar Cursor:
Los cursores deben cerrarse después de haber terminado el
procesamiento de la información.

Sintaxis:

CLOSE nombre_cursor;

Ejemplo:

CLOSE item_cursor;

Nota:

• No intente dar un FETCH a un cursor que ha sido cerrado previamente.


Procesando múltiples filas
Recuperando filas en un LOOP:
Para recuperar las filas de un cursor una por una se utiliza un LOOP. Se
puede determinar la entrada o salida del LOOP inspeccionando uno de los atributos
del cursor, los cuales se muestran a continuación:

ATRIBUTO DESCRIPCIÓN

%ISOPEN Atributo booleano que evalúa a TRUE si el cursor esta


abierto.
%NOTFOUND Atributo booleano que evalúa a TRUE si el más
reciente FETCH no retorna una fila.
%FOUND Atributo booleano que evalúa a TRUE hasta que el
mas reciente FETCH no retorne una fila. Es el
complemento de %NOTFOUND.
%ROWCOUNT Atributo numérico que devuelve el número total de
filas retornadas.

Nota:
• No se puede hacer referencia a atributos de cursor directamente dentro de una
instrucción SQL.
Procesando múltiples filas
Recuperando filas en un LOOP:
Solo se pueden recuperar filas (FETCH) cuando el cursor está abierto.
Determinar si un cursor esta abierto usando el atributo %ISOPEN, si es necesario.

Ejemplo:
Recuperar el item actual; si el cursor no esta disponible, abrir el cursor.

IF item_cursor%ISOPEN
THEN
FETCH item_cursor into v_quantity, v_price
ELSE
OPEN item_cursor;
END IF;
Procesando múltiples filas
Recuperando filas en un LOOP:
Recuperar las filas en un LOOP simple y determinar cuando salir del LOOP
usando el atributo %NOTFOUND.

Ejemplo
Recuperar los items para una orden uno por uno hasta que no hayan más.
Almacenar el total acumulativo para cada producto en una tabla separada.

DECLARE
v_ord_id s_item.ord_id%TYPE;
v_product_id s_item.product_id%TYPE;
v_item_total NUMBER(11,2)
CURSOR item_cursor IS
SELECT product_id,price*quantity
FROM s_item
WHERE ord_id = v_ord_id;
BEGIN
OPEN item_cursor;
LOOP
FETCH item_cursor INTO v_product_id,v_item_total;
EXIT WHEN item_cursor%NOTFOUND;
v_order_total := v_order_total + v_item_total;
INSERT INTO temp(product_id,cummulative_total) VALUES (v_product_id,v_order_total)
END LOOP;
CLOSE item_cursor;
COMMIT WORK;
END;
Procesando múltiples filas
Recuperando filas en un LOOP:
Equivalentemente, recuperar las filas en un LOOP WHILE, y determinar
cuando salir del LOOP usando el atributo %FOUND.

Ejemplo
Recuperar los ítems para una orden uno por uno hasta que no hayan más.
Almacenar el total acumulativo para cada producto en una tabla separada.

DECLARE
v_ord_id s_item.ord_id%TYPE;
v_product_id s_item.product_id%TYPE;
v_item_total NUMBER(11,2)
CURSOR item_cursor IS
SELECT product_id,price*quantity
FROM s_item
WHERE ord_id = v_ord_id;
BEGIN
OPEN item_cursor;
FETCH item_cursor INTO v_product_id, v_item_total;
WHILE item_cursor%FOUND LOOP
v_order_total := v_order_total + v_item_total;
INSERT INTO temp(product_id,cummulative_total) VALUES (v_product_id,v_order_total);
FETCH item_cursor INTO v_product_id, v_item_total
END LOOP;
CLOSE item_cursor;
COMMIT WORK;
END;
Procesando múltiples filas
Recuperando filas en un LOOP:
Para recuperar un número exacto de filas, recuperar las filas en un loop FOR
numérico, o recuperar en un loop simple, y determinar cuando salir del loop usando el
atributo %ROWCOUNT.

Ejemplo
Recuperar los ítems para una orden uno por uno hasta que no hayan más. Almacenar el
total acumulativo para cada producto en una tabla separada.
DECLARE
v_ord_id s_item.ord_id%TYPE;
v_product_id s_item.product_id%TYPE;
v_item_total NUMBER(11,2)
CURSOR item_cursor IS
SELECT product_id,price*quantity
FROM s_item
WHERE ord_id = v_ord_id;
BEGIN
OPEN item_cursor;
LOOP
FETCH item_cursor INTO v_product_id, v_item_total;
v_order_total := v_order_total + v_item_total;
INSERT INTO temp(product_id,cummulative_total) VALUES (v_product_id,v_order_total);
EXIT WHEN item_cursor%ROWCOUNT <= 100;
END LOOP;
CLOSE item_cursor;
COMMIT WORK;
END;
Procesando múltiples filas
Recuperando filas en un LOOP:
El loop FOR itera cada vez que una fila es retornada por el query.

Sintaxis
FOR nombre_registro IN nombre_cursor LOOP
Instrucción1;
Instrucción2;
END LOOP;

Cuando se usa un el loop FOR con un cursor:

• Un OPEN implícito es ejecutado cuando se inicia el loop.


• El FETCH implícito es ejecutado por cada iteración del loop.
• Un CLOSE implícito es ejecutado cuando el loop termina.

Nota

• No se declara el record que controla el loop.


• No usar un cursor loop FOR cuando las operaciones con el cursor se hacen
manualmente.
Procesando múltiples filas
Ejemplo
Recuperar los ítems para una orden uno por uno hasta que no hayan más. Almacenar el
total acumulativo para cada producto en una tabla separada.

DECLARE
v_ord_id s_item.ord_id%TYPE;
v_product_id s_item.product_id%TYPE;
v_item_total NUMBER(11,2)
CURSOR item_cursor IS
SELECT product_id,price*quantity
FROM s_item
WHERE ord_id = v_ord_id;
BEGIN
FOR item_record IN item_cursor LOOP
v_order_total := v_order_total + v_item_total;
INSERT INTO temp(product_id,cummulative_total) VALUES (v_product_id,v_order_total);
END LOOP;
COMMIT WORK;
END;

También podría gustarte