Está en la página 1de 30

PL/SQL

Francisco Moreno
Universidad Nacional

Introduccin al PL/SQL
Por qu PL/SQL?
A pesar de que SQL tiene mecanismos de
control condicional (clusula CASE WHEN*) e
iterativos (implcitos) en ocasiones se requiere:
- Manipular y controlar los datos de una manera
secuencial
- Mejorar el desempeo de las aplicaciones
Existen problemas cuya solucin puede ser ms
sencilla y eficiente mediante un lenguaje
procedimental que mediante SQL puro
* PL/SQL tambin la tiene. Ms adelante se ve un ejemplo.

Introduccin al PL/SQL
Ejemplo: insercin de 500 filas en una tabla:
DROP TABLE plana;
CREATE TABLE plana(nro NUMBER(3) PRIMARY KEY,
dato VARCHAR2(80));
BEGIN
FOR i IN 1..500 LOOP
INSERT INTO plana
VALUES (i,'No rayar el pupitre');
END LOOP;
END;
/

Introduccin al PL/SQL
Incorporacin de PSM* a SQL (1992) Incluye
estructuras de secuencia, decisin, iteracin,
iteracin
creacin de procedimientos, funciones, etc.
La versin PSM de Oracle se llama PL/SQL
(Procedural Language/SQL).
En SQL Server se llama Transact-SQL (T-SQL).
En PL/SQL se pueden crear procedimientos con
o sin nombre (annimos), funciones,
disparadores (triggers) y bibliotecas de
funciones y procedimientos llamadas paquetes.
paquetes
*Persistent Stored Modules

Bloques PL/SQL
Un bloque PL/SQL es una pieza de cdigo dividida en tres secciones:
DECLARE
Seccin de declaracin
BEGIN
Seccin ejecutable
EXCEPTION
Seccin de manejo de excepciones
END;

Las secciones de manejo de excepciones y de declaracin son


opcionales.
Los bloques pueden contener otros bloques (sub-bloques) ver
luego
Los comentarios van entre /* */. Si no ocupan ms de una lnea, se
pueden escribir despus de -- (dos guiones).

Variables y constantes
Tipos de datos* en PL/SQL: NUMBER, CHAR,
VARCHAR/VARCHAR2, DATE, BOOLEAN, entre otros.
La sintaxis para declarar variables o constantes es:
nombre [CONSTANT] TIPO [NOT NULL][:= expresin];

No se diferencian maysculas y minsculas.


* Algunos tienen precisin.

Los
corchetes
indican las
partes
opcionales

Se pueden declarar variables refirindose al tipo


de datos de otros elementos tales como
variables, columnas y tablas, ver ejemplos ms
adelante.
El operador de asignacin es := y el de igualdad
es =.

Alcance
El alcance o visibilidad de las variables sigue estas reglas:
1. Una variable es visible en el bloque en el cual se declara
y en todos sus sub-bloques, a menos que se aplique la
regla 2.
2. Si se declara una variable en un sub-bloque con el
mismo nombre que una variable del bloque contenedor,
la variable del sub-bloque es la que tiene prioridad en el
sub-bloque*.

* Es posible acceder en el sub-bloque a la variable del bloque

contenedor mediante etiquetas (luego se ejemplifican), pero lo ms


sencillo es usar nombres diferentes para las variables.

Alcance

Operador de
concatenacin ||

DECLARE
a NUMBER(2) := 10;
BEGIN
DBMS_OUTPUT.PUT_LINE('Valor de a externa '|| a );
DECLARE
a NUMBER(3) := 20;
BEGIN
DBMS_OUTPUT.PUT_LINE('Valor de a interna '|| a);
END;
DBMS_OUTPUT.PUT_LINE('Valor de a '|| a );
END;
Para ejecutar en SQL*Plus
/
Imprime:
Valor de a externa 10
Valor de a interna 20
Valor de a 10

Subbloque

Nota: Para ver los resultados de la


impresin en SQL*Plus se debe
ejecutar:
SQL> SET SERVEROUTPUT ON

En PL/SQL se puede usar directamente el


sublenguaje de manipulacin de datos DML de
SQL, es decir, INSERT, DELETE, UPDATE, SELECT
(el SELECT requiere usar INTO o estar
asociado con un cursor, ver luego).
Para usar sentencias DDL en PL/SQL , es decir,
CREATE, DROP, ALTER se requiere algo adicional:

BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE t(ced
NUMBER(8))';
END;
/
La sentencia DDL NO lleva punto y coma dentro
de las comillas simples.
Lo que sigue a IMMEDIATE puede ser una
variable de caracteres Luego se vern ms
ejemplos

Usar EXECUTE IMMEDIATE solo cuando sea


indispensable, lo siguiente es innecesario, aunque
funciona:
BEGIN
EXECUTE IMMEDIATE 'INSERT INTO t VALUES(97)';
END;
/
Es ms simple:
BEGIN
INSERT INTO t VALUES(97);
END;
/

En PL/SQL, las funciones numricas (SQRT,


ROUND, POWER etc.), de caracteres (LENGTH, UPPER,
INITCAP, etc.) , de fechas (ADD_MONTHS,
MONTHS_BETWEEN); se pueden usar por fuera de
una sentencia SQL pero las funciones de grupo
(COUNT, SUM, AVG, MAX, entre otras) solo se
pueden usar dentro de una sentencia SQL.

Ejemplo
DROP TABLE emp;
CREATE TABLE emp(
cod NUMBER(8) PRIMARY KEY,
nom VARCHAR2(20) NOT NULL,
fecha_ing DATE,
sueldo NUMBER(8) CHECK(sueldo > 0)
);

DECLARE
nom emp.nom%TYPE := INITCAP('adam');
fi emp.fecha_ing%TYPE;
BEGIN
fi := ADD_MONTHS(SYSDATE,-14);
INSERT INTO emp
VALUES (4329,
Ac se pueden
nom,
colocar los valores
fi,
directamente y
prescindir de las
10000
vbles.
);
END;
/

Las vbles. se
pueden inicializar
en el DECLARE o
en el BEGIN

Sobre las consultas SQL en PL/SQL:


Se debe proporcionar un lugar para guardar los
datos devueltos por una consulta (SELECT)
Esto se puede lograr mediante la clusula
SELECT INTO.
Sin embargo, un SELECT ... INTO debe retornar
una y solo una fila:
Si la consulta no recupera filas o recupera mltiples
filas, ocurre un error (excepcin, se vern luego).
Los cursores (se ven luego) sirven para consultas que
recuperan 0, 1 o mltiples filas.

Ejemplo de un borrado desde PL/SQL.


DECLARE
limite emp.sueldo%TYPE := 8000;
cuantos NUMBER(8);
BEGIN
SELECT COUNT(*) INTO cuantos FROM emp;
DBMS_OUTPUT.PUT_LINE(cuantos);
DELETE FROM emp
WHERE sueldo > limite;
SELECT COUNT(*) INTO cuantos FROM emp;
DBMS_OUTPUT.PUT_LINE(cuantos);
END;
/
Qu pasara si limite fuese un atributo de la tabla emp?

Volver a insertar el empleado anterior


Ahora ejecutar:
DECLARE
nom emp.nom%TYPE;
sue emp.sueldo%TYPE;
Luego se
BEGIN
ver como
SELECT nom, sueldo INTO nom, sue
enviar
parmetros
FROM emp WHERE cod = 4329;
/*Aqu se manipulan los datos recuperados,
por ejemplo, imprimirlos:*/
DBMS_OUTPUT.PUT_LINE('El empleado ' || nom || '
tiene sueldo ' || sue);
END;
/

Control de Flujo
Las comparaciones lgicas son la base del
control condicional en PL/SQL.
Los resultados de las comparaciones son
verdadero (TRUE), falso (FALSE) o nulo (NULL).
Cualquier cosa comparada con NULL retorna
NULL (desconocido).
Los operadores lgicos son : >, <, =, !=, <=, >=,
<>

La sentencia IF tiene la sintaxis:


IF condicin THEN
secuencia de instrucciones
[ELSIF condicin THEN
secuencia de instrucciones]
--Los ELSIF se pueden repetir
[ELSE
secuencia de instrucciones]
END IF;

Comparacin con nulo: Qu imprime el siguiente programa?:


DECLARE
a NUMBER := NULL;
BEGIN
IF a = a THEN
DBMS_OUTPUT.PUT_LINE('O sea que NULL = NULL');
ELSIF a <> a THEN
DBMS_OUTPUT.PUT_LINE('O sea que NULL <> NULL');
ELSE
DBMS_OUTPUT.PUT_LINE('Indefinido, NULL no es ni = ni
<> a NULL');
END IF;
END;
/

Lo anterior tambin se puede escribir con CASE as:


DECLARE
a NUMBER := NULL;
BEGIN
CASE
WHEN a = a THEN
DBMS_OUTPUT.PUT_LINE('O sea que NULL = NULL');
WHEN a <> a THEN
DBMS_OUTPUT.PUT_LINE('O sea que NULL <> NULL');
ELSE
DBMS_OUTPUT.PUT_LINE('Indefinido, NULL no es ni =
ni <> a NULL');
END CASE;
END;
/

Ciclos o iteraciones
a) Ciclo simple sin lmite: LOOP
LOOP
secuencia de instrucciones
END LOOP;
Para salir del ciclo se usa:
EXIT [WHEN condicin];

Ejemplo.
DECLARE
cont NUMBER(4) := 0;
BEGIN
DELETE plana;
LOOP
INSERT INTO plana VALUES(cont,
CEIL(DBMS_RANDOM.VALUE(1,100000)));
cont := cont + 1;
EXIT WHEN cont = 1000;
END LOOP;
END;
/

b) Ciclo para: FOR


Permite repetir una secuencia de instrucciones un
nmero fijo de veces. Su sintaxis es:
FOR ndice IN [REVERSE] entero .. entero LOOP
secuencia de instrucciones
END LOOP;
Notas: - El incremento del FOR siempre es 1.
- Aunque el ciclo se haga en reversa los
lmites siempre se colocan de menor a
mayor. Veamos un ejemplo:

Ejemplo:

BEGIN
DELETE plana;
FOR i IN REVERSE 1..500 LOOP
INSERT INTO plana
VALUES (i, 'No rayar el pupitre');
END LOOP;
END;
/

c) Ciclo mientras que: WHILE


WHILE repetir una secuencia de instrucciones
hasta que la condicin controladora del ciclo deje
de ser cierta. Su sintaxis es:
WHILE condicin LOOP
secuencia de instrucciones
END LOOP;

Ejemplo:

u: maysculas
l: minsculas
a: combinacon de
maysculas y
minsculas
x: alfanumricos

DECLARE
cont NUMBER(3) := 500;
BEGIN
DELETE PLANA;
WHILE cont > 0 LOOP
INSERT INTO plana VALUES
(cont, DBMS_RANDOM.STRING('u',60) || cont);
cont := cont - 1;
END LOOP;
Tamao
END;
/

Instruccin CONTINUE
CONTINUE pasa el control inmediatamente a la
siguiente iteracin de un ciclo. Solo se puede
usar en ciclos.

Continue
DECLARE
i NUMBER := 0;
BEGIN
LOOP
i := i + 1;
IF i BETWEEN 5 AND 15 THEN
CONTINUE;
END IF;
DBMS_OUTPUT.PUT_LINE(i);
EXIT WHEN i = 20;
END LOOP;
END;
/

También podría gustarte