59
Introducción a Oracle SQL y PL/SQL Introducción Se transforma requerimientos del negocio dentro de una base de datos operacional. Estrategia y análisis Diseño Construcción y documentación Transición Producción Una BD es una colección de información organizada, hay 4 tipos jerárquica, red, relacional y relacional de objetos Concepto de BD relacional Colección de objetos o relaciones Un grupo de operadores pueden actuar en las relaciones para producir otras relaciones Integridad de los datos para exactitud y consistencia Definición de una BD relacional Es una colección de relaciones o tablas en dos dimensiones Modelos de datos Son la piedra angular del diseño ayudan a entender lo que quiere el cliente. Modelos ER Los datos son divididos dentro de categorías discretas o entidades, un modelo de relación entre entidades es una ilustración de varias entidades en el negocio y la relación entre estas, los modelos separan la información requerida por los negocios de las actividades de estos. Componentes Entidad : Objeto que representa la información que se necesita Atributo : Describe o califica la entidad Relación : Asociación entre entidades mostrando opcionalidad y grado(cardinalidad). Identificadores únicos Son una combinación de atributos o relaciones o ambos, este hace que cada ocurrencia de una entidad sea única Símbolo #, secundario (#) Relacionando múltiples tablas Cada tabla contiene datos que describen exactamente una entidad, las categorías de los datos son listados en los atributos y los casos individuales en las filas. Las llaves foráneas son basadas en valores de datos y son puramente lógicos, no físicos, apuntadores. Propiedades de una BD relacional Puede ser accedida y modificada con sentencias structured query language (SQL) el cual permite comunicarse con el servidor Contiene una colección de tablas Usa un grupo de operadores Sistema de BD relacional Se puede almacenar y administrar datos con todas las ventajas de la estructura relacional PL/SQL Oracle 8 : Sistema de administración de BD relacionales de objetos Provee una nueva máquina que trae programación orientada a objetos, tipos de datos complejos, objetos de negocio complejos y total compatibilidad con el mundo relacional. Usuario define tipos de datos y objetos Soporta objetos grandes y multimedía

Introducción a Oracle SQL y PL Volumen 1 y 2

Embed Size (px)

DESCRIPTION

introduccion a oracle y pl/sql

Citation preview

Page 1: Introducción a Oracle SQL y PL Volumen 1 y 2

Introducción a Oracle SQL y PL/SQL

Introducción Se transforma requerimientos del negocio dentro de una base de datos operacional.

Estrategia y análisis Diseño Construcción y documentación Transición

Producción

Una BD es una colección de información organizada, hay 4 tipos jerárquica, red,

relacional y relacional de objetos

Concepto de BD relacional

Colección de objetos o relaciones

Un grupo de operadores pueden actuar en las relaciones para producir otras relaciones

Integridad de los datos para exactitud y consistencia

Definición de una BD relacional

Es una colección de relaciones o tablas en dos dimensiones

Modelos de datos

Son la piedra angular del diseño ayudan a entender lo que quiere el cliente.

Modelos ER

Los datos son divididos dentro de categorías discretas o entidades, un modelo de

relación entre entidades es una ilustración de varias entidades en el negocio y la

relación entre estas, los modelos separan la información requerida por los negocios de

las actividades de estos.

Componentes

Entidad : Objeto que representa la información que se necesita

Atributo : Describe o califica la entidad

Relación : Asociación entre entidades mostrando opcionalidad y grado(cardinalidad).

Identificadores únicos

Son una combinación de atributos o relaciones o ambos, este hace que cada

ocurrencia de una entidad sea única Símbolo #, secundario (#)

Relacionando múltiples tablas

Cada tabla contiene datos que describen exactamente una entidad, las categorías de

los datos son listados en los atributos y los casos individuales en las filas.

Las llaves foráneas son basadas en valores de datos y son puramente lógicos, no

físicos, apuntadores.

Propiedades de una BD relacional

Puede ser accedida y modificada con sentencias structured query language (SQL) el

cual permite comunicarse con el servidor

Contiene una colección de tablas

Usa un grupo de operadores

Sistema de BD relacional

Se puede almacenar y administrar datos con todas las ventajas de la estructura

relacional PL/SQL

Oracle 8 : Sistema de administración de BD relacionales de objetos

Provee una nueva máquina que trae programación orientada a objetos, tipos de datos

complejos, objetos de negocio complejos y total compatibilidad con el mundo

relacional.

Usuario define tipos de datos y objetos

Soporta objetos grandes y multimedía

Page 2: Introducción a Oracle SQL y PL Volumen 1 y 2

2

Oracle 8i : BD en plataforma internet

Contiene herramientas avanzadas para administrar todos los tipos de datos en web

sites.

iFS Internet File System combina el poder de Oracle 8i con el fácil uso de un FS, los

usuarios pueden fácilmente acceder a los archivos y folders en un iFS usando una

variedad de protocolos como HTML, FTP, IMAP4 .

Oracle 8i incluye una robusta, integrada y escalable máquina virtual de java dentro

del servidor Jserver

O8i provee full integración con Microsoft Transaction Server (MTS)

Plataforma de internet Oracle

Para e-commerce y data warehousing es construida en 3 piezas principales

1. Clientes Browser based para procesar presentación

2. Servidores de aplicación para ejecutar lógica de los negocios y lógica de la

presentación para clientes browser-based

3. Bases de datos para ejecutar lógica de negocios intensiva y servicio de datos

Sentencias SQL

SELECT Recuperación de datos

INSERT DML

UPDATE

DELETE

CREATE DDL

ALTER

DROP

RENAME

TRUNCATE

COMMIT Control transaccional

ROLLBACK

SAVEPOINT

GRANT Lenguaje de control de datos (DCL)

REVOKE

Hacerca de PL/SQL Es una extención de SQL , la manipulación de datos y las

sentencias de consulta de SQL son incluidas dentro de unidades de código

procedimentales

Ambiente PL/SQL Un bloque PL/SQL es procesado por la máquina PL/SQL la cual

puede residir dentro de la herramienta o dentro del servidor.

Cuando se invoca PL/SQL desde un programa, SQL *Plus o server manager, lo

procesa el servidor , este separa las sentencias SQL y las envia individualmente al

ejecutor de sentencias SQL

PL/SQL

BLOCK Ejecutor de sentencias

procedimentales

EJECUTOR DE SENTENCIAS SQL

Máquina PL/SQL

Servidor Oracle

PL/SQL

BLOCK

Page 3: Introducción a Oracle SQL y PL Volumen 1 y 2

3

Capítulo 1 escribiendo sentencias SQL básicas

Capacidades de las sentencias SQL

Se recupera información usando SELECT haciendo.

Selección : Para elegir filas de una tabla

Proyección : Elegir columnas

Join : Trae datos almacenados en diferentes tablas

SELECT [DISTINCT] (*, column [alias])

FROM table;

Escribiendo sentencias SQL

Sentencia SQL pueden ser entradas en una o más líneas

Las palabras clave no pueden ser divididas a través de líneas

Dentro de SQL*Plus una sentencia SQL es entrada en el prompt, y las líneas

siguientes son numeradas , esto se llama SQL buffer

Para seleccionar todas las filas con * o enunciándolas todas en el SELECT.

Encabezados por default de las columnas

Justificación : Fecha y carácteres a la izquierda, Números a la derecha

Default : Mayúsculas

Expresiones aritméticas Pueden contener operadores aritméticos + - / *

Nota : SQL*Plus ignora espacios en blanco antes y después del operador

Precedencia de operadores * / + - , operadores de la misma precedencia son

evaluados de izquierda a derecha, los paréntesis alteran la precedencia.

Definiendo valores NULL Es diferente de cero (número ) espacio (carácter) , es

unavailable, unassigned, unknow, en expresiones aritméticas toda se vuelve NULL.

Definiendo alias Renombra el encabezado de la columna, sigue al nombre de la

columna AS es opcional, se requiere comillas dobles si tiene espacios o carácteres

especiales, Para que el alias no salga en mayúsculas encerrarlo en comillas dobles.

Operador de concatenación | | Se combinan las columnas para que haya una sola

salida.

SELECT ename||job AS “Employes”

FROM emp;

Strings de carácteres literales Un literal es un carácter, número o fecha incluido en

el SELECT.

Deben ser encerrados en comillas simples

Cada literal sale una vez por cada fila retornada

SELECT ename | | ‘ is a ‘ | | job AS “Emplye Details”

FROM emp;

Eliminar filas duplicadas DISTINCT , UNIQUE

Interacción de SQL y SQL*Plus

SQL es un lenguaje de comandos para comunicarse con el servidor, cuando se entra

una sentencia, esta se almacena como parte de la memoria llama SQL buffer y ahí se

mantiene mientras no se entre otra sentencia.

SQL*Plus Es una herramienta que reconoce y ejecuta sentencias SQL, acepta

entradas SQL de archivos, provee un editor para modificar sentencias SQL, controla

el ambiente.

Page 4: Introducción a Oracle SQL y PL Volumen 1 y 2

4

SQL SQL*Plus

Lenguaje Reconoce sentencias SQL

Es ANSI Interfaz propietaria de

Oracle para ejecutar sentencias SQL

Manipula datos y definiciones de tablas No manipula valores en la BD

Queda en un buffer SQL Es entrado líneas a líneas al tiempo, no

es

Almacenado en el SQL buffer

No tiene carácter de continuación Si tiene (-)

No puede ser abreviado Si puede ser abreviado

Usa carácter de terminación Se ejecuta inmedíatamente

Usa funciones para formatear datos Usa comandos para formatear

SQL*Plus

Categoría Propósito

Environment Afecta en general todas las sentencias SQL para la sesión

Format Formatea resultados de la consulta

File Manipulatión Saves, Loads y corre archivos de scripts

Executión Envia sentencias SQL del buffer al servidor

Edit Modifica sentencias SQL en el buffer

Interacción Permite que se pase y se cree variables para sentencias SQL

Miscellaneous Contiene varios comandos para conectarse a la BD, manipular

el ambiente y desplegar definiciones de columnas

DESC[RIBE] tablename

Comandos de edición de SQL*Plus

Comando Descripción

A[PPEND] text Adiciona texto al final de la líneas corriente

C[HANGUE] text/old/new Cambia texto viejo por nuevo en la líneas corrienta

C[HANGUE] /text/ Borra texto de la líneas corriente

CL[EAR] BUFF[ER] Borra todas las líneas del SQL buffer

DEL Borra la líneas corriente

I[NPUT] Inserta un número indefinido de líneas

I[NPUT] text Inserta una líneas con el texto

L[IST] Lista todas las líneas en el SQL buffer

L[IST] n Lista la líneas n

L[IST] m n Lista las líneas entre m y n

N Especifica la líneas a ser la líneas corriente

n text Reemplaza la líneas n con el texto

0 text Inserta una líneas antes de la líneas 1

Command Descripción

SAV[E] filename [.ext] Salva las líneas corrientes del SQL buffer a un archivo

[REP[LACE]APP[END]]

GET filename[.ext] Trae un archivo salvado al SQL buffer

STA[RT] filename[.ext]

@filename

ED[IT] Invoca al editor y salva el buffer corriente en afiedt.buf

EDIT [Filename[.ext]]

SPO[OL] [filaname[.ext]]

OFF|OUT

EXIT

Page 5: Introducción a Oracle SQL y PL Volumen 1 y 2

5

Capítulo 2 Restringiendo y ordenando datos

Se usa la clausula WHERE para restringir datos, Comparando valores de columnas,

literales, expresiones aritméticas y funciones.

Fechas y cadenas de carácteres

Son encerrados en columnas simples, los carácteres son sensitivos, el formato por

default de las fechas es DD-MON-YYYY

SELECT ename

FROM emp

WHERE ename = ‘JAMES’;

BETWEEN : Desplegar un rango de valores

IN : Para comparar con una lista

LIKE : Comparar con un patrón de carácteres, usar comodines %, _ , se pueden

combinar los comodines. Se puede usar la opción de ESCAPE.

SELECT * FROM dept WHERE dname LIKE ‘%\_%’ ESCAPE ‘ \ ‘ ;

IS NULL : Para encontrar valores NULL, no se pueden encontrar con =

Operadores lógicos

AND : NULL and FALSE = FALSE

OR : NULL and TRUE = TRUE

NOT : NULL and TRUE = NULL

Reglas de precedencia

1 todos los operadores de comparación, 2 NOT , 3 AND y 4 OR, se alteran con

paréntesis.

ORDER BY : Para ordenar ASC, DESC, si no se usa el orden es indefinido, se

pueden organizar resultados por más de una columna.

Page 6: Introducción a Oracle SQL y PL Volumen 1 y 2

6

Capítulo 3 Funciones de una sola fila

Aceptan argumentos y siempre retornan valores.

Hay 2 tipos

1. De una sola fila : Operan en una sola fila y retornan un solo valor por fila

Carácter : Aceptan carácteres y retornan valores de carácteres o números

Numéricas : Aceptan números y retornan números

Fechas : Aceptan fechas retornan fechas excepto MONTHS_BETWEEN

Conversión : Convierten un valor de un tipo a otro

General : NVL, DECODE

2. De multiples filas : Manipulan un grupo de filas y dan un resultado por cada

grupo

Manipulan items de datos, los argumentos pueden ser Constantes, Variables,

Columnas, Expresiones. Actuan en cada fila del query, pueden retornar valores de un

tipo diferente al referenciado

Function_name (column | expression, [arg1, arg2...])

Funciones de carácter

Hay 2 tipos : De conversión, De manipulación de caracteres

LOWER (column | expresión ) course

UPPER (column | expresión) COURSE

INITCAP (column | expresión) Course

CONCAT (column | expresión, column | expresión ...)

SUBSTR (column | expresión,m,n)

LENGHT (column | expresión ) : Retorna el número de carácteres

INSTR (column | expresión,m) : Retorna la posición numérica del carácter enunciado

LPAD (column | expresión , n ,’string’) : Pega en n posicones un carácter

justificando a la derecha

TRIM (leading | trailing | both, trim_character FROM trim_source )

TRIM (‘S’ FROM ‘SSMITH’) = MITH

Funciones numéricas

ROUND (column | expresión , n ) : Redondea el valor a n lugares decimales

TRUNC (column | expresión , n ) : Trunca la columna a n valores decimales, si n es

omitido quita los decimales ( Si es negativo los números a la izquierda del decimal

son convertidos a cero (0) )

MOD (m , n ) : Retorna el residuo de la división de m entre n

ROUND (45.923 , 2 ) = 45.92

ROUND (45.923 , 0 ) = 46

ROUND (45.923 , -1 ) = 50

TRUNC (45.923 , 2 ) = 45.92

TRUNC (45.923 , 0 ) = 45

TRUNC (45.923 , -1 ) = 40

ROUND y TRUNC pueden ser usadas con funciones de fechas

Trabajando con fechas

Oracle almacena las fechas en un formato interno numérico, siglo, año, mes, día,

horas, minutos, segundos

El formato default es DD – MON – YY

SYSDATE función que retorna la fecha y el tiempo corrientes

DUAL es una tabla de SYS para cumplir con la sintaxis debido a que el SELECT y el

FROM son obligatorios.

Page 7: Introducción a Oracle SQL y PL Volumen 1 y 2

7

Aritmética con fechas

Operación Result Descripción

Date + number Date Adiciona un número de días

Date – date Número días Sustrae una fecha e otra

Date + number/24 Date Adiciona número de horas

Funciones de fecha

MONTHS_BETWEEN(date1,date2) : Meses entre las dos fechas negativo o positivo

(’01-SEPT-95’,’11-JAN-94’) = 19.6774194

ADD_MONTHS(date,n): n positivo o negativo

(’11-JAN-94’,6) = ’11-JUL-94’

NEXT_DAY(date, ‘char’) : Encuentra la fecha de el próximo día especificado de la

semana.

(‘01-SEPT-95’,’FRIDAY’) = ’08-SEPT-95’

LAST_DAY(date) : Encuentra el ultimo día del mes

(’01-SEPT-95’) = ’30-SEPT-95’

ROUND(date[,fmt]) : Retorna la fecha en la unidad especificada en el format model,

si el format model es omitido la fecha es redondeada al día mas cercano.

ROUND(’25-JUL-95’,’MONTH’) 01-AUG-95

ROUND(’25-JUL-95’,’YEAR’) 01-JAN-96

TRUNC(date[,fmt]) : Retorna la fecha con el tiempo de la porción del día truncada

TRUNC(’25-JUL-95’,’MONTH’) = 01-JUL-95

TRUNC(’25-JUL-95’,’YEAR’) = 01-JAN-95

Conversión de tipos de datos implícita

Para evaluación de expresiones

VARCHAR2 o CHAR NUMBER

VARCHAR2 o CHAR DATE

----

NUMBER VARCHAR2

DATE VARCHAR2

Conversión explicita

TO_CHAR(number | date,[fmt],[nlsparams]) : nlsparams especifica carácter decimal,

separador de grupo, símbolo de moneda local, símbolo de moneda internacional o las

abreviaciones para el día el mes , tiene un elemento fm para remover blancos o

suprimir ceros

TO_NUMBER(char,[fmt],[nlsparams]) : Convierte un string de caracteres que

contienen dígitos a un número en el formato especificado.

TO_DATE(char,[fmt],[nlsparams]) : Si fmt es omitido se usa el default DD-MON-

YY

Elementos del modelo del formato de fecha

YYY

YEAR

MM Mes en dos dígitos

MONTH Nombre completo del mes

DY Abreviación de tres letras para el día de la semana

DAY

SCC o CC Siglos S prefijo BC con –

IYYY,IYY,IY,I 4, 3 ,2 1 digito del año basado en el estándar ISO

RM mes en números romanos

WW o W semana del año o del mes

DDD o DD o D día del año, mes o semana

J día juliano

HH24:MI:SS AM 15:45:32 PM

DD “ of ” MONTH 12 of OCTOBER

Page 8: Introducción a Oracle SQL y PL Volumen 1 y 2

8

Número de sufijos para números

Ddspth fourteenth

AM o PM Indicador de meridiano

A.M o P.M Indicador de meridiano con periodos

HH o HH12 o HH24 Hora del día u hora (1-12) u hora (0-23)

MI Minuto de 0-59

SS Segundo de 0-59

SSSS Segundos pasados la media noche (0-86399)

/. , Puntuación es reproducida en el resultado

TH Número ordinario (Ej DDTH para 4TH)

SP Ej DDSP para FOUR

SPTH o THSP Ej DDSPTH para FOURTH

Usando función TO_CHAR con fechas

SELECT ename, TO_CHAR(hiredate, ‘fmDD Month YYYY’)

FROM emp

KING 17 November 1981

Usando función TO_CHAR con números

TO_CHAR(number,’fmt’)

9 Determina longitud del número 9999 1234

0 Despliega ceros 0999 001234

$ Signo flotante de dólar $999 $1234

L Símbolo de moneda local flotante L999 FF1234

. 9.999 1.234

, 9,999 9,999

MI Signo menos a la derecha 99MI 1234-

PR Paréntesis para números negativos 99PR <1234>

EEEE Notación científica 99.999EEEE 1.234E+03

V Multiplicar por 10 n veces

(n número de 9s después de la V) 9V99 100

B Desplegar valores de ceros como

Blancos, no 0 B9999.99 1234.00

SELECT TO_CHAR(sal , ‘$99,999’ )

FROM emp

$3,000

Formato de fecha RR

YY y RR son inversos

Ultimos dos dígitos

RR YY

0-49 Si año corriente superior después El siglo corriente

50-99 Si año corriente superior siglo antes El siglo corriente

Función NVL

NVL (expr1, expr2 ) convierte a números, fechas y char o varchar2

Función DECODE

Fácilita el trabajo condicional como el CASE

DECODE (col/expresión , search1 , result1

[ , search2 , result2 , ..... ,]

[ , default ]

Si el default es omitido retorna NULL si la cadena no coincide con ninguna condición

Page 9: Introducción a Oracle SQL y PL Volumen 1 y 2

9

SELECT job, sal,

DECODE( job, ‘ANALYST’ , SAL*1.1,

‘CLERK’ , SAL*1.15,

SAL )

FROM emp;

Funciones anidadas

Funciones de una sola fila pueden ser anidadas a cualquier nivel , y son evaluadas

desde la más profunda a la menos profunda. o sea de adentro hacia fuera

Page 10: Introducción a Oracle SQL y PL Volumen 1 y 2

10

Capítulo 4 desplegando datos de múltiples tablas Se trabaja haciendo JOIN entre las tablas, generalmente si se tienen n tablas se

necesitan n-1 joins para la consulta, esto no es cierto todo el tiempo Ej. Si la llave

primaria es compuesta.

Producto cartesiano

Se da cuando una condición de JOIN es omitida, es invalida, todas las filas de la

primera tabla son cruzadas con todas las filas de la segunda tabla emp 14 dept 4 = 56

Tipos de joins

Equijoin : La columna debe ser igual en las dos tablas

Se utiliza el nombre de la tabla como prefjo table.columna, esto mejora performance,

y evita ambigüedad si hay columnas con el mismo nombre en tablas diferentes. Se

usan en SELECT, WHERE y ORDER BY.

Para condiciones adicionales se utiliza los operadores como AND.

Usando alias para las tablas

Máximo 30 carácteres

Non-equijoin : Cuando la columna de una tabla no corresponde directamente a la

columna de otra Ej. BETWEEN, <=, >=

Outer-join : Se coloca a un lado de la expresión, no en los dos, se coloca al lado

donde no hay información (+), no puede usar el operador IN.

Self-join : Cruzar una tabla consigo misma

Page 11: Introducción a Oracle SQL y PL Volumen 1 y 2

11

Capítulo 5 Agregando datos usando funciones de grupo

Funciones de grupo operan en juegos de filas para dar un resultado por grupo, estas

filas pueden ser toda la tabla o divididas por grupos.

Tipos de funciones de grupo

AVG(DISTINCT | ALL | n ) Promedio de n ignorando valores NULL, números

COUNT({* | [ DISTINCT | ALL ] expr} ) Incluye nulos

MAX( [ DISTINCT | ALL ] expr ) Ignora nulos, todos los tipos de datos

MIN ([ DISTINCT | ALL ] expr ) Ignora nulos, todos los tipos de datos

STDDEV ( [ DISTINCT | ALL ]x) Desviación standar de n ignora nulos, números

SUM ( [DISTINCT | ALL ] n )

VARIANCE ( [DISTINCT | ALL ]x ) Varianza de n, ignora nulos

El servidor Oracle implícitamente ordena los resultados ascendentemente cuando usa

GROUP BY, para cambiar el orden usar ORDER BY.

Funciones de grupo y valores NULL

Todas las funciones de grupo ignoran valores NULL en la columna excepto COUNT.

Para incluir valores NULL se usa NVL.

SELECT (AVG(NVL(comm,0)))

FROM emp;

Para crear grupo GROUP BY

SELECT column , group_function(column)

FROM table

[WHERE condition ]

[GROUP BY group_by_expression ]

[ORDER BY column ]

Clausula GROUP BY

No se puede usar los alias de las columnas

Todas las columnas que no estan en una función de grupo deben estar en la clausula

GROUP BY.

Las columnas del GROUP BY pueden no estar en la lista del select.

Se puede agrupar por mas de una columna, grupos dentro de los grupos.

No se puede usar WHERE para restringir grupos para esto se usa HAVING, filas son

agrupadas, se aplica funcion de grupo, se despliega las que coincidan con HAVING.

Las funciones de grupo pueden ser anidadas a una profundidad de 2.

Page 12: Introducción a Oracle SQL y PL Volumen 1 y 2

12

Capítulo 6 subqueries

Se pueden colocar en : WHERE , HAVING, FROM

SELECT select_list

FROM table

WHERE exp operator

( SELECT select list

FROM table);

Los operadores de comparación caen en dos clases una sola fila ( <, >,=,< >,<=,>= ) y

multiples filas (IN, ALL, ANY )

El sub query se ejecuta primero y su salida completa el query total.

No adicionar una clausula ORDER BY a un subquery.

Tipos de subqueries : De una sola fila, multiples filas, multiples columnas

Se pueden usar funciones de grupo en los subqueries

SELECT ename, job

FROM emp

WHERE sal = ( SELECT MIN(sal) FROM emp );

SELECT deptno , MIN(sal)

FROM emp

GROUP BY deptno

HAVING MIN(sal) > (SELECT MIN(sal) FROM emp WHERE deptno = 20);

Subqueries de multiples filas

Operador Significado

IN Igual a cualquier miembro de la lista

ANY Compara el valor con cada valor retornado de la lista

ALL Compara el valor con todos los valores de la lista

SELECT empno

FROM emp

WHERE sal < ANY ( SELECT sal FROM emp WHERE job= ‘CLERK’)

AND job <> ‘CLERK’;

SELECT empno

FROM emp

WHERE sal > ALL ( SELECT AVG(sal) FROM emp GROUP BY deptno);

El operador NOT puede ser usado con ANY, IN , ALL

Page 13: Introducción a Oracle SQL y PL Volumen 1 y 2

13

Capítulo 7 Subqueries de multiples columnas

SELECT column, ...

FROM table

WHERE (column, column, ... ) IN ( SELECT column, column, ...

FROM table

WHERE condition );

Las comparaciones pueden ser pairwise o nonpairwise

SELECT column, ...

FROM table

WHERE column1 IN ( SELECT column FROM table WHERE condition )

AND column2 IN ( SELECT column FROM table WHERE condition );

El SELECT no retorna filas si se utiliza NOT IN y en el subquery hay un NULL

debido a que NOT IN es eqwuivalente a ¡=ALL.

IN es equivalente =ANY

Usando un subquery en la clausula FROM

SELECT a.ename, a.sal, b.salvg

FROM emp a, (SELECT deptno, avg(sal) salvg FROM emp GROUP BY deptno )

WHERE a.deptno = b.deptno

Page 14: Introducción a Oracle SQL y PL Volumen 1 y 2

14

Capítulo 8 Produciendo salidas legibles con SQL * Plus

Con & se almacenan valores temporalmente.

&user_variable Indica una variable en una sentencia SQL, si la variable no existe

SQL*Plus se la pide al usuario

SET VERIFY ON|OFF Se usa para confirmar los cambios en la sentencia SQL , este

forza a SQL*Plus a desplegar texto antes y despues de reemplazar las variables con

los valores.

Las variables de fecha o carácter deben ser encerradas entre comillas simples.

Se puede especificar variables para columnas, como condición en el ORDER BY , en

el from.

La variable &&

Para utilizar la reusar la variable sin tener que preguntar, SQL*Plus almacena el valor

usándole comando DEFINE, una vez el valor es colocado se necesita UNDEFINE

para resetear la variable.

Para definir variables se utiliza

DEFINE variable = value el cual crea una variable char y asigna el valor a esta.

DEFINE variable muestra la variable su valor y su tipo de dato

DEFINE despliega todas las variables del usuario

ACCEPT variable [datatype] [FORMAT format] [PROMPT text ] [HIDE]

Lee la líneas de la entrada por el usuario y almacena esto en una variable en donde

Datatype : es NUMBER, CHAR o DATE (CHAR tiene una longitud máxima de 240

bytes

Format : Especifica el formato Ej. A10 o 9.999

Hide : esconde la entrada del usuario por seguridad

En el comando ACCEPT no se le coloca & a la variable

Tips

DEFINE y ACCEPT crrean la variable si esta no existe

Se debe definir explícitamente un NUMBER o FECHA para variables de este tipo

DEFINE y UNDEFINE

Las variables permanecen mientras no se les de UNDEFINE o se salga de SQL*Plus,

se puede verificar los cambios con DEFINE, para definir variables para cada sessión,

se debe modificar el archivo login.sql asi las variables son creadas en el startup

Personalizando EL ambiente de SQL*Plus

Con comandos SET

SET system_variable value

Para verificar los valores seteados se usa SHOW

SQL>SET ECHO ON

SQL>SHOW ECHO

Echo ON

Para ver todas las variables

SHOW ALL

ARRAY [SIZE] {20 | n }El tamaño para el fetch de los datos

COLSEP {_ | text }Setea el texto a ser impreso entre columnas default es el espacio

FEDD[BACK] {6 | n | OFF | ON } Despliega el número de registros devueltos por

una consulta cuando selecciona por los menos n registros

HEA[DING] {ON | OFF } Determina el encabezado

LIN[SIZE] {80 | n} El número de carácteres por líneas

LONG {80 | n} Setea el máximo para desplegar valores LONG

PAGES[IZE] {24 | n} Número de líneas por pagina

PAU[SE] {OFF | ON | text} controla el scroll de la terminal

Page 15: Introducción a Oracle SQL y PL Volumen 1 y 2

15

TERM[OUT] {OFF | ON } Determina si la salida es desplegada enla pantalla

El archivo login.sql contiene los SET estandar y otros comandos SQL*Plus que se

implementan en el login.

COL[UMN] [column option ] Controla el formato de las columnas

TTI[TLE] [text |OFF | ON ] Especifica el encabezado de cada pagina

BTI[TLE] [text |OFF | ON ] Especifica el pie de cada pagina

BRE[AK] [ON report_element ]

Si se da un alias a la columna este debe ser especificado, no el nombre de la columna

El comando COLUMN

COL[UMN] [ {column | alias } [ option ] ]

CLE[AR] limpia cualquier formato de columna

FOR[MAT] format Cambia el despliegue de una columna usando el formato

HEA[DING] text Setea el encabezado de la columna ( una barra vertical (|) forza un

line feed )

JUS[TIFY] {aling} Justifica el encabezado de la columna derecha, izq o centro

NOPRI[NT] no imprime la columna

NUL[L] text Especifica el texto a ser desplegado para valores NULL

PRI[NT] muestra la columna

TRU[NCATED] Trunca el string al final de la primera líneas desplegada

WRA[PPED]

COLUMN ename HEADING ‘Employee|name’ FORMAT A15

COLUMN sal JUSTIFY LEFT FORMAT $99,999.00

COLUMN mgr FORMAT 9999999 NULL ‘no manager’

COL[UMN] ename Despliega los valores corrientes para una columna

COL[UMN] ename CLE[AR] Limpia los valores seteados para la columna

CLE[AR] COL[UMN] Limpia los valores seteados para todas las columnas

Si se tiene un comando muy largo se puede continuar colocando (-)

Modelos de formato de columnas

An despliega un ancho n

9 Solo digitos 9999 1234

0 Fuerza al cero lider 099999 01234

$ Símbolo de dólar $9999 $1234

L Moneda local L9999 L1234

.

,

El servidor Oracle despliega (#) si el número excede el tamaño dado en el formato,

tambien si el valor e alfanumerico mientras el actual es numerico

BREAK ON ename ON job Suprime duplicados para asegurar que trabaja

correctamente usar ORDER BY.

BREAK ON ename SKIP 4 ON job SKIP 2

BREAK on column [ |alias|row ] [skip n | dup | page ] on .. [on report ]

Donde

page Tira una nueva pagina cuando el valor del break cambia

skip n Salta un número de líneas cuando el valor cambia

break se activa con columna, fila , pagina, reporte

duplicate despliega valores duplicados

Para limpiar todos los juegos de BREAK usar CLEAR

CLEAR BREAK

Page 16: Introducción a Oracle SQL y PL Volumen 1 y 2

16

Capítulo 9 Manipulando datos Una transacción consiste en un grupo de sentencias DML que forman una unidad

lógica de trabajo.

Para insertar nulos implícitamente omitir la columna, explícitamente colocar ‘NULL’

y ‘ ‘ Para carácteres y fechas.

Para insertar valores especiales como fechas el formato ‘DD-MON-YYYY’ debe ser

usado de lo contrario se cambia con la funcion TO_DATE. Y el tiempo default es

00:00:00. Si se setea el formato RR el siglo puede no ser el corriente.

Se puede insertar valores usando variables de sustitución.

INSERT INTO dept (deptno, dname )

VALUES ( &department, &name );

Estos le serán pedidos al usuario al momento de ejecutar la sentencia. Se puede usar

ACCEPT.

Se puede hacer INSERT en una tabla de datos de otra con un subquerie.

Para actualizar datos con UPDATE.

Para actualizar datos con subqueries de multiples columnas.

UPDATE emp

SET (job, deptno ) = ( SELECT job, deptno FROM emp WHERE empno = 7988 )

WHERE empno = 7698;

Se puede borrar filas de una tabla basado en valores de otra.

DELETE FROM employ

WHERE deptno = ( SELECT deptno FROM dept WHERE dname = ‘SALES’);

Transacciones de BD

Consiste de .

Grupo de DMLs

Un DDL

Un DCL

Las transacciones dan mas flexibilidad y control y aseguran consistencia en el caso de

que el proceso el sistema fallen.

Controlando transacciones

COMMIT, SAVEPOINT name, ROLLBACK [TO SAVEPOINT name]

Procesamiento implicito de transacciones

Un COMMIT se da cuando hay DDL, DCL o se sale normalmente de SQL*Plus.

Un ROLLBACK se da cuando hay una salida anormal de SQL*Plus o falla el sistema

Existe el comando AUTOCOMMIT OFF|ON.

Antes de COMMIT o ROLLBACK, las filas afectadas son bloqueadas para que no

sean cambiadas.

Después del COMMIT las filas bloqueadas son liberadas, todos los savepoints son

borrados.

Se puede hacer marcas SAVEPOINT para el ROLLBACK. Si se crea un segundo

SAVEPOINT con el mismo nombre el primero es desacrtado.

El servidor Oracle implementa un SAVEPOINT implícito.

Page 17: Introducción a Oracle SQL y PL Volumen 1 y 2

17

Si un DDL falla, el usuario no puede volver a los datos anteriores porque este tiene

autocommit.

Consistencia de lectura

Garantiza una vista consistente de los datos todo el tiempo.

Cambios hechos por un usuario no tienen conflicto con los cambios hechospor otro

usuario.

El propósito es asegurar que cada usuario mire los datos como estaban con el ultimo

COMMIT, antes de que la operación DML arrancara.

El LOCKING es efectivo debido a que previene acciones destructivas entre

operaciones concurrentes.

No requiere acción de l usuario

Usa el nivel mas bajo de restricción.

Permanece por el tiempo que dure la transacción.

Tiene dos modos Exclusive : Previene que un recurso sea compartido la primera

transacción bloquea el recurso exclusivamente y Shared

Page 18: Introducción a Oracle SQL y PL Volumen 1 y 2

18

Capítulo 10 Creando y administrando tablas Tabla Unidad básica de almacenamiento

Vista Representan un subgrupo de datos de una o mas tablas

Secuencia Genera valores para PK

Index Mejora performance

Sinónimo Da nombres alternativos a los objetos

El tamaño de una tabla es definido por la cantidad de espacio asignado. El nombre

debe comenzar por una letra, 1-30 carácteres , A-Z, a-z, 0-9, _,$ y #

Create table

Se debe tener el privilegio CREATE TABLE, es un DDL estos tienen un efecto

inmedíato en la BD y graban información en el diccionario de datos.

CREATE [ GLOBAL TEMPORARY ] TABLE [schema.]table

(column datatype [DEFAULT expr ] [, .... ]);

GLOBAL TEMPORARY : La tabla es temporal y su definición es visible para todas

las sesiones, los datos de esta son visibles solo para la sesión que inserta datos.

DEFAULT expr : Especifica el valor por default si este es omitido en el INSERT,

expr puede ser un valor literal, expresión o una función SQL.

Hiredate DATE DEFAULT SYSDATE, ....

Un esquema es una colección de objetos, los objetos son estructuras lógicas que se

refieren directamente a datos en la BD, si la tabla no pertenece al usuario debe llevar

el prefijo del dueño.

Tablas en la BD Oracle

USER_

ALL_

DBA_

V$_ Vistas de performance dinamicas

Para las tablas del usuario USER_TABLES, objetos USER_OBJECTS, tablas, vistas,

sinónimos y secuencias USER_CATALOG CAT

Tipos de datos

LONG Longitud variable máximo 2G

CLOB Carácter single-byte maximo 4G

RAW y LONG RAW Datos binarios raw max 2000B

BLOB Datos binarios maximo 4G

BFILE Datos binarios max 4G

CREATE TABLE [ ( column1, column2, ... ) ]

AS subquery

Cuando se utilize una expresión se da un alias a la columna.

ALTER TABLE ADD|MODDIFY|DROP (column datatype [DEFAULT expr], ... )

Solo una columna puede ser borrada al tiempo.

ALTER TABLE table SET UNUSUED (column);

O

ALTER TABLE table SET UNUSUED column, column;

ALTER TABLE table DROP UNUSUED COLUMNS;

Page 19: Introducción a Oracle SQL y PL Volumen 1 y 2

19

DROP TABLE table;

Los sinonimos permanecen pero son invalidos, cualquier transacción pendiente es

commited, lo puede hacer el dueño o usuarios con grant DROP ANY TABLE.

Para cambiar el nombre de una tabla, vista, secuencia o sinónimo.

RENAME old_name TO new_name;

Truncando una tabla

Libera el espacio de almacenamiento usado por la tabla, DELETE no. No se puede

hacer ROLLBACK, lo hace el dueño o un usuario con el grant DELETE TABLE.

Adicionando comentarios

COMMENT ON TABLE table | COLUMN IS ‘xxxxxxx’; para consultar

ALL_COL_COMMENTS, USER_COL_COMMENTS, ALL_TAB_COMMENTS,

USER_TAB_COMMENTS.

Page 20: Introducción a Oracle SQL y PL Volumen 1 y 2

20

Capítulo 11 Incluyendo constraints Forzan las reglas a nivel de tabla

Previenen el borrado de una tabla con dependencias

NOT NULL :

UNIQUE : Especifica una columna o columnas cuyo valor debe ser unico

PRIMARY KEY

FOREIGN KEY

CHECK : Especifica una condición que debe ser verdadera.

El nombre del constraint es por default SYS_Cn, se puede crear con la tabla o

después, se hace a nivel de tabla o columna, son almacenados en diccionario de datos,

USER_CONSTRAINTS.

CREATE TABLE [schema.]table

(column datatype [DEFAULT expr]

[column constraint ],

....

[ table_constraint ] [, ... ]);

column_name datatype CONSTRAINT const_name NOT NULL...

UNIQUE KEY permite nulos a menos que se le especifique NOT NULL se puede

definir a nivel de tabla o columna, Oracle crea un indice unico

CREATE TABLE deptno ( deptno NUMBER(2),

Dname VARCHAR2(14),

CONSTRAINT dept_name_uk UNIQUE (dname));

CREATE TABLE deptno ( deptno NUMBER(2),

Dname VARCHAR2(14),

CONSTRAINT dept_name_pk PRIMARY KEY (deptno));

CREATE TABKE emp

(....

deptno NUMBER (2) CONSTRAINT emp_deptno_fk FOREIGN KEY (deptno )

REFERENCES dept(deptno),

.....

);

ON DELETE CASCADE permite el borrado en la tabla padre y las filas dependientes

en las tablas hijas.

CHECK no se puede usar CURRVAL, NEXTVAL, LEVEL y ROWNUM ni

llamadas a SYSDATE, UID, USER y USERENV, se pueden definir mas de uno por

columna a nivel de columna o de tabla.

ALTER TABLE table ADD [ CONSTRAINT constraint ] type (column );

Para adicionar constraint NOT NULL con MODIFY.

ALTER TABLE table DROP PRIMARY KEY | UNIQUE (column) |

CONSTRAINT constraint [CASCADE];

ALTER TABLE table DISABLE CONSTRAINT constraint [CASCADE];

Se puede deshabilitar un constraint en la creación de una tabla o con un ALTER.

ALTER TABLE table ENABLE CONSTRAINT constraint;

Page 21: Introducción a Oracle SQL y PL Volumen 1 y 2

21

Se se habilita UNIQUE o PRIMARY KEY un indice se crea automaticamente, un

constraint se puede habilitar en la creación de la tabla o con ALTER.

CASCADE CONSTRAINTS

Se usa con DROP COLUMN, borra todos los constraints dependientes, borra

constraints multicolumnas.

USER_CONSTRAINTS, USER_CONS_COLUMNS.

Page 22: Introducción a Oracle SQL y PL Volumen 1 y 2

22

Capítulo 12 Creando vistas

Es una tabla lógica basada en una tabla o en otra vista, no contiene datos , se usan

para restringir acceso a los datos, para hacer consultas complejas fáciles.

Hay 2 clasificaciones de vistas simples y complejas.

CREATE VIEW [OR REPLACE] [FORCE | NOFORCE] VIEW view

[ (alias, ....) ]

AS subquery

[WITH CHECK OPTION [CONSTRAINT constraint]]

[WITH READ ONLY ];

El subquery puede ser complejo, no puede contener ORDER BY.

FORCE crea la vista indiferentemente si existe o no la tabla.

WITH CHECK OPTION Especifica que solo filas accequibles por la tabla pueden ser

actualizadas o insertadas.

Se pueden usar alias en el subquery.

En USER_VIEWS , la sentencia SELECT esta en una columna LONG.

Se puede hacer operaciones DML en vistas simples, no se puede remover una fila si

contiene : funciones de grupo, GROUP BY , DISTINCT, ROWNUM.

No se puede modificar una vistas si cumple con lo anterior, columnas definidas por

expresiones.

No se puede adicionar si cumple con lo anterior, hay columnas NOT NULL en las

tablas base que no son seleccionadas por la vista.

Usando WITH CHECK OPTION

Asegura que los DML en la vista permanezcan dentro del dominio de la vista

Se puede forzar constraints a nivel de BD.

DROP VIEW view;

Solo el dueño o quien tenga DROP ANY VIEW.

Inline views

Es una subconsulta con un alias que se pued usar dentro de la sentencia SQL, no es

un objeto del esquema.

SELECT a.ename, b.maxsal

FROM emp a,(SELECT deptno, max(sal) maxsal FROM emp GROUP BY deptno) b

WHERE a.deptno = b.deptno

Analisis TOP-N

SELECT [column_list], ROWNUM

FROM (SELECT [column_list] FROM table ORDER BY top_N_column)

WHERE ROWNUM<= N;

ROWNUM asigna un valor a cada columna iniciando con 1.

En la clausula WHERE la cual especifica n filas a ser retornadas, debe usar < o <=.

Page 23: Introducción a Oracle SQL y PL Volumen 1 y 2

23

Capítulo 13 Otros objetos de BD

Que es una secuencia

Automáticamente genera números unicos, es compartida, se usa generalmente para

crear valores de llave primaria, reemplaza código de la aplicación, veloz acceso

cuando esta en cache.

CREATE SÉQUENCE séquence

[INCREMENT BY n ]

[START WITH n ]

[{MAXVALUE n | NOMAXVALUE}]

[{MINVALUE n | NOMINVALUE} ]

[{CYCLE | NOCYCLE}]

[{CACHE n | NOCACHE}]

CACHE n | NOCACHE : Especifica cuantos valores serán preasignados y colocados

en memoria (Por default 20 valores ).

USER_SECUENCES, la columna LAST_NUMBER despliega el proximo número

disponible de la secuencia.

Sequence.NEXTVAL : Retorna el proximo número disponible, retorna un unico valor

cada vez que es llamado, sequence.CURRVAL :Retorna el vlor corriente de la

secuencia NEXTVAL debe ser usado antes de que CURRVAL contenga un valor.

Pueden ser usados :

En la lista de un SELECT que no es parte de un subquery

En la lista de un SELECT de un subquery de un INSERT

En la clausula VALUES

En la cláusula SET de un UPDATE

No se pueden usar :

Una lista de un SELECT de un vista

Un SELECT con DISTINCT

Un SELECT con GROUP BY, HAVING o ORDER BY

Un subquery de un SELECT, DELETE o UPDATE

Una expresión por default en CREATE TABLE o ALTER TABLE

Saltos en la secuencia se pueden dar cuando hay ROLLBACK, falla del sistema la

secuencia es usada en otra tabla.

Se puede ver el proximo valor disponible de la secuencia en USER_SEQUENCES si

fue creada NOCACHE.

Modificando una secuencia

Se puede cambiar el valor de incremento, máximo, minimo, ciclo y cache.

ALTER SEQUENCE séquense

[INCREMENT BY n]

[{MAXVALUE n | NOMAXVALUE}]

[{MINVALUE n | NOMINVALUE}]

[{CYCLE | NOCYCLE}]

[{CACHE n | NOCACHE}]

Se debe ser el dueño o tener el GRANT ALTER ANY SEQUENCE.

DROP SEQUENCE sequence; El dueño o tener DROP ANY SEQUENCE.

Page 24: Introducción a Oracle SQL y PL Volumen 1 y 2

24

Que es un indice

Es un objeto, acelera la recuperación de filas, reduce I/O utilizando un metodo de

acceso de camino rapido, es independiente de la tabla, es mantenido por el servidor.

Automáticos : PK, UNIQUE

Manuales : no unicos creados por el usuario

CREATE INDEX index ON table (column,[column,...]);

Se crea cuando la columna es frecuentemente usada en el WHERE, la columna

cintiene un amplio rango de valores, contiene un gran número de valores NULL, la

tabla es grande y la mayoria de los querys esperan del 2-4% de las filas.

No se deben usar cuando la tabla es actualizada frecuentemente y las inversas de lo

anterior.

USER_INDEXES, USER_IND_COLUMNS.

Indices basados en función.

Es un indice basado en expresiones, la expresión se construye con columnas,

constantes, funciones SQL y funciones definidas por el usuario.

CREATE INDEX index ON table (expr)

Para asegurarse de que se usa el indice debe aasegurarse que el valor de la función es

NOT NULL.

SELECT * FROM emp WHERE UPPER(ename) IS NOT NULL;

DROP INDEX; El dueño o tener DROP ANY INDEX;

Sinonimos

Simplifica el acceso a los objetos, el objeto no puede estar contenido en un paquete.

CREATE SYNONYM [PUBLIC] FOR object;

DROP SYNONYM synonym;

Solo el DBA borra sinonimos publicos.

Page 25: Introducción a Oracle SQL y PL Volumen 1 y 2

25

Capítulo 14 Controlando acceso a los usuarios

Se tiene seguridad del sistema y seguridad de los datos.

Los privilegios del sistema dan acceso a la BD. Hay mas de 80.

CREATE USER, DROP USER, DROP ANY TABLE, BACKUP ANY TABLE.

CREATE USER user IDENTIFIED BY password;

GRANT privilege [, privilege, ... ] TO user;

Un desarrollador puede tener CREATE SESSION para conectarse, CREATE

TABLE, CREATE SEQUENCE, CREATE VIEW, CREATE PROCEDURE.

Role

Grupo de privilegios relativos que pueden ser concedidos al usuario.

CREATE ROLE role;

ALTER USER user IDENTIFIED BY new_pwd; Se debe tener el privilegio ALTER

USER.

Un grant para el sinonimo es convertido en un grant para la tabla base referenciada

por el sinonimo.

GRANT object_priv [(columns)] ON object TO [USER | role | PUBLIC]

[WITH GRANT OPTION];

WITH GRANT OPTION se revoca en cascada

ROLE_SYS_PRIVS Privilegios del sistema concedidos a los roles

ROLE_TAB_PRIVS Privilegios de las tablas concedidos a los roles

USER_ROLE_PRIVS Roles accesibles por el usuario

USER_TAB_PRIVS_MADE Privilegios de objeto concedidos a los objetos del

usuario

USER_TAB_PRIVS_RECD Privilegios de objeto concedidos al usuario

USER_COL_PRIVS_MADE Privilegios de objeto concedido a las columna de los

objetos del usuario

USER_COL_PRIVS_RECD Privilegios de objeto concedidos al usuario en columnas

especificas

REVOKE {privilege [, privilege ...] | ALL} ON object FROM {user [,user...] | role |

PUBLIC} [ CASCADE CONSTRAINTS ];

CASCADE CONSTRAINTS : Remueve cualquier constraint de integridad

referencial hechos al objeto por medio de REFERENCES

Page 26: Introducción a Oracle SQL y PL Volumen 1 y 2

26

Capítulo 16 Declarando variables

PL/SQL es una extensión de SQL con carácterísticas de lenguaje de programación,

brinda integración, mejora performance, PL/SQL puede ser usado como un grupo de

sentencias SQL dentro de un solo bloque y lo envian al servidor en una sola llamada,

reduciendo tambien trafico en la red.

PL/SQL puede cooperar con herramientas de desarrollo como Developer, Forms y

Reports, adicionando procesamiento procedimental.

Estructura de bloque PL/SQL que es estructurado por bloques.

DECLARE

xxxxxxxxxxxxxxxxx

BEGÍN

xxxxxxxxxxxxxxxxx

EXCEPTION

xxxxxxxxxxxxxxxxx

END;

Tipos de bloques

Anónimos : no tienen nombre, se puede envolver un bloque anónimo dentro de un

programa precompilado y dentro de SQL*Plus o server manager. Triggers en Oracle

Developer.

Subprogramas : Procedimientos y funciones, toman parametros y pueden ser

invocados

Función o procedimiento de aplicación : Bloque PL/SQL con nombre almacenado

en una aplicación desarrollada por Oracle o en una librería compartida que puede

aceptar parámetros y puede ser invocada repetidamente.

Uso de variables : Para almacenamiento temporal, manipulación de valores,

reusabilidad y fácil mantenimiento %ROWTYPE, %TYPE

Las variables se declaran en la sección declarativa, se asignan en la sección

ejecutable, se pueden pasar a los procedimientos como IN, OUT, IN OUT

Tipos de variables :

Scalar : Sostienen un solo valor

Tipos de datos compuestos : Registros

Tipos de datos de referencia

Lob

Variables de tipo no PL/SQL incluyen variables del host declaradas en programas

precompilados. Campos de pantalla en formas y variables del host en SQL*Plus.

Identifier [CONSTANT] datatype [NOT NULL] [ := | DEFAULT expr]

Una constante debe ser inicializada en su declaración.

Las variables no deben llevar el mismo nombre de las columnas de un tabla.

SELECT empno

INTO empno

FROM emp;

Las variables se asiganan con := , INTO o FETCH

G_mgr NUMBER(4) DEFAULT 1334;

Page 27: Introducción a Oracle SQL y PL Volumen 1 y 2

27

V_location VARCHAR2(13) NOT NULL := ‘CHICAGO’;

Tipos de datos escalares

Tienen un solo valor y no tienen componentes internos, pueden ser clasificados en 4

categorias número (integer, positive), carácter, boolean y date

Varchar2 32,767B

Date 4712 B.C 9999 A.D

Long Carácter

Long Raw Datos binarios no es interpretada por PL/SQL

Binary_integer

%TYPE declara la variable de acuerdo a una columna u otra variable previamente

declarada. Es fácil de mantener si se hacen cambios a nivel de BD.

V_ename emp.ename%TYPE;

V_balan NUMBER(7,2);

V_min v_balan%TYPE;

NOT NULL no aplica a variables declaradas con %TYPE.

Eb variables booleanas expresiones aritméticas pueden ser usadas para retornar un

valor booleano.

V_com BOOLEAN := (v_sal1 < v_sal2);

Tipos de datos compuestos : TABLE referencia y manipula colecciones de datos

como un objeto, RECORD trata tipos de datos relacionados pero disimilares como

una unidad lógica, NESTED TABLE y VARRAY

LOB : Almacena bloques de datos sin estructura 4GB

CLOB almacena grandes bloques de carácteres single-byte

BLOB objetos binarios on-line/off-line

BFILE

NCLOB single-byte o fixed-width multibyte in line o out of line.

Variables BIND

Se declara en el ambiente del host y se usa para pasar valores runtime, para ser

pasadas a uno o mas programas PL/SQL a menos que sean procedimientos, funciones

o paquetes, esto incluye variables decalradas en programas precompilados , campos

de pantalla

Para declararlas en el ambiente SQL*Plus

VARIABLE ret NUMBER

VARIABLE ret VARCHAR2(30)

Para desplegarlas

PRINT ret (no pude ser usado en un bloque PL/SQL)

Para referenciarlas

Con (:) como prefijo asi.

VARIABLE g_mon NUMBER

DECLARE

BEGÍN

:g_mon := 12;

END;

Page 28: Introducción a Oracle SQL y PL Volumen 1 y 2

28

DBMS_OUTPUT.PUT_LINE alternativa para desplegar datos en un bloque

PL/SQL, se debe habilitar SQL*Plus con SET SERVER OUTPUT ON

Ámbito y visibilidad de variables

La variable será local para el bloque en el que ha sido declarada y global para los

bloque hijos de éste, mientras que las variables declaradas en los bloque hijos no son

globales a los bloques padre.

Subtipos definidos por el usuario

Un subtipo es un tipo PL/SQL que se basa en otro tipo existente. Los subtipos pueden

emplearse para dar nombres alternativos a un tipo. La sintaxis es:

SUBTYPE nuevo_tipo IS tipo_original;

donde nuevo_tipo es el nombre del nuevo subtipo y tipo_original designa el tipo

base. Éste puede ser un tipo predefinido o un subtipo o una referencia %TYPE. Por

ejemplo:

DECLARE

SUBTYPE t_LoopCounter IS NUMBER; -- Define el nuevo subtipo

v_LoopCounter t_LoopCounter; -- Declara una variable del

subtipo

SUBTYPE t_NameType IS students, first_name%TYPE;

La definición del subtipo no puede ser restringida de modo directo. El siguiente

bloque sería ilegal:

DECLARE

SUBTYPE t_LoopCounter IS NUMBER(4); -- Restricción incorrecta

Sin embargo, hay una forma de evitar esta limitación, declarando una variable ficticia

del tipo deseado (con la restricción) y utilizando %TYPE en la definición del subtipo:

DECLARE

v_DummyVar NUMBER(4); --Variable ficticia que no se usa

SUBTYPE t_LoopCounter IS v_DummyVar%TYPE; -- Devuelve

NUMBER(4)

v_Counter t_LoopCounter; -- Declara una variable del subtipo

<<l_Outer>>

DECLARE

v_AvailableFlag BOOLEAN;

v_SSN NUMBER(9);

BEGIN

DECLARE

v_SSN CHAR(11);

v_StartDate DATE;

BEGIN

END;

END;

v_AvailableFlag y

v_SSN son visibles 1

2

3 v_AvailableFlag y

v_SSN son visibles

v_AvailableFlag, v_SSN CHAR(11) y

V_StartDate son visibles. Si queremos

acceder a v_SSN NUMBER(9) debemos

usar l_Outer.v_SSN.

Page 29: Introducción a Oracle SQL y PL Volumen 1 y 2

29

Las declaraciones de variables de un subtipo no restringido también pueden

restringir el tipo:

DECLARE

SUBTYPE t_Numeric IS NUMBER; -- Define un subtipo no

restringido

v_Counter is t_Numeric(5); -- y una variable restringida

Los subtipos se consideran de la misma familia que el tipo base.

Page 30: Introducción a Oracle SQL y PL Volumen 1 y 2

30

Capítulo 17 Escribiendo sentencias ejecutables

Las unidades léxicas pueden estar separados por Espacios, delimitadores (+,-,=..),

identificadores, literales y comentarios.

Identificadores

Pueden contener 30 letras, deben comenzar con una letra, no palabaras reservadas a

menos que se encierren entre comillas, no puede tener el mismo nombre de una

columna de una tabka de la BD.

Literales Es un número, carácter, cadena o valor booleano no representado por un

identificador

Carácteres y fechas deben ir encerrados entre comillas

Números pueden ir solos o en notación científica (2E5)

Un bloque PL/SQL termina con /

Para comentar una sola líneas ( - -) varias líneas (/* */)

Funciones SQL en PL/SQL

Numéricas de una sola fila

De carácter de una sola fila

Conversión

Date

PL/SQL funciones

Reporte de errores

miscellaneous

No disponibles DECODE o funciones de grupo (SUM,MAX,MIN ....)

CHR(10) Convierte el código ASCII a su correspondiente carácter

Bloques anidados

Sentencias pueden estar anidadas donde quiera que una sentencia es permitida

Un bloque anidado comienza con una sentencia

La sección de excepciones puede contener bloques anidados

El alcancé de un objeto es la región donde puede ser referenciado, aplica a todos los

objetos declarados incluyendo variables, cursores, excepciones definidas por el

usuario y constantes.

Operadores en PL/SQL

Las operaciones se hacen en orden de acuerdo a la precedencia tenemos operadores

Lógicos

Aritméticos

Concatenación

Paréntesis

Operador exponencial (**)

Guias de programación

Identar código

Documentar con comentarios

Convenciones de nombres para identificadores y otros objetos

Page 31: Introducción a Oracle SQL y PL Volumen 1 y 2

31

Capítulo 18 Interactuando con el servidor Oracle

Sentencias SQL en PL/SQL

Usando SELECT solo un grupo de valores puede ser retornado, se hace cambios en

las filas con DML, control de transacciones con COMMIT, ROLLBACK o

SAVEPOINT.

PL/SQL no es una unidad transaccional, no soporta DDL, DCL tal como GRANT o

REVOKE.

SELECT select_list

INTO {variable_name [ , variable_name, ...]

| record_name }

FROM table

WHERE condition;

INTO es obligatoria para variables de PL/SQL o del host.

Funciones de grupo no pueden ser usadas en PL/SQL solo en SQL.

Para manipular datos con DML en PL/SQL con DELETE, INSERT, UPDATE,

COMMIT o ROLLBACK.

Insertando datos no hay posibilidad de ambigüedad con los identificadores y los

nombres de las columnas, cualquier identificador en el INSERT debe ser un nombre

de una columna de la BD.

La asignación en PL/SQL siempre con := en SQL =.

Para evitar ambigüedad en el WHERE columnas e la BD e identificadores deben

tener nombres diferentes, los errores de sintaxis pueden darse debido a que PL/SQL

chequea primero la BD para ver si es una columna.

No hay posibilidad de ambigüedad en el SELECT ni en el FROM.

COMMIT y ROLLBACK

La transacción inicia con el primer comando DML después de un COMMIT o un

ROLLBACK.

COMMIT o ROLLBACK se usan para terminar explícitamente la transacción.

COMMIT [WORK];

SAVEPOINT savepoint_name;

ROLLBACK [WORK];

ROLLBACK [WORK] TO [SAVEPOINT] savepoint_name;

Cursores SQL : Es un área privada de memoria hay 2 tipos implícitos utilizados por

el servidor para parsear y ejecutar SQL y explícitos creados por el programador.

Usando atributos de cursor SQL , se puede verificar la salida.

SQL%ROWCOUNT Número de filas afectadas

SQL%FOUND atributo booleano especifica que fueron afectadas filas

SQL%NOTFOUND

SQL%HISOPEEN siempre es falso debido a que PL/SQL cierra los cursores

implícitos inmedíatamente después de haber sido ejecutados.

Ejecutando SQL dentro de bloques PL/SQL

PL/SQL es un lenguaje de programación de base de datos. Casi todos los programas

que escribiremos en PL/SQL leerán desde, o escribirán en, una base de datos Oracle

utilizando SQL. Aunque estas series asumen que se conoce SQL, debemos estar

conscientes de la forma en que llamamos a las sentencias desde un bloque PL/SQL.

Page 32: Introducción a Oracle SQL y PL Volumen 1 y 2

32

Y aquí hay algunas buenas noticias: Oracle hace que sea muy fácil escribir y

ejecutar sentencias SQL en PL/SQL. La mayor parte de las veces, simplemente

escribiremos las sentencias SQL directamente en nuestro bloque PL/SQL y después

agregaremos el código necesario para la interfaz entre las sentencias SQL y el código

PL/SQL.

Supongamos, por ejemplo, que tenemos una tabla llamada empleados, con una

columna clave primaria id_empleado, y una columna apellido. Podemos ver el

apellido del empleado con ID 138, como sigue:

SELECT apellido

FROM empleados

WHERE id_empleado = 138

Ahora querríamos ejecutar esta misma consulta dentro de nuestro bloque PL/SQL y

desplegar el nombre. Para hacer esto, necesitaremos “copiar” el apellido desde la

tabla a una variable local, lo cual podemos hacer con la cláusula INTO:

DECLARE

v_apellido empleados.apellido%TYPE;

BEGIN

SELECT apellido

INTO v_apellido

FROM empleados

WHERE id_empleado = 138;

DBMS_OUTPUT.put_line(v_apellido);

END;

Primero declaramos una variable local, y haciendo esto introducimos otra

carácterística elegante de PL/SQL: la capacidad de fijar el tipo de datos de nuestra

variable en función del tipo de datos de una columna en una tabla (esto será

profundizado más adelante en esta serie)

Después ejecutamos una consulta contra la base, obteniendo el apellido del empleado

y asignándolo directamente en la variable v_apellido.

Por supuesto, querremos hacer más que ejecutar sentencias SELECT en PL/SQL,

también querremos insertar, modificar y eliminar datos desde PL/SQL. Aquí hay

ejemplos de cada uno de esos tipos de sentencias DML:

• Eliminamos todos los empleados en el departamento 10 y mostramos cuántas tuplas

fueron eliminadas:

DECLARE

v_id_departamento empleados.id_departamento%TYPE := 10;

BEGIN

DELETE FROM empleados

WHERE id_departamento = v_id_departamento;

DBMS_OUTPUT.put_line(SQL%ROWCOUNT);

END;

Referenciamos la variable PL/SQL directamente dentro de la sentencia DELETE.

Cuando el bloque se ejecuta, la variable se reemplaza con el valor actual, 10, y el

DELETE es ejecutado por el motor de SQL. SQL%ROWCOUNT es un atributo

especial de cursor que retorna el número de tuplas modificadas por la última

sentencia DML ejecutada en nuestra sesión.

• Modificar todos los empleados en el departamento 10 con un 20% de incremento

salarial.

DECLARE

Page 33: Introducción a Oracle SQL y PL Volumen 1 y 2

33 v_id_departamento empleados.id_departamento%TYPE := 10;

BEGIN

UPDATE empleados

SET salario = salario * 1.2

WHERE id_departamento = v_id_departamento;

DBMS_OUTPUT.put_line(SQL%ROWCOUNT);

END;

Insertar un nuevo empleado en la tabla.

BEGIN

INSERT INTO empleados (id_empleado

, apellido

, id_departamento

, salario)

VALUES (100

, 'Feuerstein'

, 10

, 200000);

DBMS_OUTPUT.put_line(SQL%ROWCOUNT);

END;

En este bloque, proveímos los valores de las columnas como literales, en lugar de

variables, directamente dentro de la sentencia SQL.

Page 34: Introducción a Oracle SQL y PL Volumen 1 y 2

34

Capítulo 19 Escribiendo estructuras de control

Se puede controlar el flujo lógico de las sentencias usando condicionales IF y LOOP

IF –THEN –END IF

IF –THEN –ELSE –END IF

IF –THEN –ELSIF –END IF

IF condición THEN

Sentencias;

[ELSIF condición THEN

sentencias;]

[ELSE

sentencias;]

END IF;

Condición : Es una variable o expresión booleana.

THEN : Asocia la condición con la secuencia de sentencias que la siguen

Si la condición es falsa o NULL no se ejecutan las sentencias.

En IF anidados, estos deben terminar con su correspondiente END IF;

Es preferible usar ELSIF que IF anidados.

Se puede manejar valores NULL con IS NULL

Una expresión aritmética que contenga nulos se vuelve nula.

En la concatenación el null es tratado como un espacio vacio.

NULL AND FALSE = FALSE

NULL OR TRUE = TRUE

NOT NULL = NULL

Sentencias LOOP

LOOP basico

For loop : control iterativo basado en un contador

While loop : control iterativo basado en una condición

Exit : Termina un loop

LOOP

Sentencias;

EXIT [WHEN condición];

END LOOP;

LOOP FOR

FOR contador in [REVERSE]

Lower_bound..upper_bound LOOP

Ssentencias;

END LOOP;

El rango pueden ser literales, variables, expresiones.

Se referencia el contador dentro del loop solo si es indefinido fuera de este.

WHILE LOOP

WHILE condición LOOP

Sentencias;

END LOOP;

Se repite mientras la condición sea TRUE. Si la condición es NULL el loopes pasado.

Page 35: Introducción a Oracle SQL y PL Volumen 1 y 2

35

Los loops se pueden anidar , se puede usar labels para distiguir entre loops

(<<label>>) se colocan antes de LOOP, se puede salir del loop con EXIT

referenciando el label, el label se puede incluir en el END LOOP por claridad

BEGIN

<<outer_loop>>

LOOP

EXIT WHEN v_count > 10

<<inner_loop>>

LOOP

EXIT outer_loop WHEN total = ‘YES’

EXIT inner_loop WHEN inner_done = ‘YES’

END LOOP inner_loop;

END LOOP outer_loop;

END;

Page 36: Introducción a Oracle SQL y PL Volumen 1 y 2

36

Capítulo 20 Trabajando con tipos de datos compuestos

Registros PL/SQL

Tablas PL/SQL

Nested tables

Varray

Contienen componentes internos son reusables, es utiliza el RECORD para tratar

datos dissimilares como una unidad lógica, se usa TABLE para referenciar y

manipular colecciones de datos como un objeto.

Un registro es un grupo de datos relacionados almacenados en campos, que tienen su

nombre y su tipo de datos, una tabla contiene columnas y su llave primaria.

Son convenientes para sacar filas de datos de una tabla para procesamiento.

A los registros se les pueden asignar valores iniciales o definirlos como NOT NULL,

hay registros anidados.

TYPE type_name IS RECORD

{ field_declaration [,field_declaration...]};

Field_declaration field_name { field_type | variable%TYPE | table.column%TYPE |

table%ROWTYPE }

[ [NOT NULL] {:= DEFAULT } expr ]

Para referenciar los campos de un registro: record_name.field_name, su alcanze es

en el bloque o subprograma donde fue definido.

El atributo %ROWTYPE

Declara una variable de acuerdo a una colección de columnas en una tabla o vista de

la BD

DECLARE

Emp_record emp%ROWTYPE;

Ventajas de usar ROWTYPE

Desconocimiento de los campos de una tabla

Los campos cambian runtime

DECLARE

emp_rec emp%ROWTYPE;

BEGIN

SELECT * INTO emp_rec

FROM emp;

END;

Tablas PL/SQL

Tienen dos componentes * PK de tipo de datos BINARY_INTEGER, * columnas

escalaras o tipo de dato de registro.

Se incrementa dinámicamente. Son similares a un arreglo

TYPE type_name IS TABLE OF

{column_type | variable%TYPE | table.column%TYPE} [NOT NULL]

[INDEX BY BINARY_INTEGER]

TYPE ename_table_type IS TABLE OF emp.ename%TYPE

INDEX BY BINARY_INTEGER;

Ename_table ename_table_type;

No pueden ser incializadas en su declaración. Se referencian

pl_sql_table_name(primary_key_values), la PK puede ser negativa

Page 37: Introducción a Oracle SQL y PL Volumen 1 y 2

37

Usando metodos de tablas PL/SQL

Table_name.method_name[(parameters)]

EXISTS(n) Retorna TRUE si el elemento en la posición existe

COUNT Número de elementos de una tabla PL/SQL

FIRST Retorna el primero y el ultimo número de indice, NULL si esta

LAST vacia

PRIOR(n) Retorna número de indice que precede al indice n

NEXT(n) Retorna número de indice que sucede al indice n

EXTEND(n,i) * Incrementa el tamaño de la tabla

EXTEND agrega un elemento nulo

EXTEND(n) agrega n elementos nulos

EXTEND(n,i) agrega n copias de el elemento i

TRIM * remueve un elemento del final

TRIM(n) remueve n elementos del final

DELETE Remueve todos los elementos de la tabla

DELETE(n) remueve el elemento n

DELETE(m,n) Remueve elemenetos en el rango m..n

Para referirse a los elementos de una tabla

Table(index).campo

Page 38: Introducción a Oracle SQL y PL Volumen 1 y 2

38

Capítulo 21 Escribiendo cursores explícitos

El servidor implícitamente abre un cursor para procesar sentencias SELECT no

asociadas con un cursor explícito.

Cursores Implícitos

Los cursores implícitos se utilizan para realizar consultas SELECT que devuelven

un único registro.

Deben tenerse en cuenta los siguientes puntos cuando se utilizan cursores

implícitos:

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

Las variables que reciben los datos devueltos por el cursor tienen que contener

el mismo tipo de dato que las columnas de la tabla.

Los cursores implícitos solo pueden devolver una única fila. En caso de que se

devuelva más de una fila (o ninguna fila) se producirá una excepción. 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 los errores.

El siguiente ejemplo muestra un cursor implícito:

declare

vdescripcion VARCHAR2(50);

begin

SELECT DESCRIPCION

INTO vdescripcion

from PAISES

WHERE CO_PAIS = 'ESP';

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

vdescripcion);

end;

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

La lectura del cursor es: ESPAÑA

Excepciones asociadas a los cursores implícitos.

Los cursores implícitos sólo pueden devolver una fila, por lo que pueden producirse

determinadas excepciones. Las más comunes que se pueden encontrar son

no_data_found y too_many_rows. La siguiente tabla explica brevemente estas

excepciones.

Excepción Explicación

NO_DATA_FOUND Se produce cuando una sentencia SELECT intenta recuperar datos

pero ninguna fila satisface sus condiciones. Es decir, cuando "no hay

datos"

TOO_MANY_ROWS Dado que cada cursor implícito sólo es capaz de recuperar una fila ,

esta excepción detecta la existencia de más de una fila.

Cursores explícitos

Procesa cada fila retornada por un SELECT de multiples filas. El grupo de filas

retornado es llamdo grupo activo, se guarda un rastro de cual es la fila corriente, el

programador lo controla manualmente.

Se usa OPEN ejcuta el query asociado, identifica el grupo activo y la posición del

cursor , FETCH recupera la fila corriente y avanza el cursor a la proxima fila,

CLOSE deshabilita el cursor y libera lass filas.

CURSOR cursor_name IS

Select_statement;

Page 39: Introducción a Oracle SQL y PL Volumen 1 y 2

39

Abriendo el cursor

OPEN cursor_name;

Dinamicamente asigna memoria para el área de contexto, Parsea el SELECT, obtiene

posiciones de memoria de las variables de entrada, identifica el grupo activo,

posiciona el puntero justamente antes de la primera fila.

Si no retorna filas no se da una excepción , perso se puede probar la salida con los

atributos del cursor.

Para cursores declarados FOR UPDATE, se bloquean las filas.

FETCH cursor_name INTO [variable1, ... | record_name ];

Recupera la fila corriente dentro de variables, incluye el mismo número de variables,

se debe probar el curosr para ver si contiene filas.

...

Open defined_cursor;

LOOP

FETCH defined_cursor INTO defined_variables;

EXIT WHEN ....;

END LOOP;

...

CLOSE cursor_name;

Se debe cerrar para liberar recursos, esta ligado con el parámetro OPEN_CURSORS.

Atributos : %ISOPEN , %NOTFOUND, %FOUND, %ROWCOUNT número de

filas que trae el cursor.

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

Atributo Antes de abrir Al

abrir

Durante la

recuperación

Al finalizar la

recuperación

Después de

cerrar

%NOTFOUND ORA-1001 NULL FALSE TRUE ORA-1001

%FOUND ORA-1001 NULL TRUE FALSE ORA-1001

%ISOPEN FALSE TRUE TRUE TRUE FALSE

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

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

** Número de total de registros

Para procesar diferentes filas de un cursor de usa un LOOP.

FETCH emp_cursor INTO v_empno;

EXIT WHEN emp_cursor%NOTFOUND OR emp_cursor%NOTFOUND IS NULL;

IS NULL es para asegurarse asi si el FETCH nunca se ejecuta no habra problemas.

Se puede crear registros basados en las filas de un cursor.

DECLARE

CURSOR em IS

SELECT empno, ename

FROM emp;

Emp_record em%ROWTYPE;

BEGIN

OPEN em;

FETCH em INTO emp_record;

END;

Cursor para LOOPS

FOR record_name IN cursor_name LOOP

Sentencias;

END LOOP;

Page 40: Introducción a Oracle SQL y PL Volumen 1 y 2

40

Hay implicitamente OPEN, FECTH y CLOSE. y el cursor es implícitamente

declarado.

Cursores en LOOPS que usan subqueries

No se necesita declarar el cursor, y no puede usar los atributos de cursor.

BEGIN

FOR em IN ( SELECT empno FROM emp )

LOOP

Sentencias;

END LOOP;

END;

El siguiente ejemplo ilustra el trabajo con un cursor explícito. Hay que tener en

cuenta que al leer los datos del cursor debemos hacerlo sobre variables del mismo

tipo de datos de la tabla (o tablas) que trata el cursor.

DECLARE

CURSOR cpaises

IS

SELECT CO_PAIS, DESCRIPCION, CONTINENTE

FROM PAISES;

co_pais VARCHAR2(3);

descripcion VARCHAR2(50);

continente VARCHAR2(25);

BEGIN

OPEN cpaises;

FETCH cpaises INTO co_pais,descripcion,continente;

CLOSE cpaises;

END;

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

el cursor.

DECLARE

CURSOR cpaises

IS

SELECT CO_PAIS, DESCRIPCION, CONTINENTE

FROM PAISES;

registro cpaises%ROWTYPE;

BEGIN

OPEN cpaises;

FETCH cpaises INTO registro;

CLOSE cpaises;

END;

El mismo ejemplo, pero utilizando parámetros:

DECLARE

CURSOR cpaises (p_continente VARCHAR2)

IS

SELECT CO_PAIS, DESCRIPCION, CONTINENTE

FROM PAISES

WHERE CONTINENTE = p_continente;

registro cpaises%ROWTYPE;

BEGIN

OPEN cpaises('EUROPA');

FETCH cpaises INTO registro;

CLOSE cpaises;

END;

Cuando trabajamos con cursores debemos considerar:

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

Cuando leemos un cursor debemos comprobar el resultado de la lectura

utilizando los atributos de los cursores.

Page 41: Introducción a Oracle SQL y PL Volumen 1 y 2

41

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

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

Cursores de actualización

Los cursores de actualización se declaran igual que los cursores explícitos,

añadiendo FOR UPDATE al final de la sentencia select.

CURSOR nombre_cursor IS

instrucción_SELECT

FOR UPDATE

Para actualizar los datos del cursor hay que ejecutar una sentencia UPDATE

especificando la cláusula WHERE CURRENT OF <cursor_name>.

UPDATE <nombre_tabla> SET

<campo_1> = <valor_1>

[,<campo_2> = <valor_2>]

WHERE CURRENT OF <cursor_name>

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

DECLARE

CURSOR cpaises IS

select CO_PAIS, DESCRIPCION, CONTINENTE

from paises

FOR UPDATE;

co_pais VARCHAR2(3);

descripcion VARCHAR2(50);

continente VARCHAR2(25);

BEGIN

OPEN cpaises;

FETCH cpaises INTO co_pais,descripcion,continente;

WHILE cpaises%found

LOOP

UPDATE PAISES

SET CONTINENTE = CONTINENTE || '.'

WHERE CURRENT OF cpaises;

FETCH cpaises INTO co_pais,descripcion,continente;

END LOOP;

CLOSE cpaises;

COMMIT;

END;

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

siguientes consideraciones:

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

Page 42: Introducción a Oracle SQL y PL Volumen 1 y 2

42

Capítulo 23 Manejando excepciones

Manejando excepciones con PL/SQL

Una excepción es un identificador que se alcanza durante la ejecución cuando ocurre

un error Oracle o cuando se alcanza explícitamente terminando asi las acciones en el

cuerpo principal, se puede manejar atrapándola en un manejador realizando las

acciones finales o propagandola al ambiente llamado.

Se puede alcanzar la excepción explícitamente usando RAISE.

Al atrapar una excepción el procesamiento pasa al manejador de excepciones, si se

maneja exitosamente la excepción, entonces la excepción no se propaga y el bloque

PL/SQL termina con éxito. Si no el bloque PL/SQL falla y la excepción es propagada

al ambiente que fue llamada.

Tipos de excepciones

Predefinidas por Oracle : Aproximadamente 20 errores

No predefinidas por Oracle : Cualquier otro error estandar de Oracle

Definidas por el usuario : Condición que el desarrollador define como anormal

Atrapando excepciones

EXCEPTION

WHEN exception1 [OR exception2 ... ] THEN

Sentencias;

[ WHEN exception3 [ OR exception4 ... ] THEN

sentencias;

]

[ WHEN OTHERS THEN

sentencias;

]

Se puede atrapar cualquier error incluyendo la rutina correspondiente en el

manejador de excepciones, cada manejador consiste de una clausula WHEN.

OTHERS atrapa las excepciones no definidas y por esto es la ultima excepción

definida en el manejador. Solo un manejador es procesado antes de salir del bloque.

Atrapando errores predefinidos

Referenciar el nombre estándar en la rutina de manejo de excepciones.

La siguiente es la lista de las excepciones predeterminadas por PL/SQL y una breve

descripción de cuándo son accionadas:

Excepcion Se ejecuta ... SQLCODE

ACCESS_INTO_NULL El programa intentó asignar valores a los

atributos de un objeto no inicializado -6530

COLLECTION_IS_NULL El programa intentó asignar valores a una

tabla anidada aún no inicializada -6531

CURSOR_ALREADY_OPEN

El programa intentó abrir un cursor que ya se

encontraba abierto. Recuerde que un cursor de

ciclo FOR automáticamente lo abre y ello no

se debe especificar con la sentencia OPEN

-6511

DUP_VAL_ON_INDEX

El programa intentó almacenar valores

duplicados en una columna que se mantiene

con restricción de integridad de un índice

único (unique index)

-1

INVALID_CURSOR El programa intentó efectuar una operación

no válida sobre un cursor -1001

INVALID_NUMBER

En una sentencia SQL, la conversión de una

cadena de carácteres hacia un número falla

cuando esa cadena no representa un número

-1722

Page 43: Introducción a Oracle SQL y PL Volumen 1 y 2

43

válido

LOGIN_DENIED El programa intentó conectarse a Oracle con

un nombre de usuario o password inválido -1017

NO_DATA_FOUND

Una sentencia SELECT INTO no devolvió

valores o el programa referenció un elemento

no inicializado en una tabla indexada

100

NOT_LOGGED_ON El programa efectuó una llamada a Oracle sin

estar conectado -1012

PROGRAM_ERROR PL/SQL tiene un problema interno -6501

ROWTYPE_MISMATCH

Los elementos de una asignación (el valor a

asignar y la variable que lo contendrá) tienen

tipos incompatibles. También se presenta este

error cuando un parámetro pasado a un

subprograma no es del tipo esperado

-6504

SELF_IS_NULL El parámetro SELF (el primero que es pasado

a un método MEMBER) es nulo -30625

STORAGE_ERROR La memoria se terminó o está corrupta -6500

SUBSCRIPT_BEYOND_COUNT

El programa está tratando de 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 colección

-6533

SUBSCRIPT_OUTSIDE_LIMIT

El programa está referenciando un elemento

de un arreglo utilizando un número fuera del

rango permitido (por ejemplo, el elemento “-

1”)

-6532

SYS_INVALID_ROWID

La conversión de una cadena de carácteres

hacia un tipo rowid falló porque la cadena no

representa un número

-1410

TIMEOUT_ON_RESOURCE Se excedió el tiempo máximo de espera por

un recurso en Oracle -51

TOO_MANY_ROWS Una sentencia SELECT INTO devuelve más

de una fila -1422

VALUE_ERROR

Ocurrió un error aritmético, de conversión o

truncamiento. Por ejemplo, sucede cuando se

intenta calzar un valor muy grande dentro de

una variable más pequeña

-6502

ZERO_DIVIDE El programa intentó efectuar una división por

cero -1476

Atrapando excepciones no predefinidas por el servidor

Se la declara, o usando OTHERS, en pl/sql pragma EXCEPTION_INIT llama al

compilador asociando el nombre de la excepción con un número de error Oracle.

PRAGMA significa que la sentencia es una directiva de compilador.

DECLARE

E_emps EXCEPTION;

PRAGMA EXCEPTION INIT ( e_emps, -2292);

BEGÍN

....

EXCEPTION

WHEN e_emps THEN

....

END;

Funciones para atrapar excepciones

Page 44: Introducción a Oracle SQL y PL Volumen 1 y 2

44

SQLCODE retorna el valor numerico del error 0 no hay excepción, 1 excepción

definida por el usuario, +100 NO_DATA_FOUND, número negativo otro error

Oracle

SQLERRM retorna el mensaje asociado

DECLARE

V_error_code NUMBER;

V_error_message VARCHAR2(255);

BEGÍN

EXCEPTION

WHEN OTHERS THEN

ROLLBACK;

V_error_code := SQLCODE;

V_error_message := SQLERRM;

END;

DECLARE

err_num NUMBER;

err_msg VARCHAR2(255);

result NUMBER;

BEGIN

SELECT 1/0 INTO result

FROM DUAL;

EXCEPTION

WHEN OTHERS THEN

err_num := SQLCODE;

err_msg := SQLERRM;

DBMS_OUTPUT.put_line('Error:'||TO_CHAR(err_num));

DBMS_OUTPUT.put_line(err_msg);

END;

También es posible entregarle a la función SQLERRM un número negativo que represente un error

de Oracle y ésta devolverá el mensaje asociado.

DECLARE

msg VARCHAR2(255);

BEGIN

msg := SQLERRM(-1403);

DBMS_OUTPUT.put_line(MSG);

END;

Atrapando excepciones definidas por el usuario

DECLARE

RAISE

REFERENCE

DECLARE

E_invalid EXCEPTION;

BEGÍN

UPDATE product

SET descrip = “nnnnn “

WHERE prodid = 5;

IF SQL%NOTFFOUND THEN

RAISE e_invalid;

END IF;

EXCEPTION

WHEN e_invalid THEN

ROLLBACK;

END;

Page 45: Introducción a Oracle SQL y PL Volumen 1 y 2

45

DECLARE

-- Declaramos una excepcion identificada por VALOR_NEGATIVO

VALOR_NEGATIVO EXCEPTION;

valor NUMBER;

BEGIN

-- Ejecucion

valor := -1;

IF valor < 0 THEN

RAISE VALOR_NEGATIVO;

END IF;

EXCEPTION

-- Excepcion

WHEN VALOR_NEGATIVO THEN

dbms_output.put_line('El valor no puede ser negativo');

END;

RAISE_APPLICATION_ERROR

En ocasiones queremos enviar un mensaje de error personalizado al producirse una

excepción PL/SQL.

Para ello es necesario utilizar la instruccion RAISE_APPLICATION_ERROR;

La sintaxis general es la siguiente:

RAISE_APPLICATION_ERROR(<error_num>,<mensaje>);

Siendo:

error_num es un entero negativo comprendido entre -20001 y -20999

mensaje la descripcion del error

DECLARE

v_div NUMBER;

BEGIN

SELECT 1/0 INTO v_div FROM DUAL;

EXCEPTION

WHEN OTHERS THEN

RAISE_APPLICATION_ERROR(-20001,'No se puede dividir por cero');

END;

Ambientes llamados

SQL*Plus Despliega el número del error y el mensaje en la pantalla

Procedure builder “ “ “

Oracle Developer Forms utiliza ERROR_CODE y ERROR_TEXT

Aplicación precompilada accede al número de la excepción atravez de SQLCA

Bloque PL/SQL atrapa la excepción en el manejador de excepciones

RAISE_APPLICATION_ERROR (error_number, message[ , {TRUE | FALSE}]);

Permite usar mensajes de error definidos por el usuario

Error_number –20000 a –20999

TRUE | FALSE si TRUE los errores en la pila de los errores previos, FALSE el error

default reemplaza los errores previos. Se puede usar en la sección ejecutable y la

sección de excepciones.

DECLARE

fecha DATE;

FUNCTION fn_fecha RETURN DATE

IS

fecha DATE;

BEGIN

SELECT SYSDATE INTO fecha

FROM DUAL

WHERE 1=2;

RETURN fecha;

EXCEPTION

Page 46: Introducción a Oracle SQL y PL Volumen 1 y 2

46 WHEN ZERO_DIVIDE THEN

dbms_output.put_line('EXCEPCION ZERO_DIVIDE CAPTURADA

EN fn_fecha');

END;

BEGIN

fecha := fn_fecha();

dbms_output.put_line('La fecha es '||TO_CHAR(fecha,

'DD/MM/YYYY'));

EXCEPTION

WHEN NO_DATA_FOUND THEN

dbms_output.put_line('EXCEPCION NO_DATA_FOUND CAPTURADA EN

EL BLOQUE PRINCIPAL');

END;

Page 47: Introducción a Oracle SQL y PL Volumen 1 y 2

47

Capítulo 24 Ejemplos de PL/SQL Básico

PL/SQL básico

El clásico “¡Hola Mundo!” es un bloque con una sección ejecutable que llama al

procedimiento DBMS_OUTPUT.PUT_LINE para mostrar texto en pantalla:

BEGIN

DBMS_OUTPUT.put_line('¡Hola Mundo!');

END;

Las funciones y procedimientos —tipos de bloques con un nombre— son discutidos

con mayor detalle más adelante en este artículo, así como los paquetes. En pocas

palabras, sin embargo, un paquete es un contenedor de múltiples funciones y

procedimientos. Oracle extiende PL/SQL con muchos paquetes incorporados en el

lenguaje.

El siguiente bloque declara una variable de tipo VARCHAR2 (un string) con un largo

máximo de 100 bytes para contener el string ‘¡Hola Mundo!’. Después, el

procedimiento DBMS_OUTPUT.PUT_LINE acepta la variable, en lugar del literal,

para desplegarlo:

DECLARE

l_mensaje VARCHAR2(100) := '¡Hola Mundo!';

BEGIN

DBMS_OUTPUT.put_line(l_mensaje);

END;

Note que he llamado a la variable l_mensaje. Normalmente uso el prefijo l_ para

variables locales —variables definidas dentro del código de un bloque— y el prefijo

g_ para variables globales definidas en un paquete.

El siguiente ejemplo de bloque agrega una sección de manejo de excepciones que

atrapa cualquier excepción (WHEN OTHERS) que pueda ser lanzada y muestra el

mensaje de error, que es retornado por la función SQLERRM (provista por Oracle).

DECLARE

l_mensaje VARCHAR2(100) := '¡Hola Mundo!';

BEGIN

DBMS_OUTPUT.put_line(l_mensaje);

EXCEPTION

WHEN OTHERS

THEN

DBMS_OUTPUT.put_line(SQLERRM);

END;

El siguiente ejemplo de bloque demuestra la habilidad de PL/SQL de anidar bloques

dentro de bloques así como el uso del operador de concatenación (||) para unir

múltiples strings.

DECLARE

l_mensaje VARCHAR2(100) := '¡Hola';

BEGIN

DECLARE

l_mensaje2 VARCHAR2(100) := l_mensaje || ' Mundo!';

BEGIN

DBMS_OUTPUT.put_line(l_mensaje2);

END;

EXCEPTION

WHEN OTHERS

THEN

Page 48: Introducción a Oracle SQL y PL Volumen 1 y 2

48 DBMS_OUTPUT.put_line(DBMS_UTILITY.format_error_stack);

END;

Se ejecuta la función “pExeSuiComercial” del paquete

“olbgenerainfosuicomer_48765”. Se envía un mensaje de terminación correcta y de

no ser así se envía el código y mensaje de error respectivo.

BEGIN

olbgenerainfosuicomer_48765.pExeSuiComercial(7,

To_Date('01-04-2013','DD-MM-YYYY'),

To_Date('30-04-2013','DD-MM-YYYY'));

Dbms_Output.put_line('Proceso Ok');

EXCEPTION

WHEN Others THEN

Dbms_Output.put_line(SQLCODE || ':' || SQLERRM);

END;

Ejecutando el PL/SQL

Una vez que hemos escrito un bloque de código PL/SQL éste se puede ejecutar.

Existen muchas herramientas para ejecutar código PL/SQL. La más básica es

SQL*Plus, una interfaz de línea de comandos para ejecutar sentencias SQL así como

bloques PL/SQL. La Figura 1 muestra un ejemplo de ejecución del más simple de los

bloques de ejemplo de nuestro “¡Hola Mundo!” en SQL*Plus.

Figura 1: Ejecutando “¡Hola Mundo!” en SQL*Plus

La primera cosa que hacemos después de conectarnos a la base medíante SQL*Plus

es habilitar la salida del servidor, por lo que las llamadas a

DBMS_OUTPUT.PUT_LINE resultarán en la visualización de texto en la pantalla.

Luego escribimos el código que constituye nuestro bloque. Finalmente, ingresamos

una barra (/) para decirle a SQL*Plus que ejecute ese código.

SQL*Plus entonces ejecuta el bloque y muestra el “¡Hola Mundo!” en la pantalla.

SQL*Plus es provisto por Oracle como una especie de línea base de entorno donde se

pueden ejecutar sentencias SQL y bloques PL/SQL. Mientras que algunos

desarrolladores siguen utilizando únicamente SQL*Plus, la mayoría utiliza un

entorno de desarrollo integrado (IDE). Entre los más populares de estos entornos de

desarrollo (basado en encuestas informales que he tomado en mis sesiones de

entrenamiento) son

SQL Tools

Oracle SQL Developer, de Oracle

Toad y SQL Navigator, de Quest Software

PL/SQL Developer, de Allround Automations

Page 49: Introducción a Oracle SQL y PL Volumen 1 y 2

49

Cada herramienta ofrece, con algunas diferencias, ventanas y pasos para crear,

guardar, y ejecutar bloques PL/SQL, así como habilitar y deshabilitar la salida del

servidor.

Otra opción de ejecución es SQL Tools:

Figura 1: Ejecutando “pExeSuiComercial” en SQL Tools

Page 50: Introducción a Oracle SQL y PL Volumen 1 y 2

50

Capítulo 25 Subprogramas: procedimientos y funciones

¡Póngale nombre a los bloques!

Todos los bloques que hemos visto hasta el momento son “anónimos”, no tienen

nombres. Si los bloques anónimos fueran la única manera de organizar el código,

sería muy difícil usar PL/SQL para crear una aplicación grande y compleja. Por esto,

PL/SQL soporta la definición de bloques nombrados (named blocks), también

conocidos como subprogramas. Los subprogramas pueden ser procedimientos o

funciones. Generalmente, un procedimiento se utiliza para realizar una acción y una

función se utiliza para calcular y devolver un valor. Voy a tratar sobre subprogramas

con mucho más detalle en un próximo artículo de esta serie. Por ahora, vamos a

asegurarnos de que se comprendan los conceptos básicos detrás de la creación del

subprograma.

Supongamos que necesitamos mostrar "¡Hola Mundo!" desde múltiples lugares en

nuestra aplicación. Queremos evitar la repetición de la misma lógica en todos esos

lugares. Por ejemplo, ¿qué pasa cuando tenemos que cambiar el mensaje, tal vez para

"¡Hola Universo!"? Vamos a tener que encontrar todos los lugares en nuestro código

donde esta lógica aparece.

En su lugar, vamos a crear un procedimiento denominado hola_mundo medíante la

ejecución de la siguiente sentencia DDL (Data Definition Language):

CREATE OR REPLACE PROCEDURE hola_mundo IS

l_mensaje VARCHAR2(100) := '¡Hola Mundo!';

BEGIN

DBMS_OUTPUT.put_line(l_mensaje);

END hola_mundo;

Con esto hemos extendido PL/SQL. Además de llamar a los programas creados por

Oracle e instalados en la base de datos (como DBMS_OUTPUT.PUT_LINE),

podemos llamar a nuestro propio subprograma dentro de un bloque PL/SQL:

BEGIN

hola_mundo;

END;

Hemos escondido todos los detalles de cómo decir hola al mundo dentro del cuerpo

(body), o implementación, de nuestro procedimiento. Ahora podemos llamar a este

procedimiento hola_mundo y mostrar el mensaje deseado sin tener que escribir la

llamada a DBMS_OUTPUT.PUT_LINE o averiguar la forma correcta de darle

formato al texto. Podemos llamar a este procedimiento desde cualquier lugar en

nuestra aplicación. Así que si alguna vez necesitamos cambiar ese texto, lo vamos a

hacer en un solo lugar, el único punto de definición de ese texto.

El procedimiento hola_mundo es muy simple. Tus procedimientos tendrán mucho

más código, y casi siempre también tendrán parámetros. Los parámetros pasan

información a los subprogramas, cuando éstos son llamados, y es lo que permite crear

subprogramas más flexibles y genéricos. Se pueden usar en muchos contextos

diferentes.

He mencionado antes que algún día puede ser que desee mostrar "¡Hola Universo!"

en lugar de "¡Hola Mundo!". Podría hacer una copia de nuestro procedimiento

hola_mundo y cambiar el texto que se muestra:

CREATE OR REPLACE PROCEDURE hola_universo IS

l_mensaje VARCHAR2(100) := '¡Hola Universo!';

BEGIN

DBMS_OUTPUT.put_line(l_mensaje);

END hola_universo;

Page 51: Introducción a Oracle SQL y PL Volumen 1 y 2

51

Podríamos, sin embargo, terminar con las decenas de variantes del “mismo”

procedimiento hola, que haría muy difícil mantener nuestra aplicación. Un enfoque

mucho mejor es analizar el procedimiento e identificar qué partes se mantienen

incambiadas (son estáticas) cuando el mensaje tiene que cambiar y qué partes

cambian. Luego podemos pasar las partes que cambian como parámetros y tener un

procedimiento único que se puede utilizar en diferentes circunstancias.

Así que vamos a cambiar hola_mundo (y hola_universo) a un nuevo procedimiento,

hola_lugar:

CREATE OR REPLACE PROCEDURE hola_lugar (lugar_in IN VARCHAR2) IS

l_mensaje VARCHAR2(100);

BEGIN

l_mensaje := '¡Hola ' || place_in;

DBMS_OUTPUT.put_line(l_mensaje);

END hola_lugar;

Justo después del nombre del procedimiento, añadimos entre paréntesis de apertura y

cierre, un único parámetro. Podemos tener varios parámetros, pero cada parámetro de

la misma forma básica:

nombre_de_parametro modo_de_parametro tipo_de_datos

En otras palabras, debemos proveer un nombre para el parámetro, el modo o forma en

que éste será usado (IN = sólo lectura), y el tipo de dato que será pasado al

subprograma a través de este parámetro.

En este caso, vamos a pasar un texto de sólo lectura al procedimiento hola_lugar.

Y ahora podemos saludar a nuestro mundo y a nuestro universo como sigue:

BEGIN

hola_lugar('Mundo!');

hola_lugar('Universo!');

END;

Más adelante en esta serie vamos a explorar el concepto de reutilización y la manera

de evitar la repetición, pero debes ser capaz de ver en este ejemplo, el poder de

ocultar la lógica detrás de un bloque con nombre.

Ahora supongamos que no sólo queremos mostrar nuestros mensajes "Hola". A veces

tenemos que mantener los mensajes en una tabla en la base de datos; en otras

ocasiones, tenemos que pasar el texto de nuevo al entorno del cliente para su

visualización en un navegador Web. En otras palabras, necesitamos separar la forma

en que se construyó el mensaje "Hola" de la forma en que se utiliza (se visualiza, se

guarda, se envía otro programa, etc). Podemos alcanzar este nivel deseado de

flexibilidad moviendo el código que construye el mensaje a su propia función:

CREATE OR REPLACE FUNCTION

hola_mensaje(lugar_in IN VARCHAR2) RETURN VARCHAR2 IS

BEGIN

RETURN '¡Hola ' || place_in;

END hola_mensaje;

Este subprograma se diferencia del procedimiento original en lo siguiente:

• El tipo de programa es ahora FUNCTION y no PROCEDURE.

• El nombre del subprograma ahora describe los datos que se devuelven, no las

acciones tomadas.

• El cuerpo o la implementación del subprograma contiene ahora una cláusula

RETURN que construye el mensaje y lo devuelve al bloque llamador.

• La cláusula RETURN después de la lista de parámetros establece el tipo de datos

devuelto por la función.

Page 52: Introducción a Oracle SQL y PL Volumen 1 y 2

52

Teniendo el código necesario para construir el mensaje dentro de la función

hola_mensaje, podemos utilizar este mensaje de múltiples maneras. Podemos, por

ejemplo, llamar a la función para obtener el mensaje y asignárselo a una variable:

DECLARE

l_mensaje VARCHAR2(100);

BEGIN

l_mensaje := hola_mensaje('Universo');

END;

Nota que llamamos a la función hola_mensaje como parte de una sentencia PL/SQL

(en este caso, la asignación de un texto a una variable). La función hola_mensaje

devuelve un string, por lo que se puede utilizar en lugar de un string en cualquier

sentencia ejecutable.

También podemos volver a nuestro procedimiento hola_lugar y reemplazar el código

utilizado para crear el string con una llamada a la función:

CREATE OR REPLACE PROCEDURE

hola_lugar(place_in IN VARCHAR2) IS

BEGIN

DBMS_OUTPUT.put_line(hola_mensaje(place_in));

END hola_lugar;

También podemos llamar la función desde una sentencia SQL. En el siguiente

bloque, insertamos el mensaje en una tabla de la base:

BEGIN

INSERT INTO tabla_mensaje(fecha_mensaje, texto_mensaje)

VALUES (SYSDATE, hola_mensaje('Montevideo'));

END;

Aunque la lógica del “mensaje hola” es muy simple, demuestra el poder de asignar

nombres a una o más sentencias ejecutables (un algoritmo) y luego referenciar el

algoritmo simplemente especificando el nombre y los parámetros requeridos.

Los bloques PL/SQL con nombre, permiten construir aplicaciones complejas que

pueden ser comprendidas y mantenidas con relativa fácilidad.

Sobre los nombres en una base Oracle

Ahora que ya se aprecia la importancia de asignar nombres a la lógica, es tiempo de

hablar sobre las reglas para los nombres (o, para ser más precisos, identificadores)

tanto en PL/SQL como, de forma más general, en una base Oracle.

Estas son las reglas para construir identificadores válidos en una base Oracle:

• El largo máximo es de 30 carácteres.

• El primer carácter debe ser una letra, pero cada carácter después del primero puede

ser una letra, un número (0 a 9), un signo de pesos ($), un guión bajo (_), o un

numeral (#). Todos los siguientes son identificadores válidos:

hola_mundo

hola$mundo

hola#mundo

pero estos son inválidos:

1hola_mundo

hola%mundo

• PL/SQL es case-insensitive (no es sensitivo a mayúsculas y minúsculas) con

respecto a los identificadores. PL/SQL trata todos los siguientes como el mismo

Page 53: Introducción a Oracle SQL y PL Volumen 1 y 2

53

identificador:

hola_mundo

Hola_Mundo

HOLA_MUNDO

Para ofrecer más flexibilidad, Oracle permite evitar las restricciones de la segunda y

tercera regla, encerrando al identificador entre comillas dobles. Un quoted identifier

(identificador encerrado entre comillas) puede contener cualquier secuencia de

carácteres imprimibles excluyendo las comillas dobles; las diferencias entre

mayúsculas y minúsculas serán además preservadas. Así, todos los siguientes

identificadores son válidos y distintos:

"Abc"

"ABC"

"a b c"

Es muy raro encontrar identificadores entre comillas en código PL/SQL; algunos

grupos de desarrollo los usan para conformar con sus convenciones de nombres o

porque encuentran que una mezcla de mayúsculas y minúsculas resulta más fácil de

leer.

Estas mismas reglas aplican a los nombres de los objetos de base de datos como

tablas, vistas y procedimientos, con una regla adicional: a menos que se encierren

entre comillas los nombres de estos objetos, Oracle los mantendrá en mayúsculas.

Así que cuando creamos un procedimiento como el que sigue:

CREATE OR REPLACE PROCEDURE hola_mundo IS

BEGIN

DBMS_OUTPUT.put_line('¡Hola Mundo!');

END hola_mundo;

la base de datos Oracle lo mantendrá con el nombre HOLA_MUNDO.

En el bloque siguiente, llamaremos este procedimiento tres veces, y aunque el

nombre luzca diferente cada vez, siempre se ejecutará el mismo procedimiento:

BEGIN

hola_mundo;

HOLA_MUNDO;

"HOLA_MUNDO";

END;

Por otro lado, la base Oracle no será capaz de ejecutar el procedimiento si lo

llamamos como sigue:

BEGIN

"hola_mundo";

END;

Esto buscará dentro de la base un procedimiento llamado hola_mundo en lugar de

HOLA_MUNDO.

Si no se quiere que los nombres de los subprogramas se mantengan en mayúsculas,

los nombres se deben encerrar entre comillas cuando se crea el subprograma:

CREATE OR REPLACE PROCEDURE "Hola_Mundo" IS

BEGIN

DBMS_OUTPUT.put_line('¡Hola Mundo!');

END "Hola_Mundo";

Page 54: Introducción a Oracle SQL y PL Volumen 1 y 2

54

Capítulo 26 Procedimientos

Procedimientos almacenados

Un procedimiento es un subprograma que ejecuta una acción específica y que no

devuelve ningún valor. Un procedimiento tiene un nombre, un conjunto de

parámetros (opcional) y un bloque de código.

La sintaxis de un procedimiento almacenado es la siguiente:

CREATE [OR REPLACE]

PROCEDURE <procedure_name> [(<param1> [IN|OUT|IN OUT] <type>,

<param2> [IN|OUT|IN OUT] <type>, ...)]

IS

-- Declaracion de variables locales

BEGIN

-- Sentencias

[EXCEPTION]

-- Sentencias control de excepcion

END [<procedure_name>];

El uso de OR REPLACE permite sobreescribir un procedimiento existente. Si se

omite, y el procedimiento existe, se producirá, un error.

La sintaxis es muy parecida a la de un bloque anónimo, salvo porque se reemplaza

la seccion DECLARE por la secuencia PROCEDURE ... IS en la especificación del

procedimiento.

Debemos especificar el tipo de datos de cada parámetro. Al especificar el tipo de

dato del parámetro no debemos especificar la longitud del tipo.

Los parámetros pueden ser de entrada (IN), de salida (OUT) o de entrada salida

(IN OUT). El valor por defecto es IN, y se toma ese valor en caso de que no

especifiquemos nada.

CREATE OR REPLACE

PROCEDURE Actualiza_Saldo(cuenta NUMBER,

new_saldo NUMBER)

IS

-- Declaracion de variables locales

BEGIN

-- Sentencias

UPDATE SALDOS_CUENTAS

SET SALDO = new_saldo,

FX_ACTUALIZACION = SYSDATE

WHERE CO_CUENTA = cuenta;

END Actualiza_Saldo;

También podemos asignar un valor por defecto a los parámetros, utilizando la

clausula DEFAULT o el operador de asiganción (:=). Si un parámetro tiene un valor

predeterminado, no tiene por qué ser pasado desde el entorno que realiza la llamada.

CREATE OR REPLACE

PROCEDURE Actualiza_Saldo(cuenta NUMBER,

new_saldo NUMBER DEFAULT 10 )

IS

-- Declaracion de variables locales

BEGIN

-- Sentencias

UPDATE SALDOS_CUENTAS

SET SALDO = new_saldo,

FX_ACTUALIZACION = SYSDATE

WHERE CO_CUENTA = cuenta;

END Actualiza_Saldo;

Page 55: Introducción a Oracle SQL y PL Volumen 1 y 2

55

Una vez creado y compilado el procedimiento almacenado podemos

ejecutarlo. Si el sistema nos indica que el procedimiento se ha creado con errores de

compilación podemos ver estos errores de compilacion con la orden SHOW

ERRORS en SQL *Plus.

Existen dos formas de pasar argumentos a un procedimiento almacenado a la hora

de ejecutarlo (en realidad es válido para cualquier subprograma). Estas son:

Notación posicional: Se pasan los valores de los parámetros en el mismo

orden en que el procedure los define.

BEGIN

Actualiza_Saldo(200501,2500);

COMMIT;

END;

Notación nominal:Se pasan los valores en cualquier orden nombrando

explicitamente el parámetro.

BEGIN

Actualiza_Saldo(cuenta => 200501,new_saldo => 2500);

COMMIT;

END;

Opcionalmente se produce el mismo resultado.

BEGIN

Actualiza_Saldo(new_saldo => 2500,cuenta => 200501);

COMMIT;

END;

Para eliminar un procedimiento usamos:

DROP PRODEDUE nombre_prodecimiento;

Para dar privilegios de ejecución sobre un procedimiento o función usamos:

GRANT EXECUTE ON nombre_prodecimiento TO UsuarioB;

Page 56: Introducción a Oracle SQL y PL Volumen 1 y 2

56

Capítulo 27 Funciones

Funciones en PL/SQL

Una función es un subprograma que devuelve un valor.

La sintaxis para construir funciones es la siguiente:

CREATE [OR REPLACE]

FUNCTION <fn_name>[(<param1> IN <type>, <param2> IN <type>, ...)]

RETURN <return_type>

IS

result <return_type>;

BEGIN

return(result);

[EXCEPTION]

-- Sentencias control de excepcion

END [<fn_name>];

El uso de OR REPLACE permite sobreescribir una función existente. Si se omite, y

la función existe, se producirá, un error.

La sintaxis de los parámetros es la misma que en los procedimientos almacenado,

exceptuando que solo pueden ser de entrada.

Ejemplo:

CREATE OR REPLACE

FUNCTION fn_Obtener_Precio(p_producto VARCHAR2)

RETURN NUMBER

IS

result NUMBER;

BEGIN

SELECT PRECIO INTO result

FROM PRECIOS_PRODUCTOS

WHERE CO_PRODUCTO = p_producto;

return(result);

EXCEPTION

WHEN NO_DATA_FOUND THEN

return 0;

END ;

Si el sistema nos indica que el la función se ha creado con errores de compilación

podemos ver estos errores de compilacion con la orden SHOW ERRORS en SQL

*Plus.

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

DECLARE

Valor NUMBER;

BEGIN Valor := fn_Obtener_Precio('000100');

END;

Las funciones pueden utilizarse en sentencias SQL de manipulación de datos

(SELECT, UPDATE, INSERT y DELETE):

SELECT CO_PRODUCTO,

DESCRIPCION,

fn_Obtener_Precio(CO_PRODUCTO)

FROM PRODUCTOS;

Page 57: Introducción a Oracle SQL y PL Volumen 1 y 2

57

Para eliminar una funcion usamos:

DROP FUNCTION nombre_funcion;

Para dar privilegios de ejecución sobre un procedimiento o función usamos:

GRANT EXECUTE ON nombre_funcion TO UsuarioB;

Page 58: Introducción a Oracle SQL y PL Volumen 1 y 2

58

Capítulo 26 Procedimientos

¿Por qué anidar bloques?

Podemos poner BEGIN antes de cualquier conjunto de una o más sentencias

ejecutables seguidas de un END, creando un bloque anidado con esas sentencias. Hay

dos ventajas principales para hacer esto: (1) posponer la asignación de memoria para

variables que se necesitan únicamente en el bloque anidado, y (2) limitar la

propagación de una excepción lanzada por una de las sentencias del bloque anidado.

Consideremos el siguiente bloque:

DECLARE

l_mensaje1 VARCHAR2(100) := 'Hola';

l_mensaje2 VARCHAR2(100) := ' Mundo!';

BEGIN

IF SYSDATE >= TO_DATE('01-JAN-2012')

THEN

l_mensaje2 := l_mensaje1 || l_mensaje2;

DBMS_OUTPUT.put_line(l_mensaje2);

ELSE

DBMS_OUTPUT.put_line(l_mensaje1);

END IF;

END;

El bloque despliega “¡Hola Mundo!” cuando la fecha de hoy (retornada por

SYSDATE) es por lo menos el primer día de 2012; en otro caso, únicamente

despliega el mensaje “Hola”. Aunque este bloque se ejecute en 2011, asigna memoria

para la variable l_mensaje2.

Si reestructuramos este bloque, la memoria para l_mensaje2 será asignada

únicamente después del 2011:

DECLARE

l_mensaje1 VARCHAR2(100) := 'Hola';

BEGIN

IF SYSDATE > TO_DATE('01-JAN-2011')

THEN

DECLARE

l_mensaje2 VARCHAR2(100) := ' Mundo!';

BEGIN

l_mensaje2 := l_mensaje1 || l_mensaje2;

DBMS_OUTPUT.put_line(l_mensaje2);

END;

ELSE

DBMS_OUTPUT.put_line(l_mensaje1);

END IF;

END;

De forma similar, podemos agregar una sección de excepciones a este bloque

anidado, atrapando errores y permitiendo que el bloque exterior continúe con su

ejecución:

DECLARE

l_mensaje1 VARCHAR2(100) := 'Hola';

BEGIN

DECLARE

l_mensaje2 VARCHAR2(5);

BEGIN

l_mensaje2 := ' Mundo!';

DBMS_OUTPUT.put_line(l_mensaje1 || l_mensaje2);

EXCEPTION

WHEN OTHERS

THEN

DBMS_OUTPUT.put_line(DBMS_UTILITY.format_error_stack);

Page 59: Introducción a Oracle SQL y PL Volumen 1 y 2

59 END;

DBMS_OUTPUT.put_line(l_mensaje1);

END;

En este caso, el bloque anidado lanzará una excepción VALUE_ERROR, porque la

variable l_mensaje2 es muy pequeña (máximo de 5 bytes) para el texto “ Mundo!”.La

sección de excepciones del bloque anidado atrapará y desplegará el error. El bloque

exterior continuará su ejecución.

Un posterior artículo en estas series se enfocará en cómo funciona el manejo de

excepciones en PL/SQL.

Más adelante en esta serie de artículos, mostraré cómo controlar el flujo de ejecución

en nuestros bloques: lógica condicional con IF y CASE; lógica iterativa con FOR,

WHILE y LOOP; así como lanzar y manejar excepciones.