0% encontró este documento útil (0 votos)
136 vistas44 páginas

PLSQL Devjoker

Este documento explica los tipos de datos en PL/SQL. Describe los tipos numéricos como NUMBER, los caracteres como CHAR y VARCHAR2, los lógicos como BOOLEAN y las fechas como DATE. También cubre los atributos de tipo %TYPE y %ROWTYPE y la creación de tipos personalizados como registros y colecciones. Finalmente, incluye una tabla que resume los principales tipos de datos soportados por Oracle.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
136 vistas44 páginas

PLSQL Devjoker

Este documento explica los tipos de datos en PL/SQL. Describe los tipos numéricos como NUMBER, los caracteres como CHAR y VARCHAR2, los lógicos como BOOLEAN y las fechas como DATE. También cubre los atributos de tipo %TYPE y %ROWTYPE y la creación de tipos personalizados como registros y colecciones. Finalmente, incluye una tabla que resume los principales tipos de datos soportados por Oracle.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 44

www.devjoker.

com Page 1 of 1

www.Devjoker.com
PL SQL
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.

Para abordar el presente tutorial con mínimo de garantias es necesario conocer previamente SQL.

Podemos acceder a un completo tutorial de SQL desde AQUI.

PL/SQL amplia SQL con los elementos caracteristicos de los lenguajes de programación, variables,
sentencias de control de flujo, bucles ...

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.

¿Que vamos a necesitar?

Para poder seguir este tutorial correctamente necesitaremos tener los siguientes elementos:

 Una instancia de ORACLE 8i o superior funcionando correctamente.


 Herramientas cliente de ORACLE, en particular SQL*Plus para poder ejecutar los ejemplo.
 Haber configurado correctamente una conexión a ORACLE.

www.Devjoker.com

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=22 14/08/2009
www.devjoker.com Page 1 of 1

www.Devjoker.com
Fundamentos de PL/SQL
Primeros pasos con PL/SQL

Para programar en PL/SQL es necesario conocer sus fundamentos.

Como introducción vamos a ver algunos elementos y conceptos básicos del lenguaje.

 PL/SQL no es CASE-SENSITIVE, es decir, no diferencia mayúsculas de minúsculas como otros lenguajes de


programación como C o Java. Sin embargo debemos recordar que ORACLE es CASE-SENSITIVE en la
búsquedas de texto.
 Una linea en PL/SQL contiene grupos de caracteres conocidos como UNIDADES LEXICAS, que pueden ser
clasificadas como:
 DELIMITADORES
 IDENTIFICADORES
 LITERALES
 COMENTARIOS
 EXPRESIONES
 DELIMITADOR: Es un símbolo simple o compuesto que tiene una función especial en PL/SQL. Estos pueden
ser:
 Operadores Aritmeticos
 Operadores Logicos
 Operadores Relacionales
 IDENTIFICADOR: Son empleados para nombrar objetos de programas en PL/SQL asi como a unidades dentro
del mismo, estas unidades y objetos incluyen:
 Constantes
 Cursores
 Variables
 Subprogramas
 Excepciones
 Paquetes
 LITERAL: Es un valor de tipo numérico, caracter, cadena o lógico no representado por un identificador (es un
valor explícito).
 COMENTARIO: Es una aclaración que el programador incluye en el código. Son soportados 2 estilos de
comentarios, el de línea simple y de multilínea, para lo cual son empleados ciertos caracters especiales como
son:

-- Linea simple
/*
Conjunto de Lineas
*/

www.Devjoker.com

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=31 06/08/2009
www.devjoker.com Page 1 of 4

www.Devjoker.com
Tipos de datos en PL/SQL

Cada constante y variable tien un tipo de dato en el cual se especifica el formato de almacenamiento,
restricciones y rango de valores validos.

PL/SQL proporciona una variedad predefinida de tipos de datos . Casi todos los tipos de datos manejados
por PL/SQL son similares a los soportados por SQL. A continuación se muestran los TIPOS de DATOS más
comunes:

 NUMBER (Numérico): Almacena números enteros o de punto flotante, virtualmente de cualquier longitud,
aunque puede ser especificada la precisión (Número de digitos) y la escala que es la que determina el número
de decimales.

-- NUMBER [(precision, escala)]

saldo NUMBER(16,2);
/* Indica que puede almacenar un valor numérico de 16
posiciones, 2 de ellas decimales. Es decir, 14 enteros
y dos decimales */

 CHAR (Caracter): Almacena datos de tipo caracter con una longitud maxima de 32767 y cuyo valor de
longitud por default es 1

-- CHAR [(longitud_maxima)]

nombre CHAR(20);
/* Indica que puede almacenar valores alfanuméricos de 20
posiciones */

 VARCHAR2 (Caracter de longitud variable): Almacena datos de tipo caracter empleando sólo la cantidad
necesaria aún cuando la longitud máxima sea mayor.

-- VARCHAR2 (longitud_maxima)
nombre VARCHAR2(20);
/* Indica que puede almacenar valores alfanuméricos de hasta 20
posicones */
/* Cuando la longitud de los datos sea menor de 20 no se
rellena con blancos */

 BOOLEAN (lógico): Se emplea para almacenar valores TRUE o FALSE.

hay_error BOOLEAN;

 DATE (Fecha): Almacena datos de tipo fecha. Las fechas se almacenan internamente como datos numéricos,
por lo que es posible realizar operaciones aritmeticas con ellas.
 Atributos de tipo. Un atributo de tipo PL/SQL es un modificador que puede ser usado para obtener información
de un objeto de la base de datos. El atributo %TYPE permite conocer el tipo de una variable, constante o
campo de la base de datos. El atributo %ROWTYPE permite obtener los tipos de todos los campos de una
tabla de la base de datos, de una vista o de un cursor.
 PL/SQL también permite la creación de tipos personalizados (registros) y colecciones(tablas de PL/SQL), que

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=60 06/08/2009
www.devjoker.com Page 2 of 4

veremos en sus apartados correspondientes.

Existen por supuesto más tipos de datos, la siguiente tabla los muestra:

Tipo de dato / Oracle 8i Oracle 9i Descripción


Sintáxis

dec(p, e) La precisión máxima La precisión máxima Donde p es la precisión y e la


es de 38 dígitos. es de 38 dígitos. escala.

Por ejemplo: dec(3,1) es un


número que tiene 2 dígitos antes
del decimal y un dígito después del
decimal.
decimal(p, e) La precisión máxima La precisión máxima Donde p es la precisión y e la
es de 38 dígitos. es de 38 dígitos. escala.

Por ejemplo: decimal(3,1) es un


número que tiene 2 dígitos antes
del decimal y un dígito después del
decimal.
double
precision
float
int
integer
numeric(p, La precisión máxima La precisión máxima Donde p es la precisión y e la
e) es de 38 dígitos. es de 38 dígitos. escala.

Por ejemplo: numeric(7,2) es un


número que tiene 5 dígitos antes
del decimal y 2 dígitos después del
decimal.
number(p, e) La precisión máxima La precisión máxima Donde p es la precisión y e la
es de 38 dígitos. es de 38 dígitos. escala.

Por ejemplo: number(7,2) es un


número que tiene 5 dígitos antes
del decimal y 2 dígitos después del
decimal.
real
smallint
char Hasta 32767 bytes en Hasta 32767 bytes en Donde tamaño es el número de
(tamaño) PLSQL. PLSQL. caracteres a almacenar. Son
cadenas de ancho fijo. Se rellena
Hasta 2000 bytes en Hasta 2000 bytes en con espacios.
Oracle 8i. Oracle 9i.
varchar2 Hasta 32767 bytes en Hasta 32767 bytes en Donde tamaño es el número de
(tamaño) PLSQL. PLSQL. caracteres a almacenar. Son
cadenas de ancho variable.
Hasta 4000 bytes en Hasta 4000 bytes en
Oracle 8i. Oracle 9i.
long Hasta 2 gigabytes. Hasta 2 gigabytes. Son cadenas de ancho variable.

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=60 06/08/2009
www.devjoker.com Page 3 of 4

raw Hasta 32767 bytes en Hasta 32767 bytes en Son cadenas binarias de ancho
PLSQL. PLSQL. variable.

Hasta 2000 bytes en Hasta 2000 bytes en


Oracle 8i. Oracle 9i.
long raw Hasta 2 gigabytes. Hasta 2 gigabytes. Son cadenas binarias de ancho
variable.
date Una fecha entre el 1 Una fecha entre el 1
de Enero de 4712 de Enero de 4712
A.C. y el 31 de A.C. y el 31 de
Diciembre de 9999 Diciembre de 9999
D.C. D.C.
timestamp No soportado por fractional seconds Incluye año, mes día, hora,
(fractional Oracle 8i. precision debe ser minutos y segundos.
seconds un número entre 0 y
precision) 9. (El valor por Por ejemplo: timestamp(6)
defecto es 6)
timestamp No soportado por fractional seconds Incluye año, mes día, hora,
(fractional Oracle 8i. precision debe ser minutos y segundos; con un valor
seconds un número entre 0 y de desplazamiento de zona
precision) 9. (El valor por horaria.
with time defecto es 6)
zone Por ejemplo: timestamp(5) with
time zone
timestamp No soportado por fractional seconds Incluye año, mes día, hora,
(fractional Oracle 8i. precision debe ser minutos y segundos; con una zona
seconds un número entre 0 y horaria expresada como la zona
precision) 9. (El valor por horaria actual.
with local defecto es 6)
time zone Por ejemplo: timestamp(4) with
local time zone
interval year No soportado por year precision debe Período de tiempo almacenado en
(year Oracle 8i. ser un número entre años y meses.
precision) to 0 y 9. (El valor por
month defecto es 2) Por ejemplo: interval year(4) to
month
interval day No soportado por day precision debe Incluye año, mes día, hora,
(day Oracle 8i. ser un número entre minutos y segundos.
precision) to 0 y 9. (El valor por
second defecto es 2) Por ejemplo: interval day(2) to
(fractional second(6)
seconds fractional seconds
precision) precision debe ser
un número entre 0 y
9. (El valor por
defecto es 6)
rowid El formato del campo El formato del campo Datos binarios de ancho fijo. Cada
rowid es: rowid es: registro de la base de datos tiene
una dirección física o rowid.
BBBBBBB.RRRR.FFFFF BBBBBBB.RRRR.FFFFF
donde BBBBBBB es el donde BBBBBBB es el
bloque en el fichero bloque en el fichero
de la base de datos; de la base de datos;
RRRR es la fila del RRRR es la fila del
bloque; FFFFF es el bloque; FFFFF es el
fichero de la base de fichero de la base de

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=60 06/08/2009
www.devjoker.com Page 4 of 4

datos. datos.
urowid Hasta 2000 bytes. Hasta 2000 bytes. Rowid universal. Donde tamaño
[tamaño] es opcional.
boolean Válido en PLSQL, este Válido en PLSQL, este
tipo de datos no tipo de datos no
existe en Oracle 8i. existe en Oracle 9i.
nchar Hasta 32767 bytes en Hasta 32767 bytes en Donde tamaño es el número de
(tamaño) PLSQL. Hasta 2000 PLSQL. Hasta 2000 caracteres a almacenar. Cadena
bytes en Oracle 8i. bytes en Oracle 9i. NLS de ancho fijo.
nvarchar2 Hasta 32767 bytes en Hasta 32767 bytes en Donde tamaño es el número de
(tamaño) PLSQL. Hasta 4000 PLSQL. Hasta 4000 caracteres a almacenar. Cadena
bytes en Oracle 8i. bytes en Oracle 9i. NLS de ancho variable.
bfile Hasta 4 gigabytes. Hasta 4 gigabytes. Localizadores de archivo apuntan a
un objeto binario de sólo lectura
fuera de la base de datos.
blob Hasta 4 gigabytes. Hasta 4 gigabytes. Localizadores LOB apuntan a un
gran objeto binario dentro de la
base de datos.
clob Hasta 4 gigabytes. Hasta 4 gigabytes. Localizadores LOB apuntan a un
gran objeto de caracteres dentro
de la base de datos.
nclob Hasta 4 gigabytes. Hasta 4 gigabytes. Localizadores LOB apuntan a un
gran objeto NLS de caracteres
dentro de la base de datos.

www.Devjoker.com

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=60 06/08/2009
www.devjoker.com Page 1 of 1

www.Devjoker.com
Operadores en PL/SQL

La siguiente tabla ilustra los operadores de PL/SQL.

Tipo de operador Operadores

Operador de asignación := (dos puntos + igual)


Operadores aritméticos + (suma)
- (resta)
* (multiplicación)
/ (división)
** (exponente)
Operadores relacionales = (igual a)
o de comparación <> (distinto de)
< (menor que)
> (mayor que)
>= (mayor o igual a)
<= (menor o igual a)
Operadores lógicos AND (y lógico)
NOT (negacion)
OR (o lógico)
Operador de
||
concatenación

www.Devjoker.com

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=61 06/08/2009
www.devjoker.com Page 1 of 2

www.Devjoker.com
Estructuras de control en PL/SQL
Estrcuturas de control de flujo

En PL/SQL solo disponemos de la estructura condicional IF. Su sintaxis se muestra a continuación:

IF (expresion) THEN
-- Instrucciones
ELSIF (expresion) THEN
-- Instrucciones
ELSE
-- Instrucciones
END IF;

Un aspecto a tener en cuenta es que la instrucción condicional anidada es ELSIF y no "ELSEIF".

Sentencia GOTO

PL/SQL dispone de la sentencia GOTO. La sentencia GOTO desvia el flujo de ejecució a una determinada
etiqueta.

En PL/SQL las etiquetas se indican del siguiente modo: << etiqueta >>

El siguiente ejemplo ilustra el uso de GOTO.

DECLARE
flag NUMBER;
BEGIN
flag :=1 ;
IF (flag = 1) THEN
GOTO paso2;
END IF;
<<paso1>>
dbms_output.put_line('Ejecucion de paso 1');
<<paso2>>
dbms_output.put_line('Ejecucion de paso 2');
END;

Bucles

En PL/SQL tenemos a nuestra disposición los siguientes iteradores o bucles:

 LOOP
 WHILE
 FOR

El bucle LOOP, se repite tantas veces como sea necesario hasta que se fuerza su salida con la instrucción
EXIT. Su sintaxis es la siguiente

LOOP
-- Instrucciones
IF (expresion) THEN

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=33 06/08/2009
www.devjoker.com Page 2 of 2

-- Instrucciones
EXIT;
END IF;
END LOOP;

El bucle WHILE, se repite mientras que se cumpla expresion.

WHILE (expresion) LOOP


-- Instrucciones
END LOOP;

El bucle FOR, se repite tanta veces como le indiquemos en los identificadores inicio y final.

FOR contador IN [REVERSE] inicio..final LOOP

-- Instrucciones

END LOOP;

En el caso de especificar REVERSE el bucle se recorre en sentido inverso.

www.Devjoker.com

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=33 06/08/2009
www.devjoker.com Page 1 of 3

www.Devjoker.com
Bloques PL/SQL
Un programa de PL/SQL está compuesto por bloques. Un programa está compuesto como mínimo de un
bloque.

Los bloques de PL/SQL pueden ser de los siguientes tipos:

 Bloques anónimos
 Subprogramas

Estructura de un Bloque

Los bloques PL/SQL presentan una estructura específica compuesta de tres partes bien diferenciadas:

 La sección declarativa en donde se declaran todas las constantes y variables que se van a utilizar en la
ejecución del bloque.
 La sección de ejecución que incluye las instrucciones a ejecutar en el bloque PL/SQL.
 La sección de excepciones en donde se definen los manejadores de errores que soportará el bloque
PL/SQL.

Cada una de las partes anteriores se delimita por una palabra reservada, de modo que un bloque PL/SQL
se puede representar como sigue:

[ declare | is | as ]
/*Parte declarativa*/

begin
/*Parte de ejecucion*/

[ exception ]
/*Parte de excepciones*/

end;

De las anteriores partes, únicamente la sección de ejecución es obligatoria, que quedaría delimitada entre
las cláusulas BEGIN y END. Veamos un ejemplo de bloque PL/SQL muy genérico. Se trata de un bloque
anónimos, es decir no lo identifica ningún nombre. Los bloques anónimos identifican su parte declarativa con
la palabra reservada DECLARE.

DECLARE
/*Parte declarativa*/
nombre_variable DATE;
BEGIN
/*Parte de ejecucion
* Este código asigna el valor de la columna "nombre_columna"
* a la variable identificada por "nombre_variable"
*/
SELECT SYSDATE
INTO nombre_variable
FROM DUAL;
EXCEPTION
/*Parte de excepciones*/
WHEN OTHERS THEN

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=27 06/08/2009
www.devjoker.com Page 2 of 3

dbms_output.put_line('Se ha producido un error');


END;

A continuación vamos a ver cada una de estas secciones

Sección de Declaración de Variables

En esta parte se declaran las variables que va a necesitar nuestro programa. Una variable se declara
asignandole un nombre o "identificador" seguido del tipo de valor que puede contener. También se declaran
cursores, de gran utilidad para la consulta de datos, y excepciones definidas por el usuario. También
podemos especificar si se trata de una constante, si puede contener valor nulo y asignar un valor inicial.

La sintaxis generica para la declaracion de constantes y variables es:

nombre_variable [CONSTANT] <tipo_dato> [NOT NULL][:=valor_inicial]

donde:

 tipo_dato: es el tipo de dato que va a poder almacenar la variable, este puede ser cualquiera de los
tipos soportandos por ORACLE, es decir NUMBER , DATE , CHAR , VARCHAR, VARCHAR2,
BOOLEAN ... Además para algunos tipos de datos (NUMBER y VARCHAR) podemos especificar la
longitud.
 La cláusula CONSTANT indica la definición de una constante cuyo valor no puede ser modificado. Se
debe incluir la inicialización de la constante en su declaración.
 La cláusula NOT NULL impide que a una variable se le asigne el valor nulo, y por tanto debe
inicializarse a un valor diferente de NULL.
 Las variables que no son inicializadas toman el valor inicial NULL.
 La inicialización puede incluir cualquier expresión legal de PL/SQL, que lógicamente debe corresponder
con el tipo del identificador definido.
 Los tipos escalares incluyen los definidos en SQL más los tipos VARCHAR y BOOLEAN. Este último
puede tomar los valores TRUE, FALSE y NULL, y se suele utilizar para almacenar el resultado de
alguna operación lógica. VARCHAR es un sinónimo de CHAR.
 También es posible definir el tipo de una variable o constante, dependiendo del tipo de otro
identificador, mediante la utilización de las cláusulas %TYPE y %ROWTYPE. Mediante la primera
opción se define una variable o constante escalar, y con la segunda se define una variable fila, donde
identificador puede ser otra variable fila o una tabla. Habitualmente se utiliza %TYPE para definir la
variable del mismo tipo que tenga definido un campo en una tabla de la base de datos, mientras que
%ROWTYPE se utiliza para declarar varibales utilizando cursores.

Ejemplos:

Estructura de un bloque anónimo.

DECLARE
/* Se declara la variable de tipo VARCHAR2(15) identificada por v_location y se le asigna
el valor "Granada"*/
v_location VARCHAR2(15) := ’Granada’;
/*Se declara la constante de tipo NUMBER identificada por PI y se le
el valor 3.1416*/
PI CONSTANT NUMBER := 3.1416;
/*Se declara la variable del mismo tipo que tenga el campo nombre de
identificada por v_nombre y no se le asigna ningún valor */
v_nombre tabla_empleados.nombre%TYPE;
/*Se declara la variable del tipo registro correspondiente a un supue

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=27 06/08/2009
www.devjoker.com Page 3 of 3

micursor, identificada por reg_datos*/


reg_datos micursor%ROWTYPE;
BEGIN
/*Parte de ejecucion*/
EXCEPTION
/*Parte de excepciones*/
END;

Estructura de un subprograma:

CREATE PROCEDURE simple_procedure IS


/* Se declara la variable de tipo VARCHAR2(15) identificada por v_location y se le asigna
el valor "Granada"*/
v_location VARCHAR2(15) := ’Granada’;
/*Se declara la constante de tipo NUMBER identificada por PI y se le
el valor 3.1416*/
PI CONSTANT NUMBER := 3.1416;
/*Se declara la variable del mismo tipo que tenga el campo nombre de
identificada por v_nombre y no se le asigna ningún valor */
v_nombre tabla_empleados.nombre%TYPE;
/*Se declara la variable del tipo registro correspondiente a un supue
micursor, identificada por reg_datos*/
reg_datos micursor%ROWTYPE;
BEGIN
/*Parte de ejecucion*/
EXCEPTION
/*Parte de excepciones*/
END;

www.Devjoker.com

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=27 06/08/2009
www.devjoker.com Page 1 of 2

www.Devjoker.com

Cursores en PL/SQL
Introducción a cursores PL/SQL

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.

Podemos distinguir dos tipos de cursores:

 Cursores implicitos. Este tipo de cursores se utiliza para operaciones SELECT INTO. Se usan cuando
la consulta devuelve un único registro.
 Cursores explicitos. Son los cursores que son declarados y controlados por el programador. Se utilizan
cuando la consulta devuelve un conjunto de registros. Ocasionalmente también se utilizan en consultas
que devuelven un único registro por razones de eficiencia. Son más rápidos.

Un cursor se define como cualquier otra variable de PL/SQL y debe nombrarse de acuerdo a los mismos
convenios que cualquier otra variable. Los cursores implicitos no necesitan declaración.

El siguiente ejemplo declara un cursor explicito:

declare
cursor c_paises is
SELECT CO_PAIS, DESCRIPCION
FROM PAISES;
begin
/* Sentencias del bloque ...*/
end;

Para procesar instrucciones SELECT que devuelvan más de una fila, son necesarios cursores explicitos
combinados con un estructura de bloque.

Un cursor admite el uso de parámetros. Los parámetros deben declararse junto con el cursor.

El siguiente ejemplo muestra la declaracion de un cursor con un parámetro, identificado por p_continente.

declare
cursor c_paises (p_continente IN VARCHAR2) is
SELECT CO_PAIS, DESCRIPCION
FROM PAISES
WHERE CONTINENTE = p_continente;
begin
/* Sentencias del bloque ...*/
end;

El siguiente diagrama representa como se procesa una instrucción SQL a través de un cursor.

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=32 06/08/2009
www.devjoker.com Page 2 of 2

Fases para procesar una instrucción SQL

www.Devjoker.com

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=32 06/08/2009
www.devjoker.com Page 1 of 1

www.Devjoker.com
Cursores Implicitos
Declaración de cursores implicitos.

Los cursores implicitos se utilizan para realizar consultas SELECT que devuelven un único registro.

Deben tenerse en cuenta los siguientes puntos cuando se utilizan cursores implicitos:

 Con cada cursor implicito debe existir la palabra clave INTO.


 Las variables que reciben los datos devueltos por el cursor tienen que contener el mismo tipo de dato
que las columnas de la tabla.
 Los cursores implicitos solo pueden devolver una única fila. En caso de que se devuelva más de una
fila (o ninguna fila) se producirá una excepcion. No se preocupe si aún no sabe que es una excepcion,
le valdrá conocer que es el medio por el que PL/SQL gestiona los errores.

El siguiente ejemplo muestra un cursor implicito:

declare
vdescripcion VARCHAR2(50);
begin
SELECT DESCRIPCION
INTO vdescripcion
from PAISES
WHERE CO_PAIS = 'ESP';

dbms_output.put_line('La lectura del cursor es: ' || vdescripcion);


end;

La salida del programa generaría la siguiente línea:

La lectura del cursor es: ESPAÑA

Excepciones asociadas a los cursores implicitos.

Los cursores implicitos sólo pueden devolver una fila, por lo que pueden producirse determinadas
excepciones. Las más comunes que se pueden encontrar son no_data_found y too_many_rows. La
siguiente tabla explica brevemente estas excepciones.

Excepcion Explicacion
NO_DATA_FOUND Se produce cuando una sentencia SELECT intenta recuperar datos pero ninguna
fila satisface sus condiciones. Es decir, cuando "no hay datos"
TOO_MANY_ROWS Dado que cada cursor implicito sólo es capaz de recuperar una fila , esta
excepcion detecta la existencia de más de una fila.

www.Devjoker.com

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=38 06/08/2009
www.devjoker.com Page 1 of 4

www.Devjoker.com
Cursores Explicitos en PL/SQL
Declaración de cursores explicitos

Los cursores explicitos se emplean para realizar consultas SELECT que pueden devolver cero filas, o más de
una fila.

Para trabajar con un cursor explicito necesitamos realizar las siguientes tareas:

 Declarar el cursor.
 Abrir el cursor con la instrucción OPEN.
 Leer los datos del cursor con la instrucción FETCH.
 Cerrar el cursor y liberar los recursos con la instrucción CLOSE.

Para declarar un cursor debemos emplear la siguiente sintaxis:

CURSOR nombre_cursor IS
instrucción_SELECT

También debemos declarar los posibles parametros que requiera el cursor:

CURSOR nombre_cursor(param1 tipo1, ..., paramN tipoN) IS


instrucción_SELECT

Para abrir el cursor

OPEN nombre_cursor;

o bien (en el caso de un cursor con parámetros)

OPEN nombre_cursor(valor1, valor2, ..., valorN);

Para recuperar los datos en variables PL/SQL.

FETCH nombre_cursor INTO lista_variables;


-- o bien ...
FETCH nombre_cursor INTO registro_PL/SQL;

Para cerrar el cursor:

CLOSE nombre_cursor;

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=39 06/08/2009
www.devjoker.com Page 2 of 4

El siguiente ejemplo ilustra el trabajo con un cursor explicito. Hay que tener en cuenta que al leer los datos del
cursor debemos hacerlo sobre variables del mismo tipo de datos de la tabla (o tablas) que trata el cursor.

DECLARE
CURSOR cpaises
IS
SELECT CO_PAIS, DESCRIPCION, CONTINENTE
FROM PAISES;

co_pais VARCHAR2(3);
descripcion VARCHAR2(50);
continente VARCHAR2(25);
BEGIN
OPEN cpaises;
FETCH cpaises INTO co_pais,descripcion,continente;
CLOSE cpaises;
END;

Podemos simplificar el ejemplo utilizando el atributo de tipo %ROWTYPE sobre el cursor.

DECLARE
CURSOR cpaises
IS
SELECT CO_PAIS, DESCRIPCION, CONTINENTE
FROM PAISES;

registro cpaises%ROWTYPE;
BEGIN
OPEN cpaises;
FETCH cpaises INTO registro;
CLOSE cpaises;
END;

El mismo ejemplo, pero utilizando parámetros:

DECLARE
CURSOR cpaises (p_continente VARCHAR2)
IS
SELECT CO_PAIS, DESCRIPCION, CONTINENTE
FROM PAISES
WHERE CONTINENTE = p_continente;

registro cpaises%ROWTYPE;
BEGIN
OPEN cpaises('EUROPA');
FETCH cpaises INTO registro;
CLOSE cpaises;
END;

Cuando trabajamos con cursores debemos considerar:

 Cuando un cursor está cerrado, no se puede leer.


 Cuando leemos un cursor debemos comprobar el resultado de la lectura utilizando los atributos de los cursores.
 Cuando se cierra el cursor, es ilegal tratar de usarlo.
 Es ilegal tratar de cerrar un cursor que ya está cerrado o no ha sido abierto

Atributos de cursores

Toman los valores TRUE, FALSE o NULL dependiendo de la situación:

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=39 06/08/2009
www.devjoker.com Page 3 of 4

Atributo Antes de abrir Al abrir Durante la recuperación Al finalizar la recuperación Después de cerrar

%NOTFOUND ORA-1001 NULL FALSE TRUE ORA-1001

%FOUND ORA-1001 NULL TRUE FALSE ORA-1001

%ISOPEN FALSE TRUE TRUE TRUE FALSE

%ROWCOUNT ORA-1001 0 * ** ORA-1001

* Número de registros que ha recuperado hasta el momento


** Número de total de registros

Manejo del cursor

Por medio de ciclo LOOP podemos iterar a través del cursor. Debe tenerse cuidado de agregar una condición
para salir del bucle:

Vamos a ver varias formas de iterar a través de un cursor. La primera es utilizando un bucle LOOP con una
sentencia EXIT condicionada:

OPEN nombre_cursor;
LOOP
FETCH nombre_cursor INTO lista_variables;
EXIT WHEN nombre_cursor%NOTFOUND;
/* Procesamiento de los registros recuperados */
END LOOP;
CLOSE nombre_cursor;

Aplicada a nuestro ejemplo anterior:

DECLARE
CURSOR cpaises
IS
SELECT CO_PAIS, DESCRIPCION, CONTINENTE
FROM PAISES;

co_pais VARCHAR2(3);
descripcion VARCHAR2(50);
continente VARCHAR2(25);
BEGIN
OPEN cpaises;
LOOP
FETCH cpaises INTO co_pais,descripcion,continente;
EXIT WHEN cpaises%NOTFOUND;
dbms_output.put_line(descripcion);
END LOOP;
CLOSE cpaises;
END;

Otra forma es por medio de un bucle WHILE LOOP. La instrucción FECTH aparece dos veces.

OPEN nombre_cursor;
FETCH nombre_cursor INTO lista_variables;
WHILE nombre_cursor%FOUND

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=39 06/08/2009
www.devjoker.com Page 4 of 4

LOOP
/* Procesamiento de los registros recuperados */
FETCH nombre_cursor INTO lista_variables;
END LOOP;
CLOSE nombre_cursor;

DECLARE
CURSOR cpaises
IS
SELECT CO_PAIS, DESCRIPCION, CONTINENTE
FROM PAISES;

co_pais VARCHAR2(3);
descripcion VARCHAR2(50);
continente VARCHAR2(25);
BEGIN
OPEN cpaises;
FETCH cpaises INTO co_pais,descripcion,continente;
WHILE cpaises%found
LOOP
dbms_output.put_line(descripcion);
FETCH cpaises INTO co_pais,descripcion,continente;
END LOOP;
CLOSE cpaises;
END;

Por último podemos usar un bucle FOR LOOP. Es la forma más corta ya que el cursor es implicitamente se
ejecutan las instrucciones OPEN, FECTH y CLOSE.

FOR variable IN nombre_cursor LOOP


/* Procesamiento de los registros recuperados */
END LOOP;

BEGIN
FOR REG IN (SELECT * FROM PAISES)
LOOP
dbms_output.put_line(reg.descripcion);
END LOOP;
END;

www.Devjoker.com

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=39 06/08/2009
www.devjoker.com Page 1 of 1

www.Devjoker.com
Cursores de actualización
Declaración y utiización de cursores de actualización.

Los cursores de actualización se declarán igual que los cursores explicitos, añadieno FOR UPDATE al
final de la sentencia select.

CURSOR nombre_cursor IS
instrucción_SELECT
FOR UPDATE

Para actualizar los datos del cursor hay que ejecutar una sentencia UPDATE especificando la clausula
WHERE CURRENT OF <cursor_name>.

UPDATE <nombre_tabla> SET


<campo_1> = <valor_1>
[,<campo_2> = <valor_2>]
WHERE CURRENT OF <cursor_name>

El siguiente ejemplo muestra el uso de un cursor de actualización:

DECLARE
CURSOR cpaises IS
select CO_PAIS, DESCRIPCION, CONTINENTE
from paises
FOR UPDATE;
co_pais VARCHAR2(3);
descripcion VARCHAR2(50);
continente VARCHAR2(25);
BEGIN
OPEN cpaises;
FETCH cpaises INTO co_pais,descripcion,continente;
WHILE cpaises%found
LOOP
UPDATE PAISES
SET CONTINENTE = CONTINENTE || '.'
WHERE CURRENT OF cpaises;
FETCH cpaises INTO co_pais,descripcion,continente;
END LOOP;
CLOSE cpaises;
COMMIT;
END;

Cuando trabajamos con cursores de actualización debemos tener en cuenta las siguientes consideraciones:

 Los cursores de actualización generan bloqueos en la base de datos.

www.Devjoker.com

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=40 06/08/2009
www.devjoker.com Page 1 of 5

www.Devjoker.com

Excepciones en PL/SQL
Manejo de excepciones

En PL/SQL una advertencia o condición de error es llamada una excepción.

Las excepciones se controlan dentro de su propio bloque.La estructura de bloque de una excepción se
muestra a continuación.

DECLARE
-- Declaraciones
BEGIN
-- Ejecucion
EXCEPTION
-- Excepcion
END;

Cuando ocurre un error, se ejecuta la porción del programa marcada por el bloque EXCEPTION,
transfiriéndose el control a ese bloque de sentencias.

El siguiente ejemplo muestra un bloque de excepciones que captura las excepciones NO_DATA_FOUND
y ZERO_DIVIDE. Cualquier otra excepcion será capturada en el bloque WHEN OTHERS THEN.

DECLARE
-- Declaraciones
BEGIN
-- Ejecucion
EXCEPTION
WHEN NO_DATA_FOUND THEN
-- Se ejecuta cuando ocurre una excepcion de tipo NO_DATA_FOUND
WHEN ZERO_DIVIDE THEN
-- Se ejecuta cuando ocurre una excepcion de tipo ZERO_DIVIDE
WHEN OTHERS THEN
-- Se ejecuta cuando ocurre una excepcion de un tipo no tratado
-- en los bloques anteriores
END;

Como ya hemos dicho cuando ocurre un error, se ejecuta el bloque EXCEPTION, transfiriéndose el
control a las sentencias del bloque. Una vez finalizada la ejecución del bloque de EXCEPTION no se continua
ejecutando el bloque anterior.

Si existe un bloque de excepcion apropiado para el tipo de excepción se ejecuta dicho bloque. Si no existe
un bloque de control de excepciones adecuado al tipo de excepcion se ejecutará el bloque de excepcion
WHEN OTHERS THEN (si existe!). WHEN OTHERS debe ser el último manejador de excepciones.

Las excepciones pueden ser definidas en forma interna o explícitamente por el usuario. Ejemplos de
excepciones definidas en forma interna son la división por cero y la falta de memoria en tiempo de ejecución.
Estas mismas condiciones excepcionales tienen sus propio tipos y pueden ser referenciadas por ellos:
ZERO_DIVIDE y STORAGE_ERROR.

Las excepciones definidas por el usuario deben ser alcanzadas explícitamente utilizando la sentencia
RAISE.

Con las excepciones se pueden manejar los errores cómodamente sin necesidad de mantener múltiples

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=48 06/08/2009
www.devjoker.com Page 2 of 5

chequeos por cada sentencia escrita. También provee claridad en el código ya que permite mantener las
rutinas correspondientes al tratamiento de los errores de forma separada de la lógica del negocio.

Excepciones predefinidas

PL/SQL proporciona un gran número de excepciones predefinidas que permiten controlar las condiciones
de error más habituales.

Las excepciones predefinidas no necesitan ser declaradas. Simplemente se utilizan cuando estas son
lanzadas por algún error determinado.

La siguiente es la lista de las excepciones predeterminadas por PL/SQL y una breve descripción de cuándo
son accionadas:

Excepcion Se ejecuta ... SQLCODE


El programa intentó asignar valores a los
ACCESS_INTO_NULL -6530
atributos de un objeto no inicializado
El programa intentó asignar valores a una
COLLECTION_IS_NULL -6531
tabla anidada aún no inicializada
El programa intentó abrir un cursor que ya
se encontraba abierto. Recuerde que un
CURSOR_ALREADY_OPEN cursor de ciclo FOR automáticamente lo -6511
abre y ello no se debe especificar con la
sentencia OPEN
El programa intentó almacenar valores
duplicados en una columna que se
DUP_VAL_ON_INDEX -1
mantiene con restricción de integridad de
un índice único (unique index)
El programa intentó efectuar una
INVALID_CURSOR -1001
operación no válida sobre un cursor
En una sentencia SQL, la conversión de
una cadena de caracteres hacia un
INVALID_NUMBER -1722
número falla cuando esa cadena no
representa un número válido
El programa intentó conectarse a Oracle
LOGIN_DENIED con un nombre de usuario o password -1017
inválido
Una sentencia SELECT INTO no devolvió
valores o el programa referenció un
NO_DATA_FOUND 100
elemento no inicializado en una tabla
indexada
El programa efectuó una llamada a Oracle
NOT_LOGGED_ON -1012
sin estar conectado
PROGRAM_ERROR PL/SQL tiene un problema interno -6501
Los elementos de una asignación (el valor
a asignar y la variable que lo contendrá)
tienen tipos incompatibles. También se
ROWTYPE_MISMATCH -6504
presenta este error cuando un parámetro
pasado a un subprograma no es del tipo
esperado
El parámetro SELF (el primero que es
SELF_IS_NULL -30625
pasado a un método MEMBER) es nulo
STORAGE_ERROR La memoria se terminó o está corrupta -6500

El programa está tratando de referenciar


SUBSCRIPT_BEYOND_COUNT un elemento de un arreglo indexado que -6533
se encuentra en una posición más grande
que el número real de elementos de la

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=48 06/08/2009
www.devjoker.com Page 3 of 5

colección
El programa está referenciando un
elemento de un arreglo utilizando un
SUBSCRIPT_OUTSIDE_LIMIT -6532
número fuera del rango permitido (por
ejemplo, el elemento “-1”)
La conversión de una cadena de
SYS_INVALID_ROWID caracteres hacia un tipo rowid falló porque -1410
la cadena no representa un número
Se excedió el tiempo máximo de espera
TIMEOUT_ON_RESOURCE -51
por un recurso en Oracle
Una sentencia SELECT INTO devuelve más
TOO_MANY_ROWS -1422
de una fila
Ocurrió un error aritmético, de conversión
o truncamiento. Por ejemplo, sucede
VALUE_ERROR cuando se intenta calzar un valor muy -6502
grande dentro de una variable más
pequeña
El programa intentó efectuar una división
ZERO_DIVIDE -1476
por cero

Excepciones definidas por el usuario

PL/SQL permite al usuario definir sus propias excepciones, las que deberán ser declaradas y lanzadas
explícitamente utilizando la sentencia RAISE.

Las excepciones deben ser declaradas en el segmento DECLARE de un bloque, subprograma o paquete.
Se declara una excepción como cualquier otra variable, asignandole el tipo EXCEPTION. Las mismas reglas
de alcance aplican tanto sobre variables como sobre las excepciones.

DECLARE
-- Declaraciones
MyExcepcion EXCEPTION;
BEGIN
-- Ejecucion
EXCEPTION
-- Excepcion
END;

Reglas de Alcance

Una excepcion es válida dentro de su ambito de alcance, es decir el bloque o programa donde ha sido
declarada. Las excepciones predefinidas son siempre válidas.

Como las variables, una excepción declarada en un bloque es local a ese bloque y global a todos los sub-
bloques que comprende.

La sentencia RAISE

La sentencia RAISE permite lanzar una excepción en forma explícita. Es posible utilizar esta sentencia en
cualquier lugar que se encuentre dentro del alcance de la excepción.

DECLARE
-- Declaramos una excepcion identificada por VALOR_NEGATIVO
VALOR_NEGATIVO EXCEPTION;
valor NUMBER;
BEGIN

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=48 06/08/2009
www.devjoker.com Page 4 of 5

-- Ejecucion
valor := -1;
IF valor < 0 THEN
RAISE VALOR_NEGATIVO;
END IF;

EXCEPTION
-- Excepcion
WHEN VALOR_NEGATIVO THEN
dbms_output.put_line('El valor no puede ser negativo');
END;

Con la sentencia RAISE podemos lanzar una excepción definida por el usuario o predefinida, siendo el
comportamiento habitual lanzar excepciones definidas por el usuario.

Recordar la existencia de la excepción OTHERS, que simboliza cualquier condición de excepción que no
ha sido declarada. Se utiliza comúnmente para controlar cualquier tipo de error que no ha sido previsto. En
ese caso, es común observar la sentencia ROLLBACK en el grupo de sentencias de la excepción o alguna de
las funciones SQLCODE – SQLERRM, que se detallan en el próximo punto.

Uso de SQLCODE y SQLERRM

Al manejar una excepción es posible usar las funciones predefinidas SQLCode y SQLERRM para aclarar
al usuario la situación de error acontecida.

SQLcode devuelve el número del error de Oracle y un 0 (cero) en caso de exito al ejecutarse una
sentencia SQL.

Por otra parte, SQLERRM devuelve el correspondiente mensaje de error.

Estas funciones son muy útiles cuando se utilizan en el bloque de excepciones, para aclarar el significado
de la excepción OTHERS.

Estas funciones no pueden ser utilizadas directamente en una sentencia SQL, pero sí se puede asignar su
valor a alguna variable de programa y luego usar esta última en alguna sentencia.

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;

También es posible entregarle a la función SQLERRM un número negativo que represente un error de
Oracle y ésta devolverá el mensaje asociado.

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=48 06/08/2009
www.devjoker.com Page 5 of 5

DECLARE
msg VARCHAR2(255);
BEGIN
msg := SQLERRM(-1403);
DBMS_OUTPUT.put_line(MSG);
END;

www.Devjoker.com

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=48 06/08/2009
www.devjoker.com Page 1 of 1

www.Devjoker.com
Subprogramas en PL/SQL
Como hemos visto anteriormente los bloques de PL/SQL pueden ser bloques anónimos (scripts) y
subprogramas.

Los subprogramas son bloques de PL/SQL a los que asignamos un nombre identificativo y que
normalmente almacenamos en la propia base de datos para su posterior ejecución.

Los subprogramas pueden recibir parámetros.

Los subprogramas pueden ser de varios tipos:

 Procedimientos almacenados.
 Funciones.
 Triggers.
 Subprogramas en bloques anonimos.

www.Devjoker.com

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=51 06/08/2009
www.devjoker.com Page 1 of 2

www.Devjoker.com
Procedimientos almacenados

Un procedimiento es un subprograma que ejecuta una acción especifica y que no devuelve ningún valor.
Un procedimiento tiene un nombre, un conjunto de parámetros (opcional) y un bloque de código.

La sintaxis de un procedimiento almacenado es la siguiente:

CREATE [OR REPLACE]


PROCEDURE <procedure_name> [(<param1> [IN|OUT|IN OUT] <type>,
<param2> [IN|OUT|IN OUT] <type>, ...)]
IS
-- Declaracion de variables locales
BEGIN
-- Sentencias
[EXCEPTION]
-- Sentencias control de excepcion
END [<procedure_name>];

El uso de OR REPLACE permite sobreescribir un procedimiento existente. Si se omite, y el procedimiento


existe, se producirá, un error.

La sintaxis es muy parecida a la de un bloque anónimo, salvo porque se reemplaza la seccion DECLARE
por la secuencia PROCEDURE ... IS en la especificación del procedimiento.

Debemos especificar el tipo de datos de cada parámetro. 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_Saldo(cuenta NUMBER,
new_saldo NUMBER)
IS
-- Declaracion de variables locales
BEGIN
-- Sentencias
UPDATE SALDOS_CUENTAS
SET SALDO = new_saldo,
FX_ACTUALIZACION = SYSDATE
WHERE CO_CUENTA = cuenta;
END Actualiza_Saldo;

También podemos asignar un valor por defecto a los parámetros, utilizando la clausula DEFAULT o el
operador de asiganción (:=) .

CREATE OR REPLACE
PROCEDURE Actualiza_Saldo(cuenta NUMBER,
new_saldo NUMBER DEFAULT 10 )
IS
-- Declaracion de variables locales
BEGIN
-- Sentencias
UPDATE SALDOS_CUENTAS

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=52 06/08/2009
www.devjoker.com Page 2 of 2

SET SALDO = new_saldo,


FX_ACTUALIZACION = SYSDATE
WHERE CO_CUENTA = cuenta;
END Actualiza_Saldo;

Una vez creado y compilado el procedimiento almacenado podemos ejecutarlo. Si el sistema nos indica
que el procedimiento se ha creado con errores de compilación podemos ver estos errores de compilacion con
la orden SHOW ERRORS en SQL *Plus.

Existen dos formas de pasar argumentos a un procedimiento almacenado a la hora de ejecutarlo (en
realidad es válido para cualquier subprograma). Estas son:

 Notación posicional: Se pasan los valores de los parámetros en el mismo orden en que el procedure los
define.

BEGIN
Actualiza_Saldo(200501,2500);
COMMIT;
END;

 Notación nominal:Se pasan los valores en cualquier orden nombrando explicitamente el parámetro.

BEGIN
Actualiza_Saldo(cuenta => 200501,new_saldo => 2500);
COMMIT;
END;

www.Devjoker.com

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=52 06/08/2009
www.devjoker.com Page 1 of 2

www.Devjoker.com

Funciones en PL/SQL
Una función es un subprograma que devuelve un valor.

La sintaxis para construir funciones es la siguiente:

CREATE [OR REPLACE]


FUNCTION <fn_name>[(<param1> IN <type>, <param2> IN <type>, ...)]
RETURN <return_type>
IS
result <return_type>;
BEGIN

return(result);
[EXCEPTION]
-- Sentencias control de excepcion
END [<fn_name>];

El uso de OR REPLACE permite sobreescribir una función existente. Si se omite, y la función existe, se
producirá, un error.

La sintaxis de los parámetros es la misma que en los procedimientos almacenado, exceptuando que solo
pueden ser de entrada.

Ejemplo:

CREATE OR REPLACE
FUNCTION fn_Obtener_Precio(p_producto VARCHAR2)
RETURN NUMBER
IS
result NUMBER;
BEGIN
SELECT PRECIO INTO result
FROM PRECIOS_PRODUCTOS
WHERE CO_PRODUCTO = p_producto;
return(result);
EXCEPTION
WHEN NO_DATA_FOUND THEN
return 0;
END ;

Si el sistema nos indica que el la función se ha creado con errores de compilación podemos ver estos
errores de compilacion con la orden SHOW ERRORS en SQL *Plus.

Una vez creada y compilada la función podemos ejecutarla de la siguiente forma:

DECLARE
Valor NUMBER;
BEGIN
Valor := fn_Obtener_Precio('000100');
END;

Las funciones pueden utilizarse en sentencias SQL de manipulación de datos (SELECT, UPDATE, INSERT y

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=53 06/08/2009
www.devjoker.com Page 2 of 2

DELETE):

SELECT CO_PRODUCTO,
DESCRIPCION,
fn_Obtener_Precio(CO_PRODUCTO)
FROM PRODUCTOS;

www.Devjoker.com

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=53 06/08/2009
www.devjoker.com Page 1 of 1

www.Devjoker.com
Subprogramas en bloques anónimos

Dentro de la seccion DECLARE de un bloque anónimo podemos declarar funciones y procedimientos


almacenados y ejecutarlos desde el bloque de ejecución del script.

Este tipo de subprogramas son menos conocidos que los procedimientos almacenados, funciones y
triggers, pero son enormemente útiles.

El siguiente ejemplo declara y ejecuta utiliza una funcion (fn_multiplica_x2).

DECLARE
idx NUMBER;

FUNCTION fn_multiplica_x2(num NUMBER)


RETURN NUMBER
IS
result NUMBER;
BEGIN
result := num *2;
return result;
END fn_multiplica_x2;
BEGIN
FOR idx IN 1..10
LOOP
dbms_output.put_line
('Llamada a la funcion ... '||TO_CHAR(fn_multiplica_x2(idx)));
END LOOP;

END;

Notese que se utiliza la funcion TO_CHAR para convertir el resultado de la función fn_multiplica_x2
(numérico) en alfanumérico y poder mostrar el resultado por pantalla.

www.Devjoker.com

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=57 06/08/2009
www.devjoker.com Page 1 of 3

www.Devjoker.com
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>;]}

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=55 06/08/2009
www.devjoker.com Page 2 of 3

-- 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;

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=55 06/08/2009
www.devjoker.com Page 3 of 3

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.

www.Devjoker.com

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=55 06/08/2009
www.devjoker.com Page 1 of 2

www.Devjoker.com
Transacciones
Una transacción es un conjunto de operaciones que se ejecutan en una base de datos, y que son tratadas
como una única unidad lógica por el SGBD.

Es decir, una transacción es una o varias sentencias SQL que se ejecutan en una base de datos como una
única operación, confirmandose o deshaciendose en grupo.

No todas las operaciones SQL son transaccionales. Sólo son transaccionales las operaciones
correspondiente al DML, es decir, sentencias SELECT, INSERT, UPDATE y DELETE

Para confirmar una transacción se utiliza la sentencia COMMIT. Cuando realizamos COMMIT los cambios
se escriben en la base de datos.

Para deshacer una transacción se utiliza la sentencia ROLLBACK. Cuando realizamos ROLLBACK se
deshacen todas las modificaciones realizadas por la transacción en la base de datos, quedando la base de
datos en el mismo estado que antes de iniciarse la transacción.

Un ejemplo clásico de transacción son las transferencias bancarias. Para realizar una transferencia de
dinero entre dos cuentas bancarias debemos descontar el dinero de una cuenta, realizar el ingreso en la otra
cuenta y grabar las operaciones y movimientos necesarios, actuaizar los saldos ... .Si en alguno de estos
puntos se produce un fallo en el sistema podríamos hacer descontado el dinero de una de las cuentas y no
haberlo ingresado en la otra. Por lo tanto, todas estas operaciones deben ser correctas o fallar todas.
En estos casos, al confirmar la transaccion (COMMIT) o al deshacerla (ROLLBACK) garantizamos que todos
los datos quedan en un estado consistente.

En una transacción los datos modificados no son visibles por el resto de usuarios hasta que se confirme la
transacción.

El siguiente ejemplo muestra una supuesta transacción bancaria:

DECLARE
importe NUMBER;
ctaOrigen VARCHAR2(23);
ctaDestino VARCHAR2(23);
BEGIN
importe := 100;
ctaOrigen := '2530 10 2000 1234567890';
ctaDestino := '2532 10 2010 0987654321';
UPDATE CUENTAS SET SALDO = SALDO - importe
WHERE CUENTA = ctaOrigen;
UPDATE CUENTAS SET SALDO = SALDO + importe
WHERE CUENTA = ctaDestino;
INSERT INTO MOVIMIENTOS
(CUENTA_ORIGEN, CUENTA_DESTINO,IMPORTE, FECHA_MOVIMIENTO)
VALUES
(ctaOrigen, ctaDestino, importe*(-1), SYSDATE);

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=63 06/08/2009
www.devjoker.com Page 2 of 2

INSERT INTO MOVIMIENTOS


(CUENTA_ORIGEN, CUENTA_DESTINO,IMPORTE, FECHA_MOVIMIENTO)
VALUES
(ctaDestino,ctaOrigen, importe, SYSDATE);
COMMIT;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('Error en la transaccion:'||SQLERRM);
dbms_output.put_line('Se deshacen las modificaciones);
ROLLBACK;
END;

Si alguna de las tablas afectadas por la transacción tiene triggers, las operaciones que realiza el trigger
están dentro del ambito de la transacción, y son confirmadas o deshechas conjuntamente con la transacción.

Durante la ejecución de una transacción, una segunda transacción no podrá ver los cambios realizados por
la primera transacción hasta que esta se confirme.

ORACLE es completamente transaccional. Siempre debemos especificar si que queremos deshacer o


confirmar la transacion.

www.Devjoker.com

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=63 06/08/2009
www.devjoker.com Page 1 of 6

www.Devjoker.com
Funciones integradas de PL/SQL

PL/SQL tiene un gran número de funciones incorporadas, sumamente útiles. A continuación vamos a ver
algunas de las más utilizadas.

SYSDATE

Devuelve la fecha del sistema:

SELECT SYSDATE FROM DUAL;

NVL

Devuelve el valor recibido como parámetro en el caso de que expresión sea NULL,o expresión en caso
contrario.

NVL(<expresion>, <valor>)

El siguiente ejemplo devuelve 0 si el precio es nulo, y el precio cuando está informado:

SELECT CO_PRODUCTO, NVL(PRECIO, 0) FROM PRECIOS;

DECODE

Decode proporciona la funcionalidad de una sentencia de control de flujo if-elseif-else.

DECODE(<expr>, <cond1>, <val1>[, ..., <condN>, <valN>], <default>)

Esta función evalúa una expresión "<expr>", si se cumple la primera condición "<cond1>" devuelve el
valor1 "<val1>", en caso contrario evalúa la siguiente condición y así hasta que una de las condiciones se
cumpla. Si no se cumple ninguna condición se devuelve el valor por defecto.

Es muy común escribir la función DECODE identada como si se tratase de un bloque IF.

SELECT DECODE (co_pais, /* Expresion a evaluar */


'ESP', 'ESPAÑA', /* Si co_pais = 'ESP' ==> 'ESPAÑA' */
'MEX', 'MEXICO', /* Si co_pais = 'MEX' ==> 'MEXICO' */
'PAIS '||co_pais)/* ELSE ==> concatena */
FROM PAISES;

TO_DATE

Convierte una expresión al tipo fecha. El parámetro opcional formato indica el formato de entrada de la

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=67 06/08/2009
www.devjoker.com Page 2 of 6

expresión no el de salida.

TO_DATE(<expresion>, [<formato>])

En este ejemplo convertimos la expresion '01/12/2006' de tipo CHAR a una fecha (tipo DATE). Con el
parámetro formato le indicamos que la fecha está escrita como día-mes-año para que devuelve el uno de
diciembre y no el doce de enero.

SELECT TO_DATE('01/12/2006',
'DD/MM/YYYY')
FROM DUAL;

Este otro ejemplo muestra la conversión con formato de día y hora.

SELECT TO_DATE('31/12/2006 23:59:59',


'DD/MM/YYYY HH24:MI:SS')
FROM DUAL;

TO_CHAR

Convierte una expresión al tipo CHAR. El parámetro opcional formato indica el formato de salida de la
expresión.

TO_CHAR(<expresion>, [<formato>])

SELECT TO_CHAR(SYSDATE, 'DD/MM/YYYYY')


FROM DUAL;

TO_NUMBER

Convierte una expresion alfanumérica en numerica. Opcionalmente podemos especificar el formato de


salida.

TO_NUMBER(<expresion>, [<formato>])

SELECT TO_NUMBER ('10')


FROM DUAL;

TRUNC

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=67 06/08/2009
www.devjoker.com Page 3 of 6

Trunca una fecha o número.

Si el parámetro recibido es una fecha elimina las horas, minutos y segundos de la misma.

SELECT TRUNC(SYSDATE)FROM DUAL;

Si el parámetro es un número devuelve la parte entera.

SELECT TRUNC(9.99)FROM DUAL;

LENGTH

Devuelve la longitud de un tipo CHAR.

SELECT LENGTH('HOLA MUNDO')FROM DUAL;

INSTR

Busca una cadena de caracteres dentro de otra. Devuelve la posicion de la ocurrencia de la cadena
buscada.

Su sintaxis es la siguiente:

INSTR(<char>, <search_string>, <startpos>, <occurrence> )

SELECT INSTR('AQUI ES DONDE SE BUSCA', 'BUSCA', 1, 1 )


FROM DUAL;

REPLACE

Reemplaza un texto por otro en un expresion de busqueda.

REPLACE(<expresion>, <busqueda>, <reemplazo>)

El siguiente ejemplo reemplaza la palabra 'HOLA' por 'VAYA' en la cadena 'HOLA MUNDO'.

SELECT REPLACE ('HOLA MUNDO','HOLA', 'VAYA')-- devuelve VAYA MUNDO


FROM DUAL;

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=67 06/08/2009
www.devjoker.com Page 4 of 6

SUBSTR

Obtiene una parte de una expresion, desde una posición de inicio hasta una determinada longitud.

SUBSTR(<expresion>, <posicion_ini>, <longitud> )

SELECT SUBSTR('HOLA MUNDO', 6, 5) -- Devuelve MUNDO


FROM DUAL;

UPPER

Convierte una expresion alfanumerica a mayúsculas.

SELECT UPPER('hola mundo') -- Devuelve HOLA MUNDO


FROM DUAL;

LOWER

Convierte una expresion alfanumerica a minúsculas.

SELECT LOWER('HOLA MUNDO') -- Devuelve hola mundo


FROM DUAL;

ROWIDTOCHAR

Convierte un ROWID a tipo caracter.

SELECT ROWIDTOCHAR(ROWID)
FROM DUAL;

RPAD

Añade N veces una determinada cadena de caracteres a la derecha una expresión. Muy util para generar
ficheros de texto de ancho fijo.

RPAD(<expresion>, <longitud>, <pad_string> )

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=67 06/08/2009
www.devjoker.com Page 5 of 6

El siguiente ejemplo añade puntos a la expresion 'Hola mundo' hasta alcanzar una longitud de 50
caracteres.

SELECT RPAD('Hola Mundo', 50, '.')


FROM DUAL;

LPAD

Añade N veces una determinada cadena de caracteres a la izquierda de una expresión. Muy util para
generar ficheros de texto de ancho fijo.

LPAD(<expresion>, <longitud>, <pad_string> )

El siguiente ejemplo añade puntos a la expresion 'Hola mundo' hasta alcanzar una longitud de 50
caracteres.

SELECT LPAD('Hola Mundo', 50, '.')


FROM DUAL;

RTRIM

Elimina los espacios en blanco a la derecha de una expresion

SELECT RTRIM ('Hola Mundo ')


FROM DUAL;

LTRIM

Elimina los espacios en blanco a la izquierda de una expresion

SELECT LTRIM (' Hola Mundo')


FROM DUAL;

TRIM

Elimina los espacios en blanco a la izquierda y derecha de una expresion

SELECT TRIM (' Hola Mundo ')


FROM DUAL;

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=67 06/08/2009
www.devjoker.com Page 6 of 6

MOD

Devuelve el resto de la división entera entre dos números.

MOD(<dividendo>, <divisor> )

SELECT MOD(20,15) -- Devuelve el modulo de dividir 20/15


FROM DUAL

www.Devjoker.com

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=67 06/08/2009
www.devjoker.com Page 1 of 2

www.Devjoker.com

Secuencias
ORACLE proporciona los objetos de secuencia para la generación de códigos numericos automáticos.

Las secuencias son una solución fácil y elegante al problema de los codigos autogenerados.

LA sintaxis general es la siguiente:

CREATE SEQUENCE <secuence_name>


[MINVALUE <min_val>]
[MAXVALUE <max_val>]
[START WITH <ini_val>]
[INCREMENT BY <inc_val>]
[NOCACHE | CACHE <cache_val>]
[CYCLE]
[ORDER];

El siguiente ejemplo crea una secuencia SQ_PRODUCTOS.

CREATE SEQUENCE SQ_PRODUCTOS


MINVALUE 1
MAXVALUE 999999999999999999999999999
START WITH 1
INCREMENT BY 1
CACHE 20;

Se puede simplificar la orden, tomando los valores por defecto. El ejemplo anterior quedaría del siguiente
modo:

CREATE SEQUENCE SQ_PRODUCTOS;

Para obtener el siguiente valor de una secuencia debemos utilizar la función NEXTVAL. NEXTVAL se
puede utilizar el cualquier sentencia SQL DML (SELECT, INSERT, UPDATE).

SELECT SQ_PRODUCTOS.NEXTVAL
FROM DUAL;

Podemos obtener el último valor generado por la secuencia con la función CURRVAL. Para poder ejecutar
la función CURRVAL debemos haber ejecutado previamente la función NEXTVAL.

SELECT SQ_PRODUCTOS.CURRVAL
FROM DUAL;

Para eliminar una secuencia definitivamente de la base de datos debemos utilizar la sentencia DROP.

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=68 06/08/2009
www.devjoker.com Page 2 of 2

DROP SEQUENCE SQ_PRODUCTOS ;

www.Devjoker.com

http://www.devjoker.com/asp/impresion_contenido.aspx?co_contenido=68 06/08/2009

También podría gustarte