Curso PL/SQL

143
PROGRAMACION PROGRAMACION PL/SQL PL/SQL

description

Curso de programación PL/SQL

Transcript of Curso PL/SQL

Page 1: Curso PL/SQL

PROGRAMACION PROGRAMACION PL/SQLPL/SQL

Page 2: Curso PL/SQL

PrólogoPrólogo

PL/SQL amplía a SQL con los elementos PL/SQL amplía a SQL con los elementos característicos de los lenguajes de programación, característicos de los lenguajes de programación, variables, sentencias de control de flujo, bucles ...variables, sentencias de control de flujo, bucles ...

Cuando se desea realizar una aplicación completa Cuando se desea realizar una aplicación completa para el manejo de una base de datos relacional, para el manejo de una base de datos relacional,

resulta necesario utilizar alguna herramienta que resulta necesario utilizar alguna herramienta que soporte la capacidad de consulta del SQL y la soporte la capacidad de consulta del SQL y la versatilidad de los lenguajes de programación versatilidad de los lenguajes de programación

tradicionales. PL/SQL es el lenguaje de tradicionales. PL/SQL es el lenguaje de programación que proporciona programación que proporciona OracleOracle para para extender el SQL estándar con otro tipo de extender el SQL estándar con otro tipo de

instrucciones. instrucciones.

2

Page 3: Curso PL/SQL

¿Que vamos a necesitar?¿Que vamos a necesitar?

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

Una instancia de ORACLE funcionando Una instancia de ORACLE funcionando correctamente.correctamente.

Herramientas cliente de ORACLE, en Herramientas cliente de ORACLE, en particular SQL*Plus para poder ejecutar particular SQL*Plus para poder ejecutar los ejemplos.los ejemplos.

Haber configurado correctamente una Haber configurado correctamente una conexión a ORACLE.conexión a ORACLE.

3

Page 4: Curso PL/SQL

IntroducciónIntroducción

SQL es un lenguaje de consulta para los sistemas de SQL es un lenguaje de consulta para los sistemas de bases de datos relacionales (RDBMS), pero que no bases de datos relacionales (RDBMS), pero que no posee la potencia de los lenguajes de programación. posee la potencia de los lenguajes de programación. No permite el uso de estructuras de control de flujo, No permite el uso de estructuras de control de flujo, bucles y demás elementos característicos de la bucles y demás elementos característicos de la programación. programación. SQL es un lenguaje de consulta, SQL es un lenguaje de consulta, no un lenguaje de programación.no un lenguaje de programación.

SQL es la herramienta ideal para trabajar con bases SQL es la herramienta ideal para trabajar con bases de datos en sentencias DMLs. Dicho esto; PL/SQL es de datos en sentencias DMLs. Dicho esto; PL/SQL es el lenguaje de programación que extiende el SQL el lenguaje de programación que extiende el SQL estándar de Oracle y además posee elementos estándar de Oracle y además posee elementos propios de los lenguajes de programación.propios de los lenguajes de programación.

4

Page 5: Curso PL/SQL

IntroducciónIntroducción

Con PL/SQL vamos a poder programar las Con PL/SQL vamos a poder programar las unidades de programa de la base de datos unidades de programa de la base de datos ORACLE, están son:ORACLE, están son:

Procedimientos almacenadosProcedimientos almacenados FuncionesFunciones TriggersTriggers ScriptsScripts

Además PL/SQL nos permite realizar programas Además PL/SQL nos permite realizar programas sobre las siguientes herramientas de ORACLE:sobre las siguientes herramientas de ORACLE:

Oracle FormsOracle Forms Oracle ReportsOracle Reports Oracle Aplication ServerOracle Aplication Server

5

Page 6: Curso PL/SQL

Primeros pasos con PL/SQL Primeros pasos con PL/SQL Para programar en PL/SQL es necesario conocer sus Para programar en PL/SQL es necesario conocer sus fundamentos.fundamentos.PL/SQL no es CASE-SENSITIVE, es decir, no diferencia PL/SQL no es CASE-SENSITIVE, es decir, no diferencia mayúsculas de minúsculas como otros lenguajes de mayúsculas de minúsculas como otros lenguajes de programación como C o Java.programación como C o Java. Sinembargo debemos Sinembargo debemos recordar que ORACLE es CASE-SENSITIVE en la recordar que ORACLE es CASE-SENSITIVE en la búsqueda de texto.búsqueda de texto.

Una línea en PL/SQL contiene grupos de caracteres Una línea en PL/SQL contiene grupos de caracteres conocidos como UNIDADES LEXICAS, que pueden ser conocidos como UNIDADES LEXICAS, que pueden ser clasificadas como: clasificadas como:

DELIMITADORES DELIMITADORES IDENTIFICADORES IDENTIFICADORES LITERALES LITERALES COMENTARIOS COMENTARIOS EXPRESIONESEXPRESIONES

6

Page 7: Curso PL/SQL

Primeros pasos con PL/SQLPrimeros pasos con PL/SQLDELIMITADOR: Es un símbolo simple o compuesto que DELIMITADOR: Es un símbolo simple o compuesto que tiene una función especial en PL/SQL. Estos pueden tiene una función especial en PL/SQL. Estos pueden ser: ser:

Operadores Aritméticos Operadores Aritméticos Operadores Lógicos Operadores Lógicos Operadores Relacionales Operadores Relacionales

IDENTIFICADOR: Son empleados para nombrar IDENTIFICADOR: Son empleados para nombrar objetos de programas en PL/SQL así como a unidades objetos de programas en PL/SQL así como a unidades dentro del mismo, estas unidades y objetos incluyen: dentro del mismo, estas unidades y objetos incluyen:

Constantes Constantes Cursores Cursores Variables Variables Subprogramas Subprogramas Excepciones Excepciones Paquetes Paquetes

7

Page 8: Curso PL/SQL

Primeros pasos con PL/SQLPrimeros pasos con PL/SQL

LITERAL:LITERAL: Es un valor de tipo numérico, caracter, Es un valor de tipo numérico, caracter, cadena o lógico no representado por un cadena o lógico no representado por un identificador (es un valor explícito).identificador (es un valor explícito).

COMENTARIO: Es una aclaración que el COMENTARIO: Es una aclaración que el programador incluye en el código. Son soportados programador incluye en el código. Son soportados 2 estilos de comentarios, el de línea simple y de 2 estilos de comentarios, el de línea simple y de multilínea, para lo cual son empleados ciertos multilínea, para lo cual son empleados ciertos caracters especiales como son: caracters especiales como son:

-- Línea simple-- Línea simple

/* /* Conjunto de líneasConjunto de líneas*/*/

8

Page 9: Curso PL/SQL

Tipos de datos en PL/SQLTipos de datos en PL/SQL

Cada constante y variable tienen un tipo de dato Cada constante y variable tienen un tipo de dato en el cual se especifica el formato de en el cual se especifica el formato de almacenamiento, restricciones y rango de valores almacenamiento, restricciones y rango de valores válidos. válidos. PL/SQL proporciona una variedad predefinida de PL/SQL proporciona una variedad predefinida de tipos de datos, casi todos los tipos de datos tipos de datos, casi todos los tipos de datos manejados son similares a los soportados por manejados son similares a los soportados por SQL. Los tipos de datos más comunes son:SQL. Los tipos de datos más comunes son:

NUMBERNUMBER CHARCHAR VARCHAR2VARCHAR2 BOOLEANBOOLEAN DATEDATE

9

Page 10: Curso PL/SQL

Tipos de datos en PL/SQLTipos de datos en PL/SQLNUMBERNUMBER ( (NuméricoNumérico): Almacena números enteros o de punto ): Almacena números enteros o de punto flotante, virtualmente de cualquier longitud, aunque puede ser flotante, virtualmente de cualquier longitud, aunque puede ser especificada la precisión (número de dígitos) y la escala que es la especificada la precisión (número de dígitos) y la escala que es la que determina el número de decimales.que determina el número de decimales.

-- NUMBER [(precisión, escala)]-- NUMBER [(precisión, escala)]saldo saldo NUMBERNUMBER(16,2); (16,2); /* Indica que puede almacenar un valor numérico de 16 /* Indica que puede almacenar un valor numérico de 16 posiciones, 2 de ellas decimales. Es decir, 14 enteros posiciones, 2 de ellas decimales. Es decir, 14 enteros y dos decimales */y dos decimales */

CHAR CHAR ((CaracterCaracter): Almacena datos de tipo caracter con una longitud ): Almacena datos de tipo caracter con una longitud máxima de 32767 y cuyo valor de longitud por default es 1 máxima de 32767 y cuyo valor de longitud por default es 1

-- CHAR [(longitud_máxima)]-- CHAR [(longitud_máxima)]nombre nombre CHARCHAR(20);(20);/* Indica que puede almacenar valores alfanuméricos de 20 /* Indica que puede almacenar valores alfanuméricos de 20 posiciones */posiciones */

10

Page 11: Curso PL/SQL

Tipos de datos en PL/SQLTipos de datos en PL/SQLVARCHAR2VARCHAR2 ( (Caracter de longitud variableCaracter de longitud variable): Almacena datos de tipo ): Almacena datos de tipo caracter empleando sólo la cantidad necesaria aún cuando la caracter empleando sólo la cantidad necesaria aún cuando la longitud máxima sea mayor. longitud máxima sea mayor.

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

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

hay_error hay_error BOOLEANBOOLEAN; ;

DATEDATE ( (FechaFecha): Almacena datos de tipo fecha. Las fechas se almacenan ): Almacena datos de tipo fecha. Las fechas se almacenan internamente como datos numéricos, por lo que es posible realizar internamente como datos numéricos, por lo que es posible realizar operaciones aritméticas con ellas. operaciones aritméticas con ellas.

fecha_inicio fecha_inicio DATEDATE; ;

11

Page 12: Curso PL/SQL

Tipos de datos en PL/SQLTipos de datos en PL/SQL

Un Un atributo de tipoatributo de tipo PL/SQL es un modificador que PL/SQL es un modificador que puede ser usado para obtener información de un puede ser usado para obtener información de un objeto de la base de datos. objeto de la base de datos.

El atributo El atributo %TYPE%TYPE permite conocer el tipo de una permite conocer el tipo de una variable, constante o campo de la base de datos. variable, constante o campo de la base de datos.

El atributo El atributo %ROWTYPE %ROWTYPE permite obtener los tipos permite obtener los tipos de todos los campos de una tabla de la base de de todos los campos de una tabla de la base de datos, de una vista o de un cursor. datos, de una vista o de un cursor.

PL/SQL también permite la creación de tipos PL/SQL también permite la creación de tipos personalizados (registros) y colecciones (tablas de personalizados (registros) y colecciones (tablas de PL/SQL), que veremos más adelante.PL/SQL), que veremos más adelante.

12

Page 13: Curso PL/SQL

Otros tipos de datos en Otros tipos de datos en PL/SQLPL/SQL

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

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

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

13

Page 14: Curso PL/SQL

Otros tipos de datos en Otros tipos de datos en PL/SQLPL/SQL

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

real smallint char (tamaño) real smallint char (tamaño) Hasta 32767 bytes en Hasta 32767 bytes en PL/SQL. Hasta 2000 bytes en Oracle 9i. Donde PL/SQL. Hasta 2000 bytes en Oracle 9i. Donde tamañotamaño es el número de caracteres a almacenar. Son cadenas es el número de caracteres a almacenar. Son cadenas de ancho fijo. Se rellena con espacios.de ancho fijo. Se rellena con espacios.

varchar2 (tamaño)varchar2 (tamaño) Hasta 32767 bytes en PL/SQL. Hasta 32767 bytes en PL/SQL. Hasta 4000 bytes en Oracle 9i.Hasta 4000 bytes en Oracle 9i.Donde Donde tamañotamaño es el número de caracteres a almacenar. es el número de caracteres a almacenar. Son cadenas de ancho variable.Son cadenas de ancho variable.

14

Page 15: Curso PL/SQL

Otros tipos de datos en Otros tipos de datos en PL/SQLPL/SQL

longlong Hasta 2 gigabytes. Son cadenas de ancho variable.Hasta 2 gigabytes. Son cadenas de ancho variable.

raw raw Hasta 32767 bytes en PL/SQL. Hasta 2000 bytes en Hasta 32767 bytes en PL/SQL. Hasta 2000 bytes en Oracle 9i.Oracle 9i.Son cadenas binarias de ancho variable.Son cadenas binarias de ancho variable.

long raw long raw Hasta 2 gigabytes. Son cadenas binarias de ancho Hasta 2 gigabytes. Son cadenas binarias de ancho variable.variable.

datedate Una fecha entre el 1 de Enero de 4712 A.C. y el 31 de Una fecha entre el 1 de Enero de 4712 A.C. y el 31 de Diciembre de 9999 D.C.Diciembre de 9999 D.C.

timestamp (timestamp (fractional seconds precisionfractional seconds precision)) fractional fractional seconds precisionseconds precision debe ser un número entre 0 y 9. (El debe ser un número entre 0 y 9. (El valor por defecto es 6) Incluye año, mes día, hora, minutos y valor por defecto es 6) Incluye año, mes día, hora, minutos y segundos. segundos. Por ejemplo:Por ejemplo: timestamp(6) timestamp(6)

15

Page 16: Curso PL/SQL

Otros tipos de datos en Otros tipos de datos en PL/SQLPL/SQL

timestamp (timestamp (fractional seconds precisionfractional seconds precision) with ) with time zonetime zonefractional seconds precisionfractional seconds precision debe ser un número debe ser un número entre 0 y 9. (El valor por defecto es 6) Incluye año, entre 0 y 9. (El valor por defecto es 6) Incluye año, mes día, hora, minutos y segundos; con un valor de mes día, hora, minutos y segundos; con un valor de desplazamiento de zona horaria. desplazamiento de zona horaria. Ejemplo:Ejemplo: timestamp(5) with time zone timestamp(5) with time zone

timestamp (timestamp (fractional seconds precisionfractional seconds precision) with ) with local time zonelocal time zonefractional seconds precisionfractional seconds precision debe ser un número debe ser un número entre 0 y 9. (El valor por defecto es 6) Incluye año, entre 0 y 9. (El valor por defecto es 6) Incluye año, mes día, hora, minutos y segundos; con una zona mes día, hora, minutos y segundos; con una zona horaria expresada como la zona horaria actual. horaria expresada como la zona horaria actual. Ejemplo:Ejemplo: timestamp(4) with local time zone timestamp(4) with local time zone

16

Page 17: Curso PL/SQL

Otros tipos de datos en Otros tipos de datos en PL/SQLPL/SQL

interval year (interval year (year precisionyear precision) to month) to monthyear precisionyear precision debe ser un número entre 0 y 9. (El debe ser un número entre 0 y 9. (El valor por defecto es 2) Período de tiempo valor por defecto es 2) Período de tiempo almacenado en años y meses. almacenado en años y meses. Ejemplo:Ejemplo: interval year(4) to month interval year(4) to month

interval day (interval day (day precisionday precision) to second ) to second ((fractional seconds precisionfractional seconds precision) ) day precisionday precision debe ser un número entre 0 y 9. (El valor por debe ser un número entre 0 y 9. (El valor por defecto es 2) defecto es 2) fractional seconds precisionfractional seconds precision debe debe ser un número entre 0 y 9. (El valor por defecto es ser un número entre 0 y 9. (El valor por defecto es 6) Incluye año, mes día, hora, minutos y segundos.6) Incluye año, mes día, hora, minutos y segundos.Ejemplo:Ejemplo: interval day(2) to second(6) interval day(2) to second(6)

17

Page 18: Curso PL/SQL

Otros tipos de datos en Otros tipos de datos en PL/SQLPL/SQL

rowid rowid El formato del campo rowid es: El formato del campo rowid es: BBBBBBB.RRRR.FFFFF donde BBBBBBB es el BBBBBBB.RRRR.FFFFF donde BBBBBBB es el bloque en el fichero de la base de datos; RRRR es bloque en el fichero de la base de datos; RRRR es la fila del bloque; FFFFF es el fichero de la base de la fila del bloque; FFFFF es el fichero de la base de datos.datos.Contiene datos binarios de ancho fijo. Cada Contiene datos binarios de ancho fijo. Cada registro de la base de datos tiene una dirección registro de la base de datos tiene una dirección física o rowid.física o rowid.

urowid [tamaño]urowid [tamaño] Hasta 2000 bytes. Rowid Hasta 2000 bytes. Rowid universal. Donde universal. Donde tamañotamaño es opcional. es opcional.

booleanbooleanVálido en PLSQL, este tipo de datos no Válido en PLSQL, este tipo de datos no existe en Oracle 9i.existe en Oracle 9i.

18

Page 19: Curso PL/SQL

Otros tipos de datos en Otros tipos de datos en PL/SQLPL/SQL

nchar (tamaño)nchar (tamaño) Hasta 32767 bytes en PLSQL. Hasta 32767 bytes en PLSQL. Hasta 2000 bytes en Oracle 9i. Donde Hasta 2000 bytes en Oracle 9i. Donde tamañotamaño es es el número de caracteres a almacenar. Cadena NLS el número de caracteres a almacenar. Cadena NLS de ancho fijo.de ancho fijo.

nvarchar2 (tamaño)nvarchar2 (tamaño) Hasta 32767 bytes en Hasta 32767 bytes en PLSQL. Hasta 4000 bytes en Oracle 9i.Donde PLSQL. Hasta 4000 bytes en Oracle 9i.Donde tamañotamaño es el número de caracteres a almacenar. es el número de caracteres a almacenar. Cadena NLS de ancho variable.Cadena NLS de ancho variable.

bfilebfile Hasta 4 gigabytes. Localizadores de archivo Hasta 4 gigabytes. Localizadores de archivo apuntan a un objeto binario de sólo lectura fuera apuntan a un objeto binario de sólo lectura fuera de la base de datos.de la base de datos.

19

Page 20: Curso PL/SQL

Otros tipos de datos en Otros tipos de datos en PL/SQLPL/SQL

blobblob Hasta 4 gigabytes. Localizadores LOB Hasta 4 gigabytes. Localizadores LOB apuntan a un gran objeto binario dentro de la base apuntan a un gran objeto binario dentro de la base de datos.de datos.

clobclob Hasta 4 gigabytes. Localizadores LOB Hasta 4 gigabytes. Localizadores LOB apuntan a un gran objeto de caracteres dentro de apuntan a un gran objeto de caracteres dentro de la base de datos.la base de datos.

nclobnclob Hasta 4 gigabytes. Localizadores LOB Hasta 4 gigabytes. Localizadores LOB apuntan a un gran objeto NLS de caracteres dentro apuntan a un gran objeto NLS de caracteres dentro de la base de datos.de la base de datos.

20

Page 21: Curso PL/SQL

Operadores en PL/SQLOperadores en PL/SQL

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

Operadores aritméticosOperadores aritméticos+ (suma) + (suma) - (resta) - (resta) * (multiplicación)* (multiplicación)/ (división) / (división) ** (exponente)** (exponente)

Operadores relacionales o de Operadores relacionales o de comparacióncomparación

= (igual a) = (igual a) <> (distinto de) <> (distinto de) < (menor que) < (menor que) > (mayor que) > (mayor que) >= (mayor o igual a) >= (mayor o igual a) <= (menor o igual a)<= (menor o igual a)

Operadores lógicosOperadores lógicosAND (y lógico)AND (y lógico)NOT (negacion)NOT (negacion)OR   (o lógico)OR   (o lógico)

Operador de concatenaciónOperador de concatenación||||

21

Page 22: Curso PL/SQL

Estructuras de control Estructuras de control PL/SQL PL/SQL

22

Page 23: Curso PL/SQL

Estructuras de control de Estructuras de control de flujoflujo

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

IFIF (expresión) (expresión) THENTHEN

-- Instrucciones -- Instrucciones

ELSIFELSIF (expresión) (expresión) THENTHEN

-- Instrucciones -- Instrucciones

ELSEELSE

-- Instrucciones -- Instrucciones

END IFEND IF;   ;  

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

23

Page 24: Curso PL/SQL

Sentencia GOTO Sentencia GOTO

PL/SQL dispone de la sentencia GOTO. La PL/SQL dispone de la sentencia GOTO. La sentencia GOTO desvía el flujo de ejecución a una sentencia GOTO desvía el flujo de ejecución a una determinada etiqueta.determinada etiqueta.En PL/SQL las etiquetas se indican del siguiente En PL/SQL las etiquetas se indican del siguiente modo: modo: << << etiqueta etiqueta >> Ejemplo:>> Ejemplo:

DECLAREDECLARE  flag   flag NUMBERNUMBER;;BEGINBEGIN  flag :=1;  flag :=1;    IFIF (flag = 1) (flag = 1) THENTHEN          GOTOGOTO paso2;     paso2;         ENDEND IFIF;;<<paso1>><<paso1>>         dbms_output.put_line('Ejecución de paso 1');         dbms_output.put_line('Ejecución de paso 1');<<paso2>><<paso2>>         dbms_output.put_line('Ejecución de paso 2');         dbms_output.put_line('Ejecución de paso 2');ENDEND;;

24

Page 25: Curso PL/SQL

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

LOOP LOOP WHILE WHILE FORFOR

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

LOOPLOOP -- Instrucciones -- Instrucciones IFIF (expresión) (expresión) THENTHEN

-- Instrucciones -- Instrucciones EXITEXIT; ;

END IFEND IF; ; END LOOPEND LOOP;    ;   

25

Page 26: Curso PL/SQL

BuclesBuclesEl bucle El bucle WHILE, WHILE, se repite mientras que se cumpla se repite mientras que se cumpla expresiónexpresión..

WHILEWHILE (expresión) (expresión) LOOPLOOP -- Instrucciones -- Instrucciones

END LOOPEND LOOP;;

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

FORFOR contador contador ININ [ [REVERSEREVERSE] inicio..final ] inicio..final LOOPLOOP -- Instrucciones -- Instrucciones

END LOOPEND LOOP;    ;    

En el caso de especificar En el caso de especificar REVERSEREVERSE  el bucle recorre   el bucle recorre en sentido inverso.en sentido inverso.

26

Page 27: Curso PL/SQL

Bloques PL/SQLBloques PL/SQL

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

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

Bloques anónimosBloques anónimosSubprogramasSubprogramas

27

Page 28: Curso PL/SQL

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

La sección declarativa en donde se declaran todas La sección declarativa en donde se declaran todas las constantes y variables que se van a utilizar en las constantes y variables que se van a utilizar en la ejecución del bloque.la ejecución del bloque.

La sección de ejecución que incluye las La sección de ejecución que incluye las instrucciones a ejecutar en el bloque PL/SQL.instrucciones a ejecutar en el bloque PL/SQL.

La sección de excepciones en donde se definen los La sección de excepciones en donde se definen los manejadores de errores que soportará el bloque manejadores de errores que soportará el bloque PL/SQL.PL/SQL.

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

28

Page 29: Curso PL/SQL

Estructura de un BloqueEstructura de un Bloque[ declare | is | as ][ declare | is | as ]

/*Parte declarativa*/ /*Parte declarativa*/ beginbegin

/*Parte de ejecucion*//*Parte de ejecucion*/[ exception ][ exception ]

/*Parte de excepciones*//*Parte de excepciones*/end;end;   

De las anteriores partes, únicamente la sección de De las anteriores partes, únicamente la sección de ejecución es obligatoria, que quedaría delimitada entre ejecución es obligatoria, que quedaría delimitada entre las cláusulas las cláusulas BEGINBEGIN y y ENDEND. .

Veamos un ejemplo de bloque PL/SQL muy genérico. Se Veamos un ejemplo de bloque PL/SQL muy genérico. Se trata de un bloque anónimo, es decir no lo identifica trata de un bloque anónimo, es decir no lo identifica ningún nombre. Los bloques anónimos identifican su ningún nombre. Los bloques anónimos identifican su parte declarativa con la palabra reservada parte declarativa con la palabra reservada DECLAREDECLARE..

29

Page 30: Curso PL/SQL

Estructura de un BloqueEstructura de un BloqueDECLAREDECLARE

/*Parte declarativa*/ /*Parte declarativa*/ nombre_variable nombre_variable DATEDATE;;

BEGINBEGIN/* Parte de ejecucion/* Parte de ejecucion* Este código asigna el valor de la columna* Este código asigna el valor de la columna* "nombre_columna"* "nombre_columna"* a la variable identificada por "nombre_variable"* a la variable identificada por "nombre_variable"*/ */ SELECTSELECT SYSDATE SYSDATEINTOINTO nombre_variable nombre_variableFROMFROM DUAL; DUAL;

EXCEPTIONEXCEPTION/*Parte de excepciones*//*Parte de excepciones*/WHEN OTHERS THENWHEN OTHERS THENdbms_output.put_line('Se ha producido un error');dbms_output.put_line('Se ha producido un error');

END;END;     

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

30

Page 31: Curso PL/SQL

Sección de Declaración de Sección de Declaración de VariablesVariables

En esta parte se declaran las variables que va a necesitar En esta parte se declaran las variables que va a necesitar nuestro programa. Una variable se declara asignándole un nuestro programa. Una variable se declara asignándole un nombre o identificador seguido del tipo de dato que puede nombre o identificador seguido del tipo de dato que puede contener. Se declaran cursores (de gran utilidad para la contener. Se declaran cursores (de gran utilidad para la consulta de datos) y excepciones definidas por el usuario. consulta de datos) y excepciones definidas por el usuario. También podemos especificar si se trata de una constante, si También podemos especificar si se trata de una constante, si puede contener valor nulo y asignar un valor inicial.puede contener valor nulo y asignar un valor inicial.La sintaxis genérica para la declaración de constantes y La sintaxis genérica para la declaración de constantes y variables es:variables es:

nombre_variable [nombre_variable [CONSTANTCONSTANT] ] <tipo_dato><tipo_dato> [ [NOT NULLNOT NULL][:=valor_inicial]  ][:=valor_inicial]  

donde:donde:tipo_dato: es el tipo de dato que va a poder almacenar la tipo_dato: es el tipo de dato que va a poder almacenar la variable, este puede ser cualquiera de los tipos soportados variable, este puede ser cualquiera de los tipos soportados por ORACLE; es decir por ORACLE; es decir NUMBERNUMBER, , DATEDATE, , CHARCHAR, , VARCHAR, VARCHAR2,VARCHAR, VARCHAR2, BOOLEAN... BOOLEAN...

31

Page 32: Curso PL/SQL

Sección de Declaración de Sección de Declaración de VariablesVariables

Además para algunos tipos de datos (NUMBER y Además para algunos tipos de datos (NUMBER y VARCHAR) podemos especificar la longitud.VARCHAR) podemos especificar la longitud.La cláusula CONSTANT indica la definición de una La cláusula CONSTANT indica la definición de una constante cuyo valor no puede ser modificado. Se constante cuyo valor no puede ser modificado. Se debe incluir la inicialización de la constante en su debe incluir la inicialización de la constante en su declaración.declaración.La cláusula NOT NULL impide que a una variable se La cláusula NOT NULL impide que a una variable se le asigne el valor nulo, y por tanto debe inicializarse le asigne el valor nulo, y por tanto debe inicializarse a un valor diferente de NULL.a un valor diferente de NULL.

Las variables que no son inicializadas toman el valor Las variables que no son inicializadas toman el valor inicial NULL.inicial NULL.La inicialización puede incluir cualquier expresión La inicialización puede incluir cualquier expresión legal de PL/SQL, que lógicamente debe corresponder legal de PL/SQL, que lógicamente debe corresponder con el tipo del identificador definido.con el tipo del identificador definido.

32

Page 33: Curso PL/SQL

Sección de Declaración de Sección de Declaración de VariablesVariables

Los tipos escalares incluyen los definidos en SQL más los Los tipos escalares incluyen los definidos en SQL más los tipos VARCHAR y BOOLEAN. Este último puede tomar los tipos VARCHAR y BOOLEAN. Este último puede tomar los valores TRUE, FALSE y NULL, y se suele utilizar para valores TRUE, FALSE y NULL, y se suele utilizar para almacenar el resultado de alguna operación almacenar el resultado de alguna operación lógica. VARCHAR es un sinónimo de CHAR.lógica. VARCHAR es un sinónimo de CHAR.También es posible definir el tipo de una variable o También es posible definir el tipo de una variable o constante, dependiendo del tipo de otro identificador, constante, dependiendo del tipo de otro identificador, mediante la utilización de las cláusulas mediante la utilización de las cláusulas %TYPE%TYPE y y %ROWTYPE%ROWTYPE. . Mediante la primera opción se define una variable o Mediante la primera opción se define una variable o constante escalar, y con la segunda se define una variable constante escalar, y con la segunda se define una variable fila, donde identificador puede ser otra variable fila o una fila, donde identificador puede ser otra variable fila o una tabla. tabla. Habitualmente se utiliza Habitualmente se utiliza %TYPE%TYPE para definir la variable para definir la variable del mismo tipo que tenga definido un campo en una tabla del mismo tipo que tenga definido un campo en una tabla de la base de datos, mientras quede la base de datos, mientras que %ROWTYPE %ROWTYPE se utiliza se utiliza para declarar variables utilizando cursores.para declarar variables utilizando cursores.

33

Page 34: Curso PL/SQL

EjemplosEjemplos

Page 35: Curso PL/SQL

    Estructura de un bloque Estructura de un bloque anónimoanónimoDECLAREDECLARE

/* Se declara la variable de tipo VARCHAR2(15) identificada por v_location /* Se declara la variable de tipo VARCHAR2(15) identificada por v_location y se le asigna el valor "Granada“ */y se le asigna el valor "Granada“ */

v_location v_location VARCHAR2VARCHAR2(15) := ’Granada’;  (15) := ’Granada’; 

/* Se declara la constante de tipo NUMBER identificada por PI y se le /* Se declara la constante de tipo NUMBER identificada por PI y se le asigna el valor 3.1416*/asigna el valor 3.1416*/

PI PI CONSTANT NUMBERCONSTANT NUMBER := 3.1416; := 3.1416; /* Se declara la variable del mismo tipo que tenga el campo nombre de la /* Se declara la variable del mismo tipo que tenga el campo nombre de la

tabla tabla_empleados identificada por v_nombre y no se le asigna tabla tabla_empleados identificada por v_nombre y no se le asigna ningún valor */ningún valor */

v_nombre tabla_empleados.nombrev_nombre tabla_empleados.nombre%TYPE%TYPE;;

/* Se declara la variable del tipo registro correspondiente a un supuesto /* Se declara la variable del tipo registro correspondiente a un supuesto cursor, llamado micursor, identificada por reg_datos */cursor, llamado micursor, identificada por reg_datos */

reg_datos micursorreg_datos micursor%ROWTYPE%ROWTYPE;;BEGINBEGIN

/*Parte de ejecucion*//*Parte de ejecucion*/EXCEPTIONEXCEPTION

/*Parte de excepciones*//*Parte de excepciones*/END;END;

35

Page 36: Curso PL/SQL

Estructura de un Estructura de un subprogramasubprograma

CREATE PROCEDURE simple_procedure ISCREATE PROCEDURE simple_procedure IS/* Se declara la variable de tipo VARCHAR2(15) identificada por /* Se declara la variable de tipo VARCHAR2(15) identificada por

v_location y se le asigna el valor "Granada“ */v_location y se le asigna el valor "Granada“ */

v_location v_location VARCHAR2VARCHAR2(15) := ’Granada’;  (15) := ’Granada’; 

/* Se declara la constante de tipo NUMBER identificada por PI y se le /* Se declara la constante de tipo NUMBER identificada por PI y se le asigna el valor 3.1416 */asigna el valor 3.1416 */

PI PI CONSTANT NUMBERCONSTANT NUMBER := 3.1416; := 3.1416;

/* Se declara la variable del mismo tipo que tenga el campo nombre de la /* Se declara la variable del mismo tipo que tenga el campo nombre de la tabla tabla_empleados identificada por v_nombre y no se le asigna tabla tabla_empleados identificada por v_nombre y no se le asigna ningún valor */ningún valor */

v_nombre tabla_empleados.nombrev_nombre tabla_empleados.nombre%TYPE%TYPE;;

/* Se declara la variable del tipo registro correspondiente a un /* Se declara la variable del tipo registro correspondiente a un supuesto cursor, llamado micursor, identificada por reg_datos */supuesto cursor, llamado micursor, identificada por reg_datos */

reg_datos micursorreg_datos micursor%ROWTYPE%ROWTYPE;;BEGINBEGIN

/*Parte de ejecucion*//*Parte de ejecucion*/EXCEPTIONEXCEPTION

/*Parte de excepciones*//*Parte de excepciones*/END;END; 36

Page 37: Curso PL/SQL

Cursores en Cursores en PL/SQLPL/SQL

37

Page 38: Curso PL/SQL

Introducción a cursores Introducción a cursores PL/SQLPL/SQL

PL/SQL utiliza cursores para gestionar las instrucciones PL/SQL utiliza cursores para gestionar las instrucciones SELECTSELECT. . Un cursor es un conjunto de registros devuelto por una instrucción Un cursor es un conjunto de registros devuelto por una instrucción SQL. Técnicamente los cursores son fragmentos de memoria que SQL. Técnicamente los cursores son fragmentos de memoria que son reservados para procesar los resultados de una consulta son reservados para procesar los resultados de una consulta SELECTSELECT. Podemos distinguir dos tipos de cursores:. Podemos distinguir dos tipos de cursores:

Cursores implícitosCursores implícitos.. Este tipo de cursores se utiliza para Este tipo de cursores se utiliza para operaciones operaciones SELECT INTOSELECT INTO; se usan cuando la consulta devuelve un ; se usan cuando la consulta devuelve un único registro. único registro.

Cursores explícitosCursores explícitos.. Son los cursores que son declarados y Son los cursores que son declarados y controlados por el programador. Se utilizan cuando la consulta controlados por el programador. Se utilizan cuando la consulta devuelve un conjunto de registros. Ocasionalmente también se devuelve un conjunto de registros. Ocasionalmente también se utilizan en consultas que devuelven un único registro por razones de utilizan en consultas que devuelven un único registro por razones de eficiencia. Son más rápidos.eficiencia. Son más rápidos.

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

38

Page 39: Curso PL/SQL

Introducción a cursores Introducción a cursores PL/SQLPL/SQL

Este ejemplo declara un cursor explícito:Este ejemplo declara un cursor explícito:

declaredeclare cursorcursor c_paises c_paises isisSELECTSELECT CO_PAIS, DESCRIPCION CO_PAIS, DESCRIPCIONFROMFROM PAISES; PAISES;

beginbegin/* Sentencias del bloque ...*//* Sentencias del bloque ...*/

endend;   ;  

Para procesar instrucciones SELECT que Para procesar instrucciones SELECT que devuelvan más de una fila, son necesarios cursores devuelvan más de una fila, son necesarios cursores explícitos combinados con un estructura de bloque.explícitos combinados con un estructura de bloque.Un cursor admite el uso de parámetros. Los Un cursor admite el uso de parámetros. Los parámetros deben declararse junto con el cursor.parámetros deben declararse junto con el cursor.

39

Page 40: Curso PL/SQL

Introducción a cursores Introducción a cursores PL/SQLPL/SQL

El siguiente ejemplo muestra la declaración El siguiente ejemplo muestra la declaración de un cursor (c_paises) con un parámetro de un cursor (c_paises) con un parámetro (p_continente):(p_continente):

declaredeclare cursorcursor c_paises (p_continente c_paises (p_continente IN VARCHAR2IN VARCHAR2) ) isisSELECTSELECT CO_PAIS, DESCRIPCION CO_PAIS, DESCRIPCIONFROMFROM PAISES PAISESWHEREWHERE CONTINENTE = p_continente; CONTINENTE = p_continente;

beginbegin/* Sentencias del bloque ...*//* Sentencias del bloque ...*/

endend; ;   

40

Page 41: Curso PL/SQL

Introducción a cursores Introducción a cursores PL/SQLPL/SQL

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

                                                                                               

Fases para procesar una instrucción SQL

41

Page 42: Curso PL/SQL

Cursores ImplícitosCursores Implícitos Los cursores implícitos se utilizan para realizar consultas Los cursores implícitos se utilizan para realizar consultas SELECT SELECT que devuelven un único registro.que devuelven un único registro.Deben tenerse en cuenta los siguientes puntos cuando se Deben tenerse en cuenta los siguientes puntos cuando se utilizan cursores implícitos:utilizan cursores implícitos:

Con cada cursor implícito debe existir la palabra clave Con cada cursor implícito debe existir la palabra clave INTOINTO. .

Las variables que reciben los datos devueltos por el cursor tienen Las variables que reciben los datos devueltos por el cursor tienen que contener el mismo tipo de dato que las columnas de la tabla. que contener el mismo tipo de dato que las columnas de la tabla.

Los cursores implícitos solo pueden devolver una única fila. En Los cursores implícitos solo pueden devolver una única fila. En caso de que se devuelva más de una fila (o ninguna fila) se caso de que se devuelva más de una fila (o ninguna fila) se producirá una excepción. producirá una excepción.

No se preocupe si aún no sabe que es una excepción, le No se preocupe si aún no sabe que es una excepción, le valdrá conocer que es el medio por el que PL/SQL gestiona valdrá conocer que es el medio por el que PL/SQL gestiona los errores.los errores.

42

Page 43: Curso PL/SQL

Cursores ImplícitosCursores Implícitos

El siguiente ejemplo muestra un cursor El siguiente ejemplo muestra un cursor implícito:implícito:

declaredeclarevdescripcion vdescripcion VARCHAR2VARCHAR2(50);(50);

beginbeginSELECTSELECT DESCRIPCION DESCRIPCION INTOINTO vdescripcion vdescripcionfromfrom PAISES PAISESWHEREWHERE CO_PAIS = 'ESP'; CO_PAIS = 'ESP';dbms_output.put_line('La lectura del cursor es: ' || dbms_output.put_line('La lectura del cursor es: ' ||

vdescripcion);vdescripcion);endend;    ;   

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

La lectura del cursor es: ECUADORLa lectura del cursor es: ECUADOR

43

Page 44: Curso PL/SQL

Excepciones asociadas a los Excepciones asociadas a los cursores implícitoscursores implícitos

Los cursores implícitos sólo pueden devolver una Los cursores implícitos sólo pueden devolver una fila, por lo que pueden producirse determinadas fila, por lo que pueden producirse determinadas excepciones. Las más comunes que se pueden excepciones. Las más comunes que se pueden encontrar son encontrar son no_data_found no_data_found y y too_many_rowstoo_many_rows. .

NO_DATA_FOUND NO_DATA_FOUND Se produce cuando una Se produce cuando una sentencia SELECT intenta recuperar datos pero sentencia SELECT intenta recuperar datos pero ninguna fila satisface sus condiciones. Es decir, ninguna fila satisface sus condiciones. Es decir, cuando cuando "no hay datos“"no hay datos“

TOO_MANY_ROWSTOO_MANY_ROWS Dado que cada cursor Dado que cada cursor implícito sólo es capaz de recuperar una fila, esta implícito sólo es capaz de recuperar una fila, esta excepción detecta la existencia de más de una fila.excepción detecta la existencia de más de una fila.

44

Page 45: Curso PL/SQL

Cursores Explícitos en Cursores Explícitos en PL/SQLPL/SQL

Los cursores explícitos se emplean para realizar consultas Los cursores explícitos se emplean para realizar consultas SELECTSELECT que pueden devolver cero o más filas. Para trabajar con que pueden devolver cero o más filas. Para trabajar con un cursor explícito necesitamos realizar las siguientes tareas:un cursor explícito necesitamos realizar las siguientes tareas:

Declarar el cursor. Declarar el cursor. Abrir el cursor con la instrucción Abrir el cursor con la instrucción OPENOPEN. . Leer los datos del cursor con la instrucción Leer los datos del cursor con la instrucción FETCHFETCH. . Cerrar el cursor y liberar los recursos con la instrucción Cerrar el cursor y liberar los recursos con la instrucción CLOSECLOSE..

Para declarar un cursor debemos emplear la siguiente sintaxis:Para declarar un cursor debemos emplear la siguiente sintaxis:

CURSORCURSOR nombre_cursornombre_cursor ISIS instrucción_SELECTinstrucción_SELECT         

También debemos declarar los posibles parámetros que requiera También debemos declarar los posibles parámetros que requiera el cursor:el cursor:

CURSORCURSOR nombre_cursornombre_cursor(param1 tipo1, ..., paramN tipoN)(param1 tipo1, ..., paramN tipoN) ISIS instrucción_SELECTinstrucción_SELECT        

45

Page 46: Curso PL/SQL

Cursores Explícitos en Cursores Explícitos en PL/SQLPL/SQL

Para abrir el cursor:Para abrir el cursor:

OPEN OPEN nombre_cursornombre_cursor; ;

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

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

Para recuperar los datos en variables PL/SQL.Para recuperar los datos en variables PL/SQL.

FETCHFETCH nombre_cursornombre_cursor INTOINTO lista_variables;-- o bien ... lista_variables;-- o bien ...FETCHFETCH nombre_cursornombre_cursor INTOINTO registro_PL/SQL;    registro_PL/SQL;   

Para cerrar el cursor:Para cerrar el cursor:

CLOSE nombre_cursorCLOSE nombre_cursor;   ;   

46

Page 47: Curso PL/SQL

Cursores Explícitos en Cursores Explícitos en PL/SQLPL/SQL

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

DECLAREDECLARE     CURSORCURSOR cpaises cpaises ISIS    SELECTSELECT CO_PAIS, DESCRIPCION, CONTINENTE CO_PAIS, DESCRIPCION, CONTINENTE     FROMFROM PAISES; PAISES;

  co_pais   co_pais VARCHAR2VARCHAR2(3);(3);  descripcion   descripcion VARCHAR2VARCHAR2(50);(50);  continente    continente  VARCHAR2VARCHAR2(25);(25);BEGINBEGIN    OPENOPEN cpaises; cpaises;    FETCHFETCH cpaises cpaises INTOINTO co_pais,descripcion,continente; co_pais,descripcion,continente;    CLOSECLOSE cpaises; cpaises;ENDEND;    ;   

47

Page 48: Curso PL/SQL

Cursores Explícitos en Cursores Explícitos en PL/SQLPL/SQL

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

DECLARE DECLARE     CURSORCURSOR cpaises cpaises ISIS    SELECT SELECT CO_PAIS, DESCRIPCION, CONTINENTE CO_PAIS, DESCRIPCION, CONTINENTE     FROMFROM PAISES; PAISES;      registro cpaises%  registro cpaises%ROWTYPEROWTYPE;;BEGINBEGIN    OPENOPEN cpaises; cpaises;    FETCHFETCH cpaises cpaises

INTOINTO registro; registro;    CLOSECLOSE cpaises; cpaises;ENDEND;    ;    

48

Page 49: Curso PL/SQL

Cursores Explícitos en Cursores Explícitos en PL/SQLPL/SQL

El mismo ejemplo, pero utilizando parámetros:El mismo ejemplo, pero utilizando parámetros:

DECLARE DECLARE     CURSORCURSOR cpaises (p_continente cpaises (p_continente VARCHAR2VARCHAR2) ) ISIS    SELECT SELECT CO_PAIS, DESCRIPCION, CONTINENTE CO_PAIS, DESCRIPCION, CONTINENTE     FROMFROM PAISES PAISESWHERE WHERE CONTINENTE = p_continente;CONTINENTE = p_continente;      registro cpaises%  registro cpaises%ROWTYPEROWTYPE;;BEGINBEGIN    OPENOPEN cpaises(‘AMERICA'); cpaises(‘AMERICA');    FETCHFETCH cpaises cpaises INTOINTO registro; registro;    CLOSECLOSE cpaises; cpaises;ENDEND;      ;     

49

Page 50: Curso PL/SQL

ConsideracionesConsideraciones

Cuando trabajamos con cursores debemos Cuando trabajamos con cursores debemos considerar:considerar:

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

Cuando leemos un cursor debemos comprobar el Cuando leemos un cursor debemos comprobar el resultado de la lectura utilizando los atributos de los resultado de la lectura utilizando los atributos de los cursores. cursores.

Cuando se cierra el cursor, es ilegal tratar de Cuando se cierra el cursor, es ilegal tratar de usarlo. usarlo.

Es ilegal tratar de cerrar un cursor que ya está Es ilegal tratar de cerrar un cursor que ya está cerrado o no ha sido abiertocerrado o no ha sido abierto

50

Page 51: Curso PL/SQL

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

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

51

Atributo Antes de abrir

Al abrir

Durante la recuperación

Al finalizar

la recuperac

ió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 

Page 52: Curso PL/SQL

Manejo del cursorManejo del cursorPor medio de ciclo LOOP podemos iterar a través 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 Debe tenerse cuidado de agregar una condición para salir del bucle:bucle:Vamos a ver varias formas de iterar a través de un cursor. La Vamos a ver varias formas de iterar a través de un cursor. La primera es utilizando un bucle LOOP con una sentencia EXIT primera es utilizando un bucle LOOP con una sentencia EXIT condicionada:condicionada:

OPENOPEN nombre_cursor; nombre_cursor; LOOPLOOP FETCHFETCH nombre_cursor nombre_cursor INTOINTO lista_variables; lista_variables; EXITEXIT WHENWHEN nombre_cursor% nombre_cursor%NOTFOUNDNOTFOUND; ; /* Procesamiento de los registros recuperados */ /* Procesamiento de los registros recuperados */ END LOOPEND LOOP; ; CLOSECLOSE nombre_cursor; nombre_cursor;        

52

Page 53: Curso PL/SQL

Manejo del cursorManejo del cursorAplicada a nuestro ejemplo anterior:Aplicada a nuestro ejemplo anterior:

DECLAREDECLARE CURSORCURSOR cpaises cpaises ISIS SELECT SELECT CO_PAIS, DESCRIPCION, CONTINENTE CO_PAIS, DESCRIPCION, CONTINENTE FROM FROM PAISES;PAISES; co_pais co_pais VARCHAR2VARCHAR2(3);(3); descripcion descripcion VARCHAR2VARCHAR2(50);(50); continente continente VARCHAR2VARCHAR2(25);(25);BEGINBEGIN OPENOPEN cpaises; cpaises; LOOPLOOP FETCHFETCH cpaises cpaises

INTOINTO co_pais,descripcion,continente; co_pais,descripcion,continente; EXITEXIT WHENWHEN cpaises% cpaises%NOTFOUNDNOTFOUND;; dbms_output.put_line(descripcion); dbms_output.put_line(descripcion); ENDEND LOOPLOOP; ; CLOSECLOSE cpaises; cpaises;ENDEND;   ;   

Page 54: Curso PL/SQL

Manejo del cursorManejo del cursor

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

OPENOPEN nombre_cursor; nombre_cursor;

FETCHFETCH nombre_cursor nombre_cursor INTOINTO lista_variables; lista_variables; WHILEWHILE nombre_cursor% nombre_cursor%FOUNDFOUND LOOPLOOP /* Procesamiento de los registros /* Procesamiento de los registros recuperados */ recuperados */

FETCHFETCH nombre_cursor nombre_cursor INTOINTO lista_variables; lista_variables; END LOOPEND LOOP; ;

CLOSECLOSE nombre_cursor; nombre_cursor;  

54

Page 55: Curso PL/SQL

Manejo del cursorManejo del cursorDECLAREDECLARE

CURSORCURSOR cpaises cpaises ISISSELECT SELECT CO_PAIS, DESCRIPCION, CONTINENTE CO_PAIS, DESCRIPCION, CONTINENTE FROMFROM PAISES; PAISES;

co_pais co_pais VARCHAR2VARCHAR2(3);(3);descripcion descripcion VARCHAR2VARCHAR2(50);(50);continente continente VARCHAR2VARCHAR2(25);(25);

BEGINBEGINOPENOPEN cpaises; cpaises;FETCHFETCH cpaises cpaises INTOINTO co_pais,descripcion,continente; co_pais,descripcion,continente;WHILEWHILE cpaises% cpaises%foundfound LOOPLOOP dbms_output.put_line(descripcion); dbms_output.put_line(descripcion); FETCHFETCH cpaises cpaises INTOINTO co_pais,descripcion,continente; co_pais,descripcion,continente;ENDEND LOOPLOOP; ; CLOSECLOSE cpaises; cpaises;

ENDEND;;

Page 56: Curso PL/SQL

Manejo del cursorManejo del cursorPor último podemos usar un bucle FOR LOOP. Es la Por último podemos usar un bucle FOR LOOP. Es la forma más corta ya que el cursor implícitamente forma más corta ya que el cursor implícitamente ejecuta las instrucciones OPEN, FECTH y CLOSE.ejecuta las instrucciones OPEN, FECTH y CLOSE.

FORFOR variable variable ININ nombre_cursor nombre_cursor LOOPLOOP /* Procesamiento de los registros/* Procesamiento de los registros recuperados */ recuperados */ END LOOPEND LOOP;;  BEGINBEGIN FOR REG IN (SELECT * FROM PAISES) FOR REG IN (SELECT * FROM PAISES) LOOP LOOP dbms_output.put_line(reg.descripcion); dbms_output.put_line(reg.descripcion); END LOOP; END LOOP;END;END;

56

Page 57: Curso PL/SQL

Cursores de Cursores de actualizaciónactualización

Declaración y utilización de cursores de actualización.Declaración y utilización de cursores de actualización.Los cursores de actualización se declaran igual que los cursores Los cursores de actualización se declaran igual que los cursores explícitos, añadieno explícitos, añadieno FOR UPDATEFOR UPDATE al final de la sentencia select. al final de la sentencia select.

CURSORCURSOR nombre_cursornombre_cursor ISIS instrucción_SELECTinstrucción_SELECT FOR UPDATE;FOR UPDATE;

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

UPDATEUPDATE <nombre_tabla><nombre_tabla> SET SET <campo_1><campo_1> = = <valor_1><valor_1> [, [,<campo_2> = <valor_2><campo_2> = <valor_2>]]WHERE CURRENT OFWHERE CURRENT OF <cursor_name>;<cursor_name>;

Cuando trabajamos con cursores de actualización debemos tener Cuando trabajamos con cursores de actualización debemos tener en cuenta que los cursores de actualización generan bloqueos en en cuenta que los cursores de actualización generan bloqueos en la base de datos.la base de datos.

57

Page 58: Curso PL/SQL

Cursores de Cursores de actualizaciónactualización

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

DECLAREDECLARE CURSORCURSOR cpaises cpaises ISIS selectselect CO_PAIS, DESCRIPCION, CONTINENTE CO_PAIS, DESCRIPCION, CONTINENTE fromfrom paises paises FOR UPDATEFOR UPDATE;; co_pais co_pais VARCHAR2VARCHAR2(3);(3); descripcion descripcion VARCHAR2VARCHAR2(50);(50);continente continente VARCHAR2VARCHAR2(25);(25);BEGINBEGINOPENOPEN cpaises; cpaises;FETCHFETCH cpaises cpaises INTOINTO co_pais,descripcion,continente; co_pais,descripcion,continente;WHILEWHILE cpaises cpaises%found%foundLOOPLOOP UPDATEUPDATE PAISES PAISES SETSET CONTINENTE = CONTINENTE || '.' CONTINENTE = CONTINENTE || '.'WHERE CURRENT OFWHERE CURRENT OF cpaises; cpaises;

FETCHFETCH cpaises cpaises INTOINTO co_pais,descripcion,continente; co_pais,descripcion,continente;ENDEND LOOPLOOP; ; CLOSECLOSE cpaises; cpaises;COMMIT;COMMIT;

ENDEND;  ;     

58

Page 59: Curso PL/SQL

Excepciones en PL/SQLExcepciones en PL/SQLManejo de excepciones.- En PL/SQL una advertencia o Manejo de excepciones.- En PL/SQL una advertencia o condición de error es llamada una excepción.condición de error es llamada una excepción.Las excepciones se controlan dentro de su propio bloque. La Las excepciones se controlan dentro de su propio bloque. La estructura de bloque de una excepción se muestra a estructura de bloque de una excepción se muestra a continuación.continuación.

DECLAREDECLARE -- Declaraciones -- DeclaracionesBEGINBEGIN  -- Ejecucion  -- EjecucionEXCEPTIONEXCEPTION  -- Excepcion  -- ExcepcionENDEND;;        

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

59

Page 60: Curso PL/SQL

Excepciones en PL/SQLExcepciones en PL/SQLEl siguiente ejemplo muestra un bloque de excepciones que El siguiente ejemplo muestra un bloque de excepciones que captura las excepciones captura las excepciones NO_DATA_FOUND NO_DATA_FOUND y y ZERO_DIVIDE. ZERO_DIVIDE. Cualquier otra excepcion será capturada en el bloque Cualquier otra excepcion será capturada en el bloque WHEN WHEN OTHERSOTHERS..

DECLAREDECLARE  -- Declaraciones  -- DeclaracionesBEGINBEGIN  -- Ejecucion  -- EjecucionEXCEPTIONEXCEPTIONWHEN NO_DATA_FOUND THENWHEN NO_DATA_FOUND THEN  -- Se ejecuta cuando ocurre una excepcion NO_DATA_FOUND  -- Se ejecuta cuando ocurre una excepcion NO_DATA_FOUNDWHEN ZERO_DIVIDE THENWHEN ZERO_DIVIDE THEN  -- Se ejecuta cuando ocurre una excepcion ZERO_DIVIDE  -- Se ejecuta cuando ocurre una excepcion ZERO_DIVIDEWHEN OTHERS THENWHEN OTHERS THEN  /* Se ejecuta cuando ocurre una excepcion de un tipo no  /* Se ejecuta cuando ocurre una excepcion de un tipo no tratado en los bloques anteriores */tratado en los bloques anteriores */ENDEND;    ;    

60

Page 61: Curso PL/SQL

Excepciones en PL/SQLExcepciones en PL/SQLComo ya hemos dicho cuando ocurre un error, se ejecuta el bloque Como ya hemos dicho cuando ocurre un error, se ejecuta el bloque EXCEPTIONEXCEPTION, transfiriéndose el control a las sentencias del bloque. , transfiriéndose el control a las sentencias del bloque. Una vez finalizada la ejecución del bloque de Una vez finalizada la ejecución del bloque de EXCEPTION EXCEPTION no se no se continua ejecutando el bloque anterior.continua ejecutando el bloque anterior.Si existe un bloque de excepcion apropiado para el tipo de excepción 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 se ejecuta dicho bloque. Si no existe un bloque de control de excepciones adecuado al tipo de excepcion se ejecutará el bloque de excepciones adecuado al tipo de excepcion se ejecutará el bloque de excepcion excepcion WHEN OTHERS WHEN OTHERS (si existe!). (si existe!). WHEN OTHERSWHEN OTHERS debe ser el debe ser el último manejador de excepciones.último manejador de excepciones.Las excepciones pueden ser definidas en forma interna o Las excepciones pueden ser definidas en forma interna o explícitamente por el usuario. Ejemplos de excepciones definidas en 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 forma interna son la división por cero y la falta de memoria en tiempo de ejecución. Estas mismas condiciones excepcionales tienen sus de ejecución. Estas mismas condiciones excepcionales tienen sus propios tipos y pueden ser referenciadas por ellos: propios tipos y pueden ser referenciadas por ellos: ZERO_DIVIDEZERO_DIVIDE y y STORAGE_ERRORSTORAGE_ERROR..Las excepciones definidas por el usuario deben ser alcanzadas Las excepciones definidas por el usuario deben ser alcanzadas explícitamente utilizando la sentencia explícitamente utilizando la sentencia RAISERAISE..Con las excepciones se pueden manejar los errores cómodamente sin Con las excepciones se pueden manejar los errores cómodamente sin necesidad de mantener múltiples chequeos por cada sentencia escrita. necesidad de mantener múltiples chequeos por cada sentencia escrita. También provee claridad en el código ya que permite mantener las También provee claridad en el código ya que permite mantener las rutinas correspondientes al tratamiento de los errores de forma rutinas correspondientes al tratamiento de los errores de forma separada de la lógica del negocio.separada de la lógica del negocio.

Page 62: Curso PL/SQL

Excepciones Excepciones predefinidas predefinidas 

PL/SQL proporciona un gran número de excepciones predefinidas PL/SQL proporciona un gran número de excepciones predefinidas que permiten controlar las condiciones de error más habituales. que permiten controlar las condiciones de error más habituales. Las excepciones predefinidas no necesitan ser declaradas. Las excepciones predefinidas no necesitan ser declaradas. Simplemente se utilizan cuando estas son lanzadas por algún Simplemente se utilizan cuando estas son lanzadas por algún error determinado.error determinado.La siguiente es la lista de las excepciones predeterminadas por La siguiente es la lista de las excepciones predeterminadas por PL/SQL y una breve descripción de cuándo son accionadas:PL/SQL y una breve descripción de cuándo son accionadas:SQLCODEACCESS_INTO_NULL: SQLCODEACCESS_INTO_NULL: El programa intentó asignar El programa intentó asignar valores a los atributos de un objeto no inicializado-6530valores a los atributos de un objeto no inicializado-6530COLLECTION_IS_NULL: COLLECTION_IS_NULL: El programa intentó asignar valores a El programa intentó asignar valores a una tabla anidada aún no inicializada-6531una tabla anidada aún no inicializada-6531CURSOR_ALREADY_OPEN: CURSOR_ALREADY_OPEN: El programa intentó abrir un El programa intentó abrir un cursor que ya se encontraba abierto. Recuerde que un cursor de cursor que ya se encontraba abierto. Recuerde que un cursor de ciclo FOR automáticamente lo abre y ello no se debe especificar ciclo FOR automáticamente lo abre y ello no se debe especificar con la sentencia OPEN-6511con la sentencia OPEN-6511DUP_VAL_ON_INDEX: DUP_VAL_ON_INDEX: El programa intentó almacenar valores El programa intentó almacenar valores duplicados en una columna que se mantiene con restricción de duplicados en una columna que se mantiene con restricción de integridad de un índice único (unique index)-1integridad de un índice único (unique index)-1INVALID_CURSOR: INVALID_CURSOR: El programa intentó efectuar una operación El programa intentó efectuar una operación no válida sobre un cursor-1001no válida sobre un cursor-1001

62

Page 63: Curso PL/SQL

Excepciones Excepciones predefinidas predefinidas 

INVALID_NUMBER: INVALID_NUMBER: En una sentencia SQL, la conversión de una En una sentencia SQL, la conversión de una cadena de caracteres hacia un número falla cuando esa cadena no cadena de caracteres hacia un número falla cuando esa cadena no representa un número válido-1722representa un número válido-1722LOGIN_DENIED: LOGIN_DENIED: El programa intentó conectarse a Oracle con un El programa intentó conectarse a Oracle con un nombre de usuario o password inválido-1017nombre de usuario o password inválido-1017NO_DATA_FOUND: NO_DATA_FOUND: Una sentencia SELECT INTO no devolvió Una sentencia SELECT INTO no devolvió valores o el programa referenció un elemento no inicializado en valores o el programa referenció un elemento no inicializado en una tabla indexada-100una tabla indexada-100NOT_LOGGED_ON: NOT_LOGGED_ON: El programa efectuó una llamada a Oracle sin El programa efectuó una llamada a Oracle sin estar conectado-1012estar conectado-1012PROGRAM_ERROR: PROGRAM_ERROR: PL/SQL tiene un problema interno-6501PL/SQL tiene un problema interno-6501ROWTYPE_MISMATCH: ROWTYPE_MISMATCH: Los elementos de una asignación (el Los elementos de una asignación (el valor a asignar y la variable que lo contendrá) tienen tipos valor a asignar y la variable que lo contendrá) tienen tipos incompatibles. También se presenta este error cuando un incompatibles. También se presenta este error cuando un parámetro pasado a un subprograma no es del tipo esperado-6504parámetro pasado a un subprograma no es del tipo esperado-6504SELF_IS_NULL: SELF_IS_NULL: El parámetro SELF (el primero que es pasado a El parámetro SELF (el primero que es pasado a un método MEMBER) es nulo-30625un método MEMBER) es nulo-30625STORAGE_ERROR: STORAGE_ERROR: La memoria se terminó o está corrupta-6500La memoria se terminó o está corrupta-6500

Page 64: Curso PL/SQL

Excepciones Excepciones predefinidas predefinidas 

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

Page 65: Curso PL/SQL

Excepciones definidas por Excepciones definidas por el usuario el usuario 

PL/SQL permite al usuario definir sus propias excepciones, PL/SQL permite al usuario definir sus propias excepciones, las que deberán ser declaradas y lanzadas explícitamente las que deberán ser declaradas y lanzadas explícitamente utilizando la sentencia utilizando la sentencia RAISERAISE..Las excepciones deben ser declaradas en el segmento Las excepciones deben ser declaradas en el segmento DECLAREDECLARE de un bloque, subprograma o paquete. Se declara de un bloque, subprograma o paquete. Se declara una excepción como cualquier otra variable, asignándole el una excepción como cualquier otra variable, asignándole el tipo tipo EXCEPTIONEXCEPTION. Las mismas reglas de alcance aplican . Las mismas reglas de alcance aplican tanto sobre variables como sobre las excepciones.tanto sobre variables como sobre las excepciones.

DECLAREDECLARE -- DeclaracionesMyExcepcion  -- DeclaracionesMyExcepcion EXCEPTIONEXCEPTION;;BEGINBEGIN  -- Ejecucion  -- EjecucionEXCEPTIONEXCEPTION  -- Excepcion  -- ExcepcionENDEND; ;

65

Page 66: Curso PL/SQL

Reglas de AlcanceReglas de Alcance

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

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

66

Page 67: Curso PL/SQL

La sentencia RAISELa sentencia RAISELa sentencia La sentencia RAISERAISE permite lanzar una excepción en forma explícita. Es posible 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 utilizar esta sentencia en cualquier lugar que se encuentre dentro del alcance de la excepción.excepción.

DECLAREDECLARE  -- Declaramos una excepcion identificada por VALOR_NEGATIVO  -- Declaramos una excepcion identificada por VALOR_NEGATIVO VALOR_NEGATIVO VALOR_NEGATIVO EXCEPTIONEXCEPTION;; valor valor NUMBERNUMBER;;BEGINBEGIN valor := -1; valor := -1; IFIF valor < 0 valor < 0 THENTHEN RAISERAISE VALOR_NEGATIVO; VALOR_NEGATIVO; END IF;END IF;EXCEPTIONEXCEPTION WHEN VALOR_NEGATIVO THENWHEN VALOR_NEGATIVO THEN dbms_output.put_line('El valor no puede ser negativo');dbms_output.put_line('El valor no puede ser negativo');ENDEND;  ;        Con la sentencia Con la sentencia RAISERAISE podemos lanzar una excepción definida por el usuario o podemos lanzar una excepción definida por el usuario o predefinida, siendo el comportamiento habitual lanzar excepciones definidas por el predefinida, siendo el comportamiento habitual lanzar excepciones definidas por el usuario.usuario.Recordar la existencia de la excepción Recordar la existencia de la excepción OTHERSOTHERS, que simboliza cualquier condición , que simboliza cualquier condición de excepción que no ha sido declarada. Se utiliza comúnmente para controlar 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 cualquier tipo de error que no ha sido previsto. En ese caso, es común observar la sentencia sentencia ROLLBACKROLLBACK en el grupo de sentencias de la excepción o alguna de las en el grupo de sentencias de la excepción o alguna de las funciones funciones SQLCODESQLCODE – – SQLERRMSQLERRM, que se detallan en el próximo punto., que se detallan en el próximo punto. 67

Page 68: Curso PL/SQL

Uso de SQLCODE y Uso de SQLCODE y SQLERRMSQLERRM

Al manejar una excepción es posible usar las funciones predefinidas Al manejar una excepción es posible usar las funciones predefinidas SQLCODESQLCODE y y SQLERRM SQLERRM para aclarar al usuario la situación de error para aclarar al usuario la situación de error acontecida. acontecida. SQLCODESQLCODE devuelve el número del error de Oracle y un 0  devuelve el número del error de Oracle y un 0 (cero) en caso de exito al ejecutarse una sentencia SQL.(cero) en caso de exito al ejecutarse una sentencia SQL.Por otra parte, Por otra parte, SQLERRM SQLERRM devuelve el correspondiente mensaje de devuelve el correspondiente mensaje de error. Estas funciones son muy útiles cuando se utilizan en el bloque error. Estas funciones son muy útiles cuando se utilizan en el bloque de excepciones, para aclarar el significado de la excepción de excepciones, para aclarar el significado de la excepción OTHERSOTHERS..

DECLAREDECLARE  err_num   err_num NUMBERNUMBER;;  err_msg   err_msg VARCHAR2VARCHAR2(255);(255); result result NUMBERNUMBER;;BEGINBEGIN    SELECTSELECT 1/0 1/0 INTOINTO result result FROMFROM DUAL; DUAL;EXCEPTION  EXCEPTION  WHEN OTHERS THENWHEN OTHERS THEN  err_num :=   err_num := SQLCODESQLCODE;;  err_msg :=   err_msg := SQLERRMSQLERRM;  ;  DBMS_OUTPUT.put_line('Error:'||DBMS_OUTPUT.put_line('Error:'||TO_CHARTO_CHAR(err_num));(err_num));  DBMS_OUTPUT.put_line(err_msg);  DBMS_OUTPUT.put_line(err_msg);ENDEND;;

68

Page 69: Curso PL/SQL

Uso de SQLCODE y Uso de SQLCODE y SQLERRMSQLERRM

Estas funciones no pueden ser utilizadas directamente Estas funciones no pueden ser utilizadas directamente en una sentencia SQL, pero sí se puede asignar su en una sentencia SQL, pero sí se puede asignar su valor a alguna variable de programa y luego usar esta valor a alguna variable de programa y luego usar esta última en alguna sentencia.última en alguna sentencia.También es posible entregarle a la función También es posible entregarle a la función SQLERRMSQLERRM un número negativo que represente un error de Oracle un número negativo que represente un error de Oracle y ésta devolverá el mensaje asociado.y ésta devolverá el mensaje asociado.

DECLAREDECLARE  msg   msg VARCHAR2VARCHAR2(255);(255);BEGINBEGIN  msg :=   msg := SQLERRMSQLERRM(-1403);(-1403);  DBMS_OUTPUT.put_line(MSG);  DBMS_OUTPUT.put_line(MSG);ENDEND; ; 

69

Page 70: Curso PL/SQL

Excepciones personalizadas Excepciones personalizadas en PL/SQLen PL/SQL

En ocasiones queremos enviar un mensaje de error personalizado al En ocasiones queremos enviar un mensaje de error personalizado al producirse una excepción PL/SQL. Para ello es necesario utilizar la producirse una excepción PL/SQL. Para ello es necesario utilizar la instrucción instrucción RAISE_APPLICATION_ERRORRAISE_APPLICATION_ERROR;;La sintaxis general es la siguiente:La sintaxis general es la siguiente:

RAISE_APPLICATION_ERRORRAISE_APPLICATION_ERROR(<error_num>,<mensaje>);   (<error_num>,<mensaje>);      

Siendo: error_num es un entero negativo comprendido entre -20001 y Siendo: error_num es un entero negativo comprendido entre -20001 y -20999 -20999 mensaje la descripción del errormensaje la descripción del error  DECLAREDECLARE  v_div   v_div NUMBERNUMBER;;BEGINBEGIN                    SELECTSELECT 1/0 1/0 INTOINTO v_div v_div FROMFROM DUAL; DUAL;EXCEPTIONEXCEPTION     WHENWHEN OTHERSOTHERS THENTHEN    RAISE_APPLICATION_ERRORRAISE_APPLICATION_ERROR(-20001,'No se puede dividir por (-20001,'No se puede dividir por cero');cero');ENDEND; ;

70

Page 71: Curso PL/SQL

Propagación de excepciones Propagación de excepciones en PL/SQL en PL/SQL

Una de las características más interesantes de la excepciones es la Una de las características más interesantes de la excepciones es la propagación de las excepciones.propagación de las excepciones.

Cuando se lanza una excepción, el control se transfiere hasta la sección Cuando se lanza una excepción, el control se transfiere hasta la sección EXCEPTIONEXCEPTION del bloque donde se ha producido la excepción. Entonces del bloque donde se ha producido la excepción. Entonces se busca un manejador válido de la excepción se busca un manejador válido de la excepción ((WHENWHEN <excepcion><excepcion> THENTHEN, , WHEN OTHERS THENWHEN OTHERS THEN)) dentro del bloque actual. dentro del bloque actual.

En el caso de que no se encuentre ningún manejador válida el control En el caso de que no se encuentre ningún manejador válida el control del programa se desplaza hasta el bloque del programa se desplaza hasta el bloque EXCEPTIONEXCEPTION del bloque que del bloque que ha realizado la llamada PL/SQL.ha realizado la llamada PL/SQL.

Observemos el siguiente bloque de PL/SQL (Nótese que se ha añadido Observemos el siguiente bloque de PL/SQL (Nótese que se ha añadido una cláusula WHERE 1=2 para provocar una excepción una cláusula WHERE 1=2 para provocar una excepción NO_DATA_FOUNDNO_DATA_FOUND).).

La excepcion La excepcion NO_DATA_FOUND NO_DATA_FOUND se produce durante la ejecución de la se produce durante la ejecución de la funcion fn_fecha, pero como no existe ningún manejador de la excepción funcion fn_fecha, pero como no existe ningún manejador de la excepción en dicha funcion, la excepción se propaga hasta el bloque que ha en dicha funcion, la excepción se propaga hasta el bloque que ha realizado la llamada. En ese momento se captura la excepcion.realizado la llamada. En ese momento se captura la excepcion.

71

Page 72: Curso PL/SQL

Propagación de excepciones Propagación de excepciones en PL/SQLen PL/SQL

DECLAREDECLARE fecha fecha DATEDATE;;    FUNCTIONFUNCTION fn_fecha fn_fecha RETURNRETURN DATEDATE    ISIS    fecha     fecha DATEDATE;;        BEGINBEGIN              SELECTSELECT SYSDATESYSDATE INTOINTO fecha fecha              FROMFROM DUAL DUAL              WHEREWHERE 1=2; 1=2;              RETURNRETURN fecha; fecha;        EXCEPTIONEXCEPTION               WHENWHEN ZERO_DIVIDEZERO_DIVIDE THENTHEN        dbms_output.put_line('EXCEPCION ZERO_DIVIDE CAPTURADA        dbms_output.put_line('EXCEPCION ZERO_DIVIDE CAPTURADA EN fn_fecha');                 EN fn_fecha');                         ENDEND;; BEGINBEGIN      fecha := fn_fecha();fecha := fn_fecha();   dbms_output.put_line('La fecha es '||TO_CHAR(fecha,    dbms_output.put_line('La fecha es '||TO_CHAR(fecha, 'DD/MM/YYYY'));'DD/MM/YYYY')); EXCEPTIONEXCEPTION         WHENWHEN NO_DATA_FOUNDNO_DATA_FOUND THENTHEN    dbms_output.put_line('EXCEPCION NO_DATA_FOUND CAPTURADA EN     dbms_output.put_line('EXCEPCION NO_DATA_FOUND CAPTURADA EN EL BLOQUE PRINCIPAL');EL BLOQUE PRINCIPAL');ENDEND; ;   

Page 73: Curso PL/SQL

Subprogramas Subprogramas en PL/SQL en PL/SQL 

Como hemos visto anteriormente los bloques de Como hemos visto anteriormente los bloques de PL/SQL pueden ser bloques anónimos (scripts) y PL/SQL pueden ser bloques anónimos (scripts) y subprogramas. subprogramas. Los subprogramas son bloques de PL/SQL a los Los subprogramas son bloques de PL/SQL a los que asignamos un nombre identificativo y que que asignamos un nombre identificativo y que normalmente almacenamos en la propia base de normalmente almacenamos en la propia base de datos para su posterior ejecución. datos para su posterior ejecución.         Los subprogramas pueden recibir parámetros. Los subprogramas pueden recibir parámetros.         Los subprogramas pueden ser de varios tipos:Los subprogramas pueden ser de varios tipos:

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

73

Page 74: Curso PL/SQL

Procedimientos Procedimientos almacenadosalmacenados

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

CREATE [CREATE [OR OR REPLACE]REPLACE] PROCEDUREPROCEDURE <procedure_name><procedure_name> [( [(<param1><param1> [ [ININ||OUT|IN OUT|IN OUTOUT] ] <type><type>, , <param2><param2> [ [ININ||OUT|IN OUTOUT|IN OUT] ] <type><type>, ...)] , ...)] ISIS-- Declaracion de variables locales-- Declaracion de variables localesBEGINBEGIN  -- Sentencias  -- Sentencias[[EXCEPTIONEXCEPTION]]  -- Sentencias control de excepcion  -- Sentencias control de excepcionENDEND [ [<procedure_name><procedure_name>];];

74

Page 75: Curso PL/SQL

Procedimientos Procedimientos almacenadosalmacenados

El uso de OR REPLACE permite sobreescribir El uso de OR REPLACE permite sobreescribir un procedimiento existente. Si se omite, y el un procedimiento existente. Si se omite, y el procedimiento existe, se producirá, un error. procedimiento existe, se producirá, un error. La sintaxis es muy parecida a la de un bloque La sintaxis es muy parecida a la de un bloque anónimo, salvo porque se reemplaza la anónimo, salvo porque se reemplaza la sección sección DECLAREDECLARE por la secuencia por la secuencia PROCEDURE ... IS PROCEDURE ... IS en la especificación del en la especificación del procedimiento.procedimiento.Debemos especificar el tipo de datos de cada Debemos especificar el tipo de datos de cada parámetro. parámetro. Al especificar el tipo de dato Al especificar el tipo de dato del parámetro no debemos especificar la del parámetro no debemos especificar la longitud del tipolongitud del tipo..

Page 76: Curso PL/SQL

Procedimientos Procedimientos almacenadosalmacenados

Los parámetros pueden ser de entrada (Los parámetros pueden ser de entrada (ININ), de salida (), de salida (OUTOUT) o de ) o de entrada salida (entrada salida (IN OUTIN OUT). El valor por defecto es ). El valor por defecto es ININ y se toma ese y se toma ese valor en caso de que no especifiquemos nada.valor en caso de que no especifiquemos nada.

CREATECREATE OR OR REPLACEREPLACE PROCEDUREPROCEDURE Actualiza_Saldo(cuenta Actualiza_Saldo(cuenta NUMBERNUMBER, , new_saldo new_saldo NUMBERNUMBER))ISIS -- Declaracion de variables locales-- Declaracion de variables localesBEGINBEGIN  -- Sentencias  -- SentenciasUPDATEUPDATE SALDOS_CUENTAS SALDOS_CUENTAS SETSET SALDO = new_saldo, SALDO = new_saldo, FX_ACTUALIZACION = FX_ACTUALIZACION = SYSDATESYSDATE WHEREWHERE CO_CUENTA = cuenta; CO_CUENTA = cuenta;END END Actualiza_Saldo;      Actualiza_Saldo;     

76

Page 77: Curso PL/SQL

Procedimientos Procedimientos almacenadosalmacenados

También podemos asignar un valor por defecto a los parámetros, También podemos asignar un valor por defecto a los parámetros, utilizando la cláusula utilizando la cláusula DEFAULTDEFAULT  o el operador de asignación (:=) .  o el operador de asignación (:=) .

CREATECREATE OR OR REPLACEREPLACE PROCEDUREPROCEDURE Actualiza_Saldo(cuenta Actualiza_Saldo(cuenta NUMBERNUMBER, , new_saldo new_saldo NUMBER DEFAULT 10 NUMBER DEFAULT 10 ))ISIS -- Declaracion de variables locales-- Declaracion de variables localesBEGINBEGIN  -- Sentencias  -- Sentencias UPDATEUPDATE SALDOS_CUENTAS SALDOS_CUENTAS SETSET SALDO = new_saldo, SALDO = new_saldo, FX_ACTUALIZACION = FX_ACTUALIZACION = SYSDATESYSDATE WHEREWHERE CO_CUENTA = cuenta; CO_CUENTA = cuenta;ENDEND Actualiza_Saldo;     Actualiza_Saldo;    

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

Page 78: Curso PL/SQL

Procedimientos Procedimientos almacenadosalmacenados

Existen dos formas de pasar argumentos a un procedimiento Existen dos formas de pasar argumentos a un procedimiento almacenado a la hora de ejecutarlo (en realidad es válido para almacenado a la hora de ejecutarlo (en realidad es válido para cualquier subprograma). Estas son:cualquier subprograma). Estas son:Notación posicionalNotación posicional:: Se pasan los valores de los parámetros en Se pasan los valores de los parámetros en el mismo orden en que el procedure los define.el mismo orden en que el procedure los define.

BEGINBEGIN Actualiza_Saldo Actualiza_Saldo(200501,2500);(200501,2500); COMMITCOMMIT;;ENDEND; ;

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

BEGINBEGIN Actualiza_Saldo Actualiza_Saldo(cuenta => 200501,new_saldo => 2500);(cuenta => 200501,new_saldo => 2500); COMMIT;COMMIT;ENDEND; ;

Page 79: Curso PL/SQL

Funciones en PL/SQL Funciones en PL/SQL Una función es un subprograma que devuelve un valor. La Una función es un subprograma que devuelve un valor. La sintaxis para construir funciones es la siguiente:sintaxis para construir funciones es la siguiente:

CREATE [CREATE [OR OR REPLACE]REPLACE]FUNCTIONFUNCTION <fn_name>[<fn_name>[((<param1><param1> ININ <type><type>, , <param2><param2> ININ <type><type>, , ...)] ...)] RETURNRETURN <return_type><return_type> ISIS  result   result <return_type><return_type>;;BEGINBEGIN  return(result);  return(result);[[EXCEPTIONEXCEPTION]]  -- Sentencias control de excepcion  -- Sentencias control de excepcionENDEND [ [<fn_name>]<fn_name>];   ;  

El uso de OR REPLACE permite sobreescribir una función El uso de OR REPLACE permite sobreescribir una función existente. Si se omite, y la función existe, se producirá, un existente. Si se omite, y la función existe, se producirá, un error. error. La sintaxis de los parámetros es la misma que en los La sintaxis de los parámetros es la misma que en los procedimientos almacenados, exceptuando que solo pueden ser procedimientos almacenados, exceptuando que solo pueden ser de entrada. de entrada.

79

Page 80: Curso PL/SQL

Funciones en PL/SQLFunciones en PL/SQL  Ejemplo:Ejemplo:

CREATECREATE OR OR REPLACEREPLACEFUNCTIONFUNCTION fn_Obtener_Precio(p_producto fn_Obtener_Precio(p_producto VARCHAR2VARCHAR2) ) RETURNRETURN NUMBERNUMBERISIS  result   result NUMBERNUMBER;;BEGINBEGIN    SELECT SELECT PRECIO PRECIO INTOINTO result result FROMFROM PRECIOS_PRODUCTOS PRECIOS_PRODUCTOS WHERE WHERE CO_PRODUCTO = p_producto;CO_PRODUCTO = p_producto;  return(result);  return(result);EXCEPTION EXCEPTION WHEN NO_DATA_FOUNDWHEN NO_DATA_FOUND THENTHEN return 0; return 0;ENDEND ;  ;      

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

80

Page 81: Curso PL/SQL

Funciones en PL/SQLFunciones en PL/SQLUna vez creada y compilada la función podemos ejecutarla de Una vez creada y compilada la función podemos ejecutarla de la siguiente forma:la siguiente forma:

DECLAREDECLARE Valor Valor NUMBERNUMBER;;BEGINBEGIN Valor := Valor := fn_Obtener_Precio fn_Obtener_Precio('000100');('000100');ENDEND;;          

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

SELECTSELECT CO_PRODUCTO,DESCRIPCION, CO_PRODUCTO,DESCRIPCION, fn_Obtener_Preciofn_Obtener_Precio(CO_PRODUCTO)(CO_PRODUCTO)FROMFROM PRODUCTOS;   PRODUCTOS;  

81

Page 82: Curso PL/SQL

TriggersTriggersDeclaración de triggersDeclaración de triggersUn trigger es un bloque PL/SQL asociado a una tabla, que se ejecuta Un trigger es un bloque PL/SQL asociado a una tabla, que se ejecuta como consecuencia de una determinada instrucción  SQL (una operación como consecuencia de una determinada instrucción  SQL (una operación DML: INSERT, UPDATE o DELETE) sobre dicha tabla. La sintaxis para DML: INSERT, UPDATE o DELETE) sobre dicha tabla. La sintaxis para crear un trigger es la siguiente: crear un trigger es la siguiente:

CREATE [CREATE [OROR REPLACE] TRIGGER REPLACE] TRIGGER <nombre_trigger><nombre_trigger>{BEFORE|AFTER} {BEFORE|AFTER} {DELETE|INSERT|UPDATE [OF {DELETE|INSERT|UPDATE [OF col1, col2, ..., colNcol1, col2, ..., colN]][[OROR {DELETE|INSERT|UPDATE [OF {DELETE|INSERT|UPDATE [OF col1, col2, ..., colNcol1, col2, ..., colN]...]}]...]}ON ON <nombre_tabla><nombre_tabla>[FOR EACH ROW [WHEN ([FOR EACH ROW [WHEN (<<condicion>condicion>)]])]]DECLAREDECLARE  -- variables locales  -- variables localesBEGINBEGIN  -- Sentencias  -- Sentencias[[EXCEPTIONEXCEPTION]]  -- Sentencias control de excepcion    -- Sentencias control de excepcion  ENDEND <nombre_trigger><nombre_trigger>;;        

El uso de OR REPLACE permite sobreescribir un trigger existente. Si se El uso de OR REPLACE permite sobreescribir un trigger existente. Si se omite, y el trigger existe, se producirá, un error. omite, y el trigger existe, se producirá, un error.

82

Page 83: Curso PL/SQL

TriggersTriggersLos triggers pueden definirse para las operaciones Los triggers pueden definirse para las operaciones INSERT, UPDATE o DELETEINSERT, UPDATE o DELETE y pueden ejecutarse y pueden ejecutarse antes o después de la operación.  El modificador antes o después de la operación.  El modificador BEFORE AFTERBEFORE AFTER indica que el trigger se ejecutará indica que el trigger se ejecutará antes o después de ejecutarse la sentencia SQL antes o después de ejecutarse la sentencia SQL definida por DELETE INSERT  UPDATE. Si incluimos el definida por DELETE INSERT  UPDATE. Si incluimos el modificador modificador OFOF el trigger solo se ejecutará cuando la el trigger solo se ejecutará cuando la sentencia SQL afecte a los campos incluidos en la lista.sentencia SQL afecte a los campos incluidos en la lista.

El alcance de los disparadores puede ser la fila o El alcance de los disparadores puede ser la fila o de orden. El modificador de orden. El modificador FOR EACH ROWFOR EACH ROW indica que indica que el trigger se disparará cada vez que se realizan el trigger se disparará cada vez que se realizan operaciones sobre una fila de la tabla. Si se acompaña operaciones sobre una fila de la tabla. Si se acompaña del modificador del modificador WHENWHEN, se establece una restricción; el , se establece una restricción; el trigger solo actuará, sobre las filas que satisfagan la trigger solo actuará, sobre las filas que satisfagan la restricción.restricción.

83

Page 84: Curso PL/SQL

TriggersLas cláusulasLas cláusulas INSERT, DELETE, UPDATE INSERT, DELETE, UPDATE definen qué tipo de orden definen qué tipo de orden DML provoca la activación del disparador.DML provoca la activación del disparador.

BEFORE , AFTER BEFORE , AFTER definen si el disparador se activa antes o después de definen si el disparador se activa antes o después de que se ejecute la orden.que se ejecute la orden.

FOR EACH ROW FOR EACH ROW indica que los disparadores con nivel de fila se activan indica que los disparadores con nivel de fila se activan una vez por cada fila afectada por la orden que provocó el disparo. Los una vez por cada fila afectada por la orden que provocó el disparo. Los disparadores con nivel de orden se activan sólo una vez, antes o después disparadores con nivel de orden se activan sólo una vez, antes o después de la orden.     de la orden.    

La cláusula La cláusula WHENWHEN sólo es válida para los disparadores con nivel de fila. sólo es válida para los disparadores con nivel de fila.

Dentro del ámbito de un trigger disponemos de las variables Dentro del ámbito de un trigger disponemos de las variables OLDOLD y y NEW NEW que se utilizan del mismo modo que cualquier otra variable PL/SQL, pero que se utilizan del mismo modo que cualquier otra variable PL/SQL, pero no es necesario declararlas,no es necesario declararlas,  son de tiposon de tipo %ROWTYPE %ROWTYPE y contienen una y contienen una copia del registro antes (OLD) y después (NEW) de la acción SQL copia del registro antes (OLD) y después (NEW) de la acción SQL (INSERT, UPDATE, DELETE) que ha ejecutado el trigger. Utilizando (INSERT, UPDATE, DELETE) que ha ejecutado el trigger. Utilizando estas variables podemos acceder a los datos que se están insertando, estas variables podemos acceder a los datos que se están insertando, actualizando  o borrando.actualizando  o borrando.

Page 85: Curso PL/SQL

TriggersTriggersEl siguiente ejemplo muestra un trigger que inserta un registro en la El siguiente ejemplo muestra un trigger que inserta un registro en la tabla PRECIOS_PRODUCTOS cada vez que insertamos un nuevo tabla PRECIOS_PRODUCTOS cada vez que insertamos un nuevo registro en la tabla PRODUCTOS:registro en la tabla PRODUCTOS:

CREATE OR REPLACE TRIGGERCREATE OR REPLACE TRIGGER TR_PRODUCTOS_01 TR_PRODUCTOS_01    AFTER INSERT ONAFTER INSERT ON PRODUCTOS  PRODUCTOS      FOR EACH ROWFOR EACH ROWDECLAREDECLARE  -- local variables   -- local variables BEGINBEGIN    INSERT INTOINSERT INTO PRECIOS_PRODUCTOS PRECIOS_PRODUCTOS  (CO_PRODUCTO,PRECIO,FX_ACTUALIZACION)  (CO_PRODUCTO,PRECIO,FX_ACTUALIZACION)    VALUESVALUES  (:  (:NEWNEW.CO_PRODUCTO,100,SYSDATE);.CO_PRODUCTO,100,SYSDATE);ENDEND;  ;       

El trigger se ejecutará cuando sobre la tabla PRODUCTOS se ejecute El trigger se ejecutará cuando sobre la tabla PRODUCTOS se ejecute una sentencia INSERT.una sentencia INSERT.

INSERT INTOINSERT INTO PRODUCTOS (CO_PRODUCTO, DESCRIPCION) PRODUCTOS (CO_PRODUCTO, DESCRIPCION)VALUES VALUES ('000100','PRODUCTO 000100'); ('000100','PRODUCTO 000100');

85

Page 86: Curso PL/SQL

Orden de ejecución de los Orden de ejecución de los triggerstriggers

Una misma tabla puede tener varios triggers. En tal Una misma tabla puede tener varios triggers. En tal caso es necesario conocer el orden en el que se van a caso es necesario conocer el orden en el que se van a ejecutar.ejecutar.Los disparadores se activan al ejecutarse la sentencia Los disparadores se activan al ejecutarse la sentencia SQL. SQL. Si existe, se ejecuta el disparador de tipo BEFORE Si existe, se ejecuta el disparador de tipo BEFORE (disparador previo) con nivel de orden.(disparador previo) con nivel de orden. Para cada fila a la que afecte la orden: Para cada fila a la que afecte la orden:

Se ejecuta si existe, el disparador de tipo BEFORE con nivel de Se ejecuta si existe, el disparador de tipo BEFORE con nivel de fila. fila.

Se ejecuta la propia orden. Se ejecuta la propia orden. Se ejecuta si existe, el disparador de tipo AFTER (disparador Se ejecuta si existe, el disparador de tipo AFTER (disparador

posterior) con nivel de fila.posterior) con nivel de fila.

Se ejecuta, si existe, el disparador de tipo AFTER con Se ejecuta, si existe, el disparador de tipo AFTER con nivel de orden. nivel de orden. 

86

Page 87: Curso PL/SQL

Restricciones de los Restricciones de los triggerstriggers

El cuerpo de un trigger es un bloque PL/SQL. Cualquier El cuerpo de un trigger es un bloque PL/SQL. Cualquier orden que sea legal en un bloque PL/SQL, es legal en el orden que sea legal en un bloque PL/SQL, es legal en el cuerpo de un disparador, con las siguientes restricciones:cuerpo de un disparador, con las siguientes restricciones:

Un disparador no puede emitir ninguna orden de control Un disparador no puede emitir ninguna orden de control de transacciones: de transacciones: COMMITCOMMIT, , ROLLBACKROLLBACK o o SAVEPOINTSAVEPOINT. El disparador se activa como parte de la . El disparador se activa como parte de la ejecución de la orden que provocó el disparo, y forma ejecución de la orden que provocó el disparo, y forma parte de la misma transacción que dicha orden. Cuando parte de la misma transacción que dicha orden. Cuando la orden que provoca el disparo es confirmada o la orden que provoca el disparo es confirmada o cancelada, se confirma o cancela también el trabajo cancelada, se confirma o cancela también el trabajo realizado por el disparador. realizado por el disparador.

Por razones idénticas, ningún procedimiento o función Por razones idénticas, ningún procedimiento o función llamado por el disparador puede emitir órdenes de llamado por el disparador puede emitir órdenes de control de transacciones. control de transacciones.

El cuerpo del disparador no puede contener ninguna El cuerpo del disparador no puede contener ninguna declaración de variables LONG o LONG RAWdeclaración de variables LONG o LONG RAW

87

Page 88: Curso PL/SQL

Utilización de :OLD Utilización de :OLD y :NEWy :NEW

Los registros OLD y NEW son sólo válidos dentro de los Los registros OLD y NEW son sólo válidos dentro de los disparadores con nivel de fila. Podemos usar OLD y NEW como disparadores con nivel de fila. Podemos usar OLD y NEW como cualquier otra variable PL/SQL.cualquier otra variable PL/SQL.

88

ACCION SQLACCION SQL OLDOLD NEWNEW

INSERTINSERT No definido; todos los No definido; todos los campos toman valor campos toman valor NULL.NULL.

Valores que serán Valores que serán insertados cuando se insertados cuando se complete la orden.complete la orden.

UPDATEUPDATE Valores originales de Valores originales de la fila, antes de la la fila, antes de la actualización.actualización.

Nuevos valores que Nuevos valores que serán escritos cuando serán escritos cuando se complete la orden.se complete la orden.

DELETE Valores, antes del Valores, antes del borrado de la fila.borrado de la fila.

No definidos; todos No definidos; todos los campos toman el los campos toman el valor NULL.valor NULL.

Page 89: Curso PL/SQL

Utilización de predicados de los Utilización de predicados de los triggers: INSERTING, UPDATING y triggers: INSERTING, UPDATING y

DELETINGDELETINGDentro de un disparador en el que se disparan distintos tipos de Dentro de un disparador en el que se disparan distintos tipos de órdenes DML (INSERT, UPDATE y DELETE), hay tres funciones órdenes DML (INSERT, UPDATE y DELETE), hay tres funciones booleanas que pueden emplearse para determinar de qué booleanas que pueden emplearse para determinar de qué operación se trata. Estos predicados son INSERTING, UPDATING operación se trata. Estos predicados son INSERTING, UPDATING y DELETING. y DELETING.

89

PredicadPredicadoo

ComportamientoComportamiento

INSERTINGINSERTING TRUE si la orden de disparo es INSERT; FALSE TRUE si la orden de disparo es INSERT; FALSE en otro caso.en otro caso.

UPDATINGUPDATING TRUE si la orden de disparo es UPDATE; FALSE TRUE si la orden de disparo es UPDATE; FALSE en otro caso.en otro caso.

DELETINGDELETING   TRUE si la orden de disparo es DELETE; FALSE TRUE si la orden de disparo es DELETE; FALSE en otro caso.en otro caso.

Page 90: Curso PL/SQL

Subprogramas en bloques Subprogramas en bloques anónimosanónimos

Dentro de la sección DECLARE de un bloque anónimo podemos declarar funciones y Dentro de la sección DECLARE de un bloque anónimo podemos declarar funciones y procedimientos almacenados y ejecutarlos desde el bloque de ejecución del script. procedimientos almacenados y ejecutarlos desde el bloque de ejecución del script. Este tipo de subprogramas son menos conocidos que los procedimientos Este tipo de subprogramas son menos conocidos que los procedimientos almacenados, funciones y triggers, pero son enormemente útiles.almacenados, funciones y triggers, pero son enormemente útiles.El siguiente ejemplo declara, ejecuta y utiliza una funcion (fn_multiplica_x2).El siguiente ejemplo declara, ejecuta y utiliza una funcion (fn_multiplica_x2).

DECLAREDECLARE      idx       idx NUMBERNUMBER;       ;       FUNCTIONFUNCTION fn_multiplica_x2(num fn_multiplica_x2(num NUMBERNUMBER) )               RETURNRETURN NUMBERNUMBER              ISIS         result          result NUMBERNUMBER;;              BEGINBEGIN         result := num *2;         result := num *2;         return result;         return result;              ENDEND fn_multiplica_x2; fn_multiplica_x2;BEGINBEGIN          FORFOR idx idx ININ 1..10 1..10          LOOPLOOP       dbms_output.put_line       dbms_output.put_line('Llamada a la funcion ... '||('Llamada a la funcion ... '||TO_CHARTO_CHAR(fn_multiplica_x2(idx)));(fn_multiplica_x2(idx)));          END LOOPEND LOOP;;ENDEND;   ;   

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

Page 91: Curso PL/SQL

Packages en PL/SQLPackages en PL/SQLUn paquete es una estructura que agrupa objetos de PL/SQL Un paquete es una estructura que agrupa objetos de PL/SQL compilados (procedures, funciones, variables, tipos ...) en la base compilados (procedures, funciones, variables, tipos ...) en la base de datos. Esto nos permite agrupar la funcionalidad de los procesos de datos. Esto nos permite agrupar la funcionalidad de los procesos en programas.en programas.

Lo primero que debemos tener en cuenta es que los paquetes están Lo primero que debemos tener en cuenta es que los paquetes están formados por dos partes: la formados por dos partes: la especificación especificación y el y el cuerpocuerpo. La . La especificación del un paquete y su cuerpo se crean por separado.especificación del un paquete y su cuerpo se crean por separado.

La especificación es la interfaz con las aplicaciones. En ella es La especificación es la interfaz con las aplicaciones. En ella es posible declarar los tipos, variables, constantes, excepciones, posible declarar los tipos, variables, constantes, excepciones, cursores y subprogramas disponibles para su uso posterior desde cursores y subprogramas disponibles para su uso posterior desde fuera del paquete. En la especificación del paquete sólo se declaran fuera del paquete. En la especificación del paquete sólo se declaran los objetos (procedures, funciones, variables ...), no se implementa los objetos (procedures, funciones, variables ...), no se implementa el código. Los objetos declarados en la especificación del paquete 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 son accesibles desde fuera del paquete por otro script de PL/SQL o programa. Haciendo una analogía con el mundo de C, la programa. Haciendo una analogía con el mundo de C, la especificación es como el archivo de cabecera de un programa en especificación es como el archivo de cabecera de un programa en C.   C.  

91

Page 92: Curso PL/SQL

Packages en PL/SQLPackages en PL/SQLPara crear la especificación de un paquete la sintaxis general es Para crear la especificación de un paquete la sintaxis general es la siguiente:la siguiente:

CREATECREATE [OR [OR REPLACEREPLACE] ] PACKAGEPACKAGE < <pkgNamepkgName> > ISIS-- Declaraciones de tipos y registros públicas-- Declaraciones de tipos y registros públicas  {[  {[TYPETYPE < <TypeNameTypeName> > ISIS < <DatatypeDatatype>;]}>;]}-- Declaraciones de variables y constantes publicas-- Declaraciones de variables y constantes publicas-- También podemos declarar cursores-- También podemos declarar cursores  {[<  {[<ConstantNameConstantName> > CONSTANTCONSTANT < <DatatypeDatatype> := <> := <valorvalor>;]}  >;]}    {[<  {[<VariableNameVariableName> <> <DatatypeDatatype>;]}  >;]}  -- Declaraciones de procedimientos y funciones públicas-- Declaraciones de procedimientos y funciones públicas  {[  {[FUNCTIONFUNCTION < <FunctionNameFunctionName>(<>(<ParameterParameter> <> <DatatypeDatatype>,...) >,...)

RETURN RETURN <<DatatypeDatatype>;]}>;]}{[{[PROCEDUREPROCEDURE < <ProcedureNameProcedureName>(<>(<ParameterParameter> > <<DatatypeDatatype>, ...);]}>, ...);]}ENDEND < <pkgNamepkgName>;>;

Page 93: Curso PL/SQL

Packages en PL/SQLPackages en PL/SQL

El cuerpo es la implementación del paquete. El El cuerpo es la implementación del paquete. El cuerpo del paquete debe implementar lo que se cuerpo del paquete debe implementar lo que se declaró inicialmente en la especificación. Es el declaró inicialmente en la especificación. Es el donde debemos escribir el código de los donde debemos escribir el código de los subprogramas. En el cuerpo de un package subprogramas. En el cuerpo de un package podemos declarar nuevos subprogramas y tipos, podemos declarar nuevos subprogramas y tipos, pero estos serán privados para el propio pero estos serán privados para el propio package. package.   La sintaxis general para crear el cuerpo de un La sintaxis general para crear el cuerpo de un paquete es muy parecida a la de la especificación, paquete es muy parecida a la de la especificación, tan solo se añade la palabra clave tan solo se añade la palabra clave BODYBODY y se y se implementa el código de los subprogramas.implementa el código de los subprogramas.

93

Page 94: Curso PL/SQL

Packages en PL/SQLPackages en PL/SQLCREATECREATE [OR [OR REPLACEREPLACE] ] PACKAGE BODYPACKAGE BODY < <pkgNamepkgName> >

ISIS-- Declaraciones de tipos y registros privados-- Declaraciones de tipos y registros privados  {[  {[TYPETYPE < <TypeNameTypeName> > ISIS < <DatatypeDatatype>;]}>;]}-- Declaraciones de variables y constantes privadas-- Declaraciones de variables y constantes privadas-- También podemos declarar cursores-- También podemos declarar cursores  {[<  {[<ConstantNameConstantName> > CONSTANTCONSTANT < <DatatypeDatatype> := <> := <valorvalor>;]}  >;]}    {[<  {[<VariableNameVariableName> <> <DatatypeDatatype>;]}  >;]} 

-- Implementacion de procedimientos y funciones -- Implementacion de procedimientos y funciones     FUNCTIONFUNCTION < <FunctionNameFunctionName>(<>(<ParameterParameter> <> <DatatypeDatatype>,...) >,...) RETURNRETURN <Datatype> <Datatype>     ISIS    -- Variables locales de la funcion    -- Variables locales de la funcion    BEGINBEGIN    -- Implementeacion de la funcion    -- Implementeacion de la funcion    return(<Result>);    return(<Result>);  [  [EXCEPTIONEXCEPTION]]    -- Control de excepciones    -- Control de excepciones    ENDEND;;        PROCEDUREPROCEDURE < <ProcedureNameProcedureName>(<>(<ParameterParameter> <> <DatatypeDatatype>, ...)>, ...)    ISIS     -- Variables locales de la funcion    -- Variables locales de la funcion    BEGINBEGIN    -- Implementacion de procedimiento    -- Implementacion de procedimiento  [  [EXCEPTIONEXCEPTION]]    -- Control de excepciones    -- Control de excepciones    ENDEND;;

ENDEND < <pkgNamepkgName>;    >;   

Page 95: Curso PL/SQL

      Crear la especificación Crear la especificación del paquete:del paquete:

CREATE OR REPLACE PACKAGECREATE OR REPLACE PACKAGE PKG_CONTABILIDAD PKG_CONTABILIDAD ISIS  -- Declaraciones de tipos y registros públicas  -- Declaraciones de tipos y registros públicas    TYPETYPE Cuenta_contable Cuenta_contable IS RECORDIS RECORD  ( codigo_cuenta   ( codigo_cuenta VARCHAR2VARCHAR2(6),(6),    naturaleza        naturaleza    VARCHAR2VARCHAR2(2),(2),    actividad         actividad     VARCHAR2VARCHAR2(4), (4),     debe_haber        debe_haber    VARCHAR2VARCHAR2(1)(1)  );  );  -- Declaraciones de variables y constantes públicas  -- Declaraciones de variables y constantes públicas  DEBE   DEBE CONSTANT VARCHAR2CONSTANT VARCHAR2(1) := 'D';(1) := 'D';  HABER   HABER CONSTANTCONSTANT VARCHAR2VARCHAR2(1) := 'D';(1) := 'D'; ERROR_CONTABILIZAR ERROR_CONTABILIZAR EXCEPTIONEXCEPTION;  ;  -- Declaraciones de procedimientos y funciones públicas-- Declaraciones de procedimientos y funciones públicas    PROCEDUREPROCEDURE Contabilizar (mes VARCHAR2); Contabilizar (mes VARCHAR2);    FUNCTIONFUNCTION fn_Obtener_Saldo(codigo_cuenta VARCHAR2)  fn_Obtener_Saldo(codigo_cuenta VARCHAR2) RETURNRETURN NUMBERNUMBER;;ENDEND PKG_CONTABILIDADPKG_CONTABILIDAD;    ;    

Aquí  sólo hemos declarado las variables y constantes, las funciones y Aquí  sólo hemos declarado las variables y constantes, las funciones y procedimientos públicos. Es en el cuerpo del paquete cuando escribimos procedimientos públicos. Es en el cuerpo del paquete cuando escribimos el código de los subprogramas el código de los subprogramas ContabilizarContabilizar y y fn_Obtener_Saldofn_Obtener_Saldo..

95

Page 96: Curso PL/SQL

      Crear el cuerpo del Crear el cuerpo del paquete:paquete:

CREATE PACKAGE BODYCREATE PACKAGE BODY PKG_CONTABILIDADPKG_CONTABILIDAD ISIS   FUNCTIONFUNCTION fn_Obtener_Saldo(codigo_cuenta fn_Obtener_Saldo(codigo_cuenta VARCHAR2VARCHAR2) )   RETURNRETURN NUMBERNUMBER   ISIS   saldo    saldo NUMBERNUMBER;;  BEGINBEGIN    SELECT SELECT SALDO SALDO INTOINTO saldo saldo            FROMFROM SALDOS SALDOS          WHERE WHERE CO_CUENTA = codigo_cuenta;CO_CUENTA = codigo_cuenta;  return (saldo);  return (saldo);  ENDEND;;    PROCEDUREPROCEDURE Contabilizar(mes Contabilizar(mes VARCHAR2VARCHAR2) )   ISIS      CURSORCURSOR cDatos(vmes cDatos(vmes VARCHAR2VARCHAR2) )       ISIS      SELECTSELECT * *       FROMFROM FACTURACION FACTURACION       WHEREWHERE FX_FACTURACION = vmes FX_FACTURACION = vmes ANDAND PENDIENTE_CONTABILIZAR = 'S'; PENDIENTE_CONTABILIZAR = 'S';  fila cDatos%  fila cDatos%ROWTYPEROWTYPE;;  BEGINBEGIN      OPENOPEN cDatos(mes); cDatos(mes);           LOOP FETCHLOOP FETCH cDatos cDatos INTOINTO fila; fila;           EXITEXIT WHENWHEN cDatos% cDatos%NOTFOUNDNOTFOUND;;     /* Procesamiento de los registros recuperados */     /* Procesamiento de los registros recuperados */          ENDEND LOOPLOOP; ;       CLOSECLOSE cDatos; cDatos;    EXCEPTIONEXCEPTION    WHENWHEN OTHERSOTHERS THENTHEN RAISERAISE ERROR_CONTABILIZAR; ERROR_CONTABILIZAR;ENDEND Contabilizar; Contabilizar;ENDEND PKG_CONTABILIDAD; PKG_CONTABILIDAD;

96

Es posible modificar el Es posible modificar el cuerpo de un paquete sin cuerpo de un paquete sin necesidad de alterar por ello necesidad de alterar por ello la especificación del mismo.la especificación del mismo.

Los paquetes pueden llegar Los paquetes pueden llegar a ser programas muy a ser programas muy complejos y suelen complejos y suelen almacenar gran parte de la almacenar gran parte de la lógica de negocio.lógica de negocio.

Page 97: Curso PL/SQL

Registros PL/SQLRegistros PL/SQLCuando vimos los tipos de datos, omitimos intencionadamente ciertos Cuando vimos los tipos de datos, omitimos intencionadamente ciertos tipos de datos. Estos son:tipos de datos. Estos son:

Registros Registros Tablas de PL  Tablas de PL  VARRAYVARRAY

Declaración de un registro.Declaración de un registro.Un registro es una estructura de datos en PL/SQL, almacenados en Un registro es una estructura de datos en PL/SQL, almacenados en campos, cada uno de los cuales tiene su propio nombre y tipo y que se campos, cada uno de los cuales tiene su propio nombre y tipo y que se tratan como una sola unidad lógica.tratan como una sola unidad lógica.Los campos de un registro pueden ser inicializados y pueden ser Los campos de un registro pueden ser inicializados y pueden ser definidos como NOT NULL. Aquellos campos que no sean inicializados definidos como NOT NULL. Aquellos campos que no sean inicializados explícitamente, se inicializarán a NULL.explícitamente, se inicializarán a NULL.La sintaxis general es la siguiente:La sintaxis general es la siguiente:

TYPETYPE < <nombrenombre> > IS RECORDIS RECORD (( campo campo <tipo_datos> <tipo_datos> [NULL | NOT NULL] [NULL | NOT NULL] [, [,<tipo_datos><tipo_datos>...]...]); );

97

Page 98: Curso PL/SQL

Registros PL/SQLRegistros PL/SQLEl siguiente ejemplo crea un tipo PAIS, que tiene como campos el código, el El siguiente ejemplo crea un tipo PAIS, que tiene como campos el código, el nombre y el continente.nombre y el continente.

TYPETYPE PAIS PAIS IS RECORDIS RECORD (CO_PAIS (CO_PAIS NUMBER,NUMBER, DESCRIPCION DESCRIPCION VARCHAR2VARCHAR2(50),(50), CONTINENTE CONTINENTE VARCHAR2VARCHAR2(20)(20));     );    

DECLAREDECLARETYPETYPE PAIS PAIS IS RECORDIS RECORD (CO_PAIS (CO_PAIS NUMBERNUMBER ,, DESCRIPCION DESCRIPCION VARCHAR2VARCHAR2(50),(50), CONTINENTE CONTINENTE VARCHAR2VARCHAR2(20)(20) ); ); /* Declara una variable identificada por miPAIS de tipo PAIS, /* Declara una variable identificada por miPAIS de tipo PAIS, esto significa que la variable miPAIS tendrá los campos esto significa que la variable miPAIS tendrá los campos ID, DESCRIPCION y CONTINENTE. */ ID, DESCRIPCION y CONTINENTE. */ miPAIS miPAIS PAISPAIS;;BEGINBEGIN /* Asignamos valores a los campos de la variable.*/ /* Asignamos valores a los campos de la variable.*/ miPAIS.CO_PAIS := 27; miPAIS.CO_PAIS := 27; miPAIS.DESCRIPCION := 'ITALIA'; miPAIS.DESCRIPCION := 'ITALIA'; miPAIS.CONTINENTE := 'EUROPA'; miPAIS.CONTINENTE := 'EUROPA';END;END;

98

Los registros son un tipo Los registros son un tipo de datos, por lo que de datos, por lo que podremos declarar podremos declarar variables de dicho tipo de variables de dicho tipo de datos.datos.

Page 99: Curso PL/SQL

Registros PL/SQLRegistros PL/SQLLos registros pueden estar anidados. Es decir, un campo de Los registros pueden estar anidados. Es decir, un campo de un registro puede ser de un tipo de dato de otro registro.un registro puede ser de un tipo de dato de otro registro.

DECLARE DECLARE   TYPETYPE PAIS PAIS IS RECORD IS RECORD  ( CO_PAIS      ( CO_PAIS     NUMBERNUMBER  ,  ,  DESCRIPCION   DESCRIPCION VARCHAR2VARCHAR2(50),(50), CONTINENTE  CONTINENTE  VARCHAR2VARCHAR2(20) );   (20) );    TYPETYPE MONEDA MONEDA IS RECORDIS RECORD ( DESCRIPCION  ( DESCRIPCION VARCHAR2VARCHAR2(50),(50),   PAIS_MONEDA    PAIS_MONEDA PAIS PAIS ); );  miPAIS  miPAIS PAISPAIS; ;  miMONEDA  miMONEDA MONEDAMONEDA;;BEGINBEGIN /* Sentencias */ /* Sentencias */ENDEND;  ;  

99

Pueden asignarse todos los campos Pueden asignarse todos los campos de un registro utilizando una de un registro utilizando una sentencia SELECT. En este caso sentencia SELECT. En este caso hay que tener cuidado en hay que tener cuidado en especificar las columnas en el orden especificar las columnas en el orden conveniente según la declaración conveniente según la declaración de los campos del registro. Para de los campos del registro. Para este tipo de asignación es muy este tipo de asignación es muy frecuente el uso del atributo frecuente el uso del atributo %ROWTYPE que veremos más %ROWTYPE que veremos más adelante.adelante.

Page 100: Curso PL/SQL

Registros PL/SQLRegistros PL/SQL

SELECT SELECT CO_PAIS, DESCRIPCION, CONTINENTECO_PAIS, DESCRIPCION, CONTINENTEINTOINTO miPAIS miPAISFROMFROM PAISES PAISESWHERE WHERE CO_PAIS = 27;     CO_PAIS = 27;    

Puede asignarse un registro a otro cuando sean del mismo Puede asignarse un registro a otro cuando sean del mismo tipo:tipo:

DECLAREDECLARETYPETYPE PAIS PAIS IS RECORDIS RECORD ... ... miPAIS PAIS; miPAIS PAIS; otroPAIS PAIS; otroPAIS PAIS;BEGINBEGIN miPAIS.CO_PAIS := 27; miPAIS.CO_PAIS := 27; miPAIS.DESCRIPCION := 'ITALIA'; miPAIS.DESCRIPCION := 'ITALIA'; miPAIS.CONTINENTE := 'EUROPA'; miPAIS.CONTINENTE := 'EUROPA'; otroPAIS := miPAIS; otroPAIS := miPAIS; END;END;

100

Page 101: Curso PL/SQL

Declaración de registros Declaración de registros con el atributo %ROWTYPEcon el atributo %ROWTYPE

Se puede declarar un registro basándose en una colección de columnas de Se puede declarar un registro basándose en una colección de columnas de una tabla, vista o cursor de la base de datos mediante el atributo una tabla, vista o cursor de la base de datos mediante el atributo %ROWTYPE%ROWTYPE. Por ejemplo, si tengo una tabla PAISES declarada como:. Por ejemplo, si tengo una tabla PAISES declarada como:

CREATE TABLECREATE TABLE PAISES( PAISES(CO_PAIS     CO_PAIS     NUMBERNUMBER,,DESCRIPCION DESCRIPCION VARCHAR2VARCHAR2(50),(50),CONTINENTE  CONTINENTE  VARCHAR2VARCHAR2(20) );   (20) );   

Puedo declarar una variable de tipo registro como PAISESPuedo declarar una variable de tipo registro como PAISES%ROWTYPE%ROWTYPE; ;

DECLAREDECLAREmiPAIS PAISESmiPAIS PAISES%ROWTYPE%ROWTYPE;;BEGINBEGIN/* Sentencias ... *//* Sentencias ... */ENDEND;   ;      

De esta forma se crea el registro de forma dinamica y se podrán asignar De esta forma se crea el registro de forma dinamica y se podrán asignar valores a los campos de un registro a través de un select sobre la tabla, valores a los campos de un registro a través de un select sobre la tabla, vista o cursor a partir de la cual se creó el registro.vista o cursor a partir de la cual se creó el registro.

101

Lo cual significa que el Lo cual significa que el registro miPAIS tendrá la registro miPAIS tendrá la siguiente estructura: siguiente estructura: CO_PAIS NUMBER, CO_PAIS NUMBER, DESCRIPCION DESCRIPCION VARCHAR2(50), CONTINENTE VARCHAR2(50), CONTINENTE VARCHAR2(20).VARCHAR2(20).

Page 102: Curso PL/SQL

Tablas PL/SQLTablas PL/SQL

Las tablas de PL/SQL son tipos de datos que permiten Las tablas de PL/SQL son tipos de datos que permiten almacenar varios valores del mismo tipo de datos.almacenar varios valores del mismo tipo de datos.Una tabla PL/SQL es similar a un array, tiene dos Una tabla PL/SQL es similar a un array, tiene dos componentes: Un índice de tipo BINARY_INTEGER componentes: Un índice de tipo BINARY_INTEGER que permite acceder a los elementos en la tabla que permite acceder a los elementos en la tabla PL/SQL y una columna de escalares o registros que PL/SQL y una columna de escalares o registros que contienen los valores de la tabla PL/SQL contienen los valores de la tabla PL/SQL Puede incrementar su tamaño dinámicamente.Puede incrementar su tamaño dinámicamente.La sintaxis general para declarar una tabla de PL/SQL La sintaxis general para declarar una tabla de PL/SQL es la siguiente:es la siguiente:

TYPETYPE <nombre_tipo_tabla><nombre_tipo_tabla> IS TABLE OFIS TABLE OF<<tipo_datostipo_datos> [> [NOT NULLNOT NULL]]INDEX BY BINARY_INTEGERINDEX BY BINARY_INTEGER;;

102

Page 103: Curso PL/SQL

Tablas PL/SQLTablas PL/SQLUna vez que hemos definido el tipo, podemos declarar variables y Una vez que hemos definido el tipo, podemos declarar variables y asignarle valores.asignarle valores.

DECLAREDECLARE/* Definimos el tipo PAISES como tabla PL/SQL *//* Definimos el tipo PAISES como tabla PL/SQL */TYPETYPE PAISES PAISES IS IS TABLE OF TABLE OF NUMBER NUMBER INDEX BY BINARY_INTEGERINDEX BY BINARY_INTEGER; ; /* Declaramos una variable del tipo PAISES *//* Declaramos una variable del tipo PAISES */ tPAISES PAISES; tPAISES PAISES;BEGINBEGIN tPAISES(1) := 1;tPAISES(1) := 1; tPAISES(2) := 2; tPAISES(2) := 2; tPAISES(3) := 3; tPAISES(3) := 3;ENDEND;;

No es posible inicializar las tablas en la inicialización. El rango de No es posible inicializar las tablas en la inicialización. El rango de binary integer es –2147483647.. 2147483647, por lo tanto el binary integer es –2147483647.. 2147483647, por lo tanto el índice puede ser negativo, lo cual indica que el índice del primer índice puede ser negativo, lo cual indica que el índice del primer valor no tiene que ser necesariamente el cero.valor no tiene que ser necesariamente el cero.

103

Page 104: Curso PL/SQL

Tablas PL/SQL de Tablas PL/SQL de registrosregistros

Es posible declarar elementos de una tabla PL/SQL como de Es posible declarar elementos de una tabla PL/SQL como de tipo registro.tipo registro.

DECLAREDECLARE TYPE TYPE PAIS PAIS IS RECORDIS RECORD ( CO_PAIS ( CO_PAIS NUMBERNUMBER NOT NULLNOT NULL ,, DESCRIPCION DESCRIPCION VARCHAR2VARCHAR2(50),(50), CONTINENTE CONTINENTE VARCHAR2VARCHAR2(20)(20) ); ); TYPETYPE PAISES PAISES IS IS TABLE OF TABLE OF PAIS PAIS INDEX BY BINARY_INTEGERINDEX BY BINARY_INTEGER;; tPAISES PAISES; tPAISES PAISES;BEGINBEGIN tPAISES(1).CO_PAIS := 27; tPAISES(1).CO_PAIS := 27; tPAISES(1).DESCRIPCION := 'ITALIA'; tPAISES(1).DESCRIPCION := 'ITALIA'; tPAISES(1).CONTINENTE := 'EUROPA'; tPAISES(1).CONTINENTE := 'EUROPA';END;END;

104

Page 105: Curso PL/SQL

Funciones para el manejo Funciones para el manejo de tablas PL/SQLde tablas PL/SQL

Cuando trabajamos con tablas de PL podemos utilizar las siguientes Cuando trabajamos con tablas de PL podemos utilizar las siguientes funciones:funciones:FIRSTFIRST. Devuelve el menor índice de la tabla. NULL si está vacía. . Devuelve el menor índice de la tabla. NULL si está vacía. LASTLAST. Devuelve el mayor índice de la tabla. NULL si está vacía.. Devuelve el mayor índice de la tabla. NULL si está vacía.El siguiente ejemplo muestra el uso de FIRST y LAST : El siguiente ejemplo muestra el uso de FIRST y LAST : 

DECLAREDECLARE   TYPETYPE ARR_CIUDADESARR_CIUDADES IS IS TABLE OFTABLE OF VARCHAR2VARCHAR2(50) (50) INDEX BY BINARY_INTEGERINDEX BY BINARY_INTEGER;; misCiudades  misCiudades ARR_CIUDADESARR_CIUDADES;;BEGINBEGIN     misCiudades(1) := 'MADRID';     misCiudades(1) := 'MADRID';     misCiudades(2) := 'BILBAO';     misCiudades(2) := 'BILBAO';     misCiudades(3) := 'MALAGA';     misCiudades(3) := 'MALAGA';          FOR FOR i i ININ misCiudades. misCiudades.FIRSTFIRST..misCiudades...misCiudades.LASTLAST          LOOPLOOP         dbms_output.put_line(misCiudades(i));         dbms_output.put_line(misCiudades(i));          END LOOPEND LOOP;;END;END;

105

Page 106: Curso PL/SQL

Funciones para el manejo Funciones para el manejo de tablas PL/SQLde tablas PL/SQL

EXISTSEXISTS(i). Utilizada para saber si en un cierto índice hay (i). Utilizada para saber si en un cierto índice hay almacenado un valor. Devolverá TRUE si en el índice i hay un valor.almacenado un valor. Devolverá TRUE si en el índice i hay un valor.

DECLAREDECLARE     TYPETYPE ARR_CIUDADES ARR_CIUDADES IS TABLE OFIS TABLE OF VARCHAR2VARCHAR2(50) (50) INDEX BYINDEX BY BINARY_INTEGERBINARY_INTEGER;;  misCiudades   misCiudades ARR_CIUDADESARR_CIUDADES;;BEGINBEGIN  misCiudades(1) := 'MADRID';       misCiudades(1) := 'MADRID';       misCiudades(3) := 'MALAGA';  misCiudades(3) := 'MALAGA';    FORFOR i i ININ misCiudades. misCiudades.FIRSTFIRST..misCiudades...misCiudades.LASTLAST        LOOPLOOP              IFIF misCiudades. misCiudades.EXISTSEXISTS(i) (i) THENTHEN          dbms_output.put_line(misCiudades(i));          dbms_output.put_line(misCiudades(i));              ELSEELSE          dbms_output.put_line('El elemento no existe:‘ ||          dbms_output.put_line('El elemento no existe:‘ || TO_CHAR(i));TO_CHAR(i));              END IFEND IF; ;         END LOOPEND LOOP;;ENDEND;;

106

Page 107: Curso PL/SQL

Funciones para el manejo Funciones para el manejo de tablas PL/SQLde tablas PL/SQL

COUNTCOUNT. Devuelve el número de elementos de la tabla . Devuelve el número de elementos de la tabla PL/SQL. PL/SQL.

DECLAREDECLARE     TYPETYPE ARR_CIUDADES ARR_CIUDADES IS TABLE OFIS TABLE OF VARCHAR2(50) VARCHAR2(50) INDEX BY BINARY_INTEGERINDEX BY BINARY_INTEGER;;  misCiudades ARR_CIUDADES;  misCiudades ARR_CIUDADES;BEGINBEGIN  misCiudades(1) := 'MADRID';       misCiudades(1) := 'MADRID';       misCiudades(3) := 'MALAGA';  misCiudades(3) := 'MALAGA';  /* Devuelve 2, ya que solo hay dos elementos con   /* Devuelve 2, ya que solo hay dos elementos con valor */valor */  dbms_output.put_line(  dbms_output.put_line('El número de elementos es:'||misCiudades.'El número de elementos es:'||misCiudades.COUNTCOUNT);    );   

ENDEND;;

107

Page 108: Curso PL/SQL

Funciones para el manejo Funciones para el manejo de tablas PL/SQLde tablas PL/SQL

PRIOR PRIOR (n). Devuelve el número del índice anterior a n (n). Devuelve el número del índice anterior a n en la tabla. en la tabla.

DECLAREDECLARE  TYPE  TYPE ARR_CIUDADES ARR_CIUDADES IS TABLE OFIS TABLE OF VARCHAR2VARCHAR2(50) (50) INDEXINDEX BY BINARY_INTEGERBY BINARY_INTEGER;;  misCiudades   misCiudades ARR_CIUDADESARR_CIUDADES;;BEGINBEGIN  misCiudades(1) := 'MADRID';  misCiudades(1) := 'MADRID';  misCiudades(3) := 'MALAGA';   misCiudades(3) := 'MALAGA';     /* Devuelve 1, ya que el elemento 2 no existe /* Devuelve 1, ya que el elemento 2 no existe */*/  dbms_output.put_line(  dbms_output.put_line('El elemento previo a 3 es:' || 'El elemento previo a 3 es:' || misCiudades.misCiudades.PRIORPRIOR(3));(3));ENDEND;;

108

Page 109: Curso PL/SQL

Funciones para el manejo Funciones para el manejo de tablas PL/SQLde tablas PL/SQL

NEXTNEXT (n). Devuelve el número del índice posterior a n en la (n). Devuelve el número del índice posterior a n en la tabla.tabla.

DECLAREDECLARE  TYPE  TYPE ARR_CIUDADES ARR_CIUDADES IS TABLE OFIS TABLE OF VARCHAR2VARCHAR2(50) (50) INDEX INDEX BY BINARY_INTEGERBY BINARY_INTEGER;;  misCiudades   misCiudades ARR_CIUDADESARR_CIUDADES;;BEGINBEGIN  misCiudades(1) := 'MADRID';  misCiudades(1) := 'MADRID';  misCiudades(3) := 'MALAGA';   misCiudades(3) := 'MALAGA';     /* Devuelve 3, ya que el elemento 2 no existe *//* Devuelve 3, ya que el elemento 2 no existe */  dbms_output.put_line(  dbms_output.put_line('El elemento siguiente es:' || misCiudades.'El elemento siguiente es:' || misCiudades.NEXTNEXT(1));(1));ENDEND;;

109

Page 110: Curso PL/SQL

Funciones para el manejo Funciones para el manejo de tablas PL/SQLde tablas PL/SQL

TRIM:TRIM: Borra un elemento del final de la tabla Borra un elemento del final de la tabla PL/SQL. PL/SQL.

TRIMTRIM(n): Borra n elementos del final de la (n): Borra n elementos del final de la tabla PL/SQL. tabla PL/SQL.

DELETE:DELETE: Borra todos los elementos de la Borra todos los elementos de la tabla PL/SQL. tabla PL/SQL.

DELETEDELETE(n): Borra el correspondiente al (n): Borra el correspondiente al índice n. índice n.

DELETEDELETE(m,n): Borra los elementos entre m y (m,n): Borra los elementos entre m y n.n.

110

Page 111: Curso PL/SQL

VARRAYSVARRAYSUn varray se manipula de forma muy similar a las tablas de PL, pero Un varray se manipula de forma muy similar a las tablas de PL, pero se implementa de forma diferente. Los elementos en el varray se se implementa de forma diferente. Los elementos en el varray se almacenan comenzando en el índice 1 hasta la longitud máxima almacenan comenzando en el índice 1 hasta la longitud máxima declarada en el tipo varray. La sintaxis es la siguiente:declarada en el tipo varray. La sintaxis es la siguiente:

TYPETYPE <nombre_tipo><nombre_tipo> ISIS VARRAYVARRAY ( (<tamaño_maximo><tamaño_maximo>) ) OFOF <tipo_elementos><tipo_elementos>;   ;    Una consideración a tener en cuenta es que en la declaración de un Una consideración a tener en cuenta es que en la declaración de un varray el tipo de datos no puede  ser de los siguientes tipos de datos:varray el tipo de datos no puede  ser de los siguientes tipos de datos:

BOOLEAN BOOLEAN NCHAR NCHAR NCLOB NCLOB NVARCHAR(n) NVARCHAR(n) REF CURSOR REF CURSOR TABLE TABLE VARRAYVARRAY

Sin embargo se puede especificar el tipo utilizando los Sin embargo se puede especificar el tipo utilizando los atributos atributos %TYPE %TYPE yy %ROWTYPE %ROWTYPE..

111

Page 112: Curso PL/SQL

VARRAYSVARRAYSLos Los VARRAY VARRAY deben estar inicializados antes de poder deben estar inicializados antes de poder utilizarse. Para inicializar un utilizarse. Para inicializar un VARRAYVARRAY se utiliza un se utiliza un constructor (podemos inicializar el VARRAY en la sección constructor (podemos inicializar el VARRAY en la sección DECLARE o bien dentro del cuerpo del bloque):DECLARE o bien dentro del cuerpo del bloque):

DECLAREDECLARE /* Declaramos el tipo VARRAY de cinco /* Declaramos el tipo VARRAY de cinco elementos VARCHAR2*/elementos VARCHAR2*/ TYPETYPE t_cadena t_cadena IS VARRAYIS VARRAY(5) (5) OF VARCHAR2OF VARCHAR2(50);(50); /* Asignamos los valores con un constructor */ /* Asignamos los valores con un constructor */ v_lista t_cadena:= t_cadena('Ana', 'Alicia', v_lista t_cadena:= t_cadena('Ana', 'Alicia', 'Pedro','','');'Pedro','','');BEGINBEGIN v_lista(4) := 'Tito'; v_lista(4) := 'Tito'; v_lista(5) := 'Adela'; v_lista(5) := 'Adela';ENDEND;;        

112

Page 113: Curso PL/SQL

VARRAYSEl tamaño de un VARRAY se establece mediante el número El tamaño de un VARRAY se establece mediante el número de parámetros utilizados en el constructorde parámetros utilizados en el constructor, si declaramos un , si declaramos un VARRAY de cinco elementos pero al inicializarlo pasamos sólo tres VARRAY de cinco elementos pero al inicializarlo pasamos sólo tres parámetros al constructor, el tamaño del VARRAY será tres. Si se parámetros al constructor, el tamaño del VARRAY será tres. Si se hacen asignaciones a elementos que queden fuera del rango se hacen asignaciones a elementos que queden fuera del rango se producirá un error.producirá un error.

El tamaño de un VARRAY podrá aumentarse utilizando la función El tamaño de un VARRAY podrá aumentarse utilizando la función EXTEND, pero nunca con mayor dimensión que la definida en la EXTEND, pero nunca con mayor dimensión que la definida en la declaración del tipo. Por ejemplo, la variable v_lista que sólo tiene 3 declaración del tipo. Por ejemplo, la variable v_lista que sólo tiene 3 valores definidos por lo que se podría ampliar hasta cinco valores definidos por lo que se podría ampliar hasta cinco elementos pero no más allá.elementos pero no más allá.Un VARRAY comparte con las tablas de PL todas las funciones Un VARRAY comparte con las tablas de PL todas las funciones válidas para ellas, pero añade las siguientes:válidas para ellas, pero añade las siguientes:

LIMIT:LIMIT: Devuelve el número maximo de elementos que admite el Devuelve el número maximo de elementos que admite el VARRAY. VARRAY. EXTEND:EXTEND: Añade un elemento al VARRAY. Añade un elemento al VARRAY. EXTENDEXTEND(n): Añade (n) elementos al VARRAY.(n): Añade (n) elementos al VARRAY.

Page 114: Curso PL/SQL

Varrays en la base de Varrays en la base de datosdatos

Los VARRAYS pueden almacenarse en las columnas de la base de datos. Sin embargo, Los VARRAYS pueden almacenarse en las columnas de la base de datos. Sin embargo, un varray sólo puede manipularse en su integridad, no pudiendo modificarse sus un varray sólo puede manipularse en su integridad, no pudiendo modificarse sus elementos individuales de un varray.elementos individuales de un varray.Para poder crear tablas con campos de tipo VARRAY debemos crear el VARRAY como un Para poder crear tablas con campos de tipo VARRAY debemos crear el VARRAY como un objeto de la base de datos. La sintaxis general es:objeto de la base de datos. La sintaxis general es:

CREATE [OR REPLACE]CREATE [OR REPLACE]TYPETYPE <nombre_tipo><nombre_tipo> ISIS VARRAYVARRAY ( (<tamaño_maximo><tamaño_maximo>) ) OF OF <tipo_elementos><tipo_elementos>;;       Una vez que hayamos creado el tipo sobre la base de datos, podremos utilizarlo como un Una vez que hayamos creado el tipo sobre la base de datos, podremos utilizarlo como un tipo de datos más en la creacion de tablas, declaración de variables .... Vease el tipo de datos más en la creacion de tablas, declaración de variables .... Vease el siguiente ejemplo:siguiente ejemplo:

CREATECREATE OR OR REPLACEREPLACE    TYPETYPE PACK_PRODUCTOS PACK_PRODUCTOS AS VARRAYAS VARRAY(10) (10) OFOF VARCHAR2VARCHAR2(60);(60);CREATECREATE TABLETABLE OFERTAS OFERTAS(CO_OFERTA (CO_OFERTA NUMBERNUMBER,, PRODUCTOS PRODUCTOS PACK_PRODUCTOSPACK_PRODUCTOS,, PRECION PRECION NUMBERNUMBER    ););

Para modificar un varray almacenado, primero hay que seleccionarlo en una variable Para modificar un varray almacenado, primero hay que seleccionarlo en una variable PL/SQL. Luego se modifica la variable y se vuelve a almacenar en la tabla. PL/SQL. Luego se modifica la variable y se vuelve a almacenar en la tabla. La La utilización de VARRAYS en la base de datos está completamente desaconsejada.utilización de VARRAYS en la base de datos está completamente desaconsejada.

114

Page 115: Curso PL/SQL

BULK COLLECTBULK COLLECTPL/SQLPL/SQL nos permite leer varios registros en una tabla de PL con un único nos permite leer varios registros en una tabla de PL con un único acceso a través de la instrucción acceso a través de la instrucción BULK COLLECTBULK COLLECT. Esto nos permitirá . Esto nos permitirá reducir el número de accesos a disco, por lo que optimizaremos el reducir el número de accesos a disco, por lo que optimizaremos el rendimiento de nuestras aplicaciones. Como contrapartida el consumo de rendimiento de nuestras aplicaciones. Como contrapartida el consumo de memoria será mayor.memoria será mayor.

DECLAREDECLARE      TYPETYPE t_descripcion t_descripcion IS TABLE OFIS TABLE OF PAISES.DESCRIPCION% PAISES.DESCRIPCION%TYPETYPE;;      TYPETYPE t_continente  t_continente  IS TABLE OFIS TABLE OF PAISES.CONTINENTE% PAISES.CONTINENTE%TYPETYPE;   ;   v_descripcion t_descripcion;v_descripcion t_descripcion;   v_continente  t_continente;   v_continente  t_continente;BEGINBEGIN      SELECTSELECT DESCRIPCION, CONTINENTE DESCRIPCION, CONTINENTE      BULK COLLECT INTOBULK COLLECT INTO v_descripcion, v_continente v_descripcion, v_continente       FROMFROM PAISES;   PAISES;   FORFOR i i ININ v_descripcion. v_descripcion.FIRSTFIRST .. v_descripcion. .. v_descripcion.LASTLAST LOOPLOOP     dbms_output.put_line(v_descripcion(i) || ', ' ||     dbms_output.put_line(v_descripcion(i) || ', ' || v_continente(i));v_continente(i));      END LOOPEND LOOP; ; ENDEND;;//

115

Page 116: Curso PL/SQL

BULK COLLECTBULK COLLECTPodemos utilizar Podemos utilizar BULK COLLECTBULK COLLECT con registros de PL. con registros de PL.

DECLAREDECLARE      TYPETYPE PAIS PAIS IS RECORDIS RECORD (CO_PAIS  (CO_PAIS NUMBERNUMBER,,         DESCRIPCION          DESCRIPCION VARCHAR2VARCHAR2(50),(50),         CONTINENTE           CONTINENTE  VARCHAR2VARCHAR2(20)); (20));       TYPETYPE t_paises t_paises IS TABLE OFIS TABLE OF PAIS;   PAIS;   v_paises t_paises; v_paises t_paises; BEGINBEGIN      SELECTSELECT CO_PAIS, DESCRIPCION, CONTINENTE CO_PAIS, DESCRIPCION, CONTINENTE      BULK COLLECT INTOBULK COLLECT INTO v_paises v_paises      FROMFROM PAISES; PAISES;    FORFOR i i ININ v_paises. v_paises.FIRSTFIRST .. v_paises. .. v_paises.LASTLAST LOOPLOOP     dbms_output.put_line(v_paises(i).DESCRIPCION ||      dbms_output.put_line(v_paises(i).DESCRIPCION || ', ' || v_paises(i).CONTINENTE);', ' || v_paises(i).CONTINENTE);      END LOOPEND LOOP; ; ENDEND;;//

116

Page 117: Curso PL/SQL

BULK COLLECTBULK COLLECTTambién podemos utilizar el atributo También podemos utilizar el atributo ROWTYPEROWTYPE..

DECLAREDECLARE      TYPETYPE t_paises t_paises IS TABLE OFIS TABLE OF AISES% AISES%ROWTYPEROWTYPE;;      v_paises t_paises; v_paises t_paises; BEGINBEGIN      SELECTSELECT CO_PAIS, DESCRIPCION, CONTINENTE CO_PAIS, DESCRIPCION, CONTINENTE      BULK COLLECT INTOBULK COLLECT INTO v_paises v_paises      FROMFROM PAISES; PAISES;      FORFOR i i ININ v_paises. v_paises.FIRSTFIRST .. v_paises. .. v_paises.LASTLAST LOOPLOOP     dbms_output.put_line(v_paises(i).DESCRIPCION ||      dbms_output.put_line(v_paises(i).DESCRIPCION || ', ' || v_paises(i).CONTINENTE);', ' || v_paises(i).CONTINENTE);      END LOOPEND LOOP; ; ENDEND;;//

117

Page 118: Curso PL/SQL

TransaccionesTransaccionesUna transacción es un conjunto de operaciones que se ejecutan en Una transacción es un conjunto de operaciones que se ejecutan en una base de datos y son tratadas como una única unidad lógica por una base de datos y son tratadas como una única unidad lógica por el SGBD.el SGBD.Es decir, una transacción es una o varias sentencias SQL que se Es decir, una transacción es una o varias sentencias SQL que se ejecutan en una base de datos como una única operación, ejecutan en una base de datos como una única operación, confirmándose o deshaciéndose en grupo.confirmándose o deshaciéndose en grupo.

No todas las operaciones SQL son transaccionales. Sólo son No todas las operaciones SQL son transaccionales. Sólo son transaccionales las operaciones correspondiente al DML, es decir, transaccionales las operaciones correspondiente al DML, es decir, sentencias SELECT, INSERT, UPDATE y DELETEsentencias SELECT, INSERT, UPDATE y DELETEPara confirmar una transacción se utiliza la sentencia Para confirmar una transacción se utiliza la sentencia COMMITCOMMIT. . Cuando realizamos Cuando realizamos COMMIT COMMIT los cambios se escriben en la base de los cambios se escriben en la base de datos.datos.

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

118

Page 119: Curso PL/SQL

TransaccionesTransacciones

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

119

Page 120: Curso PL/SQL

TransaccionesTransaccionesEl siguiente ejemplo muestra una supuesta transacción bancaria:El siguiente ejemplo muestra una supuesta transacción bancaria:

DECLAREDECLARE      importe importe NUMBERNUMBER;;   ctaOrigen    ctaOrigen VARCHAR2VARCHAR2(23);(23);   ctaDestino    ctaDestino VARCHAR2VARCHAR2(23);(23);BEGINBEGIN     importe := 100;     importe := 100;     ctaOrigen  := '2530 10 2000 1234567890';     ctaOrigen  := '2530 10 2000 1234567890';     ctaDestino := '2532 10 2010 0987654321';     ctaDestino := '2532 10 2010 0987654321';          UPDATEUPDATE CUENTAS CUENTAS SETSET SALDO = SALDO - importe SALDO = SALDO - importe          WHEREWHERE CUENTA = ctaOrigen; CUENTA = ctaOrigen;          UPDATEUPDATE CUENTAS CUENTAS SETSET SALDO = SALDO + importe SALDO = SALDO + importe          WHEREWHERE CUENTA = ctaDestino; CUENTA = ctaDestino;          INSERTINSERT INTOINTO MOVIMIENTOS MOVIMIENTOS     (CUENTA_ORIGEN, CUENTA_DESTINO,IMPORTE, FECHA_MOVIMIENTO)     (CUENTA_ORIGEN, CUENTA_DESTINO,IMPORTE, FECHA_MOVIMIENTO)          VALUESVALUES     (ctaOrigen, ctaDestino, importe*(-1), SYSDATE);     (ctaOrigen, ctaDestino, importe*(-1), SYSDATE);          INSERTINSERT INTOINTO MOVIMIENTOS MOVIMIENTOS     (CUENTA_ORIGEN, CUENTA_DESTINO,IMPORTE, FECHA_MOVIMIENTO)     (CUENTA_ORIGEN, CUENTA_DESTINO,IMPORTE, FECHA_MOVIMIENTO)          VALUESVALUES     (ctaDestino,ctaOrigen, importe, SYSDATE);     (ctaDestino,ctaOrigen, importe, SYSDATE);          COMMITCOMMIT;;EXCEPTIONEXCEPTION WHENWHEN OTHERSOTHERS THENTHEN     dbms_output.put_line('Error en la transaccion:'||SQLERRM);     dbms_output.put_line('Error en la transaccion:'||SQLERRM);     dbms_output.put_line('Se deshacen las modificaciones);     dbms_output.put_line('Se deshacen las modificaciones);          ROLLBACKROLLBACK;;ENDEND; ;

120

Page 121: Curso PL/SQL

TransaccionesTransacciones

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

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

ORACLE es completamente transaccional. ORACLE es completamente transaccional. Siempre debemos especificar si queremos Siempre debemos especificar si queremos deshacer o confirmar la transacción.deshacer o confirmar la transacción.

121

Page 122: Curso PL/SQL

Transacciones Transacciones autónomas autónomas

En ocasiones es necesario que los datos escritos por parte de una En ocasiones es necesario que los datos escritos por parte de una transacción sean persistentes a pesar de que la transacción se deshaga transacción sean persistentes a pesar de que la transacción se deshaga con con ROLLBACKROLLBACK., PL/SQL permite marcar un bloque con ., PL/SQL permite marcar un bloque con PRAGMA PRAGMA AUTONOMOUS_TRANSACTIONAUTONOMOUS_TRANSACTION. Con esta directiva marcamos el . Con esta directiva marcamos el subprograma para que se comporte como transacción diferente a la del subprograma para que se comporte como transacción diferente a la del proceso principal, llevando el control de proceso principal, llevando el control de COMMITCOMMIT o o ROLLBACK ROLLBACK independienteindependiente..En el siguiente ejemplo. Primero creamos un procedimiento y lo En el siguiente ejemplo. Primero creamos un procedimiento y lo marcamos con marcamos con PRAGMA AUTONOMOUS_TRANSACTION.PRAGMA AUTONOMOUS_TRANSACTION.

CREATE OR REPLACE PROCEDURECREATE OR REPLACE PROCEDURE Grabar_Log(descripcion Grabar_Log(descripcion VARCHAR2VARCHAR2) ) ISISPRAGMA AUTONOMOUS_TRANSACTIONPRAGMA AUTONOMOUS_TRANSACTION;;BEGINBEGIN    INSERT INTOINSERT INTO LOG_APLICACION LOG_APLICACION  (CO_ERROR, DESCRIPICION, FX_ERROR)  (CO_ERROR, DESCRIPICION, FX_ERROR)    VALUESVALUES  (SQ_ERROR.NEXTVAL, descripcion, SYSDATE);    (SQ_ERROR.NEXTVAL, descripcion, SYSDATE);  COMMITCOMMIT; ; -- Este commit solo afecta a la transaccion autonoma-- Este commit solo afecta a la transaccion autonomaENDEND;;

122

Page 123: Curso PL/SQL

Transacciones Transacciones autónomasautónomas

A continuación utilizamos el procedimiento desde un bloque de PL/SQL:A continuación utilizamos el procedimiento desde un bloque de PL/SQL:

DECLAREDECLARE  producto PRECIOS  producto PRECIOS%TYPE%TYPE;;BEGINBEGIN     producto := '100599';     producto := '100599';          INSERT INTOINSERT INTO PRECIOS CO_PRODUCTO, PRECIO, FX_ALTA) PRECIOS CO_PRODUCTO, PRECIO, FX_ALTA)          VALUESVALUES (producto, 150, SYSDATE); (producto, 150, SYSDATE);          COMMITCOMMIT;;EXCEPTION EXCEPTION WHENWHEN OTHERSOTHERS THENTHEN     Grabar_Log(    Grabar_Log(SQLERRMSQLERRM);      );              ROLLBACKROLLBACK;;/* Los datos grabados por "Grabar_Log" se escriben en la base/* Los datos grabados por "Grabar_Log" se escriben en la basede datos a pesar del ROLLBACK, ya que el procedimiento está de datos a pesar del ROLLBACK, ya que el procedimiento está marcado como transacción autonoma.marcado como transacción autonoma.*/*/ENDEND;    ;    Es muy común que, por ejemplo, en caso de que se produzca algún tipo de Es muy común que, por ejemplo, en caso de que se produzca algún tipo de error queramos insertar un registro en una tabla de log con el error que se ha error queramos insertar un registro en una tabla de log con el error que se ha producido y hacer ROLLBACK de la transacción. Pero si hacemos ROLLBACK producido y hacer ROLLBACK de la transacción. Pero si hacemos ROLLBACK de la transacción también lo hacemos de la inserción del log. de la transacción también lo hacemos de la inserción del log.

123

Page 124: Curso PL/SQL

SQL Dinámico SQL Dinámico PL/SQL ofrece la posibilidad de ejecutar sentencias SQL  a partir de cadenas de PL/SQL ofrece la posibilidad de ejecutar sentencias SQL  a partir de cadenas de caracteres. Para ello debemos emplear la instrucción caracteres. Para ello debemos emplear la instrucción EXECUTE IMMEDIATEEXECUTE IMMEDIATE. . Podemos obtener información acerca de número de filas afectadas por la Podemos obtener información acerca de número de filas afectadas por la instrucción ejecutada por instrucción ejecutada por EXECUTE IMMEDIATE EXECUTE IMMEDIATE utilizando utilizando SQL%ROWCOUNTSQL%ROWCOUNT. . El siguiente ejemplo muestra la ejecución de un comando SQL dinámico.El siguiente ejemplo muestra la ejecución de un comando SQL dinámico.

DECLAREDECLARE  ret   ret NUMBERNUMBER;;    FUNCTIONFUNCTION fn_execute fn_execute RETURN NUMBER ISRETURN NUMBER IS    sql_str     sql_str VARCHAR2VARCHAR2(1000);(1000);BEGINBEGIN  sql_str := 'UPDATE DATOS SET NOMBRE = ''NUEVO NOMBRE'‘  sql_str := 'UPDATE DATOS SET NOMBRE = ''NUEVO NOMBRE'‘ WHERE CODIGO = 1';    WHERE CODIGO = 1';        EXECUTE IMMEDIATEEXECUTE IMMEDIATE sql_str;    sql_str;       RETURN SQL%ROWCOUNTRETURN SQL%ROWCOUNT;;ENDEND fn_execute; fn_execute;

BEGINBEGIN  ret := fn_execute();  ret := fn_execute();  dbms_output.put_line(  dbms_output.put_line(TO_CHARTO_CHAR(ret));(ret));ENDEND;     ;     Podemos además parametrizar nuestras consultas a través de variables host. Una Podemos además parametrizar nuestras consultas a través de variables host. Una variable host es una variable que pertenece al programa que está ejecutando la variable host es una variable que pertenece al programa que está ejecutando la sentencia SQL dinámica y que podemos asignar en el interior de la sentencia SQL sentencia SQL dinámica y que podemos asignar en el interior de la sentencia SQL con la palabra clave con la palabra clave USINGUSING . Las variables host van precedidas de dos puntos ":". . Las variables host van precedidas de dos puntos ":".

124

Page 125: Curso PL/SQL

EjemploEjemploEl siguiente ejemplo muestra el uso de variables host para El siguiente ejemplo muestra el uso de variables host para parametrizar una sentencia SQL dinámica.parametrizar una sentencia SQL dinámica.

DECLAREDECLARE  ret   ret NUMBERNUMBER;;    FUNCTIONFUNCTION fn_execute (nombre fn_execute (nombre VARCHAR2VARCHAR2, codigo , codigo NUMBERNUMBER)) RETURN NUMBER RETURN NUMBER IS IS    sql_str     sql_str VARCHAR2VARCHAR2(1000);(1000);    BEGINBEGIN    sql_str := 'UPDATE DATOS SET NOMBRE = :new_nombre     sql_str := 'UPDATE DATOS SET NOMBRE = :new_nombre WHERE CODIGO = :codigo';    WHERE CODIGO = :codigo';            EXECUTE IMMEDIATEEXECUTE IMMEDIATE sql_str  sql_str USINGUSING nombre, codigo;   nombre, codigo;           RETURN SQL%ROWCOUNTRETURN SQL%ROWCOUNT;;    ENDEND fn_execute; fn_execute;

BEGINBEGIN     ret := fn_execute('Devjoker',1);     ret := fn_execute('Devjoker',1);     dbms_output.put_line(     dbms_output.put_line(TO_CHARTO_CHAR(ret));(ret));ENDEND;;

125

Page 126: Curso PL/SQL

Cursores con SQL Cursores con SQL dinámicodinámico

Con SQL dinámico también podemos utilizar cursores.Con SQL dinámico también podemos utilizar cursores.Para utilizar un cursor implícito solo debemos construir Para utilizar un cursor implícito solo debemos construir nuestra sentencia SELECT en una variable de nuestra sentencia SELECT en una variable de tipo caracter y ejecutarla con EXECUTE tipo caracter y ejecutarla con EXECUTE IMMEDIATE utilizando la palabra clave INTO.IMMEDIATE utilizando la palabra clave INTO.

DECLAREDECLARE  str_sql   str_sql VARCHAR2VARCHAR2(255);(255);  l_cnt     l_cnt   VARCHAR2VARCHAR2(20);(20);BEGINBEGIN  str_sql := 'SELECT count(*) FROM PAISES';  str_sql := 'SELECT count(*) FROM PAISES';    EXECUTE IMMEDIATEEXECUTE IMMEDIATE str_sql str_sql INTOINTO l_cnt; l_cnt;  dbms_output.put_line(l_cnt);  dbms_output.put_line(l_cnt);ENDEND;    ;    

126

Page 127: Curso PL/SQL

Cursores con SQL Cursores con SQL dinámicodinámico

Trabajar con cursores explícitos es también muy fácil. Únicamente Trabajar con cursores explícitos es también muy fácil. Únicamente destacar el uso de destacar el uso de REF CURSORREF CURSOR para declarar una para declarar una variable para referirnos al cursor generado con SQL dinámico. variable para referirnos al cursor generado con SQL dinámico. 

DECLAREDECLARE  TYPE  TYPE CUR_TYP CUR_TYP ISIS REF CURSORREF CURSOR;;  c_cursor   c_cursor CUR_TYPCUR_TYP;;  fila PAISES  fila PAISES%ROWTYPE%ROWTYPE;;  v_query   v_query VARCHAR2VARCHAR2(255);(255);BEGINBEGIN  v_query := 'SELECT * FROM PAISES';  v_query := 'SELECT * FROM PAISES';      OPENOPEN c_cursor c_cursor FORFOR v_query; v_query;    LOOPLOOP        FETCHFETCH c_cursor c_cursor INTOINTO fila; fila;        EXIT WHENEXIT WHEN c_cursor c_cursor%NOTFOUND%NOTFOUND;;    dbms_output.put_line(fila.DESCRIPCION);    dbms_output.put_line(fila.DESCRIPCION);    END LOOPEND LOOP;;    CLOSECLOSE c_cursor; c_cursor;ENDEND;;

127

Page 128: Curso PL/SQL

Cursores con SQL Cursores con SQL dinámicodinámico

Las variables host también se pueden utilizar en los cursores.Las variables host también se pueden utilizar en los cursores.

DECLAREDECLARE    TYPETYPE cur_typ cur_typ IS REF CURSORIS REF CURSOR;;  c_cursor   c_cursor CUR_TYPCUR_TYP;;  fila PAISES  fila PAISES%ROWTYPE%ROWTYPE;;  v_query   v_query VARCHAR2VARCHAR2(255);(255);  codigo_pais   codigo_pais VARCHAR2VARCHAR2(3) := 'ESP';(3) := 'ESP';BEGINBEGIN  v_query := 'SELECT * FROM PAISES WHERE CO_PAIS   v_query := 'SELECT * FROM PAISES WHERE CO_PAIS = :cpais';= :cpais';    OPEN OPEN c_cursor c_cursor FORFOR v_query v_query USING USING codigo_pais;codigo_pais;    LOOPLOOP        FETCH FETCH c_cursor c_cursor INTOINTO fila; fila;        EXIT WHEN EXIT WHEN c_cursorc_cursor%NOTFOUND%NOTFOUND;;    dbms_output.put_line(fila.DESCRIPCION);    dbms_output.put_line(fila.DESCRIPCION);    END LOOPEND LOOP;;    CLOSECLOSE c_cursor; c_cursor;ENDEND;;

128

Page 129: Curso PL/SQL

Funciones integradas de Funciones integradas de PL/SQLPL/SQL

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

SYSDATE: Devuelve la fecha del sistemaSYSDATE: Devuelve la fecha del sistema

SELECT SYSDATE FROMSELECT SYSDATE FROM DUAL; DUAL;

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

NVLNVL((<expresion><expresion>, , <valor><valor>): El siguiente ejemplo devuelve 0 ): El siguiente ejemplo devuelve 0 si el precio es nulo, y el precio cuando está informado:si el precio es nulo, y el precio cuando está informado:

SELECTSELECT CO_PRODUCTO, CO_PRODUCTO, NVLNVL(PRECIO, 0) (PRECIO, 0) FROMFROM PRECIOS; PRECIOS;

129

Page 130: Curso PL/SQL

Funciones integradas de Funciones integradas de PL/SQLPL/SQL

DECODE: Proporciona la funcionalidad de una sentencia de DECODE: Proporciona la funcionalidad de una sentencia de control de flujo control de flujo if-elseif-else.if-elseif-else.

DECODEDECODE((<expr>, <cond1>, <val1>[, ..., <condN>, <expr>, <cond1>, <val1>[, ..., <condN>, <valN>], <default><valN>], <default>)   )    Esta función evalúa una expresión "Esta función evalúa una expresión "<expr>"<expr>", si se cumple la , si se cumple la primera condición "primera condición "<cond1>"<cond1>" devuelve el valor1 devuelve el valor1 "<val1>""<val1>", en , en caso contrario evalúa la siguiente condición y así hasta que caso contrario evalúa la siguiente condición y así hasta que una de las condiciones se cumpla. Si no se cumple ninguna una de las condiciones se cumpla. Si no se cumple ninguna condición se devuelve el valor por defecto. condición se devuelve el valor por defecto. Es muy común escribir la función DECODE identada como si se Es muy común escribir la función DECODE identada como si se tratase de un bloque IF.tratase de un bloque IF.

SELECTSELECT DECODEDECODE (co_pais, /* Expresion a evaluar */ (co_pais, /* Expresion a evaluar */'ESP', 'ESPAÑA', /* Si co_pais = 'ESP' ==> 'ESPAÑA' */'ESP', 'ESPAÑA', /* Si co_pais = 'ESP' ==> 'ESPAÑA' */'MEX', 'MEXICO', /* Si co_pais = 'MEX' ==> 'MEXICO' */'MEX', 'MEXICO', /* Si co_pais = 'MEX' ==> 'MEXICO' */'PAIS '||co_pais)/* ELSE ==> concatena */ 'PAIS '||co_pais)/* ELSE ==> concatena */ FROMFROM PAISES; PAISES;

130

Page 131: Curso PL/SQL

Funciones integradas de Funciones integradas de PL/SQLPL/SQL

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

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

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

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

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

SELECT TO_DATESELECT TO_DATE('31/12/2006 23:59:59','DD/MM/YYYY ('31/12/2006 23:59:59','DD/MM/YYYY HH24:MI:SS') HH24:MI:SS') FROMFROM DUAL; DUAL;

131

Page 132: Curso PL/SQL

Funciones integradas de Funciones integradas de PL/SQLPL/SQL

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

TO_CHARTO_CHAR((<expresion>, [<formato>]<expresion>, [<formato>]))SELECTSELECT TO_CHARTO_CHAR((SYSDATESYSDATE, 'DD/MM/YYYYY') , 'DD/MM/YYYYY') FROMFROM DUAL; DUAL;

TO_NUMBER:TO_NUMBER: Convierte una expresión alfanumérica en Convierte una expresión alfanumérica en numérica. Opcionalmente podemos especificar el formato de numérica. Opcionalmente podemos especificar el formato de salida.salida.

TO_NUMBERTO_NUMBER((<expresion>, [<formato>]<expresion>, [<formato>])    )    SELECT TO_NUMBERSELECT TO_NUMBER ('10') ('10')FROMFROM DUAL; DUAL;

132

Page 133: Curso PL/SQL

Funciones integradas de Funciones integradas de PL/SQLPL/SQL

TRUNC:TRUNC: Trunca una fecha o número. Si el parámetro Trunca una fecha o número. Si el parámetro recibido es una fecha  elimina las horas, minutos y segundos recibido es una fecha  elimina las horas, minutos y segundos de la misma.    de la misma.   

SELECTSELECT TRUNCTRUNC(SYSDATE)(SYSDATE)FROM FROM DUAL;DUAL;        Si el parámetro es un número devuelve la parte entera.Si el parámetro es un número devuelve la parte entera.

SELECTSELECT TRUNCTRUNC(9.99)(9.99)FROM FROM DUAL;DUAL;

LENGTH: LENGTH: Devuelve la longitud de un tipo CHAR.Devuelve la longitud de un tipo CHAR.

SELECTSELECT LENGTHLENGTH('HOLA MUNDO')('HOLA MUNDO')FROM FROM DUAL;DUAL;

133

Page 134: Curso PL/SQL

Funciones integradas de Funciones integradas de PL/SQLPL/SQL

INSTR:INSTR: Busca una cadena de caracteres dentro de otra. Devuelve la Busca una cadena de caracteres dentro de otra. Devuelve la posición de la ocurrencia de la cadena buscada. Su sintaxis es la posición de la ocurrencia de la cadena buscada. Su sintaxis es la siguiente:siguiente:

INSTRINSTR((<char>, <search_string>, <startpos>, <occurrence><char>, <search_string>, <startpos>, <occurrence> ) )SELECTSELECT INSTRINSTR('AQUI ES DONDE SE BUSCA', 'BUSCA', 1, 1 )('AQUI ES DONDE SE BUSCA', 'BUSCA', 1, 1 )FROM FROM DUAL; DUAL;

REPLACE:REPLACE: Reemplaza un texto por otro en un expresion de Reemplaza un texto por otro en un expresion de busqueda.busqueda.

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

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

SELECT REPLACE SELECT REPLACE ('HOLA MUNDO','HOLA', 'VAYA')('HOLA MUNDO','HOLA', 'VAYA')-- devuelve VAYA MUNDO-- devuelve VAYA MUNDOFROMFROM DUAL; DUAL;

134

Page 135: Curso PL/SQL

Funciones integradas de Funciones integradas de PL/SQLPL/SQL

SUBSTR: SUBSTR: Obtiene una parte de una expresión, desde una Obtiene una parte de una expresión, desde una posición de inicio hasta una determinada longitud.posición de inicio hasta una determinada longitud.

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

SELECT SUBSTRSELECT SUBSTR('HOLA MUNDO', 6, 5) -- Devuelve MUNDO('HOLA MUNDO', 6, 5) -- Devuelve MUNDOFROMFROM DUAL; DUAL;

UPPER: UPPER: Convierte una expresión alfanumérica a mayúsculas.Convierte una expresión alfanumérica a mayúsculas.

SELECT UPPERSELECT UPPER('hola mundo') -- Devuelve HOLA MUNDO('hola mundo') -- Devuelve HOLA MUNDOFROM FROM DUAL; DUAL;

LOWER:LOWER: Convierte una expresion alfanumerica a minúsculas. Convierte una expresion alfanumerica a minúsculas.

SELECT LOWERSELECT LOWER('HOLA MUNDO') -- Devuelve hola mundo('HOLA MUNDO') -- Devuelve hola mundoFROM FROM DUAL;DUAL;

135

Page 136: Curso PL/SQL

Funciones integradas de Funciones integradas de PL/SQLPL/SQL

ROWIDTOCHAR:ROWIDTOCHAR: Convierte un ROWID a tipo caracter. Convierte un ROWID a tipo caracter.SELECT ROWIDTOCHARSELECT ROWIDTOCHAR(ROWID) (ROWID) FROMFROM DUAL; DUAL;

RPAD:RPAD: Añade N veces una determinada cadena de caracteres Añade N veces una determinada cadena de caracteres a la derecha una expresión. Muy útil para generar ficheros de a la derecha una expresión. Muy útil para generar ficheros de texto de ancho fijo.texto de ancho fijo.RPADRPAD((<expresion>, <longitud>, <pad_string><expresion>, <longitud>, <pad_string>)    )     El siguiente ejemplo añade puntos a la expresión 'Hola mundo' El siguiente ejemplo añade puntos a la expresión 'Hola mundo' hasta alcanzar una longitud de 50 caracteres.hasta alcanzar una longitud de 50 caracteres.

SELECTSELECT RPADRPAD('Hola Mundo', 50, '.')('Hola Mundo', 50, '.')FROMFROM DUAL; DUAL;

136

Page 137: Curso PL/SQL

Funciones integradas de Funciones integradas de PL/SQLPL/SQL

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

LPADLPAD((<expresion>, <longitud>, <expresion>, <longitud>, <pad_string><pad_string>)    )     El siguiente ejemplo añade puntos a la expresión El siguiente ejemplo añade puntos a la expresión 'Hola mundo' hasta alcanzar una longitud de 50 'Hola mundo' hasta alcanzar una longitud de 50 caracteres.caracteres.

SELECTSELECT LPADLPAD('Hola Mundo', 50, '.')('Hola Mundo', 50, '.')FROMFROM DUAL; DUAL;

137

Page 138: Curso PL/SQL

Funciones integradas de Funciones integradas de PL/SQLPL/SQL

RTRIM:RTRIM: Elimina los espacios en blanco a la Elimina los espacios en blanco a la derecha de una expresiónderecha de una expresión

SELECTSELECT RTRIM RTRIM ('Hola Mundo ')('Hola Mundo ')FROM FROM DUAL;DUAL;

LTRIM:LTRIM: Elimina los espacios en blanco a Elimina los espacios en blanco a la izquierda de una expresiónla izquierda de una expresión

SELECTSELECT LTRIM LTRIM (' Hola Mundo')(' Hola Mundo')FROM FROM DUAL;DUAL;

138

Page 139: Curso PL/SQL

Funciones integradas de Funciones integradas de PL/SQLPL/SQL

TRIM:TRIM: Elimina los espacios en blanco a la izquierda y Elimina los espacios en blanco a la izquierda y derecha de una expresiónderecha de una expresión

SELECTSELECT TRIM TRIM (' Hola Mundo ')(' Hola Mundo ')FROM FROM DUAL; DUAL;

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

MODMOD((<dividendo>, <divisor><dividendo>, <divisor> ) )

SELECT MODSELECT MOD(20,15) (20,15) -- Devuelve el modulo de dividir 20/15 -- Devuelve el modulo de dividir 20/15 FROM FROM DUAL;DUAL;

139

Page 140: Curso PL/SQL

SecuenciasSecuenciasORACLE proporciona los objetos de secuencia para la ORACLE proporciona los objetos de secuencia para la generación de códigos numéricos automáticos. generación de códigos numéricos automáticos. Las secuencias son una solución fácil y elegante al problema Las secuencias son una solución fácil y elegante al problema de los códigos autogenerados.de los códigos autogenerados.LA sintaxis general es la siguiente:LA sintaxis general es la siguiente:

CREATE SEQUENCE CREATE SEQUENCE <secuence_name><secuence_name>[[MINVALUEMINVALUE < <min_valmin_val>]>][[MAXVALUE MAXVALUE <max_val>]<max_val>][[START WITH START WITH <ini_val>]<ini_val>][[INCREMENT BYINCREMENT BY <inc_val>]<inc_val>][[NOCACHE NOCACHE | | CACHE CACHE <cache_val>]<cache_val>][[CYCLECYCLE]][[ORDERORDER];];

140

Page 141: Curso PL/SQL

SecuenciasSecuencias

El siguiente ejemplo crea una secuencia El siguiente ejemplo crea una secuencia SQ_PRODUCTOS.SQ_PRODUCTOS.

CREATE SEQUENCECREATE SEQUENCE SQ_PRODUCTOS SQ_PRODUCTOSMINVALUE MINVALUE 11MAXVALUEMAXVALUE 999999999999999999999999999 999999999999999999999999999START WITH START WITH 11INCREMENT BYINCREMENT BY 1 1CACHECACHE 20;   20;        Se puede simplificar la orden, tomando los valores por Se puede simplificar la orden, tomando los valores por defecto. El ejemplo anterior quedaría del siguiente defecto. El ejemplo anterior quedaría del siguiente modo:modo:

CREATE SEQUENCE CREATE SEQUENCE SQ_PRODUCTOS;SQ_PRODUCTOS;

141

Page 142: Curso PL/SQL

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

SELECT SELECT SQ_PRODUCTOS.SQ_PRODUCTOS.NEXTVALNEXTVAL FROM FROM DUAL;DUAL;        

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

SELECTSELECT SQ_PRODUCTOS. SQ_PRODUCTOS.CURRVALCURRVAL FROM FROM DUAL; DUAL;      

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

DROP SEQUENCE DROP SEQUENCE SQ_PRODUCTOS;SQ_PRODUCTOS;

142

Page 143: Curso PL/SQL

PrácticaPráctica

143