Programación con PL/SQL Introducción SQL es un lenguaje de

Anuncio
Programación con PL/SQL
Introducción
SQL es un lenguaje de consulta para los sistemas de bases de datos relaciónales, pero que no
posee la potencia de los lenguajes de programación. No permite el uso de
variables, estructuras de control de flujo, bucles... y demás elementos característicos de la
programación. No es de extrañar, SQL es un lenguaje de consulta, no un lenguaje de
programación. Sin embargo, SQL es la herramienta ideal para trabajar con bases de
datos. Cuando se desea realizar una aplicación completa para el manejo de una base de datos
relacional, resulta necesario utilizar alguna herramienta que soporte la capacidad de consulta
del SQL y la versatilidad de los lenguajes de programación tradicionales. PL/SQL es el
lenguaje de programación que proporciona Oracle para extender el SQL estándar con otro
tipo de instrucciones y elementos propios de los lenguajes de programación.
Con PL/SQL vamos a poder programar las unidades de programa de la base de datos
ORACLE, estás son:




Procedimientos almacenados
Funciones
Triggers
Scripts
Pero además PL/SQL nos permite realizar programas sobre las siguientes herramientas de
ORACLE:




Oracle Forms
Oracle Reports
Oracle Graphics
Oracle Aplication Server
Identificadores
Un identificador es un nombre que se le pone a un objeto que interviene en un programa, que
puede ser variable, constante, procedimientos, excepciones, cursores... Debe tener un máximo
de 30 caracteres que empiece siempre por una letra, y puede contener letras, números, los
símbolos $, #, _, y mayúsculas y minúsculas indiferentemente. Los identificadores no pueden
ser palabras reservadas (SELECT, INSERT, DELETE, UPDATE, DROP).
Operadores
(suma) - (resta)

(multiplicación)
/ (división)

o
(exponente)
Operador de asignación
Operadores aritméticos
:= (dos puntos + igual)
Operadores relacionales o
de comparación
= (igual a)
<>, != (distinto de)
< (menor que)
> (mayor que)
>= (mayor o igual a)
<= (menor o igual a)
Operador de
concatenación
||
Comentarios
/* comentario de dos o más líneas */
-- comentario de una línea
Variables
Las variables son nombres para procesar los elementos de los datos. Declaración:
Nombre_variable tipo [NOT NULL] [:= valor | DEFAULT valor]
:= y DEFAULT son lo mismo. Si ponemos NOT NULL es obligatorio inicializar la
variable.
Ejemplos:
num_dep NUMBER(2) NOT NULL :=20
num_emple VARCHAR2(15) DEFAULT ‘Pedro’
También se puede definir una variable a partir de un campo mediante los atributos %TYPE y
%ROWTYPE, con esto damos el tipo y longitud a la variable de otra variable u objeto ya
definido.
%TYPE es la que se utiliza normalmente, %ROWTYPE es para claves de registro. El NOT
NULL y el valor inicial no se heredan, sólo el tipo de dato y longitud de ese dato.
Por ejemplo:
num_dep emple.dept_no%TYPE
Constantes [editar]
Las constantes son como las variables pero no puede modificarse su valor. Se declaran de la
siguiente manera:
nombre_constante CONSTANT tipo_de_dato := valor
Por ejemplo, el IVA es un valor fijo, y para declararlo lo haríamos de la siguiente manera:
Imp_iva constant number(2,2) := 12,5
Bloque PL/SQL [editar]
Bloque es la unidad de estructura básica en los programas PL/SQL. Supone una mejora en el
rendimiento, pues se envían los bloques completos al servidor para ser procesados en lugar de
enviar cada secuencia SQL.
Partes de un bloque:



Zona de declaraciones: zona opcional. Se declaran los objetos locales (variables,
constantes...).
Zona de instrucciones: zona obligatoria.
Zona de tratamiento de excepciones: zona opcional. Se tratan excepciones en el
programa.
Forma de crear un bloque:
[ DECLARE | IS / AS ]
<declaraciones>
BEGIN
<instrucciones>
[ EXCEPTION ]
<tratamiento de excepciones>
END;
/
La barra "/" siempre se pone al final para ejecutar el bloque.
Tipos de bloques

Anónimo (sin nombre)
Siempre comienza con DECLARE o directamente con BEGIN.
Ejemplo 1:
BEGIN
DBMS_OUTPUT.PUT_LINE (‘Hola’);
END;
/
DBMS_OUTPUT es un depurador de Oracle que sirve para visualizar cualquier cosa,
pero antes lo debemos tener activado:
SET SERVEROUTPUT ON;
Ejemplo 2:
DECLARE
v_precio number;
BEGIN
select pvp into v_precio
from tarticulos
where codigo=100;
dbms_output.put_line (v_precio);
END;
/
Ejemplo 3:
El siguiente bloque anónimo nos muestra la fecha actual con el formato “Martes, 18
de marzo de 1998, a las 13:04:55”.
DECLARE
fecha date;
BEGIN
select sysdate into fecha from dual;
dbms_output.put_line (to_char(fecha,
'day", "dd" de "month" de "yyyy", a las "hh24:mi:ss'));
END;
/

Subprogramas (tienen nombre)
Se pueden almacenar en la base de datos.
Existen dos tipos de subprogramas: Procedimientos (PROCEDURE) y Funciones
(FUNCTION)

Procedimientos en PLSQL
Los procedimientos tienen la utilidad de fomentar la reutilización de programas que
se usan comúnmente. Una vez compilado, queda almacenado en la base de datos (por
eso es también llamado 'Procedimietno almacenado') y puede ser utilizado por
múltiples aplicaciones.
La sintaxis es la siguiente
CREATE [OR REPLACE] PROCEDURE nombre_procedimiento
[nombre_parametro modo tipodatos_parametro ]
IS | AS
bloque de código
Donde "modo" puede contener los valores IN, OUT, IN OUT. Por defecto tiene el
valor IN si no se pone nada. IN indica que el parámetro es de entrada y no se podrá
modificar. OUT indica que el parámetro es de salida con lo que el procedimiento
devolverá un valor en él. IN OUT indica que el parámetro es de entrada/salida. Con lo
que al llamar al procedimiento se le dará un valor que luego podrá ser modificado por
el procedimiento y devolver este nuevo valor.
"tipodatos_parametro indica el tipo de datos que tendrá el parámetro según lo
indicado en Tipos de datos Oracle/PLSQL
Para borrar un procedimiento almacenado de la base de datos
DROP PROCEDURE nombre_procedimiento
Para utilizar un procedimiento almacenado de la base de datos
Simplemente se lo llama desde un bloque anónimo (desde la línea de comandos),
previamente habiendo inicializado el/los parametro/s (en caso que existan).
DECLARE
nombre_parametro tipodatos_parametro;
BEGIN
nombre_parametro tipodatos_parametro := valor_de_inicializacion;
nombre_procedimiento (nombre_parametro => nombre_parametro);
END;
/

Funciones en PLSQL
Una función es un bloque de código PL/SQL que tiene las mismas características que un
procedimiento almacenado. La diferencia estriba que una función devuelve un valor al
retornar. Al devolver un valor puede ser llamada como parte de una expresión.
La sintaxis sería
CREATE [OR REPLACE] FUNCTION nombre_función
[nombre_parámetro modo tipodatos_parametro ]
RETURN tipodatos_retorno IS | AS
bloque de código
Donde "modo" puede contener los valores IN, OUT, IN OUT. Por defecto tiene el
valor IN si no se pone nada. IN indica que el parámetro es de entrada y no se podrá
modificar. OUT indica que el parámetro es de salida con lo que el procedimiento
devolverá un valor en él. IN OUT indica que el parámetro es de entrada/salida. Con lo
que al llamar al procedimiento se le dará un valor que luego podrá ser modificado por
el procedimiento y devolver este nuevo valor. Sin embargo, en este caso solo tendría
sentido (por el concepto de función en sí mismo) declarar parámetros del tipo IN y
devolver el valor como retorno de la función.
"tipodatos_parametro" y "tipodatos_retorno" indican el tipo de datos que tendrá el
parámetro y el valor de retorno de la función respectivamente según lo indicado en
Tipos de datos Oracle/PLSQL
Para borrar una función de la base de datos
DROP FUNCTION nombre_función
Los procedimientos y funciones se pueden agrupar en unas estructuras llamadas Paquetes.

Triggers
Un trigger o disparador se ejecuta ante un determinado evento de manera automática.
Generalmente se utilizan para garantizar que una determinada acción siempre se
realiza después de realizar una tarea determinada. Se debe tener cuidado con este tipo
de estructuras puesto que un uso excesivo puede dar lugar a dependencias difíciles de
mantener. Además se deben tener muy claros las restricciones de integridad para
evitar problemas.
La sintaxis sería
A nivel de sentencia:
CREATE [OR REPLACE] TRIGGER nombre_trigger
momento_ejecución evento [evento] ON nombre_tabla
bloque PLSQL;
A nivel de registro:
CREATE [OR REPLACE] TRIGGER nombre_trigger
momento_ejecución evento [evento] ON nombre_tabla
[REFERENCING OLD AS old | NEW AS new]
FOR EACH ROW
[WHEN condición]
bloque PLSQL;
Donde "momento_ejecución" indica cuando se ejecuta el trigger automáticamente.
Puede contener los valores BEFORE ó AFTER.
"evento" indica la operación que provoca la ejecución de este bloque. Puede contener
los valores INSERT, UPDATE ó DELETE.
"old" indica el nombre que se le da al registro con los valores antiguos que se tenían
antes de la ejecución de la operación que activó el trigger. Mientras que "new" indica
el valor que tiene actualmente después de dicha operación.
Con la cláusula "WHEN" se puede indicar una restricción que haga que el trigger se
ejecute o no. Por ejemplo se puede indicar que el trigger se ejecute solo si el campo
"campo1" de la tabla tiene un valor mayor que 50.
La cláusula "FOR EACH ROW" indica que el trigger es a nivel de registro.
Para eliminar un trigger:
DROP TRIGGER nombre_trigger
Bloques de instrucciones PL/SQL
A continuación se muestra como es la estructura general de los bloques de instrucciones de
PL/SQL que se usarán mas adelante en la creación de procedimientos, funciones y triggers.
PL/SQL (Procedural Language/SQL) es una extensión de SQL, que agrega ciertas
construcciones propias de lenguajes procedimentales, obteniendose como resultado un
lenguaje estructural mas poderoso que SQL. La unidad de programación utilizada por
PL/SQL es el bloque. Todos los programas de PL/SQL están conformados por bloques.
Tipicamente, cada bloque lleva a cabo una acción lógica en el programa. Un bloque tendrá
siempre la siguiente estructura:
DECLARE
//Sección declarativa: variables, tipos, y subprogramas
//de uso local
BEGIN
//Sección ejecutable: las instrucciones procedimentales, y de SQL
//aparecen aquí. Es la unica sección obligatoria en el bloque.
EXCEPTION
//Sección de manejo de excepciones. Las rutinas de manejo de errores
//aparecen aqui
END;
Solo se requiere que aparezca la sección ejecutable. Lo demas es opcional. Las unicas
instrucciones SQL permitidas en un bloque PL/SQL son INSERT, UPDATE, DELETE y
SELECT, ademas de algunas instrucciones para manipulación de datos, e instrucciones para
control de transacciones. Otras instrucciones de SQL como DROP, CREATE o ALTER no
son permitidas. Se permite el uso de comentarios estilo C (/* . . .*/). PL/SQL no es case
sensitive por lo que no hay distinción entre nombres con mayusculas y minusculas.
En la sección de declaraciones, se indican las variables que serán usadas dentro del bloque y
sus tipos. Por ejemplo:
DECLARE
myBeer VARCHAR(20);
price NUMBER(6,2);
En algunos casos, es posible que se desee que el tipo de una variable coincida con el tipo usado
para una columna de una tabla determinada, en esos casos se puede usar la construcción:
DECLARE
myBeer Beers.name%TYPE;
Con lo cual se logra que la variable myBeer tenga el mismo tipo que la columna name de la
tabla Beers.
Tambien es posible inicializar las variables, mediante el operador :=. Ademas, mediante el uso
del mismo operador es posible hacer asignaciones en el cuerpo del programa. Por ejemplo:
DECLARE
price NUMBER := 300;
BEGIN
price := price + 150;
END;
run
La ejecución de este bloque no tendrá ningun efecto, ya que no se están haciendo cambios
sobre la base de datos.
Además es posible usar sentencias condicionales y ciclos dentro de los bloques de PL/SQL.
Una sentencia condicional tipica es de la forma:
IF (condicion)
THEN (lista de acciones)
ELSE (lista de acciones)
END IF;
Si se desea, se puede hacer el uso de varios casos de condición, mediante el uso de:
IF . . . THEN . . .
ELSIF . . . THEN . . .
ELSIF . . . THEN . . .
ELSE . . .
END IF;
En ambos casos, la clausula ELSE es opcional.
Si se desea crear un lazo, se puede usar la instrucción:
LOOP
lista_de_instrucciones
END LOOP;
Al menos alguna de las instrucciones debe ser:
EXIT WHEN condicion;
De esta manera, el lazo terminará cuando la condición sea verdadera. Además es posible
utilizar la instrucción:
WHILE (condicion) LOOP
lista_de_instrucciones
END LOOP;
De esta forma, el ciclo solo se inicia si la condicion es verdadera en principio. Es posible que el
programa nunca entre en el ciclo. Usando la instrucción LOOP se garantizaba que siempre se
ejecutaría el cuerpo del ciclo al menos una vez. Por último, es posible usar ciclos que se
ejecuten un numero predeterminado de veces, mediante el uso de la instrucción:
FOR i IN a..b LOOP
lista_de_instrucciones
END LOOP;En este caso i es una variable de uso local, por lo que no es necesario que sea
declarada, y puede ser usada dentro del lazo, mientras que a y b son constantes.
Procedimientos almacenados
Un procedimiento almacenado es un conjunto de instrucciones en PL/SQL, que pueden ser
llamado usando el nombre que se le haya asignadoLa sintaxis para crear un procedimiento es
la siguiente: CREATE [OR REPLACE] PROCEDURE name [(param [IN|OUT|IN OUT|]
datatype) . . .]
[IS|AS] pl/sql_subprogramEl uso de OR REPLACE permite sobreescribir un procedimiento
existente. Si se omite, y el procedimiento ya existe, se producirá un error. Los modificadores
IN, OUT, IN OUT indican si el parametro es de entrada, salida o ambos.
A continuación se presenta un ejemplo de creación de un procedimiento:
SQL> CREATE PROCEDURE credit (acc_no IN NUMBER, amount IN NUMBER)
1> AS BEGIN
2> UPDATE accounts
3> SET balance = balance + amount
4> WHERE account_id = acc_no;
5> END;
Este procedimiento actualizará la(s) tupla(s) con numero de cuenta igual al parámetro acc_no
con un incremento de amount en el balance de dicha cuenta.
Si se desea eliminar (borrar) un procedimiento almacenado, se usa la instrucción:
SQL> DROP PROCEDURE name;


Packages en PL/SQL
Un paquete es una estructura que agrupa objetos de PL/SQL
compilados(procedures, funciones, variables, tipos ...) en la base de datos. Esto nos
permite agrupar la funcionalidad de los procesos en programas.



Lo primero que debemos tener en cuenta es que los paquetes están formados por
dos partes: la especificación y el cuerpo. La especificación del un paquete y su cuerpo
se crean por separado.
La especificación es la interfaz con las aplicaciones. En ella es posible declarar los
tipos, variables, constantes, excepciones, cursores y subprogramas disponibles para su
uso posterior desde fuera del paquete. En la especificación del paquete sólo se
declaran los objetos (procedures, funciones, variables ...), no se implementa el código.
Los objetos declarados en la especificación del paquete son accesibles desde fuera del
paquete por otro script de PL/SQL o programa. Haciendo una analogía con el mundo
de C, la especificación es como el archivo de cabecera de un programa en C.
Para crear la especificación de un paquete la sintaxis general es la siguiente:
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>;


El cuerpo el laimplementación del paquete. El cuerpo del paquete debe
implementar lo que se declaró inicialmente en la especificación. Es el donde debemos
escribir el código de los subprogramas. En el cuerpo de un package podemos declarar
nuevos subprogramas y tipos, pero estos seran privados para el propio package.
La sintaxis general para crear el cuerpo de un paquete es muy parecida a la de la
especificación, tan solo se añade la palabra clave BODY, y se implementa el código de
los subprogramas.
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>;]}
-- Implementacion de procedimientos y funciones
FUNCTION <FunctionName>(<Parameter> <Datatype>,...)
RETURN <Datatype>
IS
-- Variables locales de la funcion
BEGIN
-- Implementeacion de la funcion
return(<Result>);
[EXCEPTION]
-- Control de excepciones
END;
PROCEDURE <ProcedureName>(<Parameter> <Datatype>, ...)
IS
-- Variables locales de la funcion
BEGIN
-- Implementacion de procedimiento
[EXCEPTION]
-- Control de excepciones
END;
END <pkgName>;


El siguiente ejemplo crea un paquete llamado PKG_CONTABILIDAD.
Para crear la especificación del paquete:
CREATE OR REPLACE PACKAGE PKG_CONTABILIDAD
IS
-- Declaraciones de tipos y registros públicas
TYPE Cuenta_contable IS RECORD
(
codigo_cuenta VARCHAR2(6),
naturaleza VARCHAR2(2) ,
actividad VARCHAR2(4) ,
debe_haber VARCHAR2(1)
);
-- Declaraciones de variables y constantes publicas
DEBE CONSTANT VARCHAR2(1) := 'D';
HABER CONSTANT VARCHAR2(1) := 'D';
ERROR_CONTABILIZAR EXCEPTION;
-- Declaraciones de procedimientos y funciones públicas
PROCEDURE Contabilizar (mes VARCHAR2) ;
FUNCTION fn_Obtener_Saldo(codigo_cuenta VARCHAR2) RETURN NUMBER;
END PKG_CONTABILIDAD;

Aquí sólo hemos declarado las variables y constantes, prototipado las funciones y
procedimientos públicos . Es en el cuerpo del paquete cuando escribimos el código de
los subprogramas Contabilizar y fn_Obtener_Saldo.
CREATE PACKAGE BODY PKG_CONTABILIDAD IS
FUNCTION fn_Obtener_Saldo(codigo_cuenta VARCHAR2)
RETURN NUMBER
IS
saldo NUMBER;
BEGIN
SELECT SALDO INTO saldo
FROM SALDOS
WHERE CO_CUENTA = codigo_cuenta;
return (saldo);
END;
PROCEDURE Contabilizar(mes VARCHAR2)
IS
CURSOR cDatos(vmes VARCHAR2)
IS
SELECT *
FROM FACTURACION
WHERE FX_FACTURACION = vmes
AND PENDIENTE_CONTABILIZAR = 'S';
fila cDatos%ROWTYPE;
BEGIN
OPEN cDatos(mes);
LOOP FETCH cDatos INTO fila;
EXIT WHEN cDatos%NOTFOUND;
/* Procesamiento de los registros recuperados */
END LOOP;
CLOSE cDatos;
EXCEPTION
WHEN OTHERS THEN
RAISE ERROR_CONTABILIZAR;
END Contabilizar;
END PKG_CONTABILIDAD;



Es posible modificar el cuerpo de un paquete sin necesidad de alterar por ello la
especificación del mismo.
Los paquetes pueden llegar a ser programas muy complejos y suelen almacenar
gran parte de la lógica de negocio.
Descargar