Ahora complicaremos un poco más las cosas. Hasta el momento sólo hemos visto manejo de variables, operaciones matemáticas y la declaración de un script PL/SQL básico.
En éste capítulo veremos el uso de sentencias de control. Las sentencias de control permiten cambiar el flujo de ejecución las instrucciones de nuestro código PL/SQL, de ésta manera se puede indicar la ejecución de un bloque de instrucciones cuando se cumpla una condición o simplemente hacer que se repita en tiempo de ejecución.
En PL/SQL tenemos grupos de sentencias de control:
- Condicional
- Iterativo
- Secuencial
Condicional
La estructura condicional está representada por las sentencias IF y CASE.
IF-THEN-ELSE(SI-ENTONCES-CASO CONTRARIO)
Ésta sentencia permite la ejecución de una o varias líneas de código según una condición. La condición se especifica en la cláusula IF, en caso de que la condición sea verdadera se ejecuta el bloque de código especificado bajo la cláusula THEN, en caso contrario se ejecuta el bloque de código especificado en la cláusula ELSE. La claúsula ELSE es opcional
Veamos un ejemplo:
DECLARE /*Para poder ver la utilidad de éste script basta con cambiar los valores de las variables V_A y V_B según queramos. */ V_A NUMBER := 30; V_B NUMBER := 10; BEGIN /*En caso de que la variable V_A sea mayor se mostrará un mensaje*/ IF V_A > V_B THEN dbms_output.put_line('V_A es mayor'); END IF; END;
V_A es mayor
La condición para la sentencia IF del ejemplo anterior, está dada por la comparación V_A > V_B, en caso de que el valor de V_A sea mayor que el de V_B se mostrará el mensaje "V_A es mayor", en caso de que V_B sea mayor o ambos iguales no se mostrará nada.
Ahora veamos el uso de la cláusula ELSE:
DECLARE /*Para poder ver la utilidad de éste script basta con cambiar los valores de las variables V_A y V_B según queramos. */ V_A NUMBER := 30; V_B NUMBER := 30; BEGIN /*En caso de que la variable V_A sea mayor se mostrará un mensaje*/ IF V_A > V_B THEN dbms_output.put_line('V_A es mayor'); ELSE dbms_output.put_line('V_B es mayor o igual que V_A'); END IF; END;
V_B es mayor o igual que V_A
Para el ejemplo anterior, se ha adicionado la cláusula ELSE, la cual se ejecutará cuando la variable V_A no sea mayor que la variable V_B. Puedes probar cambiando los valores de las variables a tu gusto para ver cómo se se ejecutan las instrucciones de sólo una de las cláusulas(THEN o ELSE).
CASE(CASO)
La sentencia CASE permite evaluar diferentes opciones, por cada opción se realiza una instrucción específica. Veamos un ejemplo:
DECLARE V_TIPO_TRABAJADOR VARCHAR2(2) := 'AP'; V_SALARIO NUMBER; BEGIN CASE WHEN V_TIPO_TRABAJADOR = 'AP' THEN V_SALARIO := 1500; WHEN V_TIPO_TRABAJADOR = 'AS' THEN V_SALARIO := 2300; WHEN V_TIPO_TRABAJADOR = 'JP' THEN V_SALARIO := 5000; END CASE; DBMS_OUTPUT.PUT_LINE('El salario de un ' || V_TIPO_TRABAJADOR || ' es ' || V_SALARIO); END;
El salario de un AP es 1500
También se puede usar la sentencia CASE de manera simple para realizar la asignación de un valor según la evaluación de una variable por diferentes casos:
DECLARE V_TIPO_TRABAJADOR VARCHAR2(2) := 'AP'; V_SALARIO NUMBER; BEGIN V_SALARIO:= CASE V_TIPO_TRABAJADOR WHEN 'AP' THEN 1500 WHEN 'AS' THEN 2300 WHEN 'JP' THEN 5000 END; DBMS_OUTPUT.PUT_LINE('El salario de un ' || V_TIPO_TRABAJADOR || ' es ' || V_SALARIO); END;
El salario de un AP es 1500
Finalmente, podemos hacer uso de la cláusula ELSE en caso de que ninguna de las opciones definidas en WHEN sea seleccionada:
DECLARE V_TIPO_TRABAJADOR VARCHAR2(2) := 'AR'; V_SALARIO NUMBER; V_TIENE_SALARIO BOOLEAN; BEGIN CASE WHEN V_TIPO_TRABAJADOR = 'AP' THEN V_SALARIO := 1500; V_TIENE_SALARIO := TRUE; WHEN V_TIPO_TRABAJADOR = 'AS' THEN V_SALARIO := 2300; V_TIENE_SALARIO := TRUE; WHEN V_TIPO_TRABAJADOR = 'JP' THEN V_SALARIO := 5000; V_TIENE_SALARIO := TRUE; ELSE V_TIENE_SALARIO := FALSE; END CASE; IF V_TIENE_SALARIO THEN DBMS_OUTPUT.PUT_LINE('El salario de un ' || V_TIPO_TRABAJADOR || ' es ' || V_SALARIO); ELSE DBMS_OUTPUT.PUT_LINE(V_TIPO_TRABAJADOR || ' no tiene un salario definido'); END IF; END;
AR no tiene un salario definido
Iteravito
Las sentencias iterativas permiten ejecutar varias instrucciones múltiples veces. A éstas sentencias también se les conoce por el nombre de bucles repetitivos.
FOR-LOOP
La sentencia FOR-LOOP permite especificar un rango de números enteros, finalmente ejecuta una secuencia de instrucciones para cada número entero dentro de la lista de números.
Veámos un ejemplo:
BEGIN FOR i IN 1..8 LOOP DBMS_OUTPUT.PUT_LINE('El número de ésta iteracción es:' || i); END LOOP; END;
El número de ésta iteracción es:1 El número de ésta iteracción es:2 El número de ésta iteracción es:3 El número de ésta iteracción es:4 El número de ésta iteracción es:5 El número de ésta iteracción es:6 El número de ésta iteracción es:7 El número de ésta iteracción es:8
En el ejemplo anterior, sólo existe una instrucción para imprimir un mensaje en la sentencia LOOP, pero sin embargo en la salida el mensaje se repite 8 veces con los números del 1 al 8. En la cláusula IN la expresión 1..8 genera una lista de números, para éste caso , del 1 al 8.
Probemos ahora generando la tabla de multiplicar del 7 del 1 al 12:
BEGIN FOR i IN 1..12 LOOP DBMS_OUTPUT.PUT_LINE('7*' || i || '='|| (7*i)); END LOOP; END;
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 7*8=56 7*9=63 7*10=70 7*11=77 7*12=84
WHILE-LOOP
La sentencia de control WHILE LOOP, al igual que FOR-LOOP, permite la ejecución de una o varias instrucciones. A diferencia de la sentencia FOR-LOOP, en WHILE-LOOP la ejecución se define a partir de una condición. Veamos un ejemplo:
DECLARE V_NUM NUMBER := 1; BEGIN WHILE V_NUM <= 13 LOOP DBMS_OUTPUT.PUT_LINE('El valor V_NUM es :' || V_NUM); V_NUM := V_NUM + 2.1; END LOOP; END;
El valor V_NUM es :1 El valor V_NUM es :3,1 El valor V_NUM es :5,2 El valor V_NUM es :7,3 El valor V_NUM es :9,4 El valor V_NUM es :11,5
En el ejemplo anterior, al igual que en la sentencia FOR-LOOP, el mensaje "El valor de V_NUM es ..." se repite varias veces, pero ésta vez la variable V_NUM se ve incrementada en 2.1 cada vez que la sentencia WHILE-LOOP se ejecuta. En la cláusula WHILE, mientras la condición V_NUM <= 13 es verdadera se ejecutará el código dentro de la cláusula LOOP. Finalmente debido al incremento realizado en la línea 6 (V_NUM := V_NUM + 2.1) el código sólo se repetirá 6 veces.
LOOP
La sentencia LOOP permite ejecutar un bloque de código de manera infinita, a diferencia de las otras sentencias iterativas, en la sentencia LOOP se debe utilizar la cláusula EXIT WHEN para colocar una condición para terminar el bucle:
DECLARE V_TOTAL NUMBER := 0; V_CONTADOR NUMBER := 0; BEGIN LOOP V_CONTADOR := V_CONTADOR + 1; V_TOTAL := V_TOTAL + V_CONTADOR; DBMS_OUTPUT.PUT_LINE('Valor de V_TOTAL:' || V_TOTAL); EXIT WHEN V_TOTAL > 20; END LOOP; END;
Valor de V_TOTAL:1 Valor de V_TOTAL:3 Valor de V_TOTAL:6 Valor de V_TOTAL:10 Valor de V_TOTAL:15 Valor de V_TOTAL:21
En el ejemplo anterior, la sentencia LOOP terminará cuando el valor de la variables V_TOTAL sea mayor a 20.
Secuencial
La sentencia GOTO permite cambiar la línea secuencial de la ejecución hacia una etiqueta. Las etiquetas son marcadas con los símbolos << y >>. Para ir dirigir la ejecución hacia una etiqueta simplemente hay que usar la sentencia GOTO:
DECLARE V_TOTAL NUMBER(9) := 0; V_CONTADOR NUMBER(6) := 0; BEGIN <<calcular>> V_CONTADOR := V_CONTADOR + 1; V_TOTAL := V_TOTAL + V_CONTADOR; IF V_TOTAL <= 20 THEN DBMS_OUTPUT.PUT_LINE('Valor de V_TOTAL:' || V_TOTAL); GOTO calcular; END IF; END;
Valor de V_TOTAL:1 Valor de V_TOTAL:3 Valor de V_TOTAL:6 Valor de V_TOTAL:10 Valor de V_TOTAL:15
En el ejemplo anterior, la sentencia GOTO redireccionará la ejecución hacia la línea 6 mientras el valor de V_TOTAL sea menor a 20.