+ All Categories

PL_SQL

Date post: 04-Jul-2015
Category:
Upload: luis-flores-ramos
View: 177 times
Download: 4 times
Share this document with a friend
Popular Tags:
29
Escribiendo consultas Para obtener datos se utiliza el comando SELECT. El formato es el siguiente: SELECT [ALL|DISTINCT] [expre_colum1, expre_column2, ..., expre_columN | * ] FROM [tabla1, tabla2, ..., tablaM] [WHERE condición] [GROUP BY col, col, ...] [HAVING condición] [ORDER BY col [DESC|ASC] [, col [DESC|ASC] ...]]; Donde expre_colum puede ser un a columna de tabla, una constante, una expresión aritmética, una función o varias funciones anidadas. Es importante hacer notar que cada comando SQL finaliza con punto y coma(;). Cuando se escriben scripts, estos utilizarán un slash (/) al final del comando. FROM Especifica la tabla o lista de tablas de las que se recuperarán los datos. Por ejemplo para obtener los datos del nombre y departamento de los empleados de la empresa, se puede utilizar la siguiente consulta: SELECT ename, deptno FROM emp; En el caso de que el usuario propietario de la tabla emp fuera distinto del usuario actual debe indicarse de forma prefija el esquema dueño, quedando de la siguiente forma: SELECT ename, deptno FROM dueño.emp; Debe notarse que esto para efectos de un sistema no es conveniente, pues si fuese necesario mover tablas entre esquemas o bien utilizar las mismas aplicaciones en distintas bases de datos, deben actualizarse las aplicaciones, por esta razón es conveniente definir sinónimos para las tablas de tal forma que no haya que especificar el esquema dueño, salvo casos muy específicos. WHERE Este permite filtrar las filas seleccionadas, por medio de una condición, que define el criterio de selección. El formato de la condición es la mayoría de los casos: expresión operador expresión. Las expresiones pueden ser constantes, operaciones aritméticas, valores nulos o el nombre de una columna. Mientras que los operadores de comparación son los siguientes: Operadores Comparación =, >, <, >=, <=, !=, <> IN, NOT IN, BETWEEN, NOT BETWEEN LIKE IS NULL, IS NOT NULL Se pueden construir condiciones múltiples basados en los operadores lógicos AND, OR y NOT. También se pueden utilizar los paréntesis para establecer el orden de precedencia. Algunos ejemplos de cláusulas WHERE son: WHERE job = 'SALESMAN' WHERE sal >= 500 AND hiredate < TO_DATE ( '01-01-1990', 'DD-MM-YYYY' ) WHERE mgr IS NULL AND ( ( sal > 500 ) OR ( job = 'SALESMAN' AND comm >= 20 ) ) ORDER BY
Transcript
Page 1: PL_SQL

Escribiendo consultas

Para obtener datos se utiliza el comando SELECT. El formato es el siguiente:

SELECT [ALL|DISTINCT] [expre_colum1, expre_column2, ..., expre_columN | * ]

FROM [tabla1, tabla2, ..., tablaM]

[WHERE condición]

[GROUP BY col, col, ...]

[HAVING condición]

[ORDER BY col [DESC|ASC] [, col [DESC|ASC] ...]];

Donde expre_colum puede ser un a columna de tabla, una constante, una expresión aritmética, una función o varias funciones anidadas.

Es importante hacer notar que cada comando SQL finaliza con punto y coma(;). Cuando se escriben scripts, estos utilizarán un slash (/) al final del comando.

FROM

Especifica la tabla o lista de tablas de las que se recuperarán los datos. Por ejemplo para obtener los datos del nombre y departamento de los empleados de la empresa, se puede utilizar la siguiente consulta:

SELECT ename, deptno

FROM emp;

En el caso de que el usuario propietario de la tabla emp fuera distinto del usuario actual debe indicarse de forma prefija el esquema dueño, quedando de la siguiente forma:

SELECT ename, deptno

FROM dueño.emp;

Debe notarse que esto para efectos de un sistema no es conveniente, pues si fuese necesario mover tablas entre esquemas o bien utilizar las mismas aplicaciones en distintas bases de datos, deben actualizarse las aplicaciones, por esta razón es conveniente definir sinónimos para las tablas de tal forma que no haya que especificar el esquema dueño, salvo casos muy específicos.

WHERE

Este permite filtrar las filas seleccionadas, por medio de una condición, que define el criterio de selección. El formato de la condición es la mayoría de los casos: expresión operador expresión.

Las expresiones pueden ser constantes, operaciones aritméticas, valores nulos o el nombre de una columna. Mientras que los operadores de comparación son los siguientes:

Operadores Comparación

=, >, <, >=, <=, !=, <>

IN, NOT IN, BETWEEN, NOT BETWEEN

LIKE

IS NULL, IS NOT NULL

Se pueden construir condiciones múltiples basados en los operadores lógicos AND, OR y NOT. También se pueden utilizar los paréntesis para establecer el orden de precedencia. Algunos ejemplos de cláusulas WHERE son:

WHERE job = 'SALESMAN'

WHERE sal >= 500

AND hiredate < TO_DATE ( '01-01-1990', 'DD-MM-YYYY' )

WHERE mgr IS NULL

AND (

( sal > 500 ) OR

( job = 'SALESMAN' AND comm >= 20 )

) ORDER BY

Page 2: PL_SQL

Este especifica un criterio de clasificación del resultado de la consulta, ASC especifica orden ascendente (este es el valor por defecto) y DESC, descendente. Por ejemplo,

SELECT *

FROM dept

ORDER BY dname

Se pueden situar varios criterios, siendo la precedencia de izquierda a derecha.

ALL

Esta es la opción para recuperar todas las filas de la consulta, aunque se encuentre repetidas. Es la opción por defecto.

DISTINCT

Sólo recupera las filas que son distintas. Si se consultamos los departamentos de la tabla de empleados, el resultado serían los números de departamento de existentes:

SELECT deptno

FROM emp

En este caso aparecen todos los departamentos de los empleados, aunque el número de departamento se repita entre filas. Para eliminar los repetidos se puede hacer de la siguiente forma:

SELECT DISTINCT deptno

FROM emp

Alias para tablas

En la cláusula FROM pueden utilizarse alias para distinguir o abreviar el nombre de las tablas y así referenciar las columnas en las demás secciones del SELECT.

SELECT cust.name, cust.address, cust.city

FROM customer cust;

Este ejemplo presenta un uso sencillo y pareciera no ser importante, sin embargo su mayor uso se da cuando se necesitan diferenciar columnas con idénticos nombre, entre distintas tablas.

En el caso del WHERE se utiliza para crear el criterio de selección del grupo y hacer las uniones entre tablas.

SELECT DISTINCT city, state

FROM addresses

WHERE state IN ('CA','NY','CT')

AND city IS NOT NULL;

Alias para columnas

Este se utiliza para la presentación de los encabezados en las consultas, de tal forma que no aparezca el nombre físico de la columna, sino el que nosotros deseemos. Por ejemplo:

SELECT d.dname "Nombre Departamento",

d.deptno "Número Departamento"

FROM dept d

Operadores aritméticos

Estos son utilizados para formar expresiones con constantes, valores de columnas y funciones de valores de columnas. Estos son los conocidos: +, -, * y /.

Por ejemplo:

SELECT ename, sal, comm, sal + comm "sal total"

FROM emp

WHERE comm > 0

ORDER BY ename

Page 3: PL_SQL

Operadores de comparación y lógicos

A continuación se listan dichos operadores

Operadores de Comparación

Operador Función

= Igual a

> Mayor que

>= Mayor o igual que

< Menor que

<= Menor o igual que

!= <> Distinto de

Operadores Lógicos

Operador Función

AND TRUE si ambas condiciones son TRUE

OR TRUE si una de ambas condiciones es TRUE

NOT TRUE si la condición es FALSE y FALSE si la condición es TRUE.

Operadores de comparación de hileras

Para comparar hileras podemos hacer uso del igual (=). Así podemos ubicar dentro de los empleados aquellos que sean jefes:

SELECT *

FROM emp

WHERE job = 'MANAGER'

Sin embargo, este operador no nos sirve si lo que deseamos es listar los empleados cuyo nombre inicie con la letra 'E', en cuyo caso podemos utilizar el operador LIKE, el cual permite incluir los siguientes caracteres especiales:

'%' Comodín: representa cualquier cadena de 0 o más caracteres.

'_' Marcador de posición: representa un carácter cualquiera.

Se pueden utilizar de la siguiente manera:

SELECT *

FROM emp

WHERE ename LIKE 'E%'

Comprobaciones con conjuntos

Tenemos, además de las operaciones binarias ya vistas, otras que comparar los datos contra una lista.

De esta forma el IN se puede utilizar para verificar si una expresión pertenece o no a un conjunto de valores. Su forma general es

expresión [NOT] IN (lista de valores separados por coma)

Ejemplos de utilización del IN pueden ser los siguientes:

SELECT *

Page 4: PL_SQL

FROM emp

WHERE deptno IN ( 10, 20 );

SELECT ename

FROM emp

WHERE job IN ( 'CLERK', 'SALESMAN' )

Otra opción puede ser el verificar si una expresión se encuentra o no en un rango específico, esto por medio del BETWEEN, cuyo formato es:

Expresión [NOT] BETWEEN valor_inicial AND valor_final

Ejemplo de su utilización:

SELECT ename, sal

FROM emp

WHERE sal BETWEEN 200 AND 500;

Nota: Puede observarse que ambas cláusulas pueden sustituirse por expresiones que utilicen el OR y AND. En caso del IN se crean n comparaciones de la expresión contra el conjunto de valores, unidas mediante ORs. Para el BETWEEN se pueden hacer dos comparaciones con el mayor-igual y menor-igual, y la expresión, estas unidas por un AND.

Agrupación de elemento GROUP BY y HAVING

Existen algunas funciones que permiten obtener resultados sobre un conjunto de datos, como puede ser el tener el total, promedio, máximo, etc., de una columna. Por ejemplo, podemos obtener el salario promedio de los empleados de la compañía:

SELECT AVG(sal)

FROM emp

A pesar de que aquí la totalidad de los empleados se manejan como un grupo, puede ser necesario trabajar sobre grupos más pequeños o determinados. Este podría ser el caso que querer tener el salario promedio por departamento:

SELECT deptno, AVG(sal)

FROM emp

GROUP BY deptno

Es importante hacer notar que en el group by deben de incorporarse aquellas columnas del select que no son funciones de agrupamiento o constantes.

El uso de having sirve para expresar condiciones sobre las agrupaciones, de tal forma que podemos escoger que grupos se despliegan. De esta forma podemos limitar la consulta ya vista solo para los departamentos que tengan más de 3 empleados:

SELECT deptno, AVG(sal)

FROM emp

GROUP BY deptno

HAVING COUNT(*) > 3

El having a pesar de funcionar de forma similar al where, solo puede referenciar columnas definas en el grupo o funciones de grupo.

Para conocer sus tablas y vistas

Es importante familiarizarse con el esquema de la base de datos, principalmente conocer las estructuras que nos permiten conocer la definición de nuestros esquemas.

Por ejemplo existen vistas que indican el nombre de las tablas, en este caso la vista dictionary nos muestra las tablas de la base de datos junto con sus comentarios.

SELECT table_name

FROM dictionary

ORDER BY table_name;

Otras tablas interesantes son all_tables, all_columns, all_views y all_constraints.

Para visualizar el nombre de las columnas que componen una tabla se utiliza la instrucción "DESC

Page 5: PL_SQL

nombre_tabla". El DESC viene de DESCribe, en este caso la abreviación es la más utilizada.

Otra vista muy utilizada es el cat, que muestra los objetos como tablas, secuencias y vistas propios del usuario que está conectado.

Uniones entre tablas

Esta operación de combinar las tablas incluidas en la cláusula FROM, es en la mayoría de los casos sencilla, sin embargo el no hacerlo bien puede provocar problemas de rendimiento. Debe considerarse que en una unión (join) no deben de haber demasiadas tablas juntas, pues quizás implique un mal diseño y la denormalización sea una salida para mejorar el rendimiento.

SELECT d.dname,

e.ename,

e.hiredate

FROM emp e, dept d

WHERE d.deptno = e.deptno

ORDER BY d.dname,e.ename;

Ahora agregamos el nombre del jefe del empleado a la misma consulta.

SELECT d.dname,

e.ename,

e.hiredate,

m.dname manager

FROM emp e, emp m, dept d

WHERE d.deptno = e.deptno

AND m.empno = e.mgr

ORDER BY d.dname,e.ename;

En este caso para la salida se utilizó un alias para el nombre jefe "manager".

Recuerde no crear productos cartesianos

Recuerde que esto sucede cuando dos o más tablas incluidas en el FROM no tiene la estructura adecuada en la cláusula WHERE. Por ejemplo:

SELECT X.dname,

Z.ename

FROM emp Z,

dept X

ORDER BY X.dname, Z.ename;

En este caso si emp tiene 10 empleado y departamento 3 departamentos, la consulta retornará 30 filas. Esto es por cada nombre departamento se listan todos los empleados sin importar el departamento. Es entonces necesario para agregar la cláusula WHERE X.deptno = Z.deptno, para que el resultado sea el deseado, o sea 10 filas.

Outer Joins

Cuando se habla de utilizar outer join, quiere decir que se pueden seleccionar filas de una tabla aunque no existan correspondientes en la otra tabla. Para ello se utiliza el símbolo (+):

SELECT d.dname,

e.ename

FROM emp e,

dept d,

WHERE d.deptno(+) = e.deptno

ORDER BY d.dname,e.ename

En un caso hipotético, el presidente de la compañía nunca fue asignado a un departamento, por que nunca hubiese sido obtenido en las consultas anteriores, dado que el número de departamento está nulo. El outer join hace que todos los registros de la tabla de empleados sean obtenidos, por lo cual las columnas de la tabla de departamentos quedan vacías (en este caso el nombre del departamento).

Subconsultas (subqueries)

Page 6: PL_SQL

Las subconsultas o consultas anidadas (nested), son utilizadas partiendo de una liga con la consulta padre. Dependiendo como se cree la subconsulta, ella puede ser una vez para consulta padre o bien una vez para cada registro retornado por la consulta padre, en este caso esta es una consulta correlacionada.

Una consulta correlacionada se identifica fácilmente si ella contiene referencias a columnas de la consulta padre en la cláusula WHERE. Véase que las columnas de la subconsulta no pueden ser referenciadas por la consulta padre.

SELECT e.ename,

e.job

FROM emp e

WHERE e.deptno IN (SELECT deptno

FROM dept

WHERE dname = 'ADMIN');

El anterior es un ejemplo de una consulta no correlacionada. En este caso se buscan los empleados que estén en departamento ADMIN. El uso del IN es para indicar si está contenido (puede combinarse con el NOT), y es utilizado cuando la subconsulta devuelve cero, uno o más registros. Si se utilizará el operador de igualdad (=), se asume que solo una fila es retornada. Si la subconsulta no devuelve ninguna columna o más de una se daría un error Oracle.

Además véase que consulta podría escribirse directamente con un join. Por lo que las subconsultas son utilizadas generalmente por criterios de rendimiento o porque los joins no dan la posibilidad de construir la consulta.

SELECT d.dname,

e.ename,

e.job

FROM emp e,

dept d

WHERE e.deptno = d.deptno

AND e.empno IN (SELECT repid

FROM customer

WHERE repid = e.empno)

ORDER BY d.dname, e.ename

En este caso solo los empleados que tengan al menos un cliente son tomados en cuenta. Véase que esta es una subconsulta correlacionada, pues referencia a una columna de la consulta padre dentro de ella.

SELECT d.dname,

e.ename,

e.job

FROM emp e,

dept d

WHERE e.deptno = d.deptno

AND NOT EXISTS (SELECT 'X'

FROM customer

WHERE city in ('ROCHESTER','NEW YORK')

AND repid = e.empno)

ORDER BY d.dname, e.job, e.ename;

En este caso se muestran todos los empleados y departamentos, excepto aquellos departamentos que tengan clientes que se ubiquen en 'ROCHESTER' y 'NEW YORK'. SELECT 'X' será retornado y para evaluado por el NOT EXISTS (cuando no encuentre filas en la subconsulta es falso y cuando encuentra al menos uno es verdadero).

Puede utilizar cualquier constante en lugar de la 'X' o bien un campo de las tablas de la subconsulta (es mejor la constante).

Funciones (Built-In Functions)

Page 7: PL_SQL

Las funciones son parte intrínseca de cualquier comando SQL. Aquí se muestra una lista de las funciones más comunes.

Nombre Tipo Sintaxis Retorna

ABS Number ABS(n) Valor absoluto de n.

ADD_MONTHS Date ADD_MONTHS(a,b) Suma a la fecha a, b meses (b puede ser negativo).

ASCII Character ASCII(c) Representación decimal de c.

AVG Group AVG(DISTINCT|ALL n) Promedio del valor de n. ALL es el valor por defecto default.

CEIL Number CEIL(n) Menor entero mayor o igual a n.

CHARTOROWID Conversión CHARTOROWID(c) Convierte un carácter a un tipo de datos rowid.

CHR Character CHR(n) Representación carácter del valor decimal n.

CONCAT Character CONCAT(1,2) Carácter 1 concatenado con el 2.

CONVERT Conversion CONVERT(a, dest_c [,source_c])

Convierte una hilera de caracteres a de un conjunto de caracteres a otro.

COS Number COS(n) Coseno de n.

COSH Number COSH(n) Coseno hiperbólico de n.

COUNT Group COUNT(DISTINCT|ALL e)

Número de registros en una consulta. ALL es el default y e puede ser representado como * para indicar todas las columnas.

EXP Number EXP(n) e elevado a la enésima potencia.

FLOOR Number FLOOR(n) Mayor entero menor o igual a n.

GREATEST Other GREATEST(e [,e]...) El mayor elemento de una lista de expresiones e.

HEXTORAW Conversión HEXTORAW(c) Convierte de una carácter hexadecimal a un raw.

INITCAP Character INITCAP(c) c con la primer letra de cada palabra en mayúscula.

INSTR Character INSTR(1, 2 [, n [, m]]) Busca 1 con n caracteres para la emésima ocurrencia de 2 y retorna la posición de la ocurrencia.

INSTRB Character INSTRB(1,2[,n[,m]]) Igual a INSTR, solo que los parámetros n y m se esperan en términos de bytes.

LAST_DAY Date LAST_DAY(a) Ultimo día del mes que contiene a.

LEAST Other LEAST(e [,e]...) El menor de una lista de expresiones e.

LENGTH Character LENGTH(c) Número de caracteres en c. Si c es un tipo de datos de largo fijo, todos los blancos son incluidos.

LENGTHB Character LENGTHB(c) Igual que LENGTH excepto que en bytes.

LN Number LN(n) Logaritmo natural de n, donde n > 0.

LOG Number LOG(b,n) Logaritmo en base b de n.

LOWER Character LOWER(c) c con todas las letras en minúsculas..

LPAD Character LPAD(1,n [,2]) La hilera 1 rellena a la izquierda hasta completar el largo n. Si el

Page 8: PL_SQL

carácter 2 es indicado se usa como patrón de relleno y sino se utilizan blancos.

LTRIM Character LTRIM(c [,set])

Remueve caracteres a la izquierda de c. Si el conjunto s es definido, remueve los caracteres iniciales hasta que no aparezca el conjunto set.

MAX Other MAX(DISTINCT|ALL e) Máximo de una expresión e.. ALL es el default.

MIN Other MIN(DISTINCT|ALL e) Mínimo de una expresión e. ALL es el default.

MOD Number MOD(r,n) Residuo de dividir r por n..

MONTHS_BETWEEN Date MONTHS_BETWEEN(a,b) Número de meses entre dos fechas a y b..

NEW_TIME Date NEW_TIME(a, z1, z2) Día y hora en la zona z2, cuando la fecha y hora de z1 es a.

NEXT_DAY Date NEXT_DAY(a, c) Primer día de la semana identificada por c que está después de c.

NLSSORT Character NLSSORT((c [,parm]) Hilera de bytes para ordenar c.

NLS_INITCAP Character NLS_INITCAP(c [,parm]) c con la primer letra de cada palabra en mayúscula.

NLS_LOWER Character NLS_LOWER(c [,parm]) c con todas las letras en minúscula

NLS_UPPER Character NLS_UPPER(c [,parm]) c con todas las letras en mayúscula.

NVL Other NVL(e1, e2) Si e1 es nulo, retorna e2. Si e1 no es nulo retorna e1.

POWER Number POWER(m,n) m elevado a la enésima potencia

RAWTOHEX Conversión RAWTOHEX(raw) Convierte un valor raw a su equivalente hexadecimal.

REPLACE Character REPLACE(c, s1 [, r2])

Remplaza cada ocurrencia de la hilera s1 en c con r2. Si r2 se omite las ocurrencias de r1 son borradas.

ROUND Date ROUND(n [,f])

Redondea la fecha al formato del modelo f. Si f es omitido, n será retornado para el día más cercano.

ROUND Number ROUND(n[,m]) n redondeado a m. Si m está, es redondeado a m lugares.

ROWIDTOCHAR Conversion ROWIDTOCHAR(rowid) Convierte de rowid a varchar2.

RPAD Character RPAD(1, n [, 2]) 1 rellenado a la derecha con largo n y con la hilera 2.

RTRIM Character RTRIM(c [, s]) c con los caracteres removidos al final de la hilera.

SIGN Number SIGN(n) -1 if n < 0, 0 if n = 0, 1 if n > 0.

SIN Number SIN(n) Seno de n

SINH Number SINH(n) Seno hiperbólico de n.

SOUNDEX Character SOUNDEX(c) Una hilera con la representación fonética de c.

SUBSTR Character SUBSTR(c, m [,n]) Una porción de c, iniciando en el carácter m por n caracteres. Si m

Page 9: PL_SQL

es negativo se cuentan los espacios a partir del final. Si n es omitido, son retornados todos los caracteres hasta el final de c.

SUBSTRB Character SUBSTRB(c, m [,n]) Igual que SUBSTR excepto que m y n son número de bytes.

SQRT Number SQRT(n) Raíz cuadrada de n.

STDDEV Group STDDEV(DISTINCT|ALL n) Desviación estándar de n.

SUM Group SUM(DISTINCT|ALL n) Suma de números n.

SYSDATE Date SYSDATE Fecha y hora actual.

TAN Number TAN(n) Tangente de n.

TANH Number TANH(n) Tangente hiperbólica de n.

TO_CHAR Conversion TO_CHAR(d [,f [,parm]) Convierte la fecha d a carácter con el formato f y el nls_date_language para parm.

TO_CHAR Conversion TO_CHAR(n [,f [,parm]) Convierte un número n a varchar2, según formato de parm.

TO_DATE Conversion TO_DATE(c [, f [, parm]) Convierte un varchar2 c a un tipo fecha, con el formato f y nls_date_formate parm.

TO_MULTI_BYTE Conversion TO_MULTI_BYTE(c) Convierte c a su equivalente en multibyte.

TO_NUMBER Conversion TO_NUMBER(c [,f [, parm]]) Convierte el carácter c a un número, utilizando el formato f y el nls_number_format parm.

TO_SINGLE_BYTE Conversion TO_SINGLE_BYTE(c) Convierte el carácter multibyte c a su equivalente en byte simple.

TRANSLATE Character TRANSLATE(c, f, t) c con cada ocurrencia en f con cada correspondiente carácter en t.

TRUNC Date TRUNC(c [,f]) c con la porción de hora truncada al formato f.

TRUNC Number TRUNC(n[,m]) n truncado a emésimo decimal.. Si m es omitido, se toma 0.

UID Other UID Un entero que en forma única identifica al usuario.

USER Other USER Usuario actual como varchar2.

UPPER Character UPPER(c) c con las letras en mayúscula.

VARIANCE Group VARIANCE(DISTINCT|ALL n) Varianza de n.

VSIZE Other VSIZE(e) Número de bytes que necesita la representación interna de e.

Algunos ejemplos utilizando funciones.

SELECT SUBSTR(address,1,20),

city

FROM customer

WHERE address IS NOT NULL

AND UPPER(city) = 'ROCHESTER'

Véase que UPPER hacer que al convertir a mayúscula el nombre de la ciudad, hará que si 'Rochester' aparece se convierta para luego compararse con 'ROCHESTER', de tal forma que sean iguales.

SELECT dept_no, SUM(emp_salary), AVG(emp_salary)

FROM emp

Page 10: PL_SQL

WHERE dept_no = dept_no

GROUP BY dept_no;

Aquí se puede ver el uso del SUM y AVG. Véase que cuando se utilizan otras columnas (sin uso de funciones resumen) se debe hacer el GROUP BY por estas columnas.

El comando DECODE

Este es uno de los comandos más importantes. El DECODE tiene la siguiente sintaxis:

DECODE(val, exp1, exp2, exp3, exp4, ..., def);

DECODE primero evalúa el valor o expresión val, y compara con exp1. Si val es igual exp1, la expresión exp2 es retornada. Si val no es igual a exp1, la expresión exp3 será evaluada y retorna la expresiónexp4 si val es igual a exp3. Este proceso continúa hasta que todas las expresiones hayan sido evaluadas. Si no hay coincidencias, el valor por defecto def será retornado.

Es importante siempre agregar un valor por defecto.

SELECT e.ename,

e.job,

DECODE(e.job, 'President', '******', e.sal)

FROM emp e

WHERE e.empno IN (SELECT NVL(z.mgr, e.empno)

FROM emp z);

En esta consulta todos los nombres de los jefes serán obtenidos junto con su salario. Cuando la fila del presidente es obtenida se presentará '******' en lugar de su salario.

Véase que con la función NVL para evaluar el manager_id. En este caso solo el presidente tiene el manager_id nulo y por tanto no será obtenido sin el NVL.

Aunque sal es de distinto tipo de '******', no da error pues Oracle hacer la conversión automática de sal a carácter.

SELECT e.ename,

e.job,

e.sal

FROM emp e

WHERE DECODE(USER,'PRES',e.empno, UPPER(e.ename),e.empno, 0) = e.empno;

En este caso, si el usuario es el presidente todos los empleados serán obtenidos, con los demás empleados solo se obtiene el correspondiente salario.

SELECT e.ename,

e.job

DECODE(USER,'ADMIN', DECODE(e.job, 'PRESIDENT', '*****', e.sal),

'PRES', e.sal, '******')

FROM emp e

WHERE e.empno in (SELECT NVL(z.mgr, e.empno)

FROM emp z);

Acá se utiliza un DECODE anidado dentro de otro. Si el usuario Oracle es 'ADMIN' se muestra el salario de todos excepto del presidente, si el usuario es el presidente presenta todos los salarios y para cualquier otro solo asteriscos.

SELECT d.dname,

e.job,

e.ename

FROM emp e,

dept d

WHERE d.deptno = e.deptno

ORDER BY DECODE(e.job,'PRESIDENT', 0,

DECODE(d.dname,'SALES', 1, 'ADMIN', 2, 3)),

e.ename;

En este caso se utiliza el ORDER BY para ordenar según el job, pero se ajusta para que aparezca primero el presidente luego los vendedores, administradores y todos los demás. Luego del decode son ordenados por el ename.

Page 11: PL_SQL

DDL (Data Definition Language)

El comando CREATE

El CREATE es el comando que inicia al desarrollador, acá se cubrirán los usos más comunes.

Tablas

Cada diseñador de base de datos tendrá que crear una tabla alguna vez. El privilegio de sistema CREATE TABLE es necesario para ejecutar este comando. El DBA es el responsable de administrar dichos privilegios. La sintaxis para crear una tabla es la siguiente

CREATE TABLE [schema.]nombre_tabla

(

columna tipo_dato [default expression] [NOT NULL]

[column_constraint],

...

[constraint de tabla]

)

PCTFREE x PCTUSEDx

INITRANS x MAXTRANS x

TABLESPACE nombre_tablespace

STORAGE clauseCLUSTER cluster clause

ENABLE clause DISABLE clause

AS subconsulta

Ejemplos:

CREATE TABLE addresses (

ADRS_ID NUMBER(6),

ACTIVE_DATE DATE,

BOX_NUMBER NUMBER(6),

ADDRS_1 VARCHAR2(40),

ADDRS_2 VARCHAR2(40),

CITY VARCHAR2(40),

STATE VARCHAR2(2),

ZIP VARCHAR2(10)

);

Este fue un ejemplo sencillo sin utilizar varias capacidades. A continuación se muestra otro ejemplo

CREATE TABLE addresses (

ADRS_ID NUMBER(6) CONSTRAINT PK_ADRS PRIMARY KEY,

ACTIVE_DATE DATE DEFAULT SYSDATE,

BOX_NUMBER NUMBER(6) DEFAULT NULL,

ADDRS_1 VARCHAR2(40) NOT NULL,

ADDRS_2 VARCHAR2(40) DEFAULT NULL,

CITY VARCHAR2(40) DEFAULT NULL,

STATE VARCHAR2(2) DEFAULT 'NY',

ZIP VARCHAR2(10)

)

PCTFREE 5

PCTUSED 65

TABLESPACE adrs_data

STORAGE (INITIAL 5140 NEXT 5140

MINEXTENTS 1 MAXEXTENTS 10

PCTINCREASE 10);

Page 12: PL_SQL

Índices

Estos son utilizados para incrementar el rendimiento de la base de datos. El comando es el CREATE INDEX y cada tabla puede tener varios índices.

CREATE INDEX [schema.]nombre_indice

ON schema.table (nombre_columna ASC/DESC)

CLUSTER schema.cluster

INITRANS x MAXTRANS x

PCTFREE X

TABLESPACE nombre_tablespace

STORAGE clause NOSORT

Ejemplos:

CREATE INDEX x_adrs_id ON ADDRESSES (ADRS_ID);

CREATE INDEX x_city_state ON ADDRESSES (CITY,STATE)

TABLESPACE application_indexes;

El orden de creación es importante a la hora de crear las consultas, para ellas el orden de aparición en el where debe ser el mismo del orden físico de las columnas.

Secuencias

Estas son utilizadas para la generación de llaves únicas consecutivas y enteras, de forma sencilla.

CREATE SEQUENCE [schema.]name

INCREMENT BY x

START WITH x

[MAXVALUE x | NOMAXVALUE]

[MINVALUE x | NOMINVALUE]

[CYCLE | NOCYCLE]

[CACHE x | NOCACHE]

[ORDER | NOORDER]

Para crear una secuencia para adrs_id se puede hacer de la siguiente forma:

CREATE SEQUENCE adrs_seq INCREMENT BY 5 START WITH 100;

Para obtener el nuevo número de una secuencia se utiliza la seudo columna NEXTVAL, precedida del nombre de la secuencia, por ejemplo adrs_seq.nextval retornará 100 en la primer llamada y 105 en la segunda.

Si desea obtener el valor actual de secuencia se utiliza la seudo columna CURRVAL, siempre y cuando haya accedido alguna vez al NEXTVAL.

Page 13: PL_SQL

Otros Objetos

El comando CREATE puede ser utilizado para crear otros objetos como los siguientes:

CREATE xxx, donde xxx es uno de los siguientes:

CLUSTER CONTROLFILE DATABASE

DATABASE LINK

DATAFILE FUNCTION

INDEX PACKAGE BODY PACKAGE

PROCEDURE PROFILE ROLE

ROLLBACK SEGMENT

SCHEMA SEQUENCE

SNAPSHOT SNAPSHOT LOG SYNONYM

TABLE TABLESPACE TRIGGER

USER VIEW

INSERTs, UPDATEs, y DELETEs

El comando INSERT es utilizado para agregar nuevas filas a la base de datos. Este puede ser utilizado para crear una fila a la vez utilizando la expresión VALUES o un conjunto de registros a la vez utilizando una subconsulta. La sintaxis es la siguiente:

INSERT INTO [schema.]nombre_tabla

[(columna [,columna] ...)]

{VALUES (valor [,valor] ...) | subconsulta};

Ejemplo:

INSERT INTO dept (deptno, name, loc)

VALUES (dept_seq.NEXTVAL,'CUSTOMER SERVICE', 'NEW YORK');

En este caso se insertan una fila en la tabla de departamentos. Acá se utiliza la secuencia dept_seq para obtener el siguiente valor de deptno.

INSERT INTO emp (empno, ename, deptno, hire_date,

job, sal, mgr)

SELECT emp_seq.NEXTVAL, new.ename, 30, SYSDATE,

'CUSTOMER REPRESENTATIVE', new.sal, 220

FROM candidates new

WHERE new.accept = 'YES'

AND new.deptno = 30;

En este caso se insertarán todas las filas de la tabla de candidates que han sido asignados al departamento número 30. Dado que el número de departamento y mgr son conocidos se pueden utilizar constantes en la subconsulta.

Page 14: PL_SQL

UPDATE

El comando UPDATE es utilizado para cambiar la información existente en las filas de la base de datos. La sintaxis del UPDATE es

UPDATE [schema.]nombre_tabla

SET columna1 = {expr | subconsulta}

...

[, columnan = = {expr | subconsulta}]

WHERE condicion;

Ejemplos:

UPDATE emp

SET deptno = 30

WHERE ename = 'DOE';

En este ejemplo se transfiere al empleado DOE al departamento 30. Si hubiesen más de un empleado con el nombre DOE tendría que agregarse condiciones en el WHERE.

UPDATE emp

SET sal = sal + (sal * .05);

Este da a cada empleado un 5 por ciento de incremento en el salario.

UPDATE emp a

SET a.sal = (SELECT a.sal +

(a.sal * DECODE(d.dname,

'SALES', .1,

'ADMIN', .07,

.06)

)

FROM dept d

WHERE d.deptno = a.deptno)

WHERE a.deptno = (SELECT deptno

FROM dept y

WHERE y.loc = 'ROCHESTER');

Este ejemplo da un incremento a los empleados de Rochester. El monto del incremento es manejado por el DECODE, evaluando el nombre del departamento. Los empleados de ventas reciben un 10%, los de administración reciben un 7% y los demás un 6%.

DELETE

El comando DELETE es utilizado para borrar registros de la base de datos. La sintaxis de DELETE es:

DELETE [FROM] [schema.]nombre_tabla

WHERE condición

Ejemplos:

DELETE FROM emp e

WHERE e.ename = 'DOE';

Si el empleado Doe sale de la compañía, se borra de la base de datos.

DELETE FROM dept

WHERE loc IS NULL;

En este ejemplo, todos los registros en la tabla departamento serán borrados si el loc está nulo.

Page 15: PL_SQL

Véase que en ningún caso el comando es permanente. Para que sea permanente debe aplicarse el comando COMMIT. Si se desea reversar los cambios realizados se debe utilizar el ROLLBACK (si fue usada una secuencia el consecutivo no se devuelve).

Notas

Cuando desea comparar fechas, si la idea es verificar el día y no interesa la hora (con minutos y segundos), es recomendable utilizar el TRUNC para hacerlo (siempre y cuando usted sepa que se guarda la hora).

Recuerde que cuando se comparan nulos en expresiones booleanas, siempre devuelven falso.

PL/SQL

PL/SQL

Hasta el momento se han visto distintos comandos para crear scripts SQL, sin embargo, estos tienen limitantes importantes en cuanto a la secuencia de ejecución de instrucciones, el uso de variables, la modularidad y la gestión o manejo de posibles errores.

Para poder solventar estas limitantes se incorpora en el servidor una gestor PL/SQL, al igual que en las diferentes herramientas. Este permite el manejo de variables, estructura modular (procedimientos y funciones), estructuras de control, manejo de excepciones y una integración con el entorno Oracle.

Los programas creados con PL/SQL pueden ser almacenados en la base de datos como cualquier otro objeto, de esta forma se facilita a los usuarios el acceso a estos programas. De igual forma el lenguaje permite la incorporación disparadores en el ámbito de base de datos, que permiten reflejar de mejor manera las reglas del negocio e implementar elementos de auditoría en la base de datos.

Bloques PL/SQL DECLARE-BEGIN-END

El DECLARE es un comando que limita la creación de bloques dentro de PL/SQL, como se presenta a continuación:

BEGIN

...

<<inner>>

[DECLARE

...]

BEGIN

...

END inner;

...

[EXEPTION

...]

END;

Véase que se permite el anidamiento de bloques. Ahora bien el uso del DECLARE para la creación de bloques es necesario cuando es necesario definir variables o bien cursores a ser utilizados en el cuero de ejecución.

Page 16: PL_SQL

El BEGIN y END fija el primero el inicio del bloque (cuando no está el DECLARE) y el segundo el fin de dicho BLOQUE.

En el caso de bloques anidados el bloque de adentro puede referenciar variables del bloque externo, pero no a la inversa. Ahora se presenta un ejemplo en donde se borra el departamento 20, pero antes se crea un departamento provisional, al que asigna los empleados del departamento 20.

DECLARE

v_num_empleados NUMBER(2);

BEGIN

INSERT INTO dept

VALUES ( 99, 'PROVISIONAL', NULL );

UPDATE emp

SET deptno = 99

WHERE deptno = 20;

-- se asigna el total de empleados cambiados de

-- departamento

v_num_empleados := SQL%ROWCOUNT;

DELETE FROM dept

WHERE deptno = 20;

-- para que este mensaje se muestre en SQL*PLUS

-- asegúrese de ejecutar previamente

-- SET SERVEROUTPUT ON

Dbms_output.put_line ( v_num_empleados || ' empleados ubicados en

PROVISIONAL.' );

EXCEPTION

WHEN OTHERS THEN -- en cualquier error ejecutar

ROLLBACK;

RAISE_APPLICATION_ERROR ( -20000, 'Error en la aplicación.' );

END;

Page 17: PL_SQL

Tipos de datos básicos

PL/SQL cuenta con los mismos tipos de datos de SQL, además de otros propios, para lo cual se muestra a continuación una descripción de cada uno de ellos.

Las longitudes máximas según versiones de bases de datos y PL/SQL son:

Page 18: PL_SQL

Variables

Dentro del DECLARE de un bloque se pueden declarar las variables necesarias en la ejecución del bloque PL/SQL.

Declaración e iniciación

La sintaxis para declarar variables es la siguiente:

<variable> <tipo> [NOT NULL] [{:=|DEFAULT} <valor>]

Por ejemplo

DECLARE

mi_var VARCHAR2(10) := 'AMIGOS';

tu_var NUMBER(5,2) DEFAULT 5.32;

...

Uso de %TYPE y %ROWTYPE

Estos pueden ser utilizados cuando se necesita no declarar con un tipo de datos explícito, sino que se desea obtener de una definición previa el tipo. En este caso el %TYPE sirve para declara una variable del mismo tipo de datos de otra y el %ROWTYPE para declarar un registro con los campos de otro.

Ejemplos:

DECLARE

My_employee_id emp.empid%TYPE;

Rec_cliente customer%ROWTYPE;

BEGIN ...

DECLARE

My_sal emp.sal%TYPE := 0;

My_ename emp.ename%TYPE:= 'SMITH';

BEGIN ...

Manualmente declaración de registro

DECLARE TYPE

t_employee IS RECORD ( My_empid emp.empid%TYPE,

My_lastname emp.ename%TYPE,

My_salary emp.sal%TYPE);

My_employee t_employee;

BEGIN ...

Constantes

Se pueden declarar constantes mediante el siguiente formato:

<nombre constante> CONSTANT <tipo> := <valor>

Ejemplo

CREATE FUNCTION find_circle_area ( p_radius IN circle.radius%TYPE )

RETURN NUMBER IS

My_area number := 0;

Pi CONSTANT NUMBER := 3.14159265358;

BEGIN

My_area := (p_radius*p_radius)* Pi;

RETURN my_area;

END;

Page 19: PL_SQL

Operador asignación, comparación y lógicos

Para asignar valores a las variables se utiliza el símbolo :=, de esta forma,

DECLARE

V_fecha_nac DATE;

V_nombre VARCHAR2 := 'Sin Asignar'; -- inicializa

BEGIN

. . .

V_fecha_nac := TO_DATE ( '01-01-2000', 'DD-MM-YYYY' );

V_nombre := 'Pedro Perez';

. . .

END;

En el caso de tener que comparar elementos se pueden utilizar los siguientes símbolos de comparación y lógicos:

Símbolo Descripción

> Mayor

>= Mayor o igual

< Menor

<= Menor o igual

= Igual

IN Contenido en un conjunto

AND Y lógico

OR O lógico

NOT Negación

Estructuras de Control

Las estructuras de control presentes en PL/SQL son las comunes de los lenguajes de programación estructurados: IF, WHILE, FOR y LOOP.

Control alternativo

El control para manejo de opciones es el IF, el cual tiene la siguiente sintaxis:

(1)

IF <condición> THEN

Instrucciones;

...;

END IF;

(2)

IF <condición> THEN

Instrucciones;

...;

ELSE

Page 20: PL_SQL

Instrucciones;

...;

END IF;

(3)

IF <condición> THEN

Instrucciones;

...;

ELSIF <condición2> THEN

Instrucciones;

...;

ELSIF <condición3> THEN

Instrucciones;

...;

ELSE

Instrucciones;

...;

END IF;

Vea el siguiente ejemplo:

PROCEDURE init_recip_list IS

recipient_num NUMBER;

i BINARY_INTEGER;

j BINARY_INTEGER := 1;

k BINARY_INTEGER;

BEGIN

FOR i in 1..10 LOOP

IF i = 1 THEN

j := j + 1;

ELSE

FOR k in 1..j LOOP

IF k = i THEN

j := j + 2;

ELSIF k = j THEN

j := j + 1;

END IF;

END LOOP;

END IF;

END LOOP;

END;

Otro control interactivo es el EXIT-WHEN, el cual permite combinarse con el LOOP.

OPEN c_line_item;

LOOP

FETCH c_line_item INTO rec_info;

EXIT WHEN (c_line_item%NOTFOUND) OR (c_line_item%NOTFOUND is NULL);

END LOOP;

CLOSE c_line_item;

Page 21: PL_SQL

Control repetitivo

Pueden tenerse varias condiciones para los ciclos.

WHILE

Este verifica una condición, que mientras sea verdadera se mantiene en el ciclo. La sintaxis es la siguiente:

WHILE <condición> LOOP

Instrucciones;

...;

END LOOP;

FOR numérico

Utilice este ciclo para realizar iteraciones sobre un rango de números.

FOR <variable> IN <mínimo>..<máximo> LOOP

Instrucciones;

...;

END LOOP;

FOR con cursores

Este es un tipo que combina el control de cursores y el uso de ciclos para recorrerlo. Acá no hace falta abrir y cerrar el cursor directamente, sino que el FOR se encarga de ello.

CURSOR c_line_item IS

(estatuto SQL)

BEGIN

FOR rec_info IN c_line_item LOOP

Intrucciones;

END LOOP;

END;

Véase que uno declara el rec_info, que para los efectos es un registro de tipo c_line_item (%ROWTYPE), el cual no es necesario declararlo, sino que se crean como una variable local al FOR. Por último, el FOR realiza de forma implícita el FETCH sobre el rec_info.

LOOP

Utilice el LOOP para realizar procesamiento interactivo basado en escogencias lógicas. La sintaxis común es

LOOP

Instrucciones;

...;

EXIT WHEN <condición>;

Instrucciones;

...;

END LOOP;

Page 22: PL_SQL

Cursores

En general PL/SQL utiliza cursos para todos los comandos de acceso a la base de datos. En este caso el lenguaje permite los cursores implícitos y explícitos. Los cursos implícitos son aquellos establecidos para los comandos que no cuentan con un cursor explícito declarado. Usted deberá utilizar cursores explícitos para aquellas consultas que retornen más de una fila.

Declaración de Cursores

Se debe definir el curso en el área de definición de variables, pero se utilizan las palabras reservadas CURSOR nombre_cursor IS, como se muestra a continuación:

CURSOR c_line_item IS

(comando sql)

El comando SQL puede ser cualquier consulta válida. Una vez creada la definición del cursor, usted puede ser capaz del controlar el flujo del mismo por medio del OPEN, FETCH y el CLOSE.

Control del Cursor

Para manipular los datos del cursor, usted debe usar primero el comando OPEN seguido del nombre del cursor. Posterior a esto debe utilizar el comando FETCH para extraer las filas del cursor, según el criterio seguido por el select. Por último, una vez que ha sido procesado por completo, debe utilizarse el comando CLOSE seguido del nombre del cursor, para esta forma terminar cualquier actividad asociada con el cursor abierto. Veamos un ejemplo:

OPEN c_line_item;

...

FETCH c_line_item INTO li_info;

...

(retrieved row processing)

...

CLOSE c_line_item;

En este caso el código abre el cursor c_line_item y procesa las filas extraídas. Luego de procesar toda la información cierra el cursor.

Atributos del cursor explícito

Existen cuatro atributos asociados con los cursores de PL/SQL:

%NOTFOUND

%FOUND

%ROWCOUNT

%ISOPEN

El %NOTFOUND devuelve FALSE cuando es extraída una fila, TRUE si el último FETCH no extrajo fila alguna y NULL si el SELECT del cursor no ha retornado datos.

El %FOUND es lógicamente opuesto al %FOUND en cuanto al TRUE y FALSE, pero sigue

Page 23: PL_SQL

retornando NULL si el cursor no ha retornado datos.

El %ROWCOUNT se utiliza para determinar cuantas filas han sido extraídas en un punto. Este valor se incrementa con cada fila extraída y tiene valor cero cuando apenas ha sido abierto el cursor.

Por último, el %ISOPEN, tiene valores TRUE o FALSE, dependiendo de si el cursor asociado ha sido abierto o no.

Parámetros de Cursores

Se pueden especificar parámetros para los cursores de la misma forma que se pasan a procedimientos y/o funciones. Veamos el siguiente ejemplo:

CURSOR c_line_item (p_order_num IN NUMBER) IS

SELECT merch_gross, recipient_num

FROM line_item

WHERE order_num = p_order_num;

Véase que los parámetros son siempre de tipo IN (solo de entrada), pero el tipo de datos es cualquier tipo de datos válido. La idea es referenciar el parámetro dentro de la consulta, y este se pasa a la hora de abrir el cursor.

Es posible también definir los parámetros con default, de forma tal que se puede variar la cantidad de parámetros a utilizar en el cursor.

DECLARE

CURSOR c_line_item ( order_num NUMBER DEFAULT 100,

line_num NUMBER DEFAULT 1 ) IS ...

. . .

BEGIN

...

OPEN c_line_item ( 19 ); -- valores 19, 1

...

OPEN c_line_item ( 20, 4 ); -- valores 20, 4

...

OPEN c_line_item; -- valores 100, 1

...

END;

De esta forma se pueden pasar todos, uno o ningún parámetro a la hora de abrir el cursor.

Para un cursor

DECLARE CURSOR c_emp IS

SELECT e.ename , e.empid

FROM emp e;

...

My_employee c_emp%ROWTYPE;

BEGIN

My_employee.empid := 100;

...

OPEN c_emp;

FETCH c_emp INTO My_employee;

CLOSE c_emp;

IF My_employee.sal > 200 THEN

...

END;

Page 24: PL_SQL

Excepciones

El control de excepciones es el mecanismo del PL/SQL para manejar errores de tiempo de ejecución. El utilizar este mecanismo permite continuar la ejecución del programa, si el error no es muy grave, lo cual quedaría a decisión del programador.

Usted debe definir el manejador de la excepción dentro de la especificación del programa o bloque. Cuando un error de programa ocurre el control se pasa al bloque de manejo de excepciones, luego de lo cual se regresa el control al que invoca al programa o bien termina según lo defina el programador.

Excepciones definidas por el usuario

El PL/SQL da la posibilidad de que el usuario defina excepciones en área de especificaciones. Vea el ejemplo:

ot_failure EXCEPTION;

En este caso el nombre de la excepción es ot_failure. El código asociado que maneja la excepción es:

EXCEPTION

WHEN OT_FAILURE THEN

...

Excepciones del sistema

Estas son las excepciones predefinidas del sistema. Un ejemplo de ellas es el NO_DATA_FOUND, que se dispara cuando un SELECT-INTO no obtiene registros, veamos:

DECLARE

v_empid emp.empid%TYPE;

BEGIN

...

SELECT e.empid INTO v_empid

FROM emp e

WHERE e.ename = 'CHARLIE';

EXCEPTION

WHEN NO_DATA_FOUND THEN

RAISE OT_FAILURE;

WHEN TOO_MANY_ROWS THEN

RAISE OT_FAILURE;

END;

En este caso cuando el SELECT no devuelve columnas o devuelve más de una se levanta una excepción que a su vez es atrapada para ser reenviada a una excepción definida por el usuario.

Vea a continuación la lista de excepciones del sistema;

Nombre Error Oracle

CURSOR_ALREADY_OPEN ORA-06511

DUP_VAL_ON_INDEX ORA-00001

INVALID_CURSOR ORA-01001

INVALID_NUMBER ORA-01722

LOGIN_DENIED ORA-01017

NO_DATA_FOUND ORA-01403

Page 25: PL_SQL

NOT_LOGGED_ON ORA-01012

PROGRAM_ERROR ORA-06501

STORAGE_ERROR ORA-06500

TIMEOUT_ON_RESOURCE ORA-00051

TOO_MANY_ROWS ORA-01422

TRANSACTION_BACKED_OUT ORA-00061

VALUE_ERROR ORA-06502

ZERO_DIVIDE ORA-01476

Adicional a las excepciones anteriores existe una más llamada OTHERS, que atrapa cualquier excepción que no haya sido establecida explícitamente.

WHEN OTHERS THEN

out_status_code := 'FAIL';

out_msg := g_out_msg || ' ' || SUBSTR(SQLERRM, 1, 60);

SQLERRM es válido cuando se invoca dentro de un manejador de excepción, en otro caso debe pasarse como parámetro el código del error.

Procesamiento de transacciones

Las opciones de procesamiento de transacciones son las mismas para SQL que para PL/SQL. Las operaciones para manejo de transacciones son:

SET TRANSACTION inicializa una transacción y define las características clave.

COMMIT Finaliza la transacción actual salvando los cambios en la base de datos e iniciando una

nueva transacción.

ROLLBACK Finaliza la transacción actual, descartando los cambios realizados en la base de datos.

SAVEPOINT Define un punto intermedio para que la transacción pueda realizar rollbacks parciales.

SET TRANSACTION

Este comando es utilizado para definir el inicio de una transacción. Alguno de los efectos que se puede lograr con el set transaction es que la transacción pueda ser definida de solo lectura (read-only). Ejemplos del uso del comando son:

SET TRANSACTION READ ONLY;

SET TRANSACTION READ WRITE;

COMMIT

Este comando representa el punto del tiempo donde el usuario ha realizado una serie de cambio lógicos que se han agrupado y que dado que no ha habido errores, el usuario está listo para salvar su trabajo. De forma implícita se inicia una nueva transacción luego del COMMIT.

Page 26: PL_SQL

Es importante saber que cuando el usuario sale de SQL*Plus se ejecuta un COMMIT automático, de igual forma cuando ejecuta un comando de definición de datos.

COMMIT;

COMMIT WORK;

ROLLBACK

Si el usuario se diera cuenta en cualquier punto de la transacción que cometió un error, puede descartar los cambios hechos en la base de datos utilizando el ROLLBACK. Luego del ROLLBACK, se inicia una nueva transacción. Siempre se ejecuta un rollback cuando ocurre un error en la ejecución o bien cuando el comando es finalizado con CTRL.+C.

ROLLBACK;

ROLLBACK WORK;

SAVEPOINT

En algunos casos tenemos transacciones muy grandes o que envuelven la modificación de muchos datos, y no se desea reversar la misma por haber tenido un pequeño error en la ejecución del último comando. Los savepoints permiten dividir el trabajo de la transacción diferentes segmentos. De esta forma el usuario puede ejecutar rollbacks para un savepoint solamente, dejando los cambios previos intactos. Veamos un ejemplo:

UPDATE spanky.products

SET quantity = 55

WHERE product# = 59495;

SAVEPOINT A1;

UPDATE spanky.products

SET quantity = 504;

ROLLBACK TO SAVEPOINT A1;

COMMIT;

En el anterior ejemplo los cambios realizado por el segundo UPDATE no son salvados cuando se realiza el COMMIT, dado que el ROLLBACK anterior a este los revierte.

Recuerde que la base de datos provee de los mecanismos de bloqueo para que solo un usuario pueda modificar a la vez un registro de la base de datos.

Otro aspecto importante, para el caso de PL/SQL, es que el inicio de un bloque no define el inicio de una transacción.

Page 27: PL_SQL

Procedimientos / Funciones

Para definir un procedimiento, es necesario definir el nombre y los parámetros que serán pasados.

PROCEDURE get_order_total ( in_order_num IN NUMBER,

out status_code OUT VARCHAR2,

out_msg OUT VARCHAR2,

out_merch_total OUT NUMBER,

out_shipping IN OUT NUMBER,

out_taxes IN OUT NUMBER,

out_grand_total OUT NUMBER

) IS

/* sección de declaración */

...

BEGIN

...

END;

Las funciones son parecidas y tan solo cambia el uso de la palabra reservada PROCEDURE por FUNCTION y la selección del tipo de datos devuelto;

FUNCTION calc_ship_charges ( in_merch_total IN NUMBER ) RETURN NUMBER IS

/* sección de declaración */

...

BEGIN

...

RETURN ( valor del tipo declarado de la función )

END;

Tipos de Modos para los Parámetros

Se pueden definir parámetros IN (el valor por defecto), IN OUT, o OUT, dependiendo de la naturaleza de información pasada.

IN parámetros solo de entrada (no pueden ser modificados). IN OUT entrada y salida (pueden ser cambiados). OUT solo de salida.

Especificaciones

PROCEDURE init_line_items IS

(local variables)

BEGIN

(subprogram logic)

EXCEPTION

(exception handling)

END init_line_items;

Esta es la estructura general para procedimientos, la cual es muy similar a la de las funciones.

Parámetros Default

Es posible definir valores por defecto para los parámetros de una función o procedimiento, para ello vea el siguiente ejemplo:

PROCEDURE calc_ship_charges( merch_total NUMBER DEFAULT 5.95 ) IS

...

Si el parámetro no es incluido cuando se invoca el procedimiento se toma el valor por defecto 5.95.

Page 28: PL_SQL

Paquetes

Los paquetes son utilizados para guardar subprogramas y otros objetos en la base de datos y en bibliotecas de las herramientas Oracle.

Elementos de un paquete

Un paquete se encuentra compuesto por dos elementos claramente definidos:

Especificación

En este se tienen las declaraciones públicas (accesible desde cualquier parte de la aplicación) de subprogramas, tipos, constantes, variables, cursores, excepciones, etc. Este actúa como una interfaz con otros programas.

Cuerpo

Contiene los detalles de implementación y declaraciones privadas accesibles sólo desde los objetos del paquete. Es una caja negra para el resto de programas.

Creación de un paquete

Para crear paquetes en la base de datos puede ser utilizado el SQL*PLUS mediante los comandos CREATE PACKAGE y CREATE PACKAGE BODY, cuyos formatos son los siguientes:

CREATE [OR REPLACE] PACKAGE <nombrepaquete> AS

<declaración de constantes, variables, cursores,

excepciones y otros objetos públicos>

<especificación de subprogramas>

END [<nombrepaquete>];

CREATE [OR REPLACE] PACKAGE BODY <nombrepaquete> AS

<declaración de constantes, variables, cursores,

excepciones y otros objetos privados>

<cuerpo de subprogramas>

[BEGIN

instrucciones de inicialización>;]

<END [<nombrepaquete>];

Ejemplo de declaración de un paquete:

CREATE PACKAGE emp_actions AS -- especificación

TYPE EmpRecTyp IS RECORD ( emp_id INTEGER,

salary REAL

);

CURSOR desc_salary RETURN EmpRecTyp;

PROCEDURE hire_employee ( ename VARCHAR2,

job VARCHAR2,

mgr NUMBER,

sal NUMBER,

comm NUMBER,

deptno NUMBER

);

PROCEDURE fire_employee ( emp_id NUMBER );

Page 29: PL_SQL

END emp_actions;

CREATE PACKAGE BODY emp_actions AS -- cuerpo

CURSOR desc_salary RETURN EmpRecTyp IS

SELECT empno, sal

FROM emp

ORDER BY sal DESC;

PROCEDURE hire_employee ( ename VARCHAR2,

job VARCHAR2,

mgr NUMBER,

sal NUMBER,

comm NUMBER,

deptno NUMBER

) IS

BEGIN

INSERT INTO emp VALUES (empno_seq.NEXTVAL, ename, job,

mgr, SYSDATE, sal, comm, deptno);

END hire_employee;

PROCEDURE fire_employee ( emp_id NUMBER ) IS

BEGIN

DELETE FROM emp

WHERE empno = emp_id;

END fire_employee;

END emp_actions;


Recommended