Sie sind auf Seite 1von 48

ORACLE ES UNA POTENTE HERRAMIENTA CLIENTE/SERVIDOR PARA

LA GESTIÓN DE BASES DE DATOS


EXPLICAMOS LA HERRAMIENTA Y LAS AYUDAS QUE OFRECE AL
DESARROLLADOR.
##https://desarrolloweb.com/manuales/tutorial-oracle.html##

1.- QUÉ ES ORACLE


Es básicamente una herramienta cliente/servidor para la gestión de Bases de Datos. Es
un producto vendido a nivel mundial, aunque la gran potencia que tiene y su elevado
precio hace que sólo se vea en empresas muy grandes y multinacionales, por norma
general. En el desarrollo de páginas web pasa lo mismo: como es un sistema muy caro
no está tan extendido como otras bases de datos, por ejemplo, Access, MySQL, SQL
Server, etc.
Vamos ahora en centrarnos en que es Oracle exactamente y como funciona la
programación sobre éste. Oracle como antes he mencionado se basa en la tecnología
cliente/servidor, pues bien, para su utilización primero sería necesario la instalación de
la herramienta servidor (Oracle 8i) y posteriormente podríamos atacar a la base de datos
desde otros equipos con herramientas de desarrollo como Oracle Designer y Oracle
Developer, que son las herramientas básicas de programación sobre Oracle.
Para desarrollar en Oracle utilizamos PL/SQL un lenguaje de 5ª generación, bastante
potente para tratar y gestionar la base de datos, también por norma general se suele
utilizar SQL al crear un formulario.
Nota: Podemos aprender qué es el lenguaje SQL en un artículo de DesarrolloWeb.com.
Además, existe un manual de SQL para el que desee profundizar.
Es posible lógicamente atacar a la base de datos a través del SQL plus incorporado en el
paquete de programas Oracle para poder realizar consultas, utilizando el lenguaje SQL.
El Developer es una herramienta que nos permite crear formularios en local, es decir,
mediante esta herramienta nosotros podemos crear formularios, compilarlos y
ejecutarlos, pero si queremos que los otros trabajen sobre este formulario deberemos
copiarlo regularmente en una carpeta compartida para todos, de modo que, cuando
quieran realizar un cambio, deberán copiarlo de dicha carpeta y luego volverlo a subir a
la carpeta. Este sistema como podemos observar es bastante engorroso y poco fiable
pues es bastante normal que las versiones se pierdan y se machaquen con frecuencia. La
principal ventaja de esta herramienta es que es bastante intuitiva y dispone de un modo
que nos permite componer el formulario, tal y como lo haríamos en Visual Basic o en
Visual C, esto es muy de agradecer.
Los problemas anteriores quedan totalmente resueltos con Designer que es una
herramienta que se conecta a la base de datos y por tanto creamos los formularios en
ella, de esta manera todo el mundo se conecta mediante Designer a la aplicación que
contiene todos los formularios y no hay problemas de diferentes versiones, esto es muy
útil y perfecto para evitar machacar el trabajo de otros. Pero el principal y más notable
problema es la falta de un entorno visual para diseñar el formulario, es decir, nos
aparece una estructura como de árbol en la cual insertamos un formulario, a la vez
dentro de éste insertamos bloques o módulos que son las estructuras que contendrán los
elementos del formularios, que pueden estar basados en tablas o no.
Por lo tanto si queremos hacer formularios para practicar o para probar qué es esto de
Oracle, os recomiendo que uséis Developer pues es mucho más fácil e intuitivo al
principio.

2.- SQL con Oracle


Empezamos un nuevo curso sobre SQL con Oracle que puede resultar muy interesante
para ampliar los conocimientos de SQL que habíamos adquirido anteriormente.
Introducción:
Antes de empezar me gustaría decir que este curso esta basado en Oracle, es decir los
ejemplos expuestos y material se han utilizado sobre Oracle. Por otro lado decir que
pienso que es interesante saber algo de SQL antes de comenzar con MYSQL, ya que,
aunque existen algunos cambios insignificantes, sabiendo manejar SQL sabes manejar
MYSQL.

Algunas caracteristicas:
SQL: Structured query language.
Permite la comunicación con el sistema gestor de base de datos.
En su uso se puede especificar que quiere el usuario.
Permite hacer consulta de datos.

Tipos de datos:
CHAR:
Tienen una longitud fija.
Almacena de 1 a 255.
Si se introduce una cadena de menos longitud que la definida se rellenara con blancos a
la derecha hasta quedar completada.
Si se introduce una cadena de mayor longitud que la fijada nos dará un error.

VARCHAR:
Almacena cadenas de longitud variable.
La longitud máxima es de 2000 caracteres.
Si se introduce una cadena de menor longitud que la que esta definida, se almacena con
esa longitud y no se rellenara con blancos ni con ningún otro carácter a la derecha hasta
completar la longitud definida.
Si se introduce una cadena de mayor longitud que la fijada, nos dará un error

NUMBER:
Se almacenan tanto enteros como decimales.
Number (precisión, escala)
Ejemplo:
X=number (7,2)
X=155'862 à Error ya que solo puede tomar 2 decimales
X= 155'86 à Bien
Nota: El rango máximo va de 1 a 38.

LONG:
No almacena números de gran tamaño, sino cadenas de caracteres de hasta 2 GB

DATE:
Almacena la fecha. Se almacena de la siguiente forma:

Siglo/Año/Mes/Día/Hora/Minutos/Segundos
RAW:
Almacena cadenas de Bytes (gráficos, sonidos…)
LONGRAW:
Como el anterior pero con mayor capacidad.

ROWID:
Posición interna de cada una de las columnas de las tablas.
Sentencias de consultas de datos
Select:
Select [ALL | Distinct] [expresión_columna1, expresión_columna2, …., | *]
From [nombre1, nombre_tabla1, …, nombre_tablan]
{[Where condición]
[Order By expresión_columna [Desc | Asc]…]};
Vamos a explicar como leer la consulta anterior y así seguir la pauta para todas las
demás. Cuando ponemos [] significa que debemos la que va dentro debe existir, y si
además ponemos | significa que deberemos elegir un valor de los que ponemos y no mas
de uno. En cambio si ponemos {} significa que lo que va dentro de las llaves puede ir o
no, es decir es opcional y se pondrá según la consulta.
Nota: En el select el valor por defecto entre ALL y DISTINCT es ALL.
Alias = El nuevo nombre que se le da a una tabla. Se pondrá entre comillas
Order By = Ordena ascendentemente (Asc) (valor por defecto) o descendentemente
(Desc).
All = Recupera todas las filas de la tabla aunque estén repetidas.
Distinct = Solo recupera las filas que son distintas.
Desc Emple; = Nos da un resumen de la tabla y sus columnas. En este caso de la tabla
Emple.
Not Null= Si aparece en una lista de una columna significa que la columna no puede
tener valores nulos.
Null= Si está nulo.
Nota: Nótese que cada consulta de SQL que hagamos hemos de terminarla con un punto
y coma ";".

Varios ejemplos para verlo mas claro:


SELECT JUGADOR_NO, APELLIDO, POSICION, EQUIPO
FROM JUGADORES
WHERE EQUIPO_NO = 'VALENCIA'
ORDER BY APELLIDO;
Este ejemplo mostrar el número de jugador (jugador_no) el apellido (Apellido), la
posición en la que juega (Posición), y el equipo (Equipo) al que pertenece.
Seleccionara todos los datos de la tabla jugadores donde (Where) el nombre de equipo
(Equipo_No) sea igual que la palabra 'Valencia' y se ordenara (order by) apellido.
Notemos también que no pone ni 'Distinct' ni 'All'. Por defecto generara la sentencia con
ALL.
SELECT *
FROM JUGADORES
WHERE POSICION = 'DELANTERO'
ORDER BY JUGADOR_NO;
Este ejemplo muestra todos los campos de la tabla jugadores donde (Where) la posición
sea igual que 'Delantero' y lo ordena por número de jugador. Al no poner nada se
presupone que es ascendentemente (Asc).
SELECT *
FROM JUGADORES
WHERE EQUIPO_NO = 'VALENCIA' AND POSICION = 'DELANTERO'
ORDER BY APELLIDO DESC, JUGADOR_NO ASC;
En este ejemplo selecciona todos los campos de la tabla jugadores donde (Where) el
nombre del equipo sea igual a 'Valencia' y la posición de los jugadores sea igual a
'Delantero'. Por ultimo los ordena por 'Apellido' descendentemente y por numero de
jugador ascendentemente.

3.- Instalar Oracle Database 10g Express


Pasamos a describir los pasos necesarios para instalar el sistema gestor de base de datos
Oracle Database 10g Express.
Vamos a guiar a los lectores de DesarrolloWeb.com a través de la instalación de Oracle
Database 10g Express, para que podáis tener el sistema gestor de base de datos y
realizar pruebas desde un navegador antes de instalarlo en un servidor en producción.
Lo primero que tenemos que hacer es descargar los archivos de instalación del sistema
gestor de bases de datos. Para ello accedemos a la página oficial de Oracle y nos
descargamos el archivo Oracle Database 10g Express Edition (Universal) de esta URL.
La página de Oracle solicitará nuestro registro para realizar la descarga, pues tenemos
que ser usuarios registrados para poder bajarlo. En realidad se tarda dos minutos en
registrarse.
Una vez descargado, iniciamos la instalación y lo primero que nos pedirá sera introducir
una contraseña para el usuario sys y el system (implementa la misma a los dos usuarios
por defecto). Podemos elegir cualquier clave, además siendo una instalación en local
tiene menos importancia que sea segura. De cualquier modo, lo que sí es importante es
que la recodemos, así que no estará de más el apuntar dicha contraseña en algún lugar,
ya que más adelante la necesitaremos.
Una vez instalado el sistema gestor, podemos acceder a nuestra base de datos online a
través de tu menú inicio / programas / base de datos Oracle. En este menú podemos
iniciar los servicios de Oracle, iniciar el sql *plus, así como dirigirnos a la página de
inicio de nuestra base de datos.
Es importante tener arrancados los servicios relacionados con la base de datos Oracle,
ya que si no lo están, la base de datos no funcionará. Pero cabe comentar por otro lado,
que tener los servicios funcionando come muchos recursos, por lo que os recomiendo
que, cuando no estáis utilizando la base de datos Oracle, paréis los servicios.
La puesta en marcha o parado de los servicios relacionados con la base de datos Oracle
se puede hacer desde el panel de control / herramientas administrativas / servicios.
Entonces tenéis que buscar los servicios que se llaman Oracleservicesxe y
OracleXETNSListener y cambiarlos a manual, para así poderlos arrancar y parar cuando
vosotros queráis.
Ahora podemos irnos a la pagina de inicio de nuestra base de datos, la cual accedemos
mediante el menu inico->programas->Base de datos Oracle 10g Express Edition-
>pagina de inicio de la base de datos, para ver la forma visual de hacer todas estas
cosas.
Cuando abramos la página de incio de nuestra base de datos nos pedirá un usuario y una
contraseña, tendréis que poner como usuario system y la contraseña que le hayáis dado
al instalar el sistema. Una vez dentro, tenemos las opciones de administración (todo lo
referente a la seguridad de sistema), explorador de objetos (todo lo referente a las
tablas), sql ( para hacer las cosas por linea de comando) y utilidades diversas para tu
base de datos.
Este interfaz visual que nos ofrece la pagina de inicio de nuestra base de datos te
facilitará mucho el trabajo pero no nos valdrá para hacer nada con SQL *Plus ya que
solo nos deja realizar operaciones sql básicas.
Por lo tanto, quizás nos interesará utilizar la opción que tenemos en nuestro escritorio,
que se llama "ejecutar linea de comandos SQL". Con ello nos abre una pantalla de DOS
con el editor de SQL *Plus.
Nota:Quiero recordar que esto es una versión online de tu base de datos, para instalar
una versión completa tendríamos que bajarnos el Oracle Database 10g ( que incluye
sistema cliente, ejemplos, sistema gateway y sistema clusterware para desarrolladores) y
tendríamos muchas más opciones que ya comentaremos más adelante. La diferencia
fundamental es que la version express puede manejar solamente hasta 4 GB de datos y 1
GB de memoria. Esta versión puede embeberse con otras aplicaciones de terceros y se
puede distribuir gratuitamente.

Con esto instalado ya podemos comenzar a explicar el SQL *Plus y sus múltiples
opciones.
Antes de comenzar os comento que necesitaremos una serie de tablas para ir haciendo
ejercicios y os aconsejaría que os creéis algunos usuarios más con distintos privilegios
para ir repasando lo que hemos comentado de la seguridad en Oracle . Esto lo podéis
hacer de forma visual o por linea de comando desde la pagina inicial de tu base de
datos.

4.- Gestión de seguridad en Oracle I


Conceptos básicos para la gestión de seguridad de una base de datos en Oracle.
Un administrador de Oracle puede controlar dos tipos de seguridad;
La seguridad del sistema: Se refiere a mecanismos que controlan el acceso y el uso de la
base de datos. Lo que llamamos permisos del sistema.
Seguridad de los datos: Son los mecanismos que controlan el acceso y uso de la base de
datos a nivel del objectos (tablas, vistas, usuario, etc). Son lo que llamamos los
permisos a nivel de objetos.
Seguridad del sistema
En lo referente a la seguridad del sistema es bastante importante saber que el
administrador puede crear perfiles para limitar los recursos de la base de datos.
Los factores más importantes que puede limitar son:

Recurso Descripción
El número de sesiones concurrentes que un
SESSION_PER_USER
usuario puede tener en una instancia.
El tiempo de CPU, en centenas de segundos, que
CPU_PER_SESSION
una sesión puede utilizar.
El número de minutos que una sesión puede
CONNECT_TIME
permanecer activa.
El número de minutos que una sesión puede
IDLE_TIME
permanecer sin que sea utilizada de manera activa.
El número de bloques de datos que se pueden leer
LOGICAL_READS_PER_SESSION
en una sesión.
El número de bloques de datos que se pueden leer
LOGICAL_READS_PER_CALL
en una operación.
La cantidad de espacio privado que una sesión
PRIVATE_SGA puede reservar en la zona de SQL compartido de
la SGA.
El número de total de recursos por sesión, en
unidades de servicio. Esto resulta de un calculo
ponderado de CPU_PER_SESSION,
COMPOSITE_LIMIT CONNECT_TIME,
LOGICAL_READS_PER_SESSION y
PRIVATE_SGA, cuyos pesos se pueden variar con
el comando ALTER RESOURCE COST.
La sintaxis para la creación de un perfil con varias limitaciones seria:
create profile nombre_perfil limit
{Entero [K|M] | unlimited | default};
Donde unlimited significa que no hay limite sobre un recurso particular y default
significa que coge el limite del perfil DEFAULT
Para activar los perfiles el administrador debe ejecutar la siguiente orden:
alter system set resource_limit=true;
Para borrar un perfil tenemos que ejecutar la siguiente orden:
drop profile nombre_perfil [cascade];
Es importante saber si este perfil esta asignado a algún usuario ya que, si es así,
tendremos que poner "cascade", para que lo elimine de esos usuarios también.
Otro factor importante en la seguridad a nivel de sistema es la gestión de tablespaces.
Un tablespace es un espacio de la base de datos que contiene tablas o como su
definición oficial nos dice, es una unidad lógica de almacenamiento de datos compuesta
por uno o más archivos. En Oracle antes de introducir los datos en la base de datos
tenemos que crear un tablespace para que nos deje trabajar.
Es importante tener un tablespace para cada tipo de datos es decir, un tablespace para
cada aplicación.
La sintaxis de la creación de un tablespace es la siguiente:
create tablespace nombre_tablespace
datafile 'nombre_Archivo' [size entero [K|M]] [reuse]
[autoextend {off|on clausulas}]
[,'nombre_archivo' [size entero [K|M]] [reuse]
[autoextend {off|on clausulas}] ] ...
[ default storage {
initial tamaño
next tamaño
minextents tamaño
maxextents tamaño
pctincrease valor }] [online|offline];
Donde:
datafile: especifica el archivo/s de datos que constara el tablespace
size: especifica el tamaño del tablesapce
reuse: si el archivo ya existe lo reutiliza y sino lo crea.
Dafault storage: define el almacenamiento por defecto para todos los objectos que se
creen en ese tablespace
initial: indica la extensión inicial del tablespace
next: indica la extensión siguiente
minextents: reserva extensiones adicionales a la extensión inicial y nos permite asignar
gran cantidad de espacio cuando se crea un objeto. El valor por defecto es 1
maxextents: es el número máximo de extensiones que se le asigna a un objecto
pctincrease: factor de crecimiento para la extensión. Valor por defecto 50
offline|online: nos indica si el tablespace esta operativo o no, después de su creación
Por defecto Oracle crea los siguientes tablespace:
system: donde Oracle almacena toda la información para su propia gestión
users: espacio de tablas donde se almacena la información personal de los usuarios
temporary o temp: donde Oracle almacena las tablas temporales
tools: espacio para hacer pruebas sobre la base de datos
RBS: donde Oracle guarda la información al deshacer algún cambio.
Para modificar un tablespace cambiamos el create por el alter mientras que para borrarlo
basta con hacer drop tablespace nombre_tablespace;

5.- Gestión de seguridad en Oracle II


Continuamos con los conceptos básicos en la gestión de seguridad de una base de datos.
Seguridad de los datos en Oracle.
En el articulo anterior hablábamos de que existían dos tipos de seguridad en un sistema
gestor de base de datos. El primero era el encaminado a la seguridad del sistema (enlace
al articulo anterior) y el segundo el encaminado a la seguridad de los datos, tema que
vamos a abarcar en este segundo articulo.
Lo que hace tener una cierta seguridad en nuestros datos es la utilización de usuarios.
Estos usuarios son nombres que definimos y a los cuales damos una contraseña para
acceder a la base de datos.
En Oracle cada usuario esta asignado a un esquema. Siendo un esquema una colección
lógica de objetos. Por defecto un usuario tiene acceso a todos los objectos de su
esquema y podría acceder a los objetos de otros esquemas como los permisos
necesarios.
Cuando instanciamos Oracle se crean por defecto dos usuarios importantes:
sys change_on_install: propietario del diccionario de datos de la base de datos
system manager: usuario para realizar las tareas de administración de la base de datos

La sintaxis para la creación de un usuario es la siguiente:


create user nombre_usuario
identified by contraseñas
[default tablespace nombre_tablespace]
[temporary tablespace nombre_tablespace]
[quota {entero {K|M} | unlimited} on nombre_tablespace]
[profile nombre_perfil];
Para modificar el usuario cambiaremos el create por el alter y para borrarlo tan solo
tendremos que poner drop user nombre_usuario cascade;
Cada usuario tiene ciertos privilegios, y dentro de esos privilegios podemos hablar de:
privilegios de sistema: son los que nos dan derecho a realizar ciertas operaciones sobre
objetos de un tipo especificado.
privilegios sobre objetos: estos privilegios nos permiten realizar cambios en los datos de
los objetos de otros usuarios
Cuando creamos un usuario es necesario darle privilegios, de lo contrario no podría
realizar ninguna acción.
Roles de usuario
Un rol es un conjunto de permisos que recibe un nombre común y facilita la tarea de dar
permisos a los usuarios. Para crear un rol tan solo tenemos que escribir lo siguiente:
create role nombre_role;
Oracle ofrece varios roles o funciones ya creadas que ofrecen ciertos privilegios. Esos
roles son los siguientes:
connect: Todos los permisos necesarios para iniciar una sesión en Oracle
resource: Todos los permisos necesarios para tener recursos para la creación de objetos
dba: posee todos los privilegios del sistema

La sentencia para privilegios sobre los objetos es la siguiente:


grant {privilegio_objeto[,privilegio_objeto]...| all [privileges]}
[(columna [,columna]...)]
on [usuario.]objeto}
to {usuario|rol| public [,{usuario|rol|public} ...]
[with grant option];
Mientras que la sentencia para crear privilegios de sistema es la siguiente:
grant {privilegio|rol} [,privilegio|rol}, ....]
to {usuario|rol| public [,{usuario|rol|public} ...]
[with admin option];
En ambos caso se utiliza la sentencia revoke para suprimir privilegios, cambiando la
sintaxis.
Para los privilegios de sistema:
revoke {privilegio|rol} [,privilegio|rol}] ...
from {usuario|rol|public} [,usuario|rol|public}] ...;
para los privilegios de objetos:
revoke {privilegio[,privilegio] ... | all [privileges]}
on [usuario.]objeto
from {usuario|rol|public}[ ,{usuario|rol|public}]...;
Con esto podríamos empezar a gestionar una base de datos, siempre y cuando tengamos
algunos conocimientos de pl/sql. Esto lo veremos en sucesivos artículos que iremos
publicando.

6.- Usuarios en Oracle


Todo lo relacionado con la gestión de usuarios en Oracle.
Es un nombre definido en la base de datos que se puede conectar a ella y acceder a
determinados objetos según ciertas condiciones que establece el administrador.
Los objetos del diccionario de datos a los que un usuario puede acceder se encuentran
en la vista DICTIONARY, que es propiedad del usuario SYS.
DESC DICTIONARY;

Con la orden:

SELECT TABLENAME FROM DICTIONARY;

Se visualizan los objetos del diccionario de datos a los que se puede acceder.

Creación deusuarios:

CREATE USER NOMBRE_USUARIO


IDENTIFIED BY CLAVE_ACCESO
[DEFAULT TABLESPACE ESPACIO_TABLA]
[TEMPORARY TABLESPACE ESPACIO_TABLA]
[QUOTA {ENTERO {K | M} | UNLIMITED } ON ESPACIO_TABLA]
[PROFILE PERFIL];

DEFAULT TABLESPACE= Asigna a un usuario el tablespace por defecto para


almacenar los objetos que cree. Si no se asigna ninguno, el tablespace por defecto es
SYSTEM.
TEMPORARY TABLESPACE= Especifica el nombre del tablespace para trabajar
temporales. Si no se especifica ninguno, el tablespace por defecto es SYSTEM.
QUOTA= Asigna un espacio en megabites o kilobites en el tablespace asignado. Si no
se especifica esta cláusula, el usuario no tiene cuota asignada y no podrá crear objetos
en el tablespace. Para tener espacio y acceso ilimitad a un tablespace es:

GRANT UNLIMITED TABLESPACE NOMBRE_TABLESPACE;

PROFILE= Asigna un perfil a un usuario.

Modificación de usuarios:

ALTER USER NOMBRE_USUARIO


IDENTIFIED BY CLAVE _ACCESO
[DEFAULT TABLESPACE ESPACIO_TABLA]
[TEMPORARY TABLESPACE ESPACIO_TABLA]
[QUOTA {ENTERO {K | M } | UNLIMITED } ON ESPACIO_TABLA
[PROFILE PERFIL];

Borrado de usuarios:

DROP USER USUARIO [CASCADE];

CASCADE= Suprime todos los objetos del usuario antes de borrarlo.

7.- Claves primarias con SQL con Oracle


Aprendemos a crear y definir claves primarias y sus restricciones.
Rollback:

Permite ir hasta el último COMMIT hecho o en su defecto hasta el comienzo de las


órdenes con lo que estas no se ejecutan.

Commit:

Cuando ejecutamos ordenes estas no son creadas en la tabla hasta que ponemos este
orden, por tanto los cambios realizados se perderán si al salir del programa no
realizamos esta acción. Puede programarse para que lo haga automáticamente.

Algunas ordenes que lleven COMMIT implícito:


QUIT
EXIT
CONNECT
DISCONNECT
CREATE TABLE
CREATE VIEW
GRANT
REVOQUE
DROP TABLE
DROP VIEW
ALTER
AUDIT
NO AUDIT
Creacion de una tabla:

Su primer carácter debe ser alfabético y el resto pueden ser letras, números y el carácter
subrayado.

CREATE TABBLE NOMBRETABLA


(COLUMNA1 TIPO_DATO {NOT NULL},
COLUMNA2 TIPO_DATO {NOT NULL},

) TABLESPACE ESPACIO_DE_TABLA;

Características:
Las definiciones individuales de columnas se separan mediante comas.
No se pone coma después de la última definición de columna.
Las mayúsculas y minúsculas son indiferentes.
Los usuarios pueden consultar las tablas creadas por medio de la vista USER_TABLES.

Integridad de datos:

La integridad hace referencia al hecho de que los datos de la base de datos han de
ajustarse a restricciones antes de almacenarse en ella. Una restricción de integridad será:

Una regla que restringe el rango de valores para una o más columnas en la tabla.

Restricciones en create table:

Usamos la cláusula CONSTRAINT, que puede restringir una sola columna o un grupo
de columnas de una misma tabla.
Hay dos modos de especificar restricciones:
Como parte de la definición de columnas.
Al final, una vez especificados todas las columnas.
Formato:

CREATE TABLE NOMBRE_TABLA


(COLUMNA1 TIPO_DE_DATO
{CONSTRAINT NOMBRE_RESTRICCION}
{NOT NULL}
{UNIQUE}
{PRIMARY KEY}
{DEFAULT VALOR}
{REFERENCES NOMBRETABLA [(COLUMNA, [,COLUMNA])
{ON DELETE CASCADE}}
{CHECK CONDICION},
COLUMNA2...
)
{TABLESPACE ESPACIO_DE_TABLA} ;
CREATE TABLE NOMBRE_TABLA
(COLUMNA1 TIPO_DATO ,
COLUMNA2 TIPO_DATO,
COLUMNA3 TIPO_DATO,
...
{CONSTRAINT NOMBRERESTRICCION}
[{UNIQUE} | {PRIMARY KEY} (COLUMNA [, COLUMNA])],
{CONSTRAINT NOMBRERESTRICCION}
{FOREIGN KEY (COLUMNA [, COLUMNA])
REFERENCES NOMBRETABLA {(COLUMNA [,
COLUMNA])
{ON DELETE CASCADE}},
{CONSTRINT NOMBRERESTRICCIONI}
{CHECK (CONDICION)}

)[TABLESPACE ESPACIO_DE_TABLA];

8.- Definición de claves para tablas y restricciones


Vemos claves primarias y claves externas (foreing keys) y aprendemos a aplicar
restricciones a los distintos campos de las tablas.
Clave primaria: Primary key

Es una columna o un conjunto de columnas que identifican unívocamente a cada fila.


Debe ser única, no nula y obligatoria. Como máximo, podemos definir una clave
primaria por tabla.
Esta clave se puede referenciar por una columna o columnas. Cuando se crea una clave
primaria, automáticamente se crea un índice que facilita el acceso a la tabla.

Formato de restricción de columna:


CREATE TABLE NOMBRE_TABLA
(COL1 TIPO_DATO [CONSTRAINT NOMBRE_RESTRICCION] PRIMARY KEY
COL2 TIPO_DATO

)[TABLESPACE ESPACIO_DE_TABLA];

Formato de restricción de tabla:

CREATE TABLE NOMBER_TABLA


(COL1 TIPO_DATO,
COL2 TIPO_DATO,

[CONSTRAINT NOMBRERESTRICCION] PRIMARY KEY (COLUMNA
[,COLUMNA]),

)[TABLESPACE ESPACIO_DE_TABLA];

Claves ajenas: Foreign Key:

Esta formada por una o varias columnas que están asociadas a una clave primaria de
otra o de la misma tabla. Se pueden definir tantas claves ajenas como se precise, y
pueden estar o no en la misma tabla que la clave primaria. El valor de la columna o
columnas que son claves ajenas debe ser: NULL o igual a un valor de la clave
referenciada (regla de integridad referencial).

Formato de restricción de columna:

CREATE TABLE NOMBRE_TABLA


(COLUMNA1 TIPO_DATO
[CONSTRAINT NOMBRERESTRICCION]
REFERENCES NOMBRETABLA [(COLUMNA)] [ON DELETE CASCADE]

)[TABLESPACE ESPECIO_DE_TABLA];

Formato de restricción de tabla:

CREATE TABLE NOMBRE_TABLA


(COLUMNA1 TIPO_DATO,
COLUMNA2 TIPO_DATO,

[CONTRAINT NOMBRERESTRICCION]
FOREIGN KEY (COLUMNA [,COLUMNA])
REFERENCES NOMBRETABLA [(COLUMNA [,
COLUMNA])]
[ON DELETE CASCADE],
)[TABLESPACE ESPACIO_DE_TABLA];

Notas:
En la cláusula REFERENCES indicamos la tabla a la cual remite la clave ajena.
Hay que crear primero una tabla y después aquella que le hace referencia.
Hay que borrar primero la tabla que hace referencia a otra tabla y después la tabla que
no hace referencia.
Borrado en cascada (ON DELETE CASCADE): Si borramos una fila de una tabla
maestra, todas las filas de la tabla detalle cuya clave ajena sea referenciada se borraran
automáticamente. La restricción se declara en la tabla detalle. El mensaje "n filas
borradas" solo indica las filas borradas de la tabla maestra.
NOT NULL: Significa que la columna no puede tener valores nulos.
DEFAULT: Le proporcionamos a una columna un valor por defecto cuando el valor de
la columna no se especifica en la cláusula INSERT. En la especificación DEFAULT es
posible incluir varias expresiones: constantes, funciones SQL y variables UID y
SYSDATE.
Verificación de restricciones: CHECK: Actúa como una cláusula where. Puede hacer
referencia a una o más columnas, pero no a valores de otras filas. En una cláusula
CHECK no se pueden incluir subconsultas ni las pseudoconsultas SYSDATE, UID y
USER.
Nota: La restricción NOT NULL es similar a CHECK (NOMBRE_COLUMNA
IS NOT NULL)

UNIQUE: Evita valores repetidos en la misma columna. Puede contener una o varias
columnas. Es similar a la restricción PRIMARY KEY, salvo que son posibles varias
columnas UNIQUE definidas en una tabla. Admite valores NULL. Al igual que en
PRIMARY KEY, cuando se define una restricción UNIQUE se crea un índice
automáticamente.

Vistas del diccionario de datos para las restricciones:

Contienen información general las siguientes:

USER_CONSTRAINTS: Definiciones de restricciones de tablas propiedad del usuario.


ALL_CONSTRAINTS: Definiciones de restricciones sobre tablas a las que puede
acceder el usuario.
DBA_CONSTRAINTS: Todas las definiciones de restricciones sobre todas las tablas.

Creación de una tabla con datos recuperados en una consulta:

CREATE TABLE: permite crear una tabla a partir de la consulta de otra tabla ya
existente. La nueva tabla contendrá los datos obtenidos en la consulta. Se lleva a cabo
esta acción con la cláusula AS colocada al final de la orden CREATE TABLE.

CREATE TABLE NOMBRETABLA


(COLUMNA [,COLUMNA]
)[TABLESPACE ESPACIO_DE_TABLA]
AS CONSULTA;

No es necesario especificar tipos ni tamaño de las consultas, ya que vienen


determinadas por los tipos y los tamaños de las recuperadas en la consulta.
La consulta puede tener una subconsulta, una combinación de tablas o cualquier
sentencia select valida.
Las restricciones CON NOMBRE no se crean en una tabla desde la otra, solo se crean
aquellas restricciones que carecen de nombre.

9.- Supresión y modificación de tablas con SQL


Vemos sentencias en SQL para la supresion y modificación tanto de tablas como de
restricciones.
Supresión de tablas:

DROP TABLE: suprime una tabla de la base de datos. Cada usuario puede borrar sus
propias tablas, pero solo el administrador o algún usuario con el privilegio "DROP ANY
TABLE" puede borrar las tablas de otro usuario. Al suprimir una tabla también se
suprimen los índices y los privilegios asociados a ella. Las vistas y los sinónimos
creados a partir de esta tabla dejan de funcionar pero siguen existiendo en la base de
datos por tanto deberíamos eliminarlos.
Ejemplo:
DROP TABLE [USUARIO].NOMBRETABLA [CASCADE CONSTRAINTS];

TRUNCATE: permite suprimir todas las filas de una tabla y liberar el espacio ocupado
para otros usos sin que reaparezca la definición de la tabla de la base de datos. Una
orden TRUNCATE no se puede anular, como tampoco activa disparadores DELETE.

TRUNCATE TABLE [USUARIO.]NOMBRETABLA [{DROP | REUSE}


STORAGE];

Modificación de tablas:

Se modifican las tablas de dos formas: Cambiando la definición de una columna


(MODIFY) ó añadiendo una columna a una tabla existente (ADD):
Formato:

ALTER TABLE NOMBRETABLA


{[ADD (COLUMNA [,COLUMNA]…)]
[MODIFY (COLUMNA [,COLUMNA]…)]
[ADD CONSTRAINT RESTRICCION]
[DROP CONSTRAINT RESTRICCION]};

ADD= Añade una columna o mas al final de una tabla.


MODIFY= Modifica una o mas columnas existentes en la tabla.
ADD CONSTRAINT= Añade una restricción a la definición de la tabla.
DROP CONSTRAINT= Elimina una restricción de la tabla.

A la hora de añadir una columna a una tabla hay que tener en cuenta:
Si la columna no esta definida como NOT NULL se le puede añadir en cualquier
momento.
Si la columna esta definida como NOT NULL se pueden seguir estos pasos:
Se añade una columna sin especificar NOT NULL.
Se da valor a la columna para cada una de las filas.
Se modifica la columna NOT NULL.
Al modificar una columna de duna tabla se han de tener en cuenta:
Se puede aumentar la longitud de una columna en cualquier momento.
Es posible aumentar o disminuir el numero de posiciones decimales en una columna de
tipo NUMBER.
Si la columna es NULL en todas las filas de la tabla, se puede disminuir la longitud y
modificar el tipo de dato
La opción MODIFY… NOT NULL solo será posible cuando la tabla no contenga
ninguna fila con valor nulo en la columna que se modifica.
Adición de restricciones:

Con la orden ALTER TABLE se añaden restricciones a una tabla.


Formato:

ALTER TABLE NOMBRETABLA


ADD CONSTRAINT NOMBRECONSTRAINT…
Borrado de restricciones:

La orden ALTER TABLE con la cláusula DROP CONSTRAINT; con la que se borran
las restricciones con nombre y las asignadas por el sistema. Formato:

ALTER TABLE NOMBRETABLA


DROP CONSTRAINT NOMBRE_CONSTRAINT,
NOMBRE_RESTRICCION:

10.- Manipulación de datos con SQL


Utilizando SQL con Oracle aprendemos como hacer Inserciones, actualizaciones y a
eliminar datos.
Insert, Update y Delete:

Insert:

Se añaden filas de datos en una tabla:


INSERT INTO NOMBRETABLA [(COL [,COL]…)]
VALUES (VALOR [,VALOR]…);

Nombretabla= Es la tabla en la que se van a insertar las filas.

Propiedades:
Si las columnas no se especifican en la cláusula Insert se consideran, por defecto, todas
las columnas de la tabla.
Las columnas a las que damos valores se identifican por su nombre.
La asociación columna valor es posicional.
Los valores que se dan a las columnas deben coincidir con el tipo de dato definido en la
columna.
Los valores constantes de tipo carácter han de ir encerrados entre comillas simples (' ')
(los de tipo fecha también).
Con Select:

Se añaden tantas filas como devuelva la consulta:

INSERT INTO NOMBRETABLA [(COL [,COL]…)]


SELECT {COLUMNA [, COLUMNA]… | *}
FROM NOMBRETABLA2 [CLAUSULAS DE SELECT];

Update:

Actualiza los valores de las columnas para una o varias filas de una tabla:

UPDATE NOMBRETABLA
SET COLUMNA1= VALOR1, …, COLUMNAN= VALORN
WHERE CONDICION;

Set= Indica las columnas que se van a actualizar y sus valores.


Con Select:

Cuando la subconsulta (orden select) forma parte de SET, debe seleccionar el mismo
numero de columnas, (con tipos de datos adecuados) que los que hay entre paréntesis al
lado de SET.

UPDATE NOMBRETABLA
SET COLUMNA= VALOR1, COLUMNA2= VALOR2, …
WHERE COLUMNA3= (SELECT…)

UPDATE NOMBRETABLA
SET (COLUMNA1, COLUMNA2, …)= (SELECT …)
WHERE CONDICION;

Delete:

Elimina una o varias filas de una tabla:

DELETE [FROM] NOMBRETABLA


WHERE CONDICION;

11.- SQL con Oracle. Operadores


Empezamos a ver los tipos de operadores y trabajamos con algunos ejemplos.
Operadores aritméticos:

+ = Suma
- = Resta
* = Multiplicación
/ = división

Operadores de comparación y lógicos:


!> = Distinto
>= = Mayor o igual que
<= = Menor o igual que = = Igual que
Like = Se utiliza para unir cadenas de caracteres. Propiedades:
% = representa cualquier cadena de caracteres de 0 o mas caracteres.
_= representa un único carácter cualquiera.
Not = Negación
And = y
a and b
Cierto si son ciertas a y b.
Or = o
a or b
Cierto si a o b son ciertas

Veamos un par de ejemplos:

Obtenemos los datos de los jugadores cuyos apellidos empiecen con una "S":
SELECT APELLIDO
FROM JUGADORES
WHERE APELLIDO LIKE 'S%';

Obtenemos aquellos apellidos que tengan una "R" en la segunda posición:

SELECT APELLIDO
FROM JUGADORES
WHERE APELLIDO LIKE '_R*';

Obtenemos aquellos apellidos que empiezan por "A" y tiene una "o" en su interior:

SELECT APELLIDO
FROM JUGADORES
WHERE APELLDIOS LIKE 'A%O%';

Comprobación con conjuntos de valores:


In= permite saber si una expresión pertenece o no a un conjunto de valores.
Between= permite saber si una expresión esta o no entre esos valores:
Ejemplo:

SELECT APELLIDOS
FROM JUGADORES
WHERE JUGADOR_NUM IN (10, 20);

Selecciona los apellidos de los jugadores donde el número de jugador (Jugador_num)


sea (In) o 10 o 20

SELECT APELLIDOS
FROM JUGADORES
WHERE SALARIO NOT BETWEEN 15000000 AND 20000000;

Selecciona los apellidos de los jugadores donde el salario de estos no este entre (Not
Between) 15000000 y 20000000.

12.- Funciones SQL


Vemos los distintos tipos de funciones y algunos ejemplos de las mismas con SQL para
Oracle.
Funciones de valores simples:
ABS(n)= Devuelve el valor absoluto de (n).
CEIL(n)=Obtiene el valor entero inmediatamente superior o igual a "n".
FLOOT(n) = Devuelve el valor entero inmediatamente inferior o igual a "n".
MOD (m, n)= Devuelve el resto resultante de dividir "m" entre "n".
NVL (valor, expresión)= Sustituye un valor nulo por otro valor.
POWER (m, exponente)= Calcula la potencia de un numero.
ROUND (numero [, m])= Redondea números con el numero de dígitos de precisión
indicados.
SIGN (valor)= Indica el signo del "valor".
SQRT(n)= Devuelve la raíz cuadrada de "n".
TRUNC (numero, [m])= Trunca números para que tengan una cierta cantidad de dígitos
de precisión.
VAIRANCE (valor)= Devuelve la varianza de un conjunto de valores.

Funciones de grupos de valores:

AVG(n)= Calcula el valor medio de "n" ignorando los valores nulos.


COUNT (* | Expresión)= Cuenta el numero de veces que la expresión evalúa algún dato
con valor no nulo. La opción "*" cuenta todas las filas seleccionadas.
MAX (expresión)= Calcula el máximo.
MIN (expresión)= Calcula el mínimo.
SUM (expresión)= Obtiene la suma de los valores de la expresión.
GREATEST (valor1, valor2…)= Obtiene el mayor valor de la lista.
LEAST (valor1, valor2…)= Obtiene el menor valor de la lista.

Funciones que devuelven valores de caracteres:

CHR(n) = Devuelve el carácter cuyo valor en binario es equivalente a "n".


CONCAT (cad1, cad2)= Devuelve "cad1" concatenada con "cad2".
LOWER (cad)= Devuelve la cadena "cad" en minúsculas.
UPPER (cad)= Devuelve la cadena "cad" en mayúsculas.
INITCAP (cad)= Convierte la cadena "cad" a tipo titulo.
LPAD (cad1, n[,cad2])= Añade caracteres a la izquierda de la cadena hasta que tiene
una cierta longitud.
RPAD (cad1, n[,cad2])= Añade caracteres a la derecha de la cadena hasta que tiene una
cierta longitud.
LTRIM (cad [,set])= Suprime un conjunto de caracteres a la izquierda de la cadena.
RTRIM (cad [,set])= Suprime un conjunto de caracteres a la derecha de la cadena.
REPLACE (cad, cadena_busqueda [, cadena_sustitucion])= Sustituye un carácter o
caracteres de una cadena con 0 o mas caracteres.
SUBSTR (cad, m [,n])= Obtiene parte de una cadena.
TRANSLATE (cad1, cad2, cad3)= Convierte caracteres de una cadena en caracteres
diferentes, según un plan de sustitución marcado por el usuario.

Funciones que devuelven valores numéricos:

ASCII(cad)= Devuelve el valor ASCII de la primera letra de la cadena "cad".


INSTR (cad1, cad2 [, comienzo [,m]])= Permite una búsqueda de un conjunto de
caracteres en una cadena pero no suprime ningún carácter después.
LENGTH (cad)= Devuelve el numero de caracteres de cad.

Funciones para el manejo de fechas:

SYSDATE= Devuelve la fecha del sistema.


ADD_MONTHS (fecha, n)= Devuelve la fecha "fecha" incrementada en "n" meses.
LASTDAY (fecha)= Devuelve la fecha del último día del mes que contiene "fecha".
MONTHS_BETWEEN (fecha1, fecha2)= Devuelve la diferencia en meses entre las
fechas "fecha1" y "fecha2".
NEXT_DAY (fecha, cad)= Devuelve la fecha del primer día de la semana indicado por
"cad" después de la fecha indicada por "fecha".
Funciones de conversión:

TO_CHAR= Transforma un tipo DATE ó NUMBER en una cadena de caracteres.


TO_DATE= Transforma un tipo NUMBER ó CHAR en DATE.
TO_NUMBER= Transforma una cadena de caracteres en NUMBER.

13.- Subconsultas SQL


Explicación y ejemplos de las subconsultas en SQL para Oracle.
Subconsultas:

Consulta que se hace sobre los datos que nos da otra consulta. Su formato es:
SELECT______
FROM________
WHERE CONDICION OPERADOR (SELECT ______
FROM ___________
WHERE CONDICION OPERADOR); Ejemplo:

Obtenemos los jugadores con la misma posición que "Sánchez":

SELECT APELLIDO
FORM EMPLE
WHERE POSICION = (SELECT OFICIO
FROM EMPLE
WHERE APELLIDO LIKE 'GIL');

Seleccionamos en todos los campos de la tabla Jugadores cuya sede está en Madrid o
Barcelona:

SELECT *
FROM JUGADORES
WHERE EQUIPO_NOM IN (SELECT EQUIPO_NOM
FROM SEDE
WHERE LOC IN ('MADRID', 'BARCELONA');
FROM SEDE
WHERE LOC IN ('MADRID', 'BARCELONA');

14.- Agrupación y combinación de elementos con SQL


Aprendemos a agrupar elementos y a combinar filas seleccionadas con SQL para Oracle
Agrupación de elementos. Group by y Having:

Para saber cual es el salario medio de cada departamento de la tabla Jugadores sería:

SELECT EQUIPO_NO, AVG (SALARIO) "SALARIO MEDIO"


FROM JUGADORES
GROUP BY DEPT_NO;

La sentencia "Select" posibilita agrupar uno o más conjuntos de filas. El agrupamiento


se lleva a cabo mediante la cláusula "GROUP BY" por las columnas especificadas y en
el orden especificado. Formato:
SELECT…
FROM…
GROUP BY COLUMNA1, COLUMNA2, COLUMNAN…
HAVING CONDICION
GROUP BY …

Los datos seleccionados en la sentencia "Select" que lleva el "Group By" deben ser:
Una constante.

Una función de grupo (SUM, COUNT, AVG…)

Una columna expresada en el Group By.


La cláusula Group By sirve para calcular propiedades de uno o más conjuntos de filas.
Si se selecciona más de un conjunto de filas, Group By controla que las filas de la tabla
original sean agrupadas en un temporal.

La cláusula Having se emplea para controlar cual de los conjuntos de filas se visualiza.
Se evalúa sobre la tabla que devuelve el Group By. No puede existir sin Group By.

Having es similar al Where, pero trabajo con grupos de filas; pregunta por una
característica de grupo, es decir, pregunta por los resultados de las funciones de grupo,
lo cual Where no pude hacer.

Combinación externa (outer joins):

Nos permite seleccionar algunas filas de una tabla aunque estas no tengan
correspondencia con las filas de la otra tabla con la que se combina. Formato:

SELECT TABLA1.COLUMNA1, TABLA1.COLUMNA2, TABLA2.COLUMNA1,


TABLA2.COLUMNA2
FROM TABLA1, TABLA2
WHERE TABLA1.COLUMNA1 = TABLA2.COLUMNA1 (+);

Esto selecciona todas las filas de la tabla "tabla1" aunque no tengan correspondencia
con las filas de la tabla "tabla2", se utiliza el símbolo +.
El resto de columnas de la tabla "tabla2" se rellena con NULL.

Union, intersec y minus:

Permite combinar los resultados de varios "Select" para obtener un único resultado.
Formato:

SELECT… FROM… WHERE…


OPERADOR_DE_CONJUNTO
SELECT…FROM…WHERE…

UNION= Combina los resultados de dos consultas. Las filas duplicadas que aparecen se
reducen a una fila única.
UNION ALL= Como la anterior pero aparecerán nombres duplicados.
INTERSEC= Devuelve las filas que son iguales en ambas consultas. Todas las filas
duplicadas serán eliminadas.
MINUS= Devuelve aquellas filas que están en la primera "Select" y no están en la
segunda "Select". Las filas duplicadas del primer conjunto se reducirán a una fila única
antes de que empiece la comparación con el otro conjunto.

 Reglas para la utilización de operadores de conjunto:


 Las columnas de las dos consultas se relacionan en orden, de izquierda a
derecha.
 Los nombres de columna de la primera sentencia "Select" no tiene porque ser los
mismos que los nombres de la segunda.
 Los "Select" necesitan tener el mismo numero de columnas.
 Los tipos de datos deben coincidir, aunque la longitud no tiene que ser la misma.

15.- Optimizar consultas SQL


El lenguaje SQL es no procedimental, es decir, en las sentencias se indica que queremos
conseguir y no como lo tiene que hacer el interprete para conseguirlo. Esto es pura
teoría, pues en la práctica a todos los gestores de SQL hay que especificar sus propios
truquitos para optimizar el rendimiento.

Por tanto, muchas veces no basta con especificar una sentencia SQL correcta, sino que
además, hay que indicarle como tiene que hacerlo si queremos que el tiempo de
respuesta sea el mínimo. En este apartado veremos como mejorar el tiempo de respuesta
de nuestro interprete ante unas determinadas situaciones:
Diseño de las tablas
Normaliza las tablas, al menos hasta la tercera forma normal, para asegurar que no hay
duplicidad de datos y se aprovecha al máximo el almacenamiento en las tablas. Si hay
que desnormalizar alguna tabla piensa en la ocupación y en el rendimiento antes de
proceder.
Los primeros campos de cada tabla deben ser aquellos campos requeridos y dentro de
los requeridos primero se definen los de longitud fija y después los de longitud variable.
Ajusta al máximo el tamaño de los campos para no desperdiciar espacio.
Es muy habitual dejar un campo de texto para observaciones en las tablas. Si este campo
se va a utilizar con poca frecuencia o si se ha definido con gran tamaño, por si acaso, es
mejor crear una nueva tabla que contenga la clave primaria de la primera y el campo
para observaciones.
Gestión y elección de los índices

Los índices son campos elegidos arbitrariamente por el constructor de la base de datos
que permiten la búsqueda a partir de dicho campo a una velocidad notablemente
superior. Sin embargo, esta ventaja se ve contrarrestada por el hecho de ocupar mucha
más memoria (el doble más o menos) y de requerir para su inserción y actualización un
tiempo de proceso superior.

Evidentemente, no podemos indexar todos los campos de una tabla extensa ya que
doblamos el tamaño de la base de datos. Igualmente, tampoco sirve de mucho el indexar
todos los campos en una tabla pequeña ya que las selecciones pueden efectuarse
rápidamente de todos modos.

Un caso en el que los índices pueden resultar muy útiles es cuando realizamos
peticiones simultáneas sobre varias tablas. En este caso, el proceso de selección puede
acelerarse sensiblemente si indexamos los campos que sirven de nexo entre las dos
tablas.

Los índices pueden resultar contraproducentes si los introducimos sobre campos


triviales a partir de los cuales no se realiza ningún tipo de petición ya que, además del
problema de memoria ya mencionado, estamos ralentizando otras tareas de la base de
datos como son la edición, inserción y borrado. Es por ello que vale la pena pensárselo
dos veces antes de indexar un campo que no sirve de criterio para búsquedas o que es
usado con muy poca frecuencia por razones de mantenimiento.

Campos a Seleccionar
En la medida de lo posible hay que evitar que las sentencias SQL estén embebidas
dentro del código de la aplicación. Es mucho más eficaz usar vistas o procedimientos
almacenados por que el gestor los guarda compilados. Si se trata de una sentencia
embebida el gestor debe compilarla antes de ejecutarla.
Seleccionar exclusivamente aquellos que se necesiten
No utilizar nunca SELECT * por que el gestor debe leer primero la estructura de la tabla
antes de ejecutar la sentencia
Si utilizas varias tablas en la consulta especifica siempre a que tabla pertenece cada
campo, le ahorras al gestor el tiempo de localizar a que tabla pertenece el campo. En
lugar de SELECT Nombre, Factura FROM Clientes, Facturacion WHERE IdCliente =
IdClienteFacturado, usa: SELECT Clientes.Nombre, Facturacion.Factura WHERE
Clientes.IdCliente = Facturacion.IdClienteFacturado.
Campos de Filtro
Se procurará elegir en la cláusula WHERE aquellos campos que formen parte de la
clave del fichero por el cual interrogamos. Además se especificarán en el mismo orden
en el que estén definidos en la clave.
Interrogar siempre por campos que sean clave.
Si deseamos interrogar por campos pertenecientes a índices compuestos es mejor
utilizar todos los campos de todos los índices. Supongamos que tenemos un índice
formado por el campo NOMBRE y el campo APELLIDO y otro índice formado por el
campo EDAD. La sentencia WHERE NOMBRE='Juan' AND APELLIDO Like '%'
AND EDAD = 20 sería más optima que WHERE NOMBRE = 'Juan' AND EDAD = 20
por que el gestor, en este segundo caso, no puede usar el primer índice y ambas
sentencias son equivalentes por que la condición APELLIDO Like '%' devolvería todos
los registros.
Orden de las Tablas

Cuando se utilizan varias tablas dentro de la consulta hay que tener cuidado con el
orden empleado en la cláusula FROM. Si deseamos saber cuantos alumnos se
matricularon en el año 1996 y escribimos: FROM Alumnos, Matriculas WHERE
Alumno.IdAlumno = Matriculas.IdAlumno AND Matriculas.Año = 1996 el gestor
recorrerá todos los alumnos para buscar sus matriculas y devolver las correspondientes.
Si escribimos FROM Matriculas, Alumnos WHERE Matriculas.Año = 1996 AND
Matriculas.IdAlumno = Alumnos.IdAlumnos, el gestor filtra las matrículas y después
selecciona los alumnos, de esta forma tiene que recorrer menos registros.

16.- Gestión de vistas en SQL


Creación, modificación y supresión de vistas con SQL.
Creación y uso de vistas

No contienen información por si mismas, sino que están basadas en las que contienen
otras tablas y refleja los datos de estas.
Si se suprime una tabla la vista asociada se invalida. Formato:
CREATE [OR REPLACE] VIEW NOMBREVISTA
[(COLUMNA [,COLUMNA])]
AS CONSULTA;

AS CONSULTA= Determina las columnas y las tablas que aparecerán en la vista.


[OR REPLACE]= Crea de nuevo la vista si ya existía.

Para consultar la vista creada, USER_VIEWS:

SELECT VIEW_NAME FROM…


Nota: al borrar las tablas, las vistas de esas tablas no se borran y quedan
inutilizadas.

Borrado de vistas

Se hace con DROP VIEW. Formato:

DROP VIEW NOMBREVISTA;

Operaciones sobre vistas

Se pueden realizar las mismas operaciones que se hacen sobre las tablas. Restricciones:
Actualización Si una vista esta basada en una sola tabla, se pueden modificar las filas de
la vista.
La modificación de la vista cambia la tabla sobre la que esta definida.
Borrado de filas a través de una vista= Para borrar filas de una tabla a través de una
vista, esta se debe crear:
Con filas de una sola tabla.
Sin utilizar la cláusula GROUP BY ni DISTINCT.
Sin usar funciones de grupo o referencias a pseudocolumnas.
Actualización de filas a través de una vista: Para actualizar filas en una tabla a través de
una vista, esta ha de estar definida según las restricciones anteriores y , además, ninguna
de las columnas que se va a actualizar se habrá definido como una expresión.
Inserción de filas a través de una vista: Para insertar filas en una tabla a través de una
vista se han de tener en cuenta todas las restricciones anteriores y, además, todas las
columnas obligatorias de la tabla asociada deben estar presentes en la vista.
Manejo de expresiones y de funciones en vistas: Se pueden crear vistas usando
funciones, expresiones en columnas y consultas avanzadas pero únicamente se parean
consultar estas vistas. También podemos modificar filas siempre y cuando la columna
que se va a modificar no sea la columna expresad en forma de cálculo o con funciones.
Nota: No es posible insertar filas si las columnas de la vista contiene cálculos o
funciones.

Cambios de nombre
RENAME cambia el nombre de una tabla, vista o sinónimo. El nuevo nombre no puede
ser una palabra reservada ni el nombre de un objeto que tenga creado el usuario. Las
restricciones de integridad, los índices y los permisos dados al objeto se transfieren
automáticamente al nuevo objeto.

REANME NOMBRE_ANTERIOR TO NOMBRE_NUEVO;

Con esta orden no podemos renombrar columnas de una tabla, estas se renombran
mediante CREATE TABLE AS

17.- Introducción al lenguaje PL/SQL


Qué es el lenguaje PL/SQL y primeras explicaciones para saber cómo funciona este
gestor PL/SQL.
Nos encontramos ante un gestor que va incorporado en Oracle para solventar las
grandes limitaciones que teníamos con los editores SQL, en cuanto al control de las
secuencias de ejecución de instrucciones, el uso de variables, la gestión de posibles
errores, etc.
Este lenguaje esta basado en ADA, por lo que incluye todas las características de los
lenguajes de tercera generación. Esto nos permite manejar las variables, tener una
estructura modular (procedimientos y funciones) y controlar las excepciones. Además
incorpora un completo soporte para la programación orientada a objetos (POO).
Los programas creados con PL/SQL los podemos almacenar en nuestra base de datos
como cualquier otro objeto quedando disponibles para los usuarios. El uso del lenguaje
PL/SQL es imprescindible para construir disparadores de bases de datos (triggers).
PL/SQL esta incluido en el servidor y en algunas herramientas de cliente. Soporta todos
los comandos de consulta y manipulación de datos, aportando al lenguaje SQL las
estructuras de control y otros elementos propios de los lenguajes de programación de 3º
generación.
La unidad de trabajo en PL/SQL es el bloque, constituido por un conjunto de
declaraciones, instrucciones y mecanismos de gestión de errores y excepciones.
Bloques
Con PL/SQL se pueden construir distintos tipos de programas: procedimientos,
funciones y bloques anónimos, paquetes, etc. Todos ellos tienen en común una
estructura básica denominada bloque.
Un bloque tiene 3 zonas:
Zona de declaraciones: donde se declaran objectos locales. Suele ir precedida por la
cláusula declare (o is o as en los procedimientos y funciones).
Un conjunto de instrucciones precedido por la cláusula BEGIN
Zona de excepciones: es una zona opcional precedida por la cláusula EXCEPTION,
donde se gestionan las excepciones.
El formato genérico de un bloque es el siguiente:
[ DECLARE
<declaraciones>]
BEGIN
<instrucciones>
[EXCEPTION
<gestión de excepciones>]
END;

Las únicas cláusulas obligatorias son BEGIN y END


Antes de hacer ningún bloque tenemos que ejecutar el siguiente comando en nuestra
ventana de Sql *PLUS
set serveroutput on;
Aunque ahora no entendáis mucho os dejo un ejemplo de un bloque para que os vayáis
familiarizando con la sintaxis.
DECLARE
v_num_empleados number(2);
BEGIN
insert into depart values(99,'provisional',null);
update emple set dept_no=99 where dept_no=20;
v_num_empleados:=SQL%ROWCOUNT;
delete from depart where dept_no=20
DBMS_OUTPUT.PUT_LINE (v_num_empleados || 'Empleados cambiados a
provisional');

Ya en próximos artículos nos meteremos de lleno en la construcción de bloque y en


entender las lineas arriba escritas.

18.- Características de PL/SQL primera parte


ara poder trabajar con PL/SQL tenemos que tener claros una serie de conceptos y
definiciones sobre todo en lo referente a compatibilidad de datos y estructuras de
control.
Definición de datos compatibles con SQL
Este lenguaje suele tener unos tipos de datos compatibles con SQL para las columnas de
las tablas, pero además puede tener otros tipos de datos propios.
Para declarar los datos en un bloque tenemos que utilizar una sintaxis como esta:
DECLARE
nombre_variable Tipo dato;
BEGIN
...
Un ejemplo seria este:
DECLARE
precio NUMBER(8,2);
suma NUMBER(2) DEFAULT 0;
prenda CHAR(20) NOT NULL :='Camiseta';
descripción VARCHAR2(15);
BEGIN
....
Una de las ventajas de PL/SQL es que nos permite declarar una variable del mismo tipo
que otra variable o que una columna de una tabla. Esto lo hacemos con el atributo
%TYPE.
DECLARE
nombre emple.nombre%TYPE;
Otra ventaja es que nos permite guardar el contenido de una fila entera de una tabla en
una variable. Esto lo hacemos con el atributo %ROWTYPE
DECLARE
mifila emple%ROWTYPE;
Con esto ya podemos trabajar con variables dentro de nuestro bloque. Ahora tenemos
que ver las estructuras de control que podemos manejar dentro de nuestros bloques.
Estructuras de control
Las estructuras de control son básicamente las mismas que podemos utilizar en
cualquier lenguaje de programación.
La vamos a dividir en estructuras de control alternativas (IF) y estructuras de control
repetitivas (WHILE, FOR, LOOP)
La estructura del IF seria la siguiente:
IF <condición> THEN
instrucciones
ELSEIF <condición> THEN
instrucciones
....
ELSE
instrucciones
END IF;
La estructura del WHILE seria la siguiente:
WHILE <condición> LOOP
instrucciones
END LOOP;
La estructura del FOR se escribiría así:
FOR <variable> IN <mínimo> <máximo> LOOP
instrucciones
END LOOP
Si queremos que nos vaya contando al revés, es decir de 5 hasta 0 por ejemplo, la
sintaxis seria la siguiente:
FOR <variable> IN REVERSE
<final>.......<inicio> LOOP
instrucciones
.....
END LOOP;
Y la estructura del LOOP seria de esta forma:
LOOP
instrucciones
....
EXIT WHEN <condición>
instrucciones
...
END LOOP;
Cursores implicitos
Es importante saber que en nuestros bloques PL/SQL es bastante práctico el uso de
cursores.
En este lenguaje el resultado de una consulta no va directamente al terminal del usuario,
sino que se guarda en un área de memoria a la que se accede mediante los nombrados
cursores. Para realizar una consulta en PL/SQL tenemos que guardar el resultado en
cursores. Esto es muy sencillo y basta con meter un INTO en las consultas. Un ejemplo
seria este:
select <columna/s> INTO <variable/s> from <tabla> [where]

select count(*) INTO vnum from ventas;


La variable que sigue al INTO recibe el valor de la columna. Por este motivo es
importante que el tipo de dato de la variable coincida con el tipo de dato de la columna.
19.- Características de PL/SQL segunda parte
Es importante controlar los posibles errores y además distinguir los distintos tipos de
programas que podemos crear con PL/SQL.
Gestión de excepciones
Las excepciones sirven para tratar los errores y mensajes. Oracle tiene una serie de
excepciones que son las más frecuentes y con las que la mayoría de la gente trabaja.
Unas de las más usadas son:
NO_DATA_FOUND (cuando una orden tipo select no ha devuelto ningún valor)
TOO_MANY_ROWS (cuando una orden tipo select ha devuelto mas de una fila)
OTHERS THEN RAISE_APPLICATION_ERROR (para cualquier otro tipo de error
desconocido)
Un ejemplo seria el siguiente:
DECLARE
vapellido varchar(10);
voficio varchar(20);
BEGIN
select apellido,oficio INTO vape,voficio from emple where emp=15;
DBMS_OUTPUT.PUT_LINE (vape||: - || voficio);
EXCEPTION
WHEN NO_DATA_FOUND THEN insert into temp values('No hay datos');
WHEN TOO_MANY_ROWS THEN insert into temp values ('Demasiados datos');
WHEN OTHER THEN RAISE_APPLICATION_ERROR(-2000,'Error en
aplicación');
END;
Estructura modular
En PL/SQL podemos distinguir 3 tipos de programas o bloques.
Bloques anónimos: Son los que no tienen nombre y comienzan con el DECLARE, es
decir los que hemos ido viendo hasta ahora.
Procedimientos: Se trata del programa más utilizado en PL/SQL y su formato es el
siguiente:
PROCEDURE <nombre_procedimiento>
[(<lista de parámetros>)]
IS
[<declaraciones>]
BEGIN
<instrucciones>;
[EXCEPTIONS
<excepciones>;]
END;
En el formato distinguimos dos partes claramente, la cabecera donde esta el nombre del
procedimiento y los parámetros y el cuerpo donde se situá un bloque anónimo.
Funciones: similares a los procedimientos pero con la función añadida de que pueden
devolver valores.
Si subís varias lineas y veis el ejemplo de control de excepciones, podéis ver que hemos
utilizado un atributo como DBMS_OUTPUT. Bien pues esto lo que nos permite es
visualizar en pantalla los resultados, tanto excepciones como mensajes. Lo utilizamos
porque PL/SQL no dispone de ordenes o sentencias que capturen datos introducidos por
teclado, ni tampoco para visualizar datos en pantalla.
DBMS_OUTPUT.PUT_LINE nos permite visualizar en pantalla, pero para que
funcione correctamente tenemos que poner el SET SERVEROUTPUT a ON
Si queremos que un bloque nos pida algún dato tenemos que anteponer el símbolo &
delante de la variable, de esta forma cuando el bloque llegue a ese punto nos pedirá por
pantalla el valor.
Otra sentencia importante es la que nos permite visualizar los errores que hemos podido
tener al crear el bloque o procedimiento. Esta sentencia es: show errors
Podemos agregar comentarios a nuestros bloques anteponiendo al comentario “/*
<comentario> */”
Si queremos que el bloque anónimo se ejecute directamente cuando terminamos de
crearlo debemos poner el símbolo / que, ademas de guardar el bloque en el buffer, lo
ejecuta.
También podemos guardar los bloques anónimos en ficheros para poderlos ejecutar
posteriormente. Para ello ejecutamos la siguiente sentencia:
save nombrefichero
Y para ejecutarlo primero tenemos que cargar el fichero en el buffer y para ello tenemos
que ejecutar la siguiente sentencia:
get nombrefichero
Una vez cargado el fichero ejecutamos el bloque con la sentencia run nombrefichero.
O podemos hacer los dos pasos con una sola sentencia: start nombrefichero
Sin embargo para los procedimientos es totalmente distinto ya que al tener nombre se
almacena automáticamente en la base de datos y para ejecutarlo tan solo tenemos que
realizar la siguiente operación:
execute nombre_procedimiento(parámetros);
En el siguiente capitulo revisaremos todo lo que hemos visto en la introducción del
PL/SQL, pero de una forma mas exhaustiva.

20.- Bloques anónimos y procedimientos PL/SQL


En este artículo vamos a ver el uso y ejemplos de los bloques anónimos en PL/SQL y
los procedimientos.
Para continuar las explicaciones sobre PL/SQL que estamos publicando en el Tutorial
de Oraclede Desarrolloweb.com, veamos a continuación dos importantes elementos de
esta plataforma.
Bloques anónimos PL/SQL
Empezaremos con los bloques anónimos, caracterizados porque no tienen nombre y se
suelen crear y ejecutar desde PL/SQL.
Todo bloque debe acabar en . para que sea almacenado en el buffer SQL. Una vez
guardado lo podemos ejecutar con la orden “run”. También podemos guardarlo en un
fichero con la siguiente orden:
save nombrefichero [replace]
El replace sólo lo pondremos si el fichero ya esta creado.
Para cargar y ejecutar este bloque anónimo guardado en fichero ejecutaremos la
siguiente orden:
start nombrefichero
El start lo podemos cambiar por la @ y nos funcionará igualmente.
Pero también podemos cargarlo sin ejecutarlo con la orden “get” y luego ejecutarlo
posteriormente con la orden “run”
Un ejemplo muy sencillo de bloque seria el que nos muestra en pantalla un nombre.
BEGIN
DBMS_OUTPUT.PUT_LINE('nombre');
END;
.
Además en los bloques PL/SQL se pueden utilizar lo que llamamos variables de
sustitución, que nos pedirán datos por pantalla antes de ejecutar el bloque. Estas
variables tienen que ir antepuestas del & para que funcionen.
Un ejemplo seria un bloque que nos pide el DNI de un usuario y nos muestra su
nombre.
DECLARE
Vnom clientes.nombre%TYPE;
BEGIN
select nombre into Vnom from clientes where NIF= '&V_nif';
DBMS_OUTPUT.PUT_LINE (Vnom);
END;
.
Como veis es bastante sencillo, pero no tienen tanta funcionalidad como los
procedimientos o funciones.
Procedimientos y funciones PL/SQL
Los procedimientos y funciones quedan almacenados en la base de datos a diferencia de
los bloques anónimos que se almacenaban en el buffer.
Nota: Al quedar los bloques anónimos almacenados en el buffer, a no ser que se
guardasen en ficheros, se perderían al limpiar el buffer, cosa que no ocurre con los
procedimientos y funciones, que se almacenan en la propia base de datos.

Otra cosa que nos diferencia los bloques anónimos de los procedimientos o funciones es
que en los procedimientos o funciones no se pueden utilizar variables de sustitución.
En cuanto a su construcción es la dada en el articulo Características de PL/SQL segunda
parte añadiendo al principio la siguiente secuencia “CREATE OR REPLACE” para
crearlo, o modificarlo si ya existe.
Pasamos a escribir un procedimiento que nos muestre los datos de un usuario:
CREATE OR REPLACE PROCEDURE ver_usuario(nomusu VARCHAR2)
IS
NIFusu VARCHAR2(10);
Domusu VARCHAR2(10);
BEGIN
select nif, domicilio into NIFusu,Domusu from usuario where nombre=nomusu;
DBMS_OUTPUT.PUT_LINE('Nombre:'||nomusu|| 'NIF:' ||NIFusu|| 'Domicilio' ||
Domusu);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('No hemos encontrado al usuario || nomusu);
END;
/
Si el compilador detecta errores nos saldrá un mensaje como este: “Procedimiento
creado con errores de compilación”. Para ver estos errores tenemos la orden SHOW
ERRORS.
Al tener almacenado el procedimiento en la base de datos, este puede ser llamado por
cualquier usuario que tenga los permisos oportunos. Para invocar un procedimiento
utilizamos la orden EXECUTE
Para invocar al procedimiento que hemos creado antes tendríamos que ejecutar la
siguiente orden:
EXECUTE ver_usuario('Luis');
Pero también podemos invocarlo desde un bloque PL/SQL de ls siguiente forma:
BEGIN
ver_usuario('Luis');
END;
.
Como en cualquier lenguaje, podemos agregar comentarios a nuestros procedimientos
de la siguiente forma:
- - para comentar en una sola linea
/* <comentario>*/ para varias lineas.

21.- Fundamentos del lenguaje PL/SQL


En este artículo estudiaremos los fundamentos de PL/SQL y algunos de los elementos
que constituyen este lenguaje.
Para continuar con el manual de Oracle publicado en DesarrolloWeb.com, es hora de
adentrarnos en las explicaciones de los elementos que forman parte del lenguaje
PL/SQL.
Tipos de datos
Este lenguaje dispone de los mismo tipos de datos que podemos encontrar en SQL, pero
además se han incorporado algunos nuevos:
char(n): almacena una cantidad fija de caracteres
varchar2(n): almacena cadenas de caracteres de longitudes variables
long(n): almacena cadenas de longitud variable
number(p,e): almacena numero de precisión p y escala e
boolean: almacena valores lógicos, true, false o NULL
date: almacena fechas completas, incluida la hora
raw(n): almacena datos binarios de longitud fija
long raw : almacena datos binarios de longitud variable
rowid: almacena identificadores de direcciones de fila
etc.
Además es importante señalar que el programador puede definir sus propios tipos de
datos a partir de los ya definidos.
Identificadores
Se utilizan para nombrar los objetos que intervienen en los programas PL/SQL como
son las variables, constantes, cursores, excepciones, procedimientos, etc.
Pueden tener como máximo 30 caracteres empezando siempre por una letra, que puede
ir seguida por otras letras, numeros, $, # ó _. Es importante destacar que PL/SQL no
diferencia entre mayúsculas y minúsculas. También debemos señalar que no pueden
contener espacios ni signos de puntuación.
Variables
Como doy por sentado que todos sabemos lo que son las variables, pasaremos
directamente a comentar como se declara una variable en PL/SQL.
<nombreVariable> <tipo> [NOT NULL] [{:= | DEFAULT } <valor>]
No podemos indicar una lista de variables del mismo tipo y luego declarar el tipo,
tenemos que hacerlo una a una.
Uno ejemplo de declaración de variables seria el siguiente:
DECLARE
importe NUMBER (8,2);
contador NUMBER(2'0);
nombre char(5) NOT NULL :="Sara";
...
Uso de los atributos %TYPE y %ROWTYPE
%TYPE: declara una variable del mismo tipo que otra, o que una columna de una tabla
%ROWTYPE : crea una variable registro cuyos campos se corresponden con las
columnas de una tabla o vista.
Por ejemplo si tenemos una variable definida previamente llamada cantidad podemos
definir otra de la siguiente forma:
total cantidad%TYPE;
De esta forma la variable total tendrá las mismas características que la variable cantidad.

Otro ejemplo seria declarar una variable que fuera del mismo tipo que la columna
nombre de la tabla profesor.
nombre_alta nombre%ROWTYPE;
Á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.
Constantes
Cómo en la mayoría de los lenguajes, en este también podemos declaras constantes, de
la siguiente forma:
<nombreVariable> CONSTANT <tipo> := <valor>;
Operadores
Asignación :=
AND
Lógicos OR
NOT
Concatenación ||
Is null
=
!=
<>
<
>
Comparación
<=
>=
between...and
like
in
y sus correspondientes negaciones
Aritméticos + - * / **
Funciones predefinidas
En PL/SQL tenemos las mismas funciones predefinidas que en SQL (AVG, MIN, MAX,
COUNT, SUM, etc), pero tenemos que tener dos cosas muy claras a la hora de
utilizarlas y son:
La función no modifica el valor de las variables o expresiones que se pasan como
argumentos, sino que devuelve un valor a partir de dicho argumento.
Si a una función se le pasa un valor nulo en la llamada, posiblemente devolverá un valor
nulo.
Etiquetas
Podemos utilizar etiquetas para poder irnos a cualquier parte del programa utilizando la
sentencia GOTO siempre y cuando se cumplan las siguientes reglas:
No pueden haber etiquetas con los mismos nombres en un mismo programa.
La etiqueta debe preceder a un bloque o a un conjunto de ordenes ejecutables
la etiqueta no puede estar dentro de estructuras de control (IF, LOOP)

22.- Subprogramas PL/SQL


Los subprogramas son los bloques PL/SQL con nombre que pueden recibir y devolver
valores.
En cualquier subprograma podemos distinguir:
La cabecera, compuesta por el nombre del subprograma, los parámetros y el tipo de
valor de retorno.
El cuerpo, compuesto por las declaraciones, las instrucciones y el manejo de
excepciones.

Podemos distinguir entre dos tipos de subprogramas, como ya hemos comentado en


artículos anteriores:
Procedimientos
Los procedimientos ya los hemos visto en el articulo “Bloques anónimos y
procedimientos PL/SQL ” por lo que pasamos directamente a las funciones.
Funciones
Las funciones son muy similares a los procedimiento con la diferencia que éstas
siempre devolverán un valor. Su estructura es la siguiente:
CREATE [OR REPLACE] FUNCTION NombreFuncion [(parámetros)] RETURN tipo
IS [parte declarativa]
BEGIN
instrucciones
RETURN <valor o expresión>;
[EXCEPTION excepciones]
END;
La cláusula RETURN de la cabecera nos especifica el tipo de valor que nos va a
devolver la función.
Parámetros
Todos los subprogramas utilizan parámetros para pasar y recibir información.
Dentro de los parámetros podemos distinguir dos tipos:
Parámetros actuales: son variables indicadas en la llamada a un subprograma.
Parámetros formales: son variables declaradas en la especificación del subprograma.

Además podemos hacer el paso de parámetros de un tipo a otro. Generalmente si los


tipos son compatibles PL/SQL lo hace automáticamente. En cualquier caso, podemos
hacerlo de forma manual utilizando las siguientes notaciones:
Posicional: el compilador asocia los parámetros actuales a los formales, basándose en
suposición.
Nominal: el símbolo => después del parámetro actual y antes del nombre del formal,
indica al compilador correspondencia.
Mixta: nos permite usar las dos notaciones anteriores.

Para que esto quede más claro pasamos a escribir un ejemplo de paso de parámetros y
conversión de tipos.
Tenemos la especificación de un procedimiento como esta:
PROCEDURE departamento(
n_departamento INTEGER,
localidad VARCHAR2
IS...
Desde el siguiente bloque se podrán realizar las llamadas indicadas:
DECLARE
num_departamento INTEGER;
aula VARCHAR(30)
BEGIN
...
- - posicional departamento(num_departamento, aula);
- - nominal departamento(num_departamento => n_departamento, aula =>localidad);
...
END;
Esto nos pasaría los parámetros num_departamento al mismo tipo que n_departamento
y localidad al mismo tipo que aula.
Los parámetros que soporta PL/SQL pueden ser de entrada, salida o entrada/salida
Nos permite pasar valores a un subprograma. Dentro del subprograma, el
IN parámetro actuá como una constante. Puede ser una variable, constante,
literal o expresión.
Permite devolver valores al bloque que llamó al subprograma. Dentro
OUT del subprograma, el parámetro actúa como una variable no inicializada.
Solo puede ser una variable.
Permite pasar un valor inicial y devolver un valor actualizado. Dentro
IN
del subprograma, el parámetro actuá como variable inicializada. Puede
OUT
intervenir otras expresiones. El valor actual debe ser una variable.

El formato genérico es el siguiente:


<nombrevariable> [IN | OUT | IN OUT] <tipodato>
[ { := | DEFAULT} <valor>]
Además es importante recordar que al especificar parámetros debemos indicar el tipo,
pero no el tamaño.
Creación, modificación y borrado de subprogramas
Cuando creamos subprogramas con SQL * PLUS utilizando los comandos CREATE,
Oracle automáticamente compila el código fuente, genera el código objeto y los guarda
en el diccionario de datos, quedando disponibles para su utilización.
Para volver a compilar un subprograma almacenado utilizaremos la orden ALTER en
vez del CREATE y su formato es el siguiente:
ALTER {PROCEDURE | FUNCITON} nombresubprograma COMPILE;
Para ver el código de un subprograma almacenado podemos ejecutar una sentencia
como esta;
select LINE, SUBSTR(TEXT,1,60) from USER_SOURCE where name =
'nombresubprograma';
Para borrar un subprograma almacenado utilizaremos la orden DROP de la siguiente
forma:
DROP {PROCEDURE | FUNCTION} nombresubprograma;
Nota: PL/SQL implementa la recursividad en los subprogramas, esto quiere decir, que
un programa puede llamarse a si mismo.
23.- Cursores en PL/SQL primera parte
Comenzamos a explicar los cursores de PL/SQL. Veremos los cursores explícitos, sus
atributos y las variables de acoplamiento .
En los anteriores capítulos hemos visto los fundamentos del lenguaje PL/SQL, bien
pues, a partir de ahora pasaremos a estudiar el manejo de este lenguaje para trabar con
el gestor de Oracle. Empezaremos con la utilización de cursores.
Hasta ahora hemos utilizado cursores implícitos, cuando devolvíamos el resultado de
una select mediante la clausula into a una variable. Pero esto es un problema cuando el
resultado de una subconsulta nos devolvía varias filas, porque esto nos daria un error al
ejecutar la consulta Para que no nos salte un error en estos casos debemos utilizar los
cursores explícitos.
Cursores explícitos
Los cursores explícitos los utilizamos cuando tenemos consultas que nos devuelven más
de una fila.
Tenemos 4 operaciones básicas para trabajar con un cursor explícito.
Declaración del cursor: lo tenemos que declarar en la zona de declaraciones, con el
siguiente formato: CURSOR <nombrecursor> IS <sentencia SELECT>;
Apertura del cursor: Deberá colocarse en la zona de instrucciones, con el siguiente
formato:
OPEN <nombrecursor>;
Al hacerlo se ejecuta automáticamente la sentencia select y sus resultados se almacenan
en las estructuras internas de memoria manejadas por el cursor.
Recogida de información: Para recuperar la información anteriormente guardada en las
estructuras de memoria interna tenemos que usar el siguiente formato:
FETCH <nombrecursor> INTO {<variable> | <listavariables>};
Si tenemos una única variable que recoge los datos de todas las columnas, el formato de
la variable seria el siguiente:
<variable> <nombrecursor>%ROWTYPE;
Si tenemos una lista de variables, cada una recogerá la columna correspondiente de la
cláusula select, por lo que serán del mismo tipo que las columnas.
- Cierre del cursor:
CLOSE <nombrecursor>;
Ahora, veamos un ejemplo de utilización de cursores explícitos:
DECLARE
CURSOR C1 IS SELECT nombre, apellido FROM arbitro;
Vnom VARCHAR2(12);
Vape VARCHAR2(20);
BEGIN
OPEN C1;
LOOP
FETCH C1 INTO Vnom, Vape;
EXIT WHEN C1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(Vnom || '' || Vapen);
END LOOP;
CLOSE C1;
END;
Si nos fijamos, en la declaración de los cursores explícitos no utilizamos la cláusula
INTO, que sí se utilizaba en los cursores implícitos.
Ademas podéis ver que después del FETCH hemos comprobado si nos devuelve valores
con la linea del EXIT. Es algo importante ya que si no nos devuelve nada el LOOP se
interrumpirá.
Atributos del cursor
Para conocer detalles de la situación del cursor tenemos 4 atributos:
%FOUND: devuelve verdadero di el ultimo FETCH ha recuperado algún valor; en caso
contrario devuelve falso; si el cursor no esta abierto nos devuelve error.
%NOTFOUND: hace justamente lo contrario al anterior.
%ROWCOUNT: nos devuelve el número de filas recuperadas hasta el momento.
%ISOPEN: devuelve verdadero si el cursor esta abierto.
Veamos ahora un ejemplo de utilización de %ROWCOUNT:
DECLARE
CURSOR C1 IS SELECT nombre from futbolista WHERE Cod='e1';
Vnom VARCHAR2(15);
BEGIN
OPEN C1;
LOOP
FETCH C1 INTO Vnom;
EXIT WHEN C1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE (C1%ROWCOUNT || Vnom);

END LOOP;
CLOSE C1;
END;
Variables de acoplamientos en el manejo de cursores
En el ejemplo siguiente podemos observar que en la cláusula WHERE se incluye una
variable que se debería haber declarado previamente. Este tipo de variables reciben el
nombre de variables de acoplamiento. El programa la sustituirá por su valor en el
momento en que se abre el cursor, y se seleccionarán las filas según dicho valor. Aunque
ese valor cambie durante la recuperación de los datos con FETCH, el conjunto de filas
que contiene el cursor no variará.
El ejemplo nos muestra los futbolistas de un equipo cualquiera.
CREATE OR REPLACE PROCEDURE ver_futbolistas_por_equipos(codeq
VARCHAR2)
IS
Vequi VARCHAR2(3);
CURSOR C1 IS SELECT nombre from futbolista where codeq=Vequi;
Vnom VARCHAR(15);
BEGIN
vequi:=codeq;
OPEN C1;
FETCH C1 INTO vnom;
WHILE C1%FOUND LOOP
DBMS_OUTPUT.PUT_LINE(Vnom);
FETCH C1 INTO Vnom;
END LOOP;
CLOSE C1;
END;

24.- Cursores PL/SQL segunda parte


Continuamos con los cursores de PL/SQL, esta vez vamos a ver variables de
acoplamiento y cursores con parámetros.
Dando continuidad al Manual de Oracle que estamos publicando en
DesarrolloWeb.com, y en el apartado del lenguaje PL/SQL, continuamos nuestras
explicaciones sobre los cursores, que habíamos comenzado a explicar en el artículo
anterior.
Variables de acoplamiento
Si os fijáis en el siguiente ejemplo veréis que en la cláusula where se incluye una
variable que se deberá declarar previamente. Este tipo de variables recibe el nombre de
variables de acoplamiento. El programa la sustituirá por su valor en el momento en que
se abre el cursor, y se seleccionarán las filas según dicho valor.
Create or replace procedure ver_jugador(codeq varchar2)
IS
vequi varchar2(3);
cursor c1 is select nombre from jugador where cod=vequi;
vnom varchar2(15);
BEGIN
vequi:=codeq;
OPEN c1;
FETCH c1 INTO vnom;
WHILE c1%found LOOP
DBMS_OUTPUT.PUT_LINE(vnom);
FETCH c1 INTO vnom;
END LOOP;
CLOSE c1;
END;
Cursor FOR …. LOOP
El trabajo normal de un cursor consiste en declarar un cursor, declarar una variable que
recogerá los datos del cursor, abrir el cursor, recuperar con fetch, una a una, las filas
extraídas introduciendo los datos en las variables, procesándolos y comprobando si se
han recuperado datos o no.
Para resumir todas esas tareas, tenemos una estructura cursor FOR...LOOP que hace
todas estas cosas de forma implícita, todas menos la declaración del cursor.
El formato y el uso de esta estructura es:
se declara la información cursor en la sección correspondiente
Se presenta el cursor utilizando el siguiente formato: FOR nombreVarReg IN
nombreCursor
LOOP …. END LOOP;
Al entrar en el bucle se abre el cursor de manera automática, se declara implícitamente
la variable nombreVarReg de tipo nombrecursor%ROWTYPE y se ejecuta el primer
fetch cuyo resultado quedarán en nombreVarReg. A continuación se realizaran las
acciones que correspondas hasta llegar al END LOOP.

Este es un ejemplo del LOOP …. END LOOP:


DECLARE
cursor c2 is select nombre, peso, estatura from jugador where salario>1200;
BEGIN
FOR vreg IN c2 LOOP
DBMS_OUTPUT.PUT_LINE (vreg.nombre || '-' ||vreg.peso || '-' || vreg.estatura);
END LOOP;
END;
Cursores con parámetros
Un cursor puede tener parámetros; en este caso se aplicara el siguiente formato
genérico:
CURSOR nombrecursor [(parámetros)] IS SELECT <sentencia select en la que
intervendrán los parámetros>;
Los parámetros formales indicados después del nombre del cursor tienen la siguiente
sintaxis:
nombreCursor [IN] tipodato [{:=|DEFAULT} valor]
Todos los parámetros formales de un cursor son parámetros de entrada y su ámbito es
local al cursor por eso sólo pueden ser referenciados dentro de la consulta.
Un ejemplo seria el siguiente:
DECLARE
...
CURSOR C1 (vpeso number, vestatura number DEFAULT 170) is select nficha,
nombre FROM emple WHERE estatura=vestatura AND peso=vpeso;

Para abrir un cursor con parámetros lo haremos de la siguiente forma:

OPEN nombrecursor [(parámetros)];

25.- Cursores PL/SQL tercera parte


Continuamos con los cursores, esta vez vamos a ver atributos con cursores explícitos y
uso de cursores para actualizar filas.
Atributos con Cursores implícitos
Los atributos de los cursores implícitos que se crean son los siguientes:
SQL%NOTFOUND: nos dice si el último insert, update,delete o select into no han
afectado a ninguna fila.
SQL%FOUND: nos dice si el último insert, update,delete o select into ha afectado a una
o mas filas
SQL%ROWCOUNT: devuelve el número de filas afectadas por el último insert, update,
delete o select into
SQL%ISOPEN: Nos dice si el cursor esta cerrado, por lo que en teoría siempre nos dará
falso ya que Oracle cierra automáticamente el cursor después de cada orden SQL.

Es importante tener en cuenta una serie de cosas:


Si se trata de un select into tenemos que tener en cuenta que solo puede devolver una
única fila de lo contrario nos levantará automáticamente una de estas dos excepciones:
 NO_DATA_FOUND: si la consulta no devuelve ninguna fila
 TOO_MANY_ROWS: si la consulta devuelve más de una fila
Cuando un select into hace referencia a una función de grupo nuca se levantará la
excepción NO_DATA_FOUND y SQL%FOUND siempre será verdadero. Esto se
explica porque las funciones de grupo siempre devuelven algún valor (NULL se
considera un valor).
Uso de cursores para actualizar filas

Para realizar una actualización con un cursor tenemos que añadir la siguiente FOR
UPDATE al final de la declaración del cursor:
CURSOR nombre_cursor <declaraciones> FOR UPDATE
Esto indica que las filas seleccionadas por el cursor van a ser actualizadas o borradas.
Una vez declarado un cursor FOR UPDATE, se incluirá el especificador CURRENT OF
nombre_cursor en la cláusula WHERE para actualizar o borrar la última fila recuperada
mediante la orden FETCH.
{UPDATE|DELETE}... WHERE CURRENT OF nombre_cursor.
Os pongo un ejemplo para que quede claro:
Subir el salario a todos los empleados del departamento indicado en la llamada. El
porcentaje se indicará también en la llamada.
CREATE OR REPLACE PROCEDURE subir_salario (num_dept NUMBER, incre
NUMBER)
IS
CURSOR c IS SELECT oficio, salario FROM empleados WHERE
cod_dept=num_dept
FOR UPDATE;
reg c%ROWTYPE;
inc NUMBER (8);
BEGIN
OPEN c;
FETCH c INTO reg;
WHILE c%FOUND LOOP
inc :=(reg.salario/100 )* inc;
UPDATE empleados SET salario=salario+inc WHERE CURRENT OF c
FETCH c INTO reg;
END LOOP;
END;
También podemos usar ROWID en lugar de FOR UPDATE. ROWID nos indicará la fila
que se va a actualizar. Para ello, al declarar el cursor en la cláusula SELECT
indicaremos que seleccione también el identificador de fila:
CURSOR nombre_cursor IS SELECT columna1,columna2,...ROWID FROM tabla;
Al ejecutarse el FETCH se guardará el número de fila en una variable y después ese
número se podrá usar en la cláusula WHERE de la actualización:
{UPDATE |DELETE } ... WHERE ROWID = variable_rowid
El ejemplo anterior utilizando ROWID quedaría de la siguiente manera:
CREATE OR REPLACE PROCEDURE subir_salario (num_dept NUMBER, incre
NUMBER)
IS
CURSOR c IS SELECT oficio, salario,ROWID FROM empleados WHERE
cod_dept=num_dept
FOR UPDATE;
reg c%ROWTYPE;
inc NUMBER (8);
BEGIN
OPEN c;
FETCH c INTO reg;
WHILE c%FOUND LOOP
inc :=(reg.salario/100 )* inc;
UPDATE empleados SET salario=salario+inc WHERE ROWID =
reg.ROWID;
FETCH c INTO reg;
END LOOP;
END;
Con este artículo damos por terminado todo lo referente a cursores y empezamos a tratar
las excepciones en el siguiente artículo.

26.- Excepciones en Oracle y PL/SQL


Las excepciones en el sistema gestor Oracle y el lenguaje PL/SQL, nos ayudan a
detectar y tratar errores en tiempo de ejecución.
En este artículo del Manual de PL/SQL de Oracle vamos a ver lo que son las
excepciones, para qué sirven y cómo utilizarlas. Daremos un repaso también a los tipos
de excepciones, las excepciones definidas por el usuario y la sintaxis con la que
tenemos que especificarlas.
Por último, de paso que vemos cosas acerca del tratamiento de errores en PL/SQL,
explicaremos el RAISE_APPLICATION_ERROR, un componente del sistema gestor
de base de datos Oracle que ayuda a gestionar errores y sus mensajes de error.
Qué son las excepciones en Oracle
Las excepciones, presentes en la mayoría de los lenguajes de programación, sirven para
tratar errores en tiempo de ejecución. En el sistema que nos ocupa, Oracle, sirven
también para definir qué se debe hacer frente a errores en sentencias definidas por el
usuario. Cuando se produce un error PL/SQL levanta una excepción y pasa el control a
la sección excepción correspondiente al bloque PL/SQL.
El formato sería el siguiente:
BEGIN
.........
......
......
EXCEPTION
WHEN <nombre_excepción> THEN
<instrucciones>;
......
[WHEN OTHERS THEN <instrucciones>;]
END;
Excepciones predefinidas
Son aquellas que se disparan automáticamente al producirse determinados errores. Estas
son las más comunes:
too_many_rows: Se produce cuando select … into devuelve más de una fila.
no_data_found: se produce cuando un select …. into no devuelve ninguna fila.
login_denied: error cuando intentamos conectarnos a Oracle con un login y clave no
validos.
not_logged_on: se produce cuando intentamos acceder a la base de datos sin estar
conectados.
program_error: se produce cuando hay un problema interno en la ejecución del
programa.
value_error: se produce cuando hay un error aritmético o de conversión.
zero_divide: se puede cuando hay una división entre 0.
dupval_on_index: se crea cuando se intenta almacenar un valor que crearía duplicados
en la clave primaria o en una columna con restricción UNIQUE.
invalid_number: se produce cuando se intenta convertir una cadena a un valor
numérico.
Hay alguna más pero estas son las más utilizadas y tenemos que tener en cuenta que no
es necesario declararlas en la sección DECLARE.
Excepciones definidas por el usuario
Son aquellas que crea el usuario. Para ello se requieren tres pasos:
Definición: se realiza en la zona de DECLARE con el siguiente formato:
nombre_excepción EXCEPTION
Disparar o levantar la excepción mediante la orden raise: RAISE ;
Tratar la excepción en el apartado EXCEPTION: WHEN THEN ;

Para que esto quede más claro ponemos un ejemplo a continuación.


DECLARE
...
Importe_mal EXCEPTION;
...
BEGIN
...
IF precio NOT BETWEEN mínimo and máximo THEN
RAISE importe_mal;
END IF;
...
EXCEPTION
WHEN importe_mal THEN DBMS_OUTPUT.PUT_LINE("Importe incorrecto");
...
END;
Otras excepciones
Existen otros errores internos de Oracle que no tienen asignada una excepción, sino un
código de error y un mensaje, a los que se accede mediante funciones SQLCODE y
SQLERRM. Cuando se produce un error de estos se trasfiere directamente el control a
la sección EXCEPTION donde se tratara el error en la clausula WHEN OTHERS de la
siguiente forma:
WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE('Error'||SQLCODE||
SQLERRM.)
Utilización de RAISE_APPLICATION_ERROR
En el paquete DBMS_STANDARD se incluye un procedimiento llamado
RAISE_APPLICATION_ERROR que nos sirve para levantar errores y definir mensajes
de error. Su formato es el siguiente:
RAISE_APPLICATION_ERROR(numero_error,mensaje_error);
Es importante saber que el numero de error esta comprendido entre -20000 y -20999 y
el mensaje es una cadena de caracteres de hasta 512 bytes.
Este procedimiento crea una excepción que solo puede ser tratada en WHEN OTHERS.
Ponemos un ejemplo para que nos quede más claro.
CREATE or REPLACE PROCEDURE subir_horas (emple NUMBER, horas_subir
NUMBER)
IS
horas_actuales NUMBER;
BEGIN
Select horas into horas_actuales from empleados where id_empleado=emple;
if horas_actuales is NULL then
RAISE_APPLICATION_ERROR(-20010,'No tiene horas');
else
update empleados set horas=horas_actuales + horas_subir where
id_empleado=emple;
end if;
End subir_horas;

27.- Control de transacciones


Control de transacciones en Oracle. Una transacción se define como un conjunto de
operaciones sobre la base de datos.
En Oracle si se ejecuta un conjunto de operaciones y una de ellas falla se aborta la
transacción entera. En este artículo veremos todo lo que debemos saber sobre
transacciones y algunos ejemplos interesantes. Está englogado dentro del Manual de
Oracle que venimos publicando en DesarrolloWeb.com.
La transacción finaliza cuando se ejecuta un comando de control de transacciones como
rollback o commit work (se puede abreviar poniendo simplemente commit).
Un ejemplo:
BEGIN
....

update alumnos set edad=20 where n_alumno=109;


update nuevos set apellido='perez' where n_alumno=200;
commit work;

...

EXCEPTION
WHEN OTHERS THEN
rollback work;
END;
Comandos utilizados para el control de transacciones
Commit
Este comando da por concluida la transacción actual y hace definitivos los cambios
realizados liberando las filas bloqueadas. Sólo después de que se ejecute commit
tendremos acceso a los datos modificados.
Rollback
Este comando da por concluida la transacción actual y deshace los cambios que se
pudiesen haber producido en la misma, liberando las filas bloqueadas. Se utiliza
especialmente cuando no se puede concluir una transacción porque se han levantado
excepciones.
Savepoint
Se utiliza para poner marcas o puntos de salvaguarda al procesar transacciones. Se
utiliza junto con rollback permitiendo deshacer cambios hasta los savepoint.
El número de savepoint esta limitado a 5 por sesión pero lo podemos modificar con la
siguiente sentencia:
savepoint numero;
Rollback implicito
Este comando se ejecuta cuando un programa almacenado (procedimiento o función)
falla y no se controla la excepción que produjo el fallo. Pero si en el programa tenemos
un commit estos cambios no serán deshechos.
Rollback to
Deshace el trabajo realizado después del punto indicado. Pero no se confirma el trabajo
hecho hasta el savepoint. La transacción no finaliza hasta que se ejecuta un comando de
control de transacciones o hasta que finaliza la sesión.
Os dejo a continuación un ejemplo bastante completo de lo que seria el control de
transacciones:
create or replace procedure prueba (nfilas number)
as
begin
savepoint ninguna;
insert into tmp values ('primera fila');
savepoint una;
insert into tmp values ('segunda fila');
savepoint dos;
if nfilas=1 then
rollback to una;
else if nfilas=2 then
rollback to dos;
else
rollback to ninguna;
end if;
commit;
exception
when other then
rollback
end prueba;
Con este artículo terminamos la parte básica sobre oracle, PL/SQL y pasamos a lo que
podemos denominar programación avanzada de sql. Empezaremos con triggers en el
siguiente artículo.

28.- Triggers a tablas en PL/SQL


Explicamos que son los triggers o disparadores de base de datos en PL/SQL de Oracle.
Como ya comentábamos en el articulo anterior, publicado en el Manual de Oracle de
DesarrolloWeb.com, comenzamos lo que podríamos denominar programación avanzada
dentro de PL/SQL.
En el presente artículo vamos a estudiar acerca de los triggers, donde veremos qué son y
como se construyen, comenzando con los trigger de tablas y más tarde veremos los
trigger de sustitución y los de sistema. Para ello lo primero que tenemos que ver es su
definición.
Trigger a tablas
Un trigger es un bloque de código PL/SQL que se almacenan en la base de datos. Los
bloques de código de los triggers están asociados a una tabla y se ejecutan
automáticamente cuando se producen ciertos eventos asociados a la tabla.
Se suelen utilizar para prevenir transacciones erróneas y nos sirven también para
implementar restricciones de integridad o seguridad.
Su formato básico es el siguiente:
create or replace trigger nombre_trigger
{before | after} {delete | insert | update[of lista_columnas]}
[or {before | after} {delete|insert|update [of lista_columnas]}]
on nombre_tabla
[for each {row | statement | when (condición)}]
/* comienza el trigger */
[declare]
<declaraciones>
begin
<instrucciones>
[exception]
<excepciones>
end;
Elementos de un trigger
before / after: elemento que dispara el trigger
nombre: nombre del trigger que tiene que ser único.
for each: nivel del disparo del trigger que por defecto es statement que significa que se
dispara una sola vez por cada operación independientemente del número de filas
afectadas.
for each row: salta por cada fila afectada.
Variables posibles para update: la primera es :old que hace referencia a los valores
anteriores y :new que hace referencia a los nuevos valores de actualización de la fila.
Tenemos que tener en cuanta unos cuantos aspectos:
Cuando el evento que dispara el trigger es un delete haremos referencia al valor :old
porque el valor :new es nulo
Cuando el evento que dispara el trigger es un insert haremos referencia al valor :new
porque el :old es nulo.
Cuando el evento es un update tiene sentido hacer referencia a los dos valores.
Sólo se pueden utilizar cuando el trigger es a nivel de fila (for each row).

Vamos a a crear un trigger que se disparé automáticamente después de la modificación


del salario de la tabla empleado y pase un comentario a la tabla auditar.
Create or replace trigger auditar_salario
after update of salario
on empleado
for each row
begin
insert into auditar values
('se ha modificado el salario' || :old.num_empleado);
end;
Orden de ejecución de los trigger
Una misma tabla puede tener varios triggers y el orden de disparo seria el siguiente:
Antes de comenzar a ejecutar la orden que provoca el disparo se ejecutaran los triggers
del tipo before.... for each statement
Para cada fila afectada por la orden:
a) se ejecutan los triggers del tipo before … for each row
b) se ejecuta la actualización de la fila
c) se ejecutan los triggers after... for each row
Una vez realizada la operación se ejecuta el after … for each statement
Cuanndo se dispara un trigger este forma parte de la operación que lo disparó de manera
que si el trigger falla, Oracle dará por fallida la operación completa. Aunque el fallo sea
a nivel de fila se hará rollback a toda la operación.
Ejemplo:
create or replace trigger nombre_trigger
before insert or delete
begin
if insert then
.....
elseif deleting then
....
elseif updating then
...
end if
....
end;
En el siguiente articulo veremos los triggers de sustitución y los del sistema.

29.- Triggers de sustitución y de sistema


Vemos lo que es un disparador de sustitución y el de sistema, así como su creación en
Oracle.
Disparadores de sustitución
Podemos crear triggers que no se ejecutan antes ni después de una instrucción sino en
lugar de (instead of).
Solo podemos utilizar estos triggers si están asociados a vistas, además actúan siempre a
nivel de fila.
La sintaxis de este tipo de trigger es la siguiente:
create [or replace] trigger nombre_trigger
instead of { insert | delete | update [of columnas]}
[ or { insert | delete | update}]
on nombre vista
[ for each row]
[declare]
declaraciones
begin
instrucciones
[execption]
excepciones
end;
Sobre una vista podemos hacer un select pero si hacemos un insert, delete o update
puede darnos problemas y no dejar ejecutarse la orden correctamente.
Los trigger sobre vistas vas a sustituir a estas operaciones por las correspondientes en
las tablas que forman la vista.
Un ejemplo de trigger de sustitución seria el siguiente:
create or replace trigger t_borrado_emp
instead of delete on empleado
for each row
begin
delete from emple where emp_num=:old.cod
end;
Disparadores de sistema
Estos trigger se disparan cuando se arranca o para la base de datos, entra o sale un
usuario, cuando se crea, modifica o elimina un objeto, etc.
En Oracle para crear este tipo de trigger tenemos que tener privilegios de Administer
database trigger.
La sintaxis de este trigger seria la siguiente:
create [or replace] trigger nombre_trigger
{ before | after } { <lista eventos de definición> | <lista eventos del sistema>}
on { database | schema} [when (condición)]
<cuerpo del trigger (bloque PL/SQL)>
Donde la lista de eventos de definición puede tener uno o más eventos DDL separados
por or y la lista de eventos del sistema igualmente separados por or.
Al asociar un disparador a un evento debemos indicar el momento en que se dispare. A
continuación os dejo una tabla de evento, momento y cuando se dispararía para dejarlo
todo mas o menos claro.
Evento Momento Se disparan:
STARTUP AFTER Después de arrancar la instancia
SHUTDOWN BEFORE Antes de apagar la istancia
Después de que el usuario se conecte a la base de
LOGON AFTER
datos.
LOGOFF BEFORE Antes de la desconexión de un usuario
SERVERERROR AFTER Cuando ocurre un error en el servidor
BEFORE |
CREATE Antes o después de crear un objeto en el esquema
AFTER
BEFORE |
DROP Antes o después de borrar un objeto en el esquema
AFTER
BEFORE |
ALTER Antes o después de cambiar un objeto en el esquema
AFTER
BEFORE |
TRUNCATE Antes o después de ejecutar un comando truncate
AFTER
BEFORE |
GRANT Antes o después de ejecutar un comando grant
AFTER
BEFORE |
REVOKE Antes o después de ejecutar un comando revoke
AFTER
BEFORE | Antes o después de ejecutar cualquier comando de
DLL
AFTER definición de datos

Oracle tiene algunas funciones que permiten acceder a los atributos del evento del
disparo ORA_YSEVENT, ORA_LOGIN, etc. Estas funciones pueden usarse en la
clausula WHEN o en el cuerpo del disparador. En el manual de Oracle podéis encontrar
el listado de todas estas funciones.
Un ejemplo seria un trigger que nos guarda los datos de un usuario al hacer login en la
base de datos:
create or replace trigger control
after logon
on database
begin
insert into control_conexion (usuario, momento, evento)
values {ORA_LOGIN_USER, SYSTIMESTAMP, ORA_SYSEVENT);
end;
30.- Paquetes en Oracle
Vamos a ver que son los paquetes en el sistema gestor de base de datos Oracle,
explicando estructura y funcionamiento.
En este artículo que pertenece al tutorial de Oracle trateremos el tema de los paquetes de
forma detenida.
Los paquetes en Oracle se utilizan para guardar subprogramas y otros objetos de la base
de datos.
Un paquete consta de los siguientes elementos:
Especificación o cabecera: contiene las declaraciones públicas (es decir, accesibles
desde cualquier parte de la aplicación) de sus programas, tipos, constantes, variables,
cursores, excepciones, etc.
Cuerpo: contiene los detalles de implementación y declaraciones privadas, es decir,
accesibles solamente desde los objetos del paquete.
La sintaxis de la cabecera es la siguiente:
create [or replace] package nombre_paquete as
<declaraciones públicas>
<especificaciones de subprogramas>
end nombre_paquete;
La sintaxis del cuerpo sería la siguiente:
create [or replace] package body nombre_paquete as
<declaraciones privadas>
<código de subprogramas>
[begin
<instrucciones iniciales>]
end nombre_paquete;
Como podéis observar la cabecera se compila independientemente del cuerpo. Os dejo
un ejemplo de paquete para que lo veáis más claro.
/* Cabecera */
create or replace package busar_emple as
TYPE t_reg_emple is RECORD
(num_empleado emple.emp_no%TYPE,
apellido emple.apellido%TYPE,
salario emple.salario%TYPE,
departamento emple.dept_no%TYPE);
procedure ver_por_numero(v_cod emple.emp_no%TYPE);
procedure ver_por_apellido(v_ape emple.apellido%TYPE);
function datos (v_cod emple.emp_no%TYPE)
return t_reg_emple;
end buscar_emple;

/* Cuerpo */

create or replace package body buscar_emple as


vg_emple t_reg_emple;
procedure ver_emple; /* procedimiento privado*/
procedure ver_por_numero (v_cod emple.emp_no%TYPE)
is
begin
select emp_no, apellido, salario, dept_no into vg_emple from emple where
emp_no=v_cod;
ver_emple;
end ver_por_numero;
procedure ver_por_apellido (v_ape emple.apellido%TYPE)
is
begin
select emp_no,apellido,salario,dept_no into vg_emple from emple where
apellido=v_apellido;
ver_emple;
end ver_por_apellido;
function datos (v_cod emple.emp_no%TYPE)
return t_reg_emple
is
begin
select emp_no,apellido,salario,dept_no into vg_emple from emple where
emp_no=v_cod;
procedure ver_emple
is
begin
DBMS_OUTPUT.PUT_LINE(vg_emple.num_empleado || '*' || vg_emple.apellido
|| '*' || vg_emple.salario || '*'|| vg_emple.departamento);
end ver_emple;
end buscar_emple;
Como podéis ver este paquete nos permite buscar un empleado de tres formas distintas y
visualizar sus datos.
Utilización de los objetos definidos en los paquetes
Podemos utilizar los objetos definidos en los paquetes básicamente de dos maneras
distintas:
Desde el mismo paquete: esto quiere decir que cualquier objeto puede ser utilizado
dentro del paquete por otro objeto declarado en el mismo.
Para utilizar un objeto dentro del paquete tan sólo tendríamos que llamarlo. La llamada
sería algo así: v_emple :=buscar_emple.datos(v_n_ape); (como veis no utilizamos el
execute ya que nos encontramos dentro del paquete).
Desde fuera del paquete: Podemos utilizar los objetos de un paquete siempre y cuando
haya sido declarado en la especificación del mismo. Para llamar a un objeto o
procedimiento desde fuera del paquete utilizaríamos la siguiente notación: execute
nombre_paquete.nombre_procedimiento(lista de parametros);
Declaración de cursores en paquetes
En los paquetes también podemos introducir cursores, para ello debemos declararlo en
la cabecera del paquete indicando su nombre, los parámetros y tipo devuelto. Para que
lo veáis más claro os dejo un ejemplo a continuación:
CREATE or REPLACE PACKAGE empleados AS
.....
CURSOR a RETURN empleado%ROWTYPE;
...
END empleados;

CREATE or REPLACE PACKAGE BODY empleados AS


....
CURSOR a RETURN empleado%ROWTYPE
SELECT * FROM empleado WHERE salario < 10000;
....
END empleados;
Los paquetes suministrados por Oracle son:
Standard : tiene la función to_char y abs
dbms_standard: tiene la función raise_aplication_error
dbms_output: con la función put_line
dbms_sql: que utiliza sql de forma dinámica.
NOTA: sql dinámico significa que el programa es capaz de ejecutar órdenes de
definición y manipulación sobre objetos que sólo se conocen al ejecutar el paquete.
Un ejemplo de la utilización de dbms_sql es el siguiente:
BEGIN
......
id_cursor := DBMS_SQL.OPEN_CURSOR;
DMBS_SQL.PARSE(id_cursor, instrucción,DMBS_SQL.V3);
v_dum :=DMBS_SQL.EXECUTE(id_cursor);
DMBS_SQL.CLOSE_CURSOR(id_cursor);
......
Lo que hacemos es abrir el cursor y nos devuelve el id del mismo para poder trabajar
con él.
Después tenemos el DMBS_SQL.PARSE que analiza la instrucción que se va a ejecutar.
Ya en la siguiente linea ejecutamos la sentencia y por último cerramos el cursor.
No os preocupéis si no habéis terminado de entenderlo ya que dedicaremos un articulo
completo a la utilización de DBSM_SQL.

Das könnte Ihnen auch gefallen