Tutorial de Oracle
Tutorial de Oracle
Tutorial de Oracle
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.
Algunas caracteristicas:
SQL: Structured query language.
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:
NUMBER:
LONG:
DATE:
Siglo/Año/Mes/Día/Hora/Minutos/Segundos
RAW:
Almacena cadenas de Bytes (gráficos, sonidos…)
LONGRAW:
ROWID:
Vamos a explicar cómo 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 más 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.
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.
Una vez descargado, iniciamos la instalación y lo primero que nos pedirá será 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 página de inicio de nuestra base de datos, la cual accedemos
mediante el menu inico->programas->Base de datos Oracle 10g Express Edition->página de
inicio de la base de datos, para ver la forma visual de hacer todas estas cosas.
Cuando abramos la página de inicio 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 página inicial de tu base de datos.
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.
Recurso Descripción
SESSION_PER_USER El número de sesiones concurrentes que un usuario puede tener en una instancia.
CPU_PER_SESSION El tiempo de CPU, en centenas de segundos, que una sesión puede utilizar.
El número de minutos que una sesión puede permanecer sin que sea utilizada de
IDLE_TIME manera activa.
Donde unlimited significa que no hay limite sobre un recurso particular y default significa que
coge el limite del perfil DEFAULT
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.
Donde:
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.
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
En ambos caso se utiliza la sentencia revoke para suprimir privilegios, cambiando la sintaxis.
Para los privilegios de sistema:
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.
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:
Se visualizan los objetos del diccionario de datos a los que se puede acceder.
Creación deusuarios:
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:
Modificación de usuarios:
Borrado de usuarios:
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.
Su primer carácter debe ser alfabético y el resto pueden ser letras, números y el carácter
subrayado.
Características:
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.
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.
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).
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.
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.
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.
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.
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:
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.
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:
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:
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:
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:
Insert:
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:
Update:
Actualiza los valores de las columnas para una o varias filas de una tabla:
UPDATE NOMBRETABLA
SET COLUMNA1= VALOR1, …, COLUMNAN= VALORN
WHERE CONDICION;
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:
+ = Suma
- = Resta
* = Multiplicación
/ = división
!> = 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
Obtenemos los datos de los jugadores cuyos apellidos empiecen con una "S":
SELECT APELLIDO
FROM JUGADORES
WHERE APELLIDO LIKE 'S%';
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%';
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.
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 conversión:
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:
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');
Para saber cual es el salario medio de cada departamento de la tabla Jugadores sería:
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.
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.
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:
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.
Permite combinar los resultados de varios "Select" para obtener un único resultado. Formato:
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.
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:
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.
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:
Nota: al borrar las tablas, las vistas de esas tablas no se borran y quedan inutilizadas.
Borrado de 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:
o Con filas de una sola tabla.
o Sin utilizar la cláusula GROUP BY ni DISTINCT.
o 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.
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.
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.
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;
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');
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.
IF <condición> THEN
instrucciones
ELSEIF <condición> THEN
instrucciones
....
ELSE
instrucciones
END IF;
La estructura del WHILE seria la siguiente:
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:
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.
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
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.
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]
Para cargar y ejecutar este bloque anónimo guardado en fichero ejecutaremos la siguiente
orden:
start nombrefichero
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.
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.
Para invocar al procedimiento que hemos creado antes tendríamos que ejecutar la siguiente
orden:
EXECUTE ver_usuario('Luis');
BEGIN
ver_usuario('Luis');
END;
.
Como en cualquier lenguaje, podemos agregar comentarios a nuestros procedimientos de la
siguiente forma:
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:
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.
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:
AND
OR
Lógicos 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:
1. 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.
2. 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)
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:
Parámetros
Todos los subprogramas utilizan parámetros para pasar y recibir información.
Dentro de los parámetros podemos distinguir dos tipos:
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.
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 parámetro actuá como
IN una constante. Puede ser una variable, constante, literal o expresión.
Permite devolver valores al bloque que llamó al subprograma. Dentro del subprograma, el
OUT 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 del subprograma, el
IN parámetro actuá como variable inicializada. Puede intervenir otras expresiones. El valor actual
OUT debe ser una variable.
Para volver a compilar un subprograma almacenado utilizaremos la orden ALTER en vez del
CREATE y su formato es el siguiente:
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.
1. Declaración del cursor: lo tenemos que declarar en la zona de declaraciones, con el siguiente
formato:CURSOR <nombrecursor> IS <sentencia SELECT>;
2. 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.
3. 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.
4. - 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á.
%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á.
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.
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.
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:
DECLARE
...
CURSOR C1 (vpeso number, vestatura number DEFAULT 170) is select nficha, nombre FROM
emple WHERE estatura=vestatura AND peso=vpeso;
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.
Para realizar una actualización con un cursor tenemos que añadir la siguiente FOR UPDATE al final de la
declaración del cursor:
Subir el salario a todos los empleados del departamento indicado en la llamada. El porcentaje se
indicará también en la llamada.
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.
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:
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:
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.
Control de transacciones
Por Sara Alvarez
06 de noviembre de 2009
0 Comentarios
Oracle
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.
Un ejemplo:
BEGIN
....
...
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:
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.
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.
1. Antes de comenzar a ejecutar la orden que provoca el disparo se ejecutaran los triggers del tipo before.... for
each statement
2. 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
3. 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:
En Oracle para crear este tipo de trigger tenemos que tener privilegios de Administer database
trigger.
DLL BEFORE | AFTER Antes o después de ejecutar cualquier comando de 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:
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.
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:
/* 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 */
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:
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 línea ejecutamos la sentencia y por último cerramos el cursor.