Está en la página 1de 150

1 - Instalacin de Oracle.

Para este curso utilizaremos la versin Oracle 10g XE (Express Edition para Windows) Para descargar el mismo debemos ingresar al sitio de Oracle:
1. Oracle 10g XE 2. Para permitir descargarlo del sitio seleccionamos con el mouse el control Radio "Accept License Agreement". 3. Luego seleccionamos la versin "Oracle Database 10g Express Edition (Universal)" (OracleXEUniv.exe (216,933,372 bytes)) 4. El sitio de Oracle requiere que nos registremos. Debemos seleccionar "sign up now" y luego "Create your Oracle account now", es decir crear una cuenta Oracle. Luego de habernos registrado podemos descargar el motor de base de datos Oracle. 5. El paso siguiente es instalar el gestor de base de datos propiamente dicho. Ejecutamos el archivo que acabamos de descargar: OracleXEUniv.exe Debemos ir presionando el botn "siguiente" en el asistente de instalacin, salvo cuando nos pide ingresar la contrasea de la base de datos, es importante no olvidar dicha clave. Luego de algunos minutos ya tenemos instalado el gestor de bases de datos Oracle en nuestro equipo.

La segunda aplicacin que instalaremos ser el "Oracle SQL Developer". Es un entorno visual que nos permite comunicar con nuestro gestor de base de datos Oracle. Desde este entorno aprenderemos a administrar una base de datos Oracle.
1. Debemos ingresar a la siguiente pgina para descargar el Oracle SQL Developer 2. Aceptamos la licencia y seleccionamos "Oracle SQL Developer for Windows (JDK1.5.0_06 is bundled in this zip) 3. Luego de descargar el archivo procedemos a descomprimir el archivo zip en una carpeta (este programa no requiere instalacin) 4. En la carpeta donde descomprimimos debemos ejecutar el archivo sqldeveloper.exe

2 - Crear tablas (create table - describe - all_tables drop table)


Existen varios objetos de base de datos: tablas, constraints (restricciones), vistas, secuencias, ndices, agrupamientos (clusters), disparadores (triggers), instantaneas (snapshots), procedimientos, funciones, paquetes, sinnimos, usuarios, perfiles, privilegios, roles, etc. Los primeros objetos que veremos son tablas. Una base de datos almacena su informacin en tablas, que es la unidad bsica de almacenamiento. Una tabla es una estructura de datos que organiza los datos en columnas y filas; cada columna es un campo (o atributo) y cada fila, un registro. La interseccin de una columna con una fila, contiene un dato especfico, un solo valor. Cada registro contiene un dato por cada columna de la tabla. Cada campo (columna) debe tener un nombre. El nombre del campo hace referencia a la informacin que almacenar. Cada campo (columna) tambin debe definir el tipo de dato que almacenar. Las tablas forman parte de una base de datos. Nosotros trabajaremos con la base de datos ya creada. Para ver las tablas existentes tipeamos:
select *from all_tables;

Aparece una tabla que nos muestra en cada fila, los datos de una tabla especfica; en la columna "TABLE_NAME" aparece el nombre de cada tabla existente. Al crear una tabla debemos resolver qu campos (columnas) tendr y que tipo de datos almacenarn cada uno de ellos, es decir, su estructura. La sintaxis bsica y general para crear una tabla es la siguiente:
create table NOMBRETABLA( NOMBRECAMPO1 TIPODEDATO, ... NOMBRECAMPON TIPODEDATO );

La tabla debe ser definida con un nombre que la identifique y con el cual accederemos a ella. Creamos una tabla llamada "usuarios" y entre parntesis definimos los campos y sus tipos:

create table usuarios( nombre varchar2(30), clave varchar2(10) );

Cada campo con su tipo debe separarse con comas de los siguientes, excepto el ltimo. Cuando se crea una tabla debemos indicar su nombre y definir al menos un campo con su tipo de dato. En esta tabla "usuarios" definimos 2 campos: - nombre: que contendr una cadena de caracteres de 30 caracteres de longitud, que almacenar el nombre de usuario y - clave: otra cadena de caracteres de 10 de longitud, que guardar la clave de cada usuario. Cada usuario ocupar un registro de esta tabla, con su respectivo nombre y clave. Para nombres de tablas, se puede utilizar cualquier caracter permitido para nombres de directorios, el primero debe ser un caracter alfabtico y no puede contener espacios. La longitud mxima es de 30 caracteres. Si intentamos crear una tabla con un nombre ya existente (existe otra tabla con ese nombre), mostrar un mensaje indicando que a tal nombre ya lo est utilizando otro objeto y la sentencia no se ejecutar. Para ver la estructura de una tabla usamos el comando "describe" junto al nombre de la tabla:
describe usuarios;

Aparece la siguiente informacin:


Name Null Type ------------------------------NOMBRE VARCHAR2(30) CLAVE VARCHAR2(10)

Esta es la estructura de la tabla "usuarios"; nos muestra cada campo, su tipo y longitud y otros valores que no analizaremos por el momento. Para eliminar una tabla usamos "drop table" junto al nombre de la tabla a eliminar:
drop table NOMBRETABLA;

En el siguiente ejemplo eliminamos la tabla "usuarios":


drop table usuarios;

Si intentamos eliminar una tabla que no existe, aparece un mensaje de error indicando tal situacin y la sentencia no se ejecuta.

3 - Ingresar registros (insert into- select)


Un registro es una fila de la tabla que contiene los datos propiamente dichos. Cada registro tiene un dato por cada columna (campo). Nuestra tabla "usuarios" consta de 2 campos, "nombre" y "clave". Al ingresar los datos de cada registro debe tenerse en cuenta la cantidad y el orden de los campos. La sintaxis bsica y general es la siguiente:
insert into NOMBRETABLA (NOMBRECAMPO1, ..., NOMBRECAMPOn) values (VALORCAMPO1, ..., VALORCAMPOn);

Usamos "insert into", luego el nombre de la tabla, detallamos los nombres de los campos entre parntesis y separados por comas y luego de la clusula "values" colocamos los valores para cada campo, tambin entre parntesis y separados por comas. En el siguiente ejemplo se agrega un registro a la tabla "usuarios", en el campo "nombre" se almacenar "Mariano" y en el campo "clave" se guardar "payaso":
insert into usuarios (nombre, clave) values ('Mariano','payaso');

Luego de cada insercin aparece un mensaje indicando la cantidad de registros ingresados. Note que los datos ingresados, como corresponden a cadenas de caracteres se colocan entre comillas simples. Para ver los registros de una tabla usamos "select":
select *from usuarios;

El comando "select" recupera los registros de una tabla. Con el asterisco indicamos que muestre todos los campos de la tabla "usuarios". Aparece la tabla, sus campos y registros ingresados; si no tiene registros, apareceran solamente los campos y la tabla vaca).

Es importante ingresar los valores en el mismo orden en que se nombran los campos: En el siguiente ejemplo se lista primero el campo "clave" y luego el campo "nombre" por eso, los valores tambin se colocan en ese orden:
insert into usuarios (clave, nombre) values ('River','Juan');

Si ingresamos los datos en un orden distinto al orden en que se nombraron los campos, no aparece un mensaje de error y los datos se guardan de modo incorrecto. En el siguiente ejemplo se colocan los valores en distinto orden en que se nombran los campos, el valor de la clave (la cadena "Boca") se guardar en el campo "nombre" y el valor del nombre (la cadena "Luis") en el campo "clave":
insert into usuarios (nombre,clave) values ('Boca','Luis');

4 - Tipos de datos
Ya explicamos que al crear una tabla debemos resolver qu campos (columnas) tendr y que tipo de datos almacenar cada uno de ellos, es decir, su estructura. El tipo de dato especifica el tipo de informacin que puede guardar un campo: caracteres, nmeros, etc. Estos son algunos tipos de datos bsicos de Oracle (posteriormente veremos otros y con ms detalle):

- varchar2: se emplea para almacenar cadenas de caracteres. Una cadena es una secuencia de caracteres. Se coloca entre comillas simples; ejemplo: 'Hola', 'Juan Perez', 'Colon 123'. Este tipo de dato definen una cadena de longitud variable en la cual determinamos el mximo de caracteres entre parntesis. Puede guardar hasta xxx caracteres. Por ejemplo, para almacenar cadenas de hasta 30 caracteres, definimos un campo de tipo varchar2 (30), es decir, entre parntesis, junto al nombre del campo colocamos la longitud. Si intentamos almacenar una cadena de caracteres de mayor longitud que la definida, la cadena no se carga, aparece un mensaje indicando tal situacin y la sentencia no se ejecuta. Por ejemplo, si definimos un campo de tipo varchar(10) e intentamos almacenar en l la cadena 'Buenas tardes', aparece un mensaje indicando que el valor es demasiado grande para la columna. - number(p,s): se usa para guardar valores numricos con decimales, de 1.0 x10120 a 9.9...(38 posiciones). Definimos campos de este tipo cuando queremos almacenar valores numricos con los cuales luego realizaremos operaciones

matemticas, por ejemplo, cantidades, precios, etc. Puede contener nmeros enteros o decimales, positivos o negativos. El parmetro "p" indica la precisin, es decir, el nmero de dgitos en total (contando los decimales) que contendr el nmero como mximo. El parmetro "s" especifica la escala, es decir, el mximo de dgitos decimales. Por ejemplo, un campo definido "number(5,2)" puede contener cualquier nmero entre 0.00 y 999.99 (positivo o negativo). Para especificar nmero enteros, podemos omitir el parmetro "s" o colocar el valor 0 como parmetro "s". Se utiliza como separador el punto (.). Si intentamos almacenar un valor mayor fuera del rango permitido al definirlo, tal valor no se carga, aparece un mensaje indicando tal situacin y la sentencia no se ejecuta. Por ejemplo, si definimos un campo de tipo number(4,2) e intentamos guardar el valor 123.45, aparece un mensaje indicando que el valor es demasiado grande para la columna. Si ingresamos un valor con ms decimales que los definidos, el valor se carga pero con la cantidad de decimales permitidos, los dgitos sobrantes se omiten. Antes de crear una tabla debemos pensar en sus campos y optar por el tipo de dato adecuado para cada uno de ellos. Por ejemplo, si en un campo almacenaremos nmeros telefnicos o un nmeros de documento, usamos "varchar2", no "number" porque si bien son dgitos, con ellos no realizamos operaciones matemticas. Si en un campo guardaremos apellidos, y suponemos que ningn apellido superar los 20 caracteres, definimos el campo "varchar2(20)". Si en un campo almacenaremos precios con dos decimales que no superarn los 999.99 pesos definimos un campo de tipo "number(5,2)", es decir, 5 dgitos en total, con 2 decimales. Si en un campo almacenaremos valores enteros de no ms de 3 dgitos, definimos un campo de tipo "number(3,0)".

5 - Recuperar algunos campos (select)


Hemos aprendido cmo ver todos los registros de una tabla, empleando la instruccin "select". La sintaxis bsica y general es la siguiente:
select *from NOMBRETABLA;

El asterisco (*) indica que se seleccionan todos los campos de la tabla. Podemos especificar el nombre de los campos que queremos ver, separndolos por comas:
select titulo,autor from libros;

La lista de campos luego del "select" selecciona los datos correspondientes a los campos nombrados. En el ejemplo anterior seleccionamos los campos "titulo" y "autor" de la tabla "libros", mostrando todos los registros.

6 - Recuperar algunos registros (where)


Hemos aprendido a seleccionar algunos campos de una tabla. Tambin es posible recuperar algunos registros. Existe una clusula, "where" con la cual podemos especificar condiciones para una consulta "select". Es decir, podemos recuperar algunos registros, slo los que cumplan con ciertas condiciones indicadas con la clusula "where". Por ejemplo, queremos ver el usuario cuyo nombre es "Marcelo", para ello utilizamos "where" y luego de ella, la condicin:
select nombre, clave from usuarios where nombre='Marcelo';

La sintaxis bsica y general es la siguiente:


select NOMBRECAMPO1, ..., NOMBRECAMPOn from NOMBRETABLA where CONDICION;

Para las condiciones se utilizan operadores relacionales (tema que trataremos ms adelante en detalle). El signo igual(=) es un operador relacional. Para la siguiente seleccin de

registros especificamos una condicin que solicita los usuarios cuya clave es igual a "River":
select nombre,clave from usuarios where clave='River';

Si ningn registro cumple la condicin establecida con el "where", no aparecer ningn registro. Entonces, con "where" establecemos condiciones para recuperar algunos registros. Para recuperar algunos campos de algunos registros combinamos en la consulta la lista de campos y la clusula "where":
select nombre from usuarios where clave='River';

En la consulta anterior solicitamos el nombre de todos los usuarios cuya clave sea igual a "River".

7 - Operadores relacionales
Los operadores son smbolos que permiten realizar operaciones matemticas, concatenar cadenas, hacer comparaciones. Oracle reconoce de 4 tipos de operadores:
1) 2) 3) 4) relacionales (o de comparacin) aritmticos de concatenacin lgicos

Por ahora veremos solamente los primeros. Los operadores relacionales (o de comparacin) nos permiten comparar dos expresiones, que pueden ser variables, valores de campos, etc. Hemos aprendido a especificar condiciones de igualdad para seleccionar registros de una tabla; por ejemplo:
select *from libros where autor='Borges';

Utilizamos el operador relacional de igualdad. Los operadores relacionales vinculan un campo con un valor para que Oracle compare cada registro (el campo especificado) con el valor dado. Los operadores relacionales son los siguientes:
= <> > < >= <= igual distinto mayor menor mayor o igual menor o igual

Podemos seleccionar los registros cuyo autor sea diferente de "Borges", para ello usamos la condicin:
select * from libros where autor<>'Borges';

Podemos comparar valores numricos. Por ejemplo, queremos mostrar los ttulos y precios de los libros cuyo precio sea mayor a 20 pesos:
select titulo, precio from libros where precio>20;

Queremos seleccionar los libros cuyo precio sea menor o igual a 30:
select *from libros where precio<=30;

Los operadores relacionales comparan valores del mismo tipo. Se emplean para comprobar si un campo cumple con una condicin. No son los nicos, existen otros que veremos mas adelante.

8 - Borrar registros (delete)


Para eliminar los registros de una tabla usamos el comando "delete". Sintaxis bsica:
delete from NOMBRETABLA;

Se coloca el comando delete seguido de la palabra clave "from" y el nombre de la tabla de la cual queremos eliminar los registros. En el siguiente ejemplo se eliminan los registros de la tabla "usuarios":
delete from usuarios;

Luego, un mensaje indica la cantidad de registros que se han eliminado. Si no queremos eliminar todos los registros, sino solamente algunos, debemos indicar cul o cules; para ello utilizamos el comando "delete" junto con la clausula "where" con la cual establecemos la condicin que deben cumplir los registros a borrar. Por ejemplo, queremos eliminar aquel registro cuyo nombre de usuario es "Marcelo":
delete from usuarios where nombre='Marcelo';

Si solicitamos el borrado de un registro que no existe, es decir, ningn registro cumple con la condicin especificada, aparecer un mensaje indicando que ningn registro fue eliminado, pues no encontr registros con ese dato. Tenga en cuenta que si no colocamos una condicin, se eliminan todos los registros de la tabla especificada.

9 - Actualizar registros (update)


Decimos que actualizamos un registro cuando modificamos alguno de sus valores. Para modificar uno o varios datos de uno o varios registros utilizamos "update" (actualizar). Sintaxis bsica:
update NOMBRETABLA set CAMPO=NUEVOVALOR;

Utilizamos "update" junto al nombre de la tabla y "set" junto con el campo a modificar y su nuevo valor. El cambio afectar a todos los registros. Por ejemplo, en nuestra tabla "usuarios", queremos cambiar los valores de todas las claves, por "RealMadrid":
update usuarios set clave='RealMadrid';

Podemos modificar algunos registros, para ello debemos establecer condiciones de seleccin con "where". Por ejemplo, queremos cambiar el valor correspondiente a la clave de nuestro usuario llamado "Federicolopez", queremos como nueva clave "Boca", necesitamos una condicin "where" que afecte solamente a este registro:
update usuarios set clave='Boca' where nombre='Federicolopez';

Si Oracle no encuentra registros que cumplan con la condicin del "where", un mensaje indica que ningn registro fue modificado. Las condiciones no son obligatorias, pero si omitimos la clusula "where", la actualizacin afectar a todos los registros. Tambin podemos actualizar varios campos en una sola instruccin:
update usuarios set nombre='Marceloduarte', clave='Marce' where nombre='Marcelo';

Para ello colocamos "update", el nombre de la tabla, "set" junto al nombre del campo y el nuevo valor y separado por coma, el otro nombre del campo con su nuevo valor.

10 - Comentarios
Para aclarar algunas instrucciones, en ocasiones, necesitamos agregar comentarios. Es posible ingresar comentarios en la lnea de comandos, es decir, un texto que no se ejecuta; para ello se emplean dos guiones (--):
select *from libros;--mostramos los registros de libros

en la lnea anterior, todo lo que est luego de los guiones (hacia la derecha) no se ejecuta. Para agregar varias lneas de comentarios, se coloca una barra seguida de un asterisco (/*) al comienzo del bloque de comentario y al finalizarlo, un asterisco seguido de una barra (*/)
select titulo, autor /*mostramos ttulos y nombres de los autores*/ from libros;

todo lo que est entre los smbolos "/*" y "*/" no se ejecuta.

11 - Valores nulos (null)


"null' significa "dato desconocido" o "valor inexistente". A veces, puede desconocerse o no existir el dato correspondiente a algn campo de un registro. En estos casos decimos que el campo puede contener valores nulos. Por ejemplo, en nuestra tabla de libros, podemos tener valores nulos en el campo "precio" porque es posible que para algunos libros no le hayamos establecido el precio para la venta. En contraposicin, tenemos campos que no pueden estar vacos jams. Veamos un ejemplo. Tenemos nuestra tabla "libros". El campo "titulo" no debera estar vaco nunca, igualmente el campo "autor". Para ello, al crear la tabla, debemos especificar que tales campos no admitan valores nulos:
create table libros( titulo varchar2(30) not null, autor varchar2(20) not null, editorial varchar2(15) null, precio number(5,2) );

Para especificar que un campo NO admita valores nulos, debemos colocar "not null" luego de la definicin del campo. En el ejemplo anterior, los campos "editorial" y "precio" si admiten valores nulos. Cuando colocamos "null" estamos diciendo que admite valores nulos (caso del campo "editorial"); por defecto, es decir, si no lo aclaramos, los campos permiten valores nulos (caso del campo "precio"). Cualquier campo, de cualquier tipo de dato permite ser definido para aceptar o no valores nulos. Un valor "null" NO es lo mismo que un valor 0 (cero) o una cadena de espacios en blanco (" "). Si ingresamos los datos de un libro, para el cual an no hemos definido el precio podemos colocar "null" para mostrar que no tiene precio:
insert into libros (titulo,autor,editorial,precio) values('El aleph','Borges','Emece',null);

Note que el valor "null" no es una cadena de caracteres, NO se coloca entre comillas.

Entonces, si un campo acepta valores nulos, podemos ingresar "null" cuando no conocemos el valor. Tambin podemos colocar "null" en el campo "editorial" si desconocemos el nombre de la editorial a la cual pertenece el libro que vamos a ingresar:
insert into libros (titulo,autor,editorial,precio) values('Alicia en el pais','Lewis Carroll',null,25);

Una cadena vaca es interpretada por Oracle como valor nulo; por lo tanto, si ingresamos una cadena vaca, se almacena el valor "null". Si intentamos ingresar el valor "null" (o una cadena vaca) en campos que no admiten valores nulos (como "titulo" o "autor"), Oracle no lo permite, muestra un mensaje y la insercin no se realiza; por ejemplo:
insert into libros (titulo,autor,editorial,precio) values(null,'Borges','Siglo XXI',25);

Cuando vemos la estructura de una tabla con "describe", en la columna "Null", aparece "NOT NULL" si el campo no admite valores nulos y no aparece en caso que si los permita. Para recuperar los registros que contengan el valor "null" en algn campo, no podemos utilizar los operadores relacionales vistos anteriormente: = (igual) y <> (distinto); debemos utilizar los operadores "is null" (es igual a null) y "is not null" (no es null). Los valores nulos no se muestran, aparece el campo vaco. Entonces, para que un campo no permita valores nulos debemos especificarlo luego de definir el campo, agregando "not null". Por defecto, los campos permiten valores nulos, pero podemos especificarlo igualmente agregando "null".

12 - Operadores relacionales (is null)


Para recuperar los registros que contengan el valor "null" en algn campo, no podemos utilizar los operadores relacionales vistos anteriormente: = (igual) y <> (distinto); debemos utilizar los operadores "is null" (es igual a null) y "is not null" (no es null). Con la siguiente sentencia recuperamos los libros que contienen valor nulo en el campo "editorial":
select *from libros where editorial is null;

Recuerde que los valores nulos no se muestran, aparece el campo vaco. Las siguientes sentencias tendrn una salida diferente:
select *from libros where editorial is null; select *from libros where editorial=' ';

Con la primera sentencia veremos los libros cuya editorial almacena el valor "null" (desconocido); con la segunda, los libros cuya editorial guarda una cadena de 3 espacios en blanco. Para obtener los registros que no contienen "null", se puede emplear "is not null", esto mostrar los registros con valores conocidos. Para ver los libros que NO tienen valor "null" en el campo "precio" tipeamos:
select *from libros where precio is not null;

13 - Clave primaria (primary key)


Una clave primaria es un campo (o varios) que identifica un solo registro (fila) en una tabla. Para un valor del campo clave existe solamente un registro. Veamos un ejemplo, si tenemos una tabla con datos de personas, el nmero de documento puede establecerse como clave primaria, es un valor que no se repite; puede haber personas con igual apellido y nombre, incluso el mismo domicilio (padre e hijo por ejemplo), pero su documento ser siempre distinto. Si tenemos la tabla "usuarios", el nombre de cada usuario puede establecerse como clave primaria, es un valor que no se repite; puede haber usuarios con igual clave, pero su nombre de usuario ser siempre diferente. Podemos establecer que un campo sea clave primaria al momento de crear la tabla o luego que ha sido creada. Vamos a aprender a establecerla al crear la tabla. No existe una nica manera de hacerlo, por ahora veremos la sintaxis ms sencilla. Tenemos nuestra tabla "usuarios" definida con 2 campos ("nombre" y "clave"). La sintaxis bsica y general es la siguiente:
create table NOMBRETABLA( CAMPO TIPO, ..., CAMPO TIPO,

PRIMARY KEY (CAMPO) );

Lo que hacemos agregar, luego de la definicin de cada campo, "primary key" y entre parntesis, el nombre del campo que ser clave primaria. En el siguiente ejemplo definimos una clave primaria, para nuestra tabla "usuarios" para asegurarnos que cada usuario tendr un nombre diferente y nico:
create table usuarios( nombre varchar2(20), clave varchar2(10), primary key(nombre) );

Una tabla slo puede tener una clave primaria. Cualquier campo (de cualquier tipo) puede ser clave primaria, debe cumplir como requisito, que sus valores no se repitan ni sean nulos. Por ello, al definir un campo como clave primaria, automticamente Oracle lo convierte a "not null". Luego de haber establecido un campo como clave primaria, al ingresar los registros, Oracle controla que los valores para el campo establecido como clave primaria no estn repetidos en la tabla; si estuviesen repetidos, muestra un mensaje y la insercin no se realiza. Es decir, si en nuestra tabla "usuarios" ya existe un usuario con nombre "juanperez" e intentamos ingresar un nuevo usuario con nombre "juanperez", aparece un mensaje y la instruccin "insert" no se ejecuta. Igualmente, si realizamos una actualizacin, Oracle controla que los valores para el campo establecido como clave primaria no estn repetidos en la tabla, si lo estuviese, aparece un mensaje indicando que se viola la clave primaria y la actualizacin no se realiza. Podemos ver el campo establecido como clave primaria de una tabla realizando la siguiente consulta:
select uc.table_name, column_name from user_cons_columns ucc join user_constraints uc on ucc.constraint_name=uc.constraint_name where uc.constraint_type='P' and uc.table_name='USUARIOS';

No explicaremos la consulta anterior por el momento, slo la ejecutaremos; si la consulta retorna una tabla vaca, significa que la tabla especificada no tiene clave primaria. El nombre de la tabla DEBE ir en maysculas, sino Oracle no la encontrar.

14 - Vaciar la tabla (truncate table)

Aprendimos que para borrar todos los registro de una tabla se usa "delete" sin condicin "where". Tambin podemos eliminar todos los registros de una tabla con "truncate table". Sintaxis:
truncate table NOMBRETABLA;

Por ejemplo, queremos vaciar la tabla "libros", usamos:


truncate table libros;

La sentencia "truncate table" vaca la tabla (elimina todos los registros) y conserva la estructura de la tabla. La diferencia con "drop table" es que esta sentencia elimina la tabla, no solamente los registros, "truncate table" la vaca de registros. La diferencia con "delete" es la siguiente, al emplear "delete", Oracle guarda una copia de los registros borrados y son recuperables, con "truncate table" no es posible la recuperacin porque se libera todo el espacio en disco ocupado por la tabla; por lo tanto, "truncate table" es ms rpido que "delete" (se nota cuando la cantidad de registros es muy grande).

15 - Tipos de datos alfanumricos


Ya explicamos que al crear una tabla debemos elegir la estructura adecuada, esto es, definir los campos y sus tipos ms precisos, segn el caso. Para almacenar valores alfanumricos (texto) usamos cadenas de caracteres. Las cadenas se colocan entre comillas simples. Podemos almacenar letras, smbolos y dgitos con los que no se realizan operaciones matemticas, por ejemplo, cdigos de identificacin, nmeros de documentos, nmeros telefnicos. Tenemos los siguientes tipos: 1) char(x): define una cadena de caracteres de longitud fija determinada por el argumento "x". Si se omite el argumento, por defecto coloca 1. "char" viene de character, que significa caracter en ingls. Su rango es de 1 a 2000 caracteres. Que sea una cadena de longitud fija significa que, si definimos un campo como "char(10)" y almacenamos el valor "hola" (4 caracteres), Oracle rellenar las 6 posiciones restantes con espacios, es decir, ocupar las 10 posiciones; por lo tanto, si la longitud es invariable, es conveniente utilizar el tipo char; caso contrario, el tipo varchar2. Si almacenamos "hola" en un campo definido "char(10)" Oracle almacenar "hola ".

2) varchar2(x): almacena cadenas de caracteres de longitud variable determinada por el argumento "x" (obligatorio). Que sea una cadena de longitud variable significa que, si definimos un campo como "varchar2(10)" y almacenamos el valor "hola" (4 caracteres), Oracle solamente ocupa las 4 posiciones (4 bytes y no 10 como en el caso de "char"); por lo tanto, si la longitud es variable, es conveniente utilizar este tipo de dato y no "char", as ocupamos menos espacio de almacenamiento en disco. Su rango es de 1 a 4000 caracteres. 3) nchar(x): es similar a "char" excepto que permite almacenar caracteres ASCII, EBCDIC y Unicode; su rango va de 1 a 1000 caracteres porque se emplean 2 bytes por cada caracter. 4) nvarchar2(x): es similar a "varchar2", excepto que permite almacenar caracteres Unicode; su rango va de 1 a 2000 caracteres porque se emplean 2 bytes por cada caracter. 5 y 6) varchar(x) y char2(x): disponibles en Oracle8. 7) long: guarda caracteres de longitud variable; puede contener hasta 2000000000 caracteres (2 Gb). No admite argumento para especificar su longitud. En Oracle8 y siguientes versiones conviene emplear "clob" y "nlob" para almacenar grandes cantidades de datos alfanumricos. En general se usarn los 2 primeros. Si intentamos almacenar en un campo alfanumrico una cadena de caracteres de mayor longitud que la definida, aparece un mensaje indicando que el valor es demasiado grande y la sentencia no se ejecuta. Por ejemplo, si definimos un campo de tipo varchar2(10) y le asignamos la cadena 'Aprenda PHP' (11 caracteres), aparece un mensaje y la sentencia no se ejecuta. Si ingresamos un valor numrico (omitiendo las comillas), lo convierte a cadena y lo ingresa como tal. Por ejemplo, si en un campo definido como varchar2(5) ingresamos el valor 12345, lo toma como si hubisemos tipeado '12345', igualmente, si ingresamos el valor 23.56, lo convierte a '23.56'. Si el valor numrico, al ser convertido a cadena supera la longitud definida, aparece un mensaje de error y la sentencia no se ejecuta. Es importante elegir el tipo de dato adecuado segn el caso. Para almacenar cadenas que varan en su longitud, es decir, no todos los registros tendrn la misma longitud en un campo determinado, se emplea "varchar2" en lugar de "char". Por ejemplo, en campos que guardamos nombres y apellidos, no todos los nombres y apellidos tienen la misma longitud.

Para almacenar cadenas que no varan en su longitud, es decir, todos los registros tendrn la misma longitud en un campo determinado, se emplea "char". Por ejemplo, definimos un campo "codigo" que constar de 5 caracteres, todos los registros tendrn un cdigo de 5 caracteres, ni ms ni menos. Para almacenar valores superiores a 4000 caracteres se debe emplear "long".

16 - Tipos de datos numricos


Ya explicamos que al crear una tabla debemos elegir la estructura adecuada, esto es, definir los campos y sus tipos ms precisos, segn el caso. Los valores numricos no se ingresan entre comillas. Se utiliza el punto como separador de decimales. Para almacenar valores NUMERICOS Oracle dispone de dos tipos de datos: 1) number(t,d): para almacenar valores enteros o decimales, positivos o negativos. Su rango va de 1.0 x 10-130 hasta 9.999...(38 nueves). Definimos campos de este tipo cuando queremos almacenar valores numricos con los cuales luego realizaremos operaciones matemticas, por ejemplo, cantidades, precios, etc. El parmetro "t" indica el nmero total de dgitos (contando los decimales) que contendr el nmero como mximo (es la precisin). Su rango va de 1 a 38. El parmetro "d" indica el mximo de dgitos decimales (escala). La escala puede ir de -84 a 127. Para definir nmero enteros, se puede omitir el parmetro "d" o colocar un 0. Un campo definido "number(5,2)" puede contener cualquier nmero entre -999.99 y 999.99. Para especificar nmero enteros, podemos omitir el parmetro "d" o colocar el valor 0. Si intentamos almacenar un valor mayor fuera del rango permitido al definirlo, tal valor no se carga, aparece un mensaje indicando tal situacin y la sentencia no se ejecuta. Por ejemplo, si definimos un campo de tipo "number(4,2)" e intentamos guardar el valor 123.45, aparece un mensaje indicando que el valor es demasiado grande para la columna. Si ingresamos un valor con ms decimales que los definidos, el valor se carga pero con la cantidad de decimales permitidos, los dgitos sobrantes se omiten. 2) float (x): almacena un nmero en punto decimal. El parmetro indica la precisin binaria mxima; con un rango de 1 a 126. Si se omite, por defecto es 126. Para ambos tipos numricos:

- si ingresamos un valor con ms decimales que los permitidos, redondea al ms cercano; por ejemplo, si definimos "float(4,2)" e ingresamos el valor "12.686", guardar "12.69", redondeando hacia arriba; si ingresamos el valor "12.682", guardar "12.67", redondeando hacia abajo. - si intentamos ingresar un valor fuera de rango, no lo acepta. - si ingresamos una cadena, Oracle intenta convertirla a valor numrico, si dicha cadena consta solamente de dgitos, la conversin se realiza, luego verifica si est dentro del rango, si es as, la ingresa, sino, muestra un mensaje de error y no ejecuta la sentencia. Si la cadena contiene caracteres que Oracle no puede convertir a valor numrico, muestra un mensaje de error y la sentencia no se ejecuta. Por ejemplo, definimos un campo de tipo "numberl(5,2)", si ingresamos la cadena '12.22', la convierte al valor numrico 12.22 y la ingresa; si intentamos ingresar la cadena '1234.56', la convierte al valor numrico 1234.56, pero como el mximo valor permitido es 999.99, muestra un mensaje indicando que est fuera de rango. Si intentamos ingresar el valor '12y.25', Oracle no puede realizar la conversin y muestra un mensaje de error.

17 - Ingresar algunos campos


Hemos aprendido a ingresar registros listando todos los campos y colocando valores para todos y cada uno de ellos luego de "values". Si ingresamos valores para todos los campos, podemos omitir la lista de nombres de los campos. Por ejemplo, si tenemos creada la tabla "libros" con los campos "titulo", "autor" y "editorial", podemos ingresar un registro de la siguiente manera:
insert into libros values ('Uno','Richard Bach','Planeta');

Tambin es posible ingresar valores para algunos campos. Ingresamos valores solamente para los campos "titulo" y "autor":
insert into libros (titulo, autor) values ('El aleph','Borges');

Oracle almacenar el valor "null" en el campo "editorial", para el cual no hemos explicitado un valor. Al ingresar registros debemos tener en cuenta:

- la lista de campos debe coincidir en cantidad y tipo de valores con la lista de valores luego de "values". Si se listan ms (o menos) campos que los valores ingresados, aparece un mensaje de error y la sentencia no se ejecuta. - si ingresamos valores para todos los campos podemos obviar la lista de campos. - podemos omitir valores para los campos que permitan valores nulos (se guardar "null"); si omitimos el valor para un campo "not null", la sentencia no se ejecuta.

18 - Valores por defecto (default)


Hemos visto que si al insertar registros no se especifica un valor para un campo que admite valores nulos, se ingresa automticamente "null". A este valor se le denomina valor por defecto o predeterminado. Un valor por defecto se inserta cuando no est presente al ingresar un registro. Para campos de cualquier tipo no declarados "not null", es decir, que admiten valores nulos, el valor por defecto es "null". Para campos declarados "not null", no existe valor por defecto, a menos que se declare explcitamente con la clusula "default". Podemos establecer valores por defecto para los campos cuando creamos la tabla. Para ello utilizamos "default" al definir el campo. Por ejemplo, queremos que el valor por defecto del campo "autor" de la tabla "libros" sea "Desconocido" y el valor por defecto del campo "cantidad" sea "0":
create table libros( titulo varchar2(40) not null, autor varchar2(30) default 'Desconocido' not null, editorial varchar2(20), precio number(5,2), cantidad number(3) default 0 );

Si al ingresar un nuevo registro omitimos los valores para el campo "autor" y "cantidad", Oracle insertar los valores por defecto; en "autor" colocar "Desconocido" y en cantidad "0". Entonces, si al definir el campo explicitamos un valor mediante la clusula "default", se ser el valor por defecto. La clusula "default" debe ir antes de "not null" (si existiese), sino aparece un mensaje de error.

Para ver si los campos de la tabla "libros" tiene definidos valores por defecto y cules son, podemos realizar la siguiente consulta:
select column_name,nullable,data_default from user_tab_columns where TABLE_NAME = 'libros';

Muestra una fila por cada campo, en la columna "data_default" aparece el valor por defecto (si lo tiene), en la columna "nullable" aparece "N" si el campo no est definido "not null" y "Y" si admite valores "null". Tambin se puede utilizar "default" para dar el valor por defecto a los campos en sentencias "insert", por ejemplo:
insert into libros (titulo,autor,editorial,precio,cantidad) values ('El gato con botas',default,default,default,100);

Entonces, la clusula "default" permite especificar el valor por defecto de un campo. Si no se explicita, el valor por defecto es "null", siempre que el campo no haya sido declarado "not null". Los campos para los cuales no se ingresan valores en un "insert" tomarn los valores por defecto: - si permite valores nulos y no tiene clusula "default", almacenar "null"; - si tiene clusula "default" (admita o no valores nulos), el valor definido como predeterminado; - si est declarado explcitamente "not null" y no tiene valor "default", no hay valor por defecto, as que causar un error y el "insert" no se ejecutar. Un campo slo puede tener un valor por defecto. Una tabla puede tener todos sus campos con valores por defecto. Que un campo tenga valor por defecto no significa que no admita valores nulos, puede o no admitirlos. Un campo definido como clave primaria acepta un valor "default", pero no tiene sentido ya que el valor por defecto solamente podr ingresarse una vez; si intenta ingresarse cuando otro registro ya lo tiene almacenado, aparecer un mensaje de error indicando que se intenta duplicar la clave.

19 - Operadores aritmticos y de concatenacin (columnas calculadas)


Aprendimos que los operadores son smbolos que permiten realizar distintos tipos de operaciones. Dijimos que Oracle tiene 4 tipos de operadores: 1) relacionales o de comparacin (los vimos), 2) aritmticos, 3) de concatenacin y 4) lgicos (lo veremos ms adelante). Los operadores aritmticos permiten realizar clculos con valores numricos. Son: multiplicacin (*), divisin (/), suma (+) y resta (-). Es posible obtener salidas en las cuales una columna sea el resultado de un clculo y no un campo de una tabla. Si queremos ver los ttulos, precio y cantidad de cada libro escribimos la siguiente sentencia:
select titulo,precio,cantidad from libros;

Si queremos saber el monto total en dinero de un ttulo podemos multiplicar el precio por la cantidad por cada ttulo, pero tambin podemos hacer que Oracle realice el clculo y lo incluya en una columna extra en la salida:
select titulo, precio,cantidad, precio*cantidad from libros;

Si queremos saber el precio de cada libro con un 10% de descuento podemos incluir en la sentencia los siguientes clculos:
select titulo,precio, precio-(precio*0.1) from libros;

Tambin podemos actualizar los datos empleando operadores aritmticos:


update libros set precio=precio-(precio*0.1);

Para concatenar cadenas de caracteres existe el operador de concatenacin ||. Para concatenar el ttulo y el autor de cada libro usamos el operador de concatenacin ("||"):
select titulo||'-'||autor from libros;

Note que concatenamos adems un guin para separar los campos. Oracle puede convertir automticamente valores numricos a cadenas para una concatenacin; por ejemplo, en el siguiente ejemplo mostramos el ttulo y precio de cada libro concatenado con el operador "||":
select titulo||' $'||precio from libros;

20 - Alias (encabezados de columnas)


Una manera de hacer ms comprensible el resultado de una consulta consiste en cambiar los encabezados de las columnas. Por ejemplo, tenemos la tabla "libros" con un campo "cantidad" (entre otros) en el cual se almacena la cantidad de libros en stock; queremos que al mostrar la informacin de dicha tabla aparezca como encabezado del campo "cantidad" el texto "stock", para ello colocamos un alias de la siguiente manera:
select titulo, cantidad as stock, precio from libros;

Para reemplazar el nombre de un campo del encabezado por otro, se coloca la palabra clave "as" seguido del texto del encabezado. Si el alias consta de una sola cadena las comillas no son necesarias, pero si contiene ms de una palabra, es necesario colocarla entre comillas dobles:
select titulo, cantidad as "stock disponible", precio from libros;

Tambin se puede crear un alias para columnas calculadas. Por ejemplo:


select titulo,precio, precio*0.1 as descuento, precio-(precio*0.1) as "preciofinal" from libros;

La palabra clave "as" es opcional, pero es conveniente usarla. Entonces, un "alias" se usa como nombre de un campo o de una expresin. En estos casos, son opcionales, sirven para hacer ms comprensible el resultado.

21 - Funciones string
Las funciones de manejo de caracteres alfanumricos aceptan argumentos de tipo caracter y retornan caracteres o valores numricos. Las siguientes son algunas de las funciones que ofrece Oracle para trabajar con cadenas de caracteres: - chr(x): retorna un caracter equivalente al cdigo enviado como argumento "x". Ejemplo:
select chr(65) from dual;-- retorna 'A'. select chr(100) from dual;-- retorna 'd'.

- concat(cadena1,cadena2): concatena dos cadenas de caracteres; es equivalente al operador ||. Ejemplo:


select concat('Buenas',' tardes') from dual;--retorna 'Buenas tardes'.

- initcap(cadena): retorna la cadena enviada como argumento con la primera letra (letra capital) de cada palabra en mayscula. Ejemplo:
select initcap('buenas tardes alumno') from dual;--retorna 'Buenas Tardes Alumno'.

- lower(cadena): retorna la cadena enviada como argumento en minsculas. "lower" significa reducir en ingls. Ejemplo:
select lower('Buenas tardes ALUMNO') from dual;--retorna "buenas tardes alumno".

- upper(cadena): retorna la cadena con todos los caracteres en maysculas. Ejemplo:


select upper('www.oracle.com') from dual;-- 'WWW.ORACLE.COM'

- lpad(cadena,longitud,cadenarelleno): retorna la cantidad de caracteres especificados por el argumento "longitud", de la cadena enviada como primer argumento (comenzando desde el primer caracter); si "longitud" es mayor que el tamao de la cadena enviada, rellena los espacios restantes con la cadena enviada como tercer argumento (en caso de omitir el tercer argumento rellena con espacios); el relleno comienza desde la izquierda. Ejemplos:
select lpad('alumno',10,'xyz') from dual;-- retorna 'xyzxalumno' select lpad('alumno',4,'xyz') from dual;-- retorna 'alum'

- rpad(cadena,longitud,cadenarelleno): retorna la cantidad de caracteres especificados por el argumento "longitud", de la cadena enviada como primer argumento (comenzando desde el primer caracter); si "longitud" es mayor que el tamao de la cadena enviada, rellena los

espacios restantes con la cadena enviada como tercer argumento (en caso de omitir el tercer argumento rellena con espacios); el relleno comienza desde la derecha (ltimo caracter). Ejemplos:
select rpad('alumno',10,'xyz') from dual;-- retorna 'alumnoxyzx' select rpad('alumno',4,'xyz') from dual;-- retorna 'alum'

- ltrim(cadena1,cadena2): borra todas las ocurrencias de "cadena2" en "cadena1", si se encuentran al comienzo; si se omite el segundo argumento, se eliminan los espacios. Ejemplo:
select ltrim('la casa de la cuadra','la') from dual;-- ' casa de la cuadra' select ltrim(' es la casa de la cuadra','la') from dual;-- no elimina ningn caracter select ltrim(' la casa') from dual;-- 'la casa'

- rtrim(cadena1,cadena2): borra todas las ocurrencias de "cadena2" en "cadena1", si se encuentran por la derecha (al final de la cadena); si se omite el segundo argumento, se borran los espacios. Ejemplo:
select rtrim('la casa lila','la') from dual;-- 'la casa li' select rtrim('la casa lila ','la') from dual;-- no borra ningn caracter select rtrim('la casa lila ') from dual; --'la casa lila'

- trim(cadena): retorna la cadena con los espacios de la izquierda y derecha eliminados. "Trim" significa recortar. Ejemplo:
select trim(' oracle ') from dual;--'oracle'

- replace(cadena,subcade1,subcade2): retorna la cadena con todas las ocurrencias de la subcadena de reemplazo (subcade2) por la subcadena a reemplazar (subcae1). Ejemplo:
select replace('xxx.oracle.com','x','w') from dual;

retorna "www.oracle.com'. - substr(cadena,inicio,longitud): devuelve una parte de la cadena especificada como primer argumento, empezando desde la posicin especificada por el segundo argumento y de tantos caracteres de longitud como indica el tercer argumento. Ejemplo:
select substr('www.oracle.com',1,10) from dual;-- 'www.oracle' select substr('www.oracle.com',5,6) from dual;-- 'oracle'

- length(cadena): retorna la longitud de la cadena enviada como argumento. "lenght" significa longitud en ingls. Ejemplo:
select length('www.oracle.com') from dual;-- devuelve 14.

- instr (cadena,subcadena): devuelve la posicin de comienzo (de la primera ocurrencia) de la subcadena especificada en la cadena enviada como primer argumento. Si no la encuentra retorna 0. Ejemplos:
select instr('Jorge Luis Borges','or') from dual;-- 2 select instr('Jorge Luis Borges','ar') from dual;-- 0, no se encuentra

- translate(): reemplaza cada ocurrencia de una serie de caracteres con otra serie de acracteres. La diferencia con "replace" es que aquella trabaja con cadenas de caracteres y reemplaza una cadena completa por otra, en cambio "translate" trabaja con caracteres simples y reemplaza varios. En el siguiente ejemplo se especifica que se reemplacen todos los caracteres "O" por el caracter "0", todos los caracteres "S" por el caracter "5" y todos los caracteres "G" por "6":
select translate('JORGE LUIS BORGES','OSG','056') from dual;--'J0R6E LUI5 B0R6E5'

Se pueden emplear estas funciones enviando como argumento el nombre de un campo de tipo caracter.

22 - Funciones matemticas.
Las funciones matemticas realizan operaciones con expresiones numricas y retornan un resultado, operan con tipos de datos numricos. Las funciones numricas aceptan parmetros de entrada de tipo numrico y retornan valores numricos. Oracle tiene algunas funciones para trabajar con nmeros. Aqu presentamos algunas. - abs(x): retorna el valor absoluto del argumento "x". Ejemplo:
select abs(-20) from dual;--retorna 20.

La tabla dual es una tabla virtual que existe en todas las Bases de datos Oracle. - ceil(x): redondea a entero, hacia arriba, el argumento "x". Ejemplo:
select ceil(12.34) from dual;--retorna 13.

- floor(x): redondea a entero, hacia abajo, el argumento "x". Ejemplo:


select floor(12.34) from dual; --12

- mod(x,y): devuelve el resto de la divisin x/y. Ejemplos:


select mod(10,3) from dual;--retorna 1. select mod(10,2) from dual;--retorna 0.

- power(x,y): retorna el valor de "x" elevado a la "y" potencia. Ejemplo:


select power(2,3) from dual;--retorna 8.

- round(n,d): retorna "n" redondeado a "d" decimales; si se omite el segundo argumento, redondea todos los decimales. Si el segundo argumento es positivo, el nmero de decimales es redondeado segn "d"; si es negativo, el nmero es redondeado desde la parte entera segn el valor de "d". Ejemplos:
select round(123.456,2) from dual;-- retorna "123.46", es decir, redondea desde el segundo decimal. select round(123.456,1) from dual;-- 123.5, es decir, redondea desde el primer decimal. select round(123.456,-1) from dual;-- 120, redondea desde el primer valor entero (hacia la izquierda). select round(123.456,-2) from dual;-- 100, redondea desde el segundo valor entero (hacia la izquierda). select round(123.456) from dual;-- 123.

- sign(x): si el argumento es un valor positivo, retorna 1, si es negativo, devuelve -1 y 0 si es 0. Ejemplo:


select sign(-120) from dual;--retorna -1 select sign(120) from dual;--retorna 1

- trunc(n,d): trunca un nmero a la cantidad de decimales especificada por el segundo argumento. Si se omite el segundo argumento, se truncan todos los decimales. Si "d" es negativo, el nmero es truncado desde la parte entera. Ejemplo:
select select select select trunc(1234.5678,2) from dual;--retorna 1234.56 trunc(1234.5678,-2) from dual;--retorna 1200 trunc(1234.5678,-1) from dual;--retorna 1230 trunc(1234.5678) from dual;--retorna 1234

- sqrt(x): devuelve la raiz cuadrada del valor enviado como argumento. Ejemplo:
select sqrt(9) from dual;--retorna 3

Oracle dispone de funciones trigonomtricas que retornan radianes, calculan seno, coseno, inversas, etc.: acos, asin, atan, atan2, cos, cosh, exp, ln, log, sin, sinh, tan, tanh. No las veremos en detalle. Se pueden emplear las funciones matemticas enviando como argumento el nombre de un campo de tipo numrico.

23 - Funciones de fechas y horas


Oracle dispone de varias funciones que operan con tipos de datos "date". Estas son algunas: - add_months(f,n): agrega a una fecha, un nmero de meses. Si el segundo argumento es positivo, se le suma a la fecha enviada tal cantidad de meses; si es negativo, se le resta a la fecha enviada tal cantidad de meses. Ejemplo:
select add_months('10/06/2007',5) from dual; --retorna "10/11/07" select add_months('10/06/2007',-5) from dual; --retorna "10/01/07" select add_months('30/01/2007',1) from dual;-- retorna "25/02/07" ya que es el ltimo da de ese mes.

- last_day(f): retorna el ultimo da de mes de la fecha enviada como argumento. Ejemplo:


select last_day('10/02/2007') from dual;-- "28/02/07" select last_day('10/08/2007') from dual;-- "31/08/07"

- months_between(f1,f2): retorna el numero de meses entre las fechas enviadas como argumento. Ejemplo:
select months_between('19/05/2003','21/06/05') from dual;-- retorna

- next_day(fecha,dia): retorna una fecha correspondiente al primer da especificado en "dia" luego de la fecha especificada. En el siguiente ejemplo se busca el lunes siguiente a la fecha especificada:
select next_day('10/08/2007','LUNES') from dual;

- current_date: retorna la fecha actual. Ejemplo:


select current_date from dual;

- current_timestamp: retorna la fecha actual


select current_timestamp from dual;

Retorna: 10/08/07 09:59:44,109000000 AMERICA/BUENOS_AIRES - sysdate: retorna la fecha y hora actuales en el servidor de Oracle. -systimestamp: retorna fecha y hora actuales.
select systimestamp from dual;

Retorna 10/08/07 10:33:48,984000000 -03:00

- to_date: convierte una cadena a tipo de dato "date". Ejemplo:


select to_date ('05-SEP-2007 10:00 AM','DD-MON-YYYY HH:MI AM') from dual;

Retorna 05/09/07 - to_char: convierte una fecha a cadena de caracteres. Ejemplo:


select to_char('10/10/2007')from dual;

- extract(parte,fecha): retorna la parte (especificada por el primer argumento) de una fecha. Puede extraer el ao (year), mes (month), da (day), hora (hour), minuto (minute), segundo (second), etc. Ejemplo:
select extract(month from sysdate) from dual;

retorna el nmero mes de la fecha actual. En Oracle: Los operadores aritmticos "+" (ms) y "-" (menos) pueden emplearse con fechas. Por ejemplos:
select sysdate-3:

Retorna 3 das antes de la fecha actual.


select to_date('15/12/2007')-5 from dual;

Retorna 10/12/07 Se pueden emplear estas funciones enviando como argumento el nombre de un campo de tipo date.

24 - Ordenar registros (order by)


Podemos ordenar el resultado de un "select" para que los registros se muestren ordenados por algn campo, para ello usamos la clusula "order by". La sintaxis bsica es la siguiente:
select *from NOMBRETABLA order by CAMPO;

Por ejemplo, recuperamos los registros de la tabla "libros" ordenados por el ttulo:

select *from libros order by titulo;

Aparecen los registros ordenados alfabticamente por el campo especificado. Tambin podemos colocar el nmero de orden del campo por el que queremos que se ordene en lugar de su nombre, es decir, referenciar a los campos por su posicin en la lista de seleccin. Por ejemplo, queremos el resultado del "select" ordenado por "precio":
select titulo,autor,precio from libros order by 3;

Si colocamos un nmero mayor a la cantidad de campos de la lista de seleccin, aparece un mensaje de error y la sentencia no se ejecuta. Por defecto, si no aclaramos en la sentencia, los ordena de manera ascendente (de menor a mayor). Podemos ordenarlos de mayor a menor, para ello agregamos la palabra clave "desc":
select *libros order by editorial desc;

Tambin podemos ordenar por varios campos, por ejemplo, por "titulo" y "editorial":
select *from libros order by titulo,editorial;

Incluso, podemos ordenar en distintos sentidos, por ejemplo, por "titulo" en sentido ascendente y "editorial" en sentido descendente:
select *from libros order by titulo asc, editorial desc;

Debe aclararse al lado de cada campo, pues estas palabras claves afectan al campo inmediatamente anterior. Es posible ordenar por un campo que no se lista en la seleccin incluso por columnas calculados. Se puede emplear "order by" con campos de tipo caracter, numrico y date.

25 - Operadores lgicos (and - or - not)


Hasta el momento, hemos aprendido a establecer una condicin con "where" utilizando operadores relacionales. Podemos establecer ms de una condicin con la clusula "where", para ello aprenderemos los operadores lgicos. Son los siguientes:
and, significa "y", or, significa "y/o", not, significa "no", invierte el resultado (), parntesis

Los operadores lgicos se usan para combinar condiciones. Si queremos recuperar todos los libros cuyo autor sea igual a "Borges" y cuyo precio no supere los 20 pesos, necesitamos 2 condiciones:
select *from libros where (autor='Borges') and (precio<=20);

Los registros recuperados en una sentencia que une dos condiciones con el operador "and", cumplen con las 2 condiciones. Queremos ver los libros cuyo autor sea "Borges" y/o cuya editorial sea "Planeta":
select *from libros where autor='Borges' or editorial='Planeta';

En la sentencia anterior usamos el operador "or"; indicamos que recupere los libros en los cuales el valor del campo "autor" sea "Borges" y/o el valor del campo "editorial" sea "Planeta", es decir, seleccionar los registros que cumplan con la primera condicin, con la segunda condicin y con ambas condiciones. Los registros recuperados con una sentencia que une dos condiciones con el operador "or", cumplen una de las condiciones o ambas. Queremos recuperar los libros que NO cumplan la condicin dada, por ejemplo, aquellos cuya editorial NO sea "Planeta":
select *from libros where not editorial='Planeta';

El operador "not" invierte el resultado de la condicin a la cual antecede. Los registros recuperados en una sentencia en la cual aparece el operador "not", no cumplen con la condicin a la cual afecta el "NOT". Los parntesis se usan para encerrar condiciones, para que se evalen como una sola expresin. Cuando explicitamos varias condiciones con diferentes operadores lgicos (combinamos "and", "or") permite establecer el orden de prioridad de la evaluacin; adems permite diferenciar las expresiones ms claramente. Por ejemplo, las siguientes expresiones devuelven un resultado diferente:
select *from libros where (autor='Borges') or (editorial='Paidos' and precio<20); select *from libros where (autor='Borges' or editorial='Paidos') and (precio<20);

Si bien los parntesis no son obligatorios en todos los casos, se recomienda utilizarlos para evitar confusiones. El orden de prioridad de los operadores lgicos es el siguiente: "not" se aplica antes que "and" y "and" antes que "or", si no se especifica un orden de evaluacin mediante el uso de parntesis. El orden en el que se evalan los operadores con igual nivel de precedencia es indefinido, por ello se recomienda usar los parntesis. Entonces, para establecer ms de una condicin en un "where" es necesario emplear operadores lgicos. "and" significa "y", indica que se cumplan ambas condiciones; "or" significa "y/o", indica que se cumpla una u otra condicin (o ambas); "not" significa "no.", indica que no se cumpla la condicin especificada.

26 - Otros operadores relacionales (between)


Hemos visto los operadores relacionales: = (igual), <> (distinto), > (mayor), < (menor), >= (mayor o igual), <= (menor o igual), is null/is not null (si un valor es NULL o no). Otro operador relacional es "between", trabajan con intervalos de valores.

Hasta ahora, para recuperar de la tabla "libros" los libros con precio mayor o igual a 20 y menor o igual a 40, usamos 2 condiciones unidas por el operador lgico "and":
select *from libros where precio>=20 and precio<=40;

Podemos usar "between" y as simplificar la consulta:


select *from libros where precio between 20 and 40;

Averiguamos si el valor de un campo dado (precio) est entre los valores mnimo y mximo especificados (20 y 40 respectivamente). "between" significa "entre". Trabaja con intervalo de valores. Este operador no tiene en cuenta los valores "null". Si agregamos el operador "not" antes de "between" el resultado se invierte, es decir, se recuperan los registros que estn fuera del intervalo especificado. Por ejemplo, recuperamos los libros cuyo precio NO se encuentre entre 20 y 30, es decir, los menores a 20 y mayores a 30:
select *from libros where precio not between 20 and 30;

Podemos especificar un intervalo de valores de tipo fecha con "between":


select *from libros where edicion between '01/05/2000' and '01/05/2007';

Entonces, empleamos el operador "between" para reducir las condiciones "where".

27 - Otros operadores relacionales (in)


Se utiliza "in" para averiguar si el valor de un campo est incluido en una lista de valores especificada. En la siguiente sentencia usamos "in" para averiguar si el valor del campo autor est incluido en la lista de valores especificada (en este caso, 2 cadenas). Hasta ahora, para recuperar los libros cuyo autor sea 'Paenza' o 'Borges' usbamos 2 condiciones:

select *from libros where autor='Borges' or autor='Paenza';

Podemos usar "in" y simplificar la consulta:


select *from libros where autor in('Borges','Paenza');

Para recuperar los libros cuyo autor no sea 'Paenza' ni 'Borges' usbamos:
select *from libros where autor<>'Borges' and autor<>'Paenza';

Tambin podemos usar "in" anteponiendo "not":


select *from libros where autor not in ('Borges','Paenza');

Empleando "in" averiguamos si el valor del campo est incluido en la lista de valores especificada; con "not" antecediendo la condicin, invertimos el resultado, es decir, recuperamos los valores que no se encuentran (no coinciden) con la lista de valores. Los valores "null" no se consideran.

28 - Bsqueda de patrones (like - not like)


Existe un operador relacional que se usa para realizar comparaciones exclusivamente de cadenas, "like" y "not like". Hemos realizado consultas utilizando operadores relacionales para comparar cadenas. Por ejemplo, sabemos recuperar los libros cuyo autor sea igual a la cadena "Borges":
select *from libros where autor='Borges';

El operador igual ("=") nos permite comparar cadenas de caracteres, pero al realizar la comparacin, busca coincidencias de cadenas completas, realiza una bsqueda exacta. Imaginemos que tenemos registrados estos 2 libros:
"El Aleph", "Borges"; "Antologia poetica", "J.L. Borges";

Si queremos recuperar todos los libros de "Borges" y especificamos la siguiente condicin:


select *from libros where autor='Borges';

slo aparecer el primer registro, ya que la cadena "Borges" no es igual a la cadena "J.L. Borges". Esto sucede porque el operador "=" (igual), tambin el operador "<>" (distinto) comparan cadenas de caracteres completas. Para comparar porciones de cadenas utilizamos los operadores "like" y "not like". Entonces, podemos comparar trozos de cadenas de caracteres para realizar consultas. Para recuperar todos los registros cuyo autor contenga la cadena "Borges" debemos tipear:
select *from libros where autor like "%Borges%";

El smbolo "%" (porcentaje) reemplaza cualquier cantidad de caracteres (incluyendo ningn caracter). Es un caracter comodn. "like" y "not like" son operadores de comparacin que sealan igualdad o diferencia. Para seleccionar todos los libros que comiencen con "M":
select *from libros where titulo like 'M%';

Note que el smbolo "%" ya no est al comienzo, con esto indicamos que el ttulo debe tener como primera letra la "M" y luego, cualquier cantidad de caracteres. Para seleccionar todos los libros que NO comiencen con "M":
select *from libros where titulo not like 'M%';

As como "%" reemplaza cualquier cantidad de caracteres, el guin bajo "_" reemplaza un caracter, es otro caracter comodn. Por ejemplo, queremos ver los libros de "Lewis Carroll" pero no recordamos si se escribe "Carroll" o "Carrolt", entonces tipeamos esta condicin:
select *from libros where autor like "%Carrol_";

"like" se emplea con tipos de datos caracter y date. Si empleamos "like" con tipos de datos que no son caracteres, Oracle convierte (si es posible) el tipo de dato a caracter. Por ejemplo, queremos buscar todos los libros cuyo precio se encuentre entre 10.00 y 19.99:
select titulo,precio from libros where precio like '1_,%';

Queremos los libros que NO incluyen centavos en sus precios:


select titulo,precio from libros where precio not like '%,%';

Los valores nulos no se incluyen en las bsquedas con "like" y "not like".

29 - Contar registros (count)


Existen en Oracle funciones que nos permiten contar registros, calcular sumas, promedios, obtener valores mximos y mnimos. Estas funciones se denominan funciones de grupo y operan sobre un conjunto de valores (registros), no con datos individuales y devuelven un nico valor. Imaginemos que nuestra tabla "libros" contiene muchos registros. Para averiguar la cantidad sin necesidad de contarlos manualmente usamos la funcin "count()":
select count(*) from libros;

La funcin "count()" cuenta la cantidad de registros de una tabla, incluyendo los que tienen valor nulo. Tambin podemos utilizar esta funcin junto con la clausula "where" para una consulta ms especfica. Queremos saber la cantidad de libros de la editorial "Planeta":
select count(*) from libros where editorial='Planeta';

Para contar los registros que tienen precio (sin tener en cuenta los que tienen valor nulo), usamos la funcin "count()" y en los parntesis colocamos el nombre del campo que necesitamos contar:
select count(precio) from libros;

Note que "count(*)" retorna la cantidad de registros de una tabla (incluyendo los que tienen valor "null") mientras que "count(precio)" retorna la cantidad de registros en los cuales el campo "precio" no es nulo. No es lo mismo. "count(*)" cuenta registros, si en lugar de un asterisco colocamos como argumento el nombre de un campo, se contabilizan los registros cuyo valor en ese campo NO es nulo.

30 - Funciones de grupo (count - max min - sum - avg)


Hemos visto que Oracle dispone de funciones que nos permiten contar registros, calcular sumas, promedios, obtener valores mximos y mnimos, las funciones de grupo. Las funciones de grupo operan sobre un conjunto de valores (registros) y retornan un solo valor. Ya hemos aprendido una de ellas, "count()", veamos otras. Se pueden usar en una instruccin "select" y combinarlas con la clusula "group by" (la veremos posteriormente). Todas estas funciones retornan "null" si ningn registro cumple con la condicion del "where" (excepto "count" que en tal caso retorna cero). El tipo de dato del campo determina las funciones que se pueden emplear con ellas. Las relaciones entre las funciones de agrupamiento y los tipos de datos es la siguiente: - count: se puede emplear con cualquier tipo de dato. - min y max: con cualquier tipo de dato. - sum y avg: slo en campos de tipo numrico. La funcin "sum()" retorna la suma de los valores que contiene el campo especificado. Si queremos saber la cantidad total de libros que tenemos disponibles para la venta, debemos sumar todos los valores del campo "cantidad":
select sum(cantidad) from libros;

Para averiguar el valor mximo o mnimo de un campo usamos las funciones "max()" y "min()" respectivamente. Queremos saber cul es el mayor precio de todos los libros:
select max(precio) from libros;

Entonces, dentro del parntesis de la funcin colocamos el nombre del campo del cul queremos el mximo valor. La funcin "avg()" retorna el valor promedio de los valores del campo especificado. Queremos saber el promedio del precio de los libros referentes a "PHP":

select avg(precio) from libros where titulo like '%PHP%';

Ahora podemos entender porque estas funciones se denominan "funciones de grupo", porque operan sobre conjuntos de registros, no con datos individuales. Tratamiento de los valores nulos: Si realiza una consulta con la funcin "count" incluyendo entre parntesis un campo y la tabla contiene 18 registros, 2 de los cuales contienen valor nulo en "precio", el resultado devuelve un total de 16 filas porque no considera aquellos con valor nulo. Todas las funciones de grupo, excepto "count(*)", excluye los valores nulos de los campos; "count(*)" cuenta todos los registros, incluidos los que contienen "null".

31 - Agrupar registros (group by)


Hemos aprendido que las funciones de grupo permiten realizar varios clculos operando con conjuntos de registros. Las funciones de grupo solas producen un valor de resumen para todos los registros de un campo. Podemos generar valores de resumen para un solo campo, combinando las funciones de agregado con la clusula "group by", que agrupa registros para consultas detalladas. Queremos saber la cantidad de libros de cada editorial, podemos tipear la siguiente sentencia:
select count(*) from libros where editorial='Planeta';

y repetirla con cada valor de "editorial":


select where select where ... count(*) from libros editorial='Emece'; count(*) from libros editorial='Paidos';

Pero hay otra manera, utilizando la clusula "group by":

select editorial, count(*) from libros group by editorial;

La instruccin anterior solicita que muestre el nombre de la editorial y cuente la cantidad agrupando los registros por el campo "editorial". Como resultado aparecen los nombres de las editoriales y la cantidad de registros para cada valor del campo. Los valores nulos se procesan como otro grupo. Entonces, para saber la cantidad de libros que tenemos de cada editorial, utilizamos la funcin "count()", agregamos "group by" (que agrupa registros) y el campo por el que deseamos que se realice el agrupamiento, tambin colocamos el nombre del campo a recuperar; la sintaxis bsica es la siguiente:
select CAMPO, FUNCIONDEAGREGADO from NOMBRETABLA group by CAMPO;

Tambin se puede agrupar por ms de un campo, en tal caso, luego del "group by" se listan los campos, separados por comas. Todos los campos que se especifican en la clusula "group by" deben estar en la lista de seleccin.
select CAMPO1, CAMPO2, FUNCIONDEAGREGADO from NOMBRETABLA group by CAMPO1,CAMPO2;

Para obtener la cantidad libros con precio no nulo, de cada editorial utilizamos la funcin "count()" envindole como argumento el campo "precio", agregamos "group by" y el campo por el que deseamos que se realice el agrupamiento (editorial):
select editorial, count(precio) from libros group by editorial;

Como resultado aparecen los nombres de las editoriales y la cantidad de registros de cada una, sin contar los que tienen precio nulo. Recuerde la diferencia de los valores que retorna la funcin "count()" cuando enviamos como argumento un asterisco o el nombre de un campo: en el primer caso cuenta todos los registros incluyendo los que tienen valor nulo, en el segundo, los registros en los cuales el campo especificado es no nulo. Para conocer el total de libros agrupados por editorial:
select editorial, sum(cantidad) from libros group by editorial;

Para saber el mximo y mnimo valor de los libros agrupados por editorial:
select editorial, max(precio) as mayor, min(precio) as menor from libros group by editorial;

Para calcular el promedio del valor de los libros agrupados por editorial:
select editorial, avg(precio) from libros group by editorial;

Es posible limitar la consulta con "where". Si incluye una clusula "where", slo se agrupan los registros que cumplen las condiciones. Vamos a contar y agrupar por editorial considerando solamente los libros cuyo precio sea menor a 30 pesos:
select editorial, count(*) from libros where precio<30 group by editorial;

Note que las editoriales que no tienen libros que cumplan la condicin, no aparecen en la salida. Entonces, usamos "group by" para organizar registros en grupos y obtener un resumen de dichos grupos. Oracle produce una columna de valores por cada grupo, devolviendo filas por cada grupo especificado.

32 - Seleccionar grupos (Having)


As como la clusula "where" permite seleccionar (o rechazar) registros individuales; la clusula "having" permite seleccionar (o rechazar) un grupo de registros. Si queremos saber la cantidad de libros agrupados por editorial usamos la siguiente instruccin ya aprendida:
select editorial, count(*) from libros group by editorial;

Si queremos saber la cantidad de libros agrupados por editorial pero considerando slo algunos grupos, por ejemplo, los que devuelvan un valor mayor a 2, usamos la siguiente instruccin:
select editorial, count(*) from libros group by editorial having count(*)>2;

Se utiliza "having", seguido de la condicin de bsqueda, para seleccionar ciertas filas retornadas por la clusula "group by". Veamos otros ejemplos. Queremos el promedio de los precios agrupados por editorial, pero solamente de aquellos grupos cuyo promedio supere los 25 pesos:
select editorial, avg(precio) from libros group by editorial having avg(precio)>25;

En algunos casos es posible confundir las clusulas "where" y "having". Queremos contar los registros agrupados por editorial sin tener en cuenta a la editorial "Planeta". Analicemos las siguientes sentencias:
select editorial, count(*) from libros where editorial<>'Planeta' group by editorial; select editorial, count(*) from libros group by editorial having editorial<>'Planeta';

Ambas devuelven el mismo resultado, pero son diferentes. La primera, selecciona todos los registros rechazando los de editorial "Planeta" y luego los agrupa para contarlos. La segunda, selecciona todos los registros, los agrupa para contarlos y finalmente rechaza fila con la cuenta correspondiente a la editorial "Planeta". No debemos confundir la clusula "where" con la clusula "having"; la primera establece condiciones para la seleccin de registros de un "select"; la segunda establece condiciones para la seleccin de registros de una salida "group by". Veamos otros ejemplos combinando "where" y "having". Queremos la cantidad de libros, sin considerar los que tienen precio nulo, agrupados por editorial, sin considerar la editorial "Planeta":
select editorial, count(*) from libros where precio is not null group by editorial having editorial<>'Planeta';

Aqu, selecciona los registros rechazando los que no cumplan con la condicin dada en "where", luego los agrupa por "editorial" y finalmente rechaza los grupos que no cumplan con la condicin dada en el "having". Se emplea la clusula "having" con funciones de grupo, esto no puede hacerlo la clusula "where". Por ejemplo queremos el promedio de los precios agrupados por editorial, de aquellas editoriales que tienen ms de 2 libros:
select editorial, avg(precio) from libros group by editorial having count(*) > 2;

En una clusula "having" puede haber varias condiciones. Cuando utilice varias condiciones, tiene que combinarlas con operadores lgicos (and, or, not). Podemos encontrar el mayor valor de los libros agrupados y ordenados por editorial y seleccionar las filas que tengan un valor menor a 100 y mayor a 30:
select editorial, max(precio) as mayor from libros group by editorial having min(precio)<100 and min(precio)>30 order by editorial;

Entonces, usamos la clausula "having" para restringir las filas que devuelve una salida "group by". Va siempre despus de la clusula "group by" y antes de la clusula "order by" si la hubiere.

33 - Registros duplicados (Distinct)


Con la clusula "distinct" se especifica que los registros con ciertos datos duplicados sean obviadas en el resultado. Por ejemplo, queremos conocer todos los autores de los cuales tenemos libros, si utilizamos esta sentencia:
select autor from libros;

Aparecen repetidos. Para obtener la lista de autores sin repeticin usamos:


select distinct autor from libros;

Tambin podemos tipear:

select autor from libros group by autor;

Note que en los tres casos anteriores aparece "null" como un valor para "autor" Si slo queremos la lista de autores conocidos, es decir, no queremos incluir "null" en la lista, podemos utilizar la sentencia siguiente:
select distinct autor from libros where autor is not null;

Para contar los distintos autores, sin considerar el valor "null" usamos:
select count(distinct autor) from libros;

Note que si contamos los autores sin "distinct", no incluir los valores "null" pero si los repetidos:
select count(autor) from libros;

Esta sentencia cuenta los registros que tienen autor. Podemos combinarla con "where". Por ejemplo, queremos conocer los distintos autores de la editorial "Planeta":
select distinct autor from libros where editorial='Planeta';

Tambin puede utilizarse con "group by" para contar los diferentes autores por editorial:
select editorial, count(distinct autor) from libros group by editorial;

La clusula "distinct" afecta a todos los campos presentados. Para mostrar los ttulos y editoriales de los libros sin repetir ttulos ni editoriales, usamos:
select distinct titulo,editorial from libros order by titulo;

Note que los registros no estn duplicados, aparecen ttulos iguales pero con editorial diferente, cada registro es diferente. Entonces, "distinct" elimina registros duplicados.

34 - Clave primaria compuesta


Las claves primarias pueden ser simples, formadas por un solo campo o compuestas, ms de un campo. Recordemos que una clave primaria identifica un solo registro en una tabla. Para un valor del campo clave existe solamente un registro. Los valores no se repiten ni pueden ser nulos. Existe una playa de estacionamiento que almacena cada da los datos de los vehculos que ingresan en la tabla llamada "vehiculos" con los siguientes campos:
patente char(6) not null, tipo char (1), 'a'= auto, 'm'=moto, horallegada date, horasalida date,

Necesitamos definir una clave primaria para una tabla con los datos descriptos arriba. No podemos usar solamente la patente porque un mismo auto puede ingresar ms de una vez en el da a la playa; tampoco podemos usar la hora de entrada porque varios autos pueden ingresar a una misma hora. Tampoco sirven los otros campos. Como ningn campo, por si slo cumple con la condicin para ser clave, es decir, debe identificar un solo registro, el valor no puede repetirse, debemos usar dos campos. Definimos una clave compuesta cuando ningn campo por si solo cumple con la condicin para ser clave. En este ejemplo, un auto puede ingresar varias veces en un da a la playa, pero siempre ser a distinta hora. Usamos 2 campos como clave, la patente junto con la hora de llegada, as identificamos unvocamente cada registro. Para establecer ms de un campo como clave primaria usamos la siguiente sintaxis:
create table vehiculos( patente char(6) not null, tipo char(1),--'a'=auto, 'm'=moto horallegada date, horasalida date, primary key(patente,horallegada) );

Nombramos los campos que formarn parte de la clave separados por comas.

Al ingresar los registros, Oracle controla que los valores para los campos establecidos como clave primaria no estn repetidos en la tabla; si estuviesen repetidos, muestra un mensaje y la insercin no se realiza. Lo mismo sucede si realizamos una actualizacin. Para ver la clave primaria de una tabla podemos realizar la siguiente consulta:
select uc.table_name, column_name, position from user_cons_columns ucc join user_constraints uc on ucc.constraint_name=uc.constraint_name where uc.constraint_type='P' and uc.table_name='VEHICULOS';

Entonces, si un solo campo no identifica unvocamente un registro podemos definir una clave primaria compuesta, es decir formada por ms de un campo.

35 - Secuencias (create sequence - currval - nextval - drop sequence)


Hemos aprendido que existen varios objetos de base de datos, hasta ahora hemos visto TABLAS y algunas FUNCIONES predefinidas. Otro objeto de base de datos es la secuencia. Una secuencia (sequence) se emplea para generar valores enteros secuenciales nicos y asignrselos a campos numricos; se utilizan generalmente para las claves primarias de las tablas garantizando que sus valores no se repitan. Una secuencia es una tabla con un campo numrico en el cual se almacena un valor y cada vez que se consulta, se incrementa tal valor para la prxima consulta. Sintaxis general:
create sequence NOMBRESECUENCIA start with VALORENTERO increment by VALORENTERO maxvalue VALORENTERO minvalue VALORENTERO cycle | nocycle;

- La clusula "start with" indica el valor desde el cual comenzar la generacin de nmeros secuenciales. Si no se especifica, se inicia con el valor que indique "minvalue".

- La clusula "increment by" especifica el incremento, es decir, la diferencia entre los nmeros de la secuencia; debe ser un valor numrico entero positivo o negativo diferente de 0. Si no se indica, por defecto es 1. - "maxvalue" define el valor mximo para la secuencia. Si se omite, por defecto es 99999999999999999999999999. - "minvalue" establece el valor mnimo de la secuencia. Si se omite ser 1. - La clusula "cycle" indica que, cuando la secuencia llegue a mximo valor (valor de "maxvalue") se reinicie, comenzando con el mnimo valor ("minvalue") nuevamente, es decir, la secuencia vuelve a utilizar los nmeros. Si se omite, por defecto la secuencia se crea "nocycle". Si no se especifica ninguna clusula, excepto el nombre de la secuencia, por defecto, comenzar en 1, se incrementar en 1, el mnimo valor ser 1, el mximo ser 999999999999999999999999999 y "nocycle". En el siguiente ejemplo creamos una secuencia llamada "sec_codigolibros", estableciendo que comience en 1, sus valores estn entre 1 y 99999 y se incrementen en 1, por defecto, ser "nocycle":
create sequence sec_codigolibros start with 1 increment by 1 maxvalue 99999 minvalue 1;

Si bien, las secuencias son independientes de las tablas, se utilizarn generalmente para una tabla especfica, por lo tanto, es conveniente darle un nombre que referencie a la misma. Otro ejemplo:
create sequence sec_numerosocios increment by 5 cycle;

La secuencia anterior, "sec_numerosocios", incrementa sus valores en 5 y al llegar al mximo valor recomenzar la secuencia desde el valor mnimo; no se especifican las otras clusulas, por lo tanto, por defecto, el valor mnimo es 1, el mximo 999999999999999999999999999 y el valor inicial es 1. Dijimos que las secuencias son tablas; por lo tanto se accede a ellas mediante consultas, empleando "select". La diferencia es que utilizamos pseudocolumnas para recuperar el valor actual y el siguiente de la secuencia. Estas pseudocolumnas pueden incluirse en el "from" de una consulta a otra tabla o de la tabla "dual".

Para recuperar los valores de una secuencia empleamos las pseudocolumnas "currval" y "nextval". Primero debe inicializarse la secuencia con "nextval". La primera vez que se referencia "nextval" retorna el valor de inicio de la secuencia; las siguientes veces, incrementa la secuencia y nos retorna el nuevo valor: NOMBRESECUENCIA.NEXTVAL; se coloca el nombre de la secuencia seguido de un punto y la pseudocolumna "nextval" (que es una forma abreviada de "next value", siguiente valor). Para recuperar el valor actual de una secuencia usamos:
NOMBRESECUENCIA.CURRVAL;

es decir, el nombre de la secuencia, un punto y la pseudocolumna "currval" (que es una forma abreviada de "current value", valor actual). Los valores retornados por "currval" y "nextval" pueden usarse en sentencias "insert" y "update". Veamos un ejemplo completo: Creamos una secuencia para el cdigo de la tabla "libros", especificando el valor mximo, el incremento y que no sea circular:
create sequence sec_codigolibros maxvalue 999999 increment by 1 nocycle;

Luego inicializamos la secuencia


select sec_codigolibros.nextval from dual;

Recuerde que la primera vez que se referencie la secuencia debe emplearse "nextval" para inicializarla. Ingresamos un registro en "libros", almacenando en el campo "codigo" el valor actual de la secuencia:
insert into libros values (sec_codigolibros.currval,'El aleph', 'Borges','Emece');

Ingresamos otro registro en "libros", almacenando en el campo "codigo" el valor siguiente de la secuencia:

insert into libros values (sec_codigolibros.nextval,'Matematica estas ahi', 'Paenza','Nuevo siglo');

Para ver todas las secuencias de la base de datos actual realizamos la siguiente consulta:
select *from all_sequences;

Nos muestra el propietario de la secuencia, el nombre de la misma, los valores mnimo y mximo, el valor de incremento y si es circular o no, entre otros datos que no analizaremos por el momento. Tambin podemos ver todos los objetos de la base de datos actual tipeando;
select *from all_objects;

En la tabla resultado aparecen todos los objetos de la base de datos, incluidas las secuencias; si es una secuencia en la columna OBJECT_TYPE se muestra "SEQUENCE". Podemos consultar "all_objects" especificando que nos muestre el nombre de todas las secuencias:
select object_name from all_objects where object_type='SEQUENCE';

Para eliminar una secuencia empleamos "drop sequence". Sintaxis:


drop sequence NOMBRESECUENCIA;

Si la secuencia no existe aparecer un mensaje indicando tal situacin. En el siguiente ejemplo se elimina la secuencia "sec_codigolibros":
drop sequence sec_codigolibros;

36 - Alterar secuencia (alter sequence)


Es posible modificar una secuencia, su valor de incremento, los valores mnimo y mximo y el atributo "cycle" (el valor de inicio no puede modificarse); para ello empleamos la sentencia "alter sequence". Sintaxis:
alter sequence NOMBRESECUENCIA ATRIBUTOSAMODIFICAR;

Definimos una secuencia denominada "sec_codigolibros" con los siguientes atributos:

create sequence sec_codigolibros start with 1 increment by 1 maxvalue 999 minvalue 1 nocycle;

Para modificar el mximo valor a 99999 y el incremento a 2, tipeamos:


alter sequence sec_codigolibros increment by 2 maxvalue 99999;

Los valores de incremento y mnimo han sido modificados, los dems atributos no especificados en la sentencia "alter sequence" se mantienen.

37 - Integridad de datos
Es importante, al disear una base de datos y las tablas que contiene, tener en cuenta la integridad de los datos, esto significa que la informacin almacenada en las tablas debe ser vlida, coherente y exacta. Hasta el momento, hemos controlado y restringido la entrada de valores a un campo mediante el tipo de dato que le definimos (cadena, numricos, etc.), la aceptacin o no de valores nulos, el valor por defecto. Tambin hemos asegurado que cada registro de una tabla sea nico definiendo una clave primaria y empleando secuencias. Oracle ofrece ms alternativas, adems de las aprendidas, para restringir y validar los datos, las veremos ordenadamente y al finalizar haremos un resumen de las mismas. Comenzamos por las restricciones. Las restricciones (constraints) son un mtodo para mantener la integridad de los datos, asegurando que los valores ingresados sean vlidos y que las relaciones entre las tablas se mantenga. Las restricciones pueden establecerse a nivel de campo o de tabla. Pueden definirse al crear la tabla ("create table") o agregarse a una tabla existente (empleando "alter table") y se pueden aplicar a un campo o a varios. Tambin es posible habilitarlas y deshabilitarlas. Oracle ofrece varios tipos de restricciones:

- not null: a nivel de campo. - primary key: a nivel de tabla. Es un campo o varios que identifican cada registro de una tabla. - foreign key: a nivel de tabla. Establece que un campo (o varios) relacione una clave primaria de una tabla con otra. - check: a nivel de tabla. Restringe los valores que pueden ingresarse en un campo especifico. - unique: a nivel de tabla. Se pueden crear, modificar y eliminar las restricciones sin eliminar la tabla y volver a crearla. Para obtener informacin de las restricciones podemos consultar los catlogos "all_objects", "all_constraints" y "all_cons_columns". El catlogo "all_constraints" retorna varias columnas, entre ellas: OWNER (propietario), CONSTRAINT_NAME (nombre de la restriccin), CONSTRAINT_TYPE (tipo de restriccin, si es primary key (P), foreign key (), unique (U), etc.), TABLE_NAME (nombre de la tabla), SEARCH_CONDITION (en caso de ser Check u otra), DELETE_RULE (), STATUS (estado), DEFERRABLE (), DEFERRED (), VALIDATED (), GENERATED (), INDEX_OWNER (), INDEX_NAME (). El catlogo "all_cons_columnas" retorna las siguientes columnas: OWNER (propietario), CONSTRAINT_NAME (nombre), TABLE_NAME (nombre de la tabla), COLUMN_NAME (campo), POSITION (posicin).

38 - Restriccin primary key


La restriccin "primary key" asegura que los valores sean nicos para cada registro. Anteriormente, para establecer una clave primaria para una tabla emplebamos la siguiente sintaxis al crear la tabla, por ejemplo:
create table libros( codigo int not null, titulo varchar(30), autor varchar(30), editorial varchar(20),

primary key(codigo) );

Cada vez que establecamos la clave primaria para la tabla, Oracle creaba automticamente una restriccin "primary key" para dicha tabla. Dicha restriccin, a la cual no le dbamos un nombre, reciba un nombre dado por Oracle que consta de una serie de letras y nmeros aleatorios. Podemos agregar una restriccin "primary key" a una tabla existente con la sintaxis bsica siguiente:
alter table NOMBRETABLA add constraint NOMBRECONSTRAINT primary key (CAMPO,...);

En el siguiente ejemplo definimos una restriccin "primary key" para nuestra tabla "libros" para asegurarnos que cada libro tendr un cdigo diferente y nico:
alter table libros add constraint PK_libros_codigo primary key(codigo);

Con esta restriccin, si intentamos ingresar un registro con un valor para el campo "codigo" que ya existe o el valor "null", aparece un mensaje de error, porque no se permiten valores duplicados ni nulos. Igualmente, si actualizamos. Por convencin, cuando demos el nombre a las restricciones "primary key" seguiremos el formato "PK_NOMBRETABLA_NOMBRECAMPO". Cuando agregamos una restriccin a una tabla que contiene informacin, Oracle controla los datos existentes para confirmar que cumplen las exigencias de la restriccin, si no los cumple, la restriccin no se aplica y aparece un mensaje de error. Por ejemplo, si intentamos definir la restriccin "primary key" para "libros" y hay registros con cdigos repetidos o con un valor "null", la restriccin no se establece. Cuando establecamos una clave primaria al definir la tabla, automticamente Oracle redefina el campo como "not null"; lo mismo sucede al agregar una restriccin "primary key", los campos que se establecen como clave primaria se redefinen automticamente "not null". Se permite definir solamente una restriccin "primary key" por tabla, que asegura la unicidad de cada registro de una tabla. Si consultamos el catlogo "user_constraints", podemos ver las restricciones "primary key" (y todos los tipos de restricciones) de todas las tablas del usuario actual. El resultado es una tabla que nos informa el propietario de la restriccin (OWNER), el nombre de la restriccin (CONSTRAINT_NAME), el tipo (CONSTRAINT_TYPE, si es "primary key" muestra una

"P"), el nombre de la tabla en la cual se aplica (TABLE_NAME), y otra informacin que no analizaremos por el momento. Tambin podemos consultar el catlogo "user_cons_columns"; nos mostrar el propietario de la restriccin (OWNER), el nombre de la restriccin (CONSTRAINT_NAME), la tabla a la cual se aplica (TABLE_NAME), el campo (COLUMN_NAME) y la posicin (POSITION).

39 - Restriccin unique
Anteriormente aprendimos la restriccin "primary key", otra restriccin que asegura valores nicos para cada registro es "unique". La restriccin "unique" impide la duplicacin de claves alternas (no primarias), es decir, especifica que dos registros no puedan tener el mismo valor en un campo. Se permiten valores nulos. Se pueden aplicar varias restricciones de este tipo a una misma tabla, y pueden aplicarse a uno o varios campos que no sean clave primaria. Se emplea cuando ya se estableci una clave primaria (como un nmero de legajo) pero se necesita asegurar que otros datos tambin sean nicos y no se repitan (como nmero de documento). La sintaxis general es la siguiente:
alter table NOMBRETABLA add constraint NOMBRERESTRICCION unique (CAMPO);

Ejemplo:
alter table alumnos add constraint UQ_alumnos_documento unique (documento);

En el ejemplo anterior se agrega una restriccin "unique" sobre el campo "documento" de la tabla "alumnos", esto asegura que no se pueda ingresar un documento si ya existe. Esta restriccin permite valores nulos, asi que si se ingresa el valor "null" para el campo "documento", se acepta.

Por convencin, cuando demos el nombre a las restricciones "unique" seguiremos la misma estructura: "UQ_NOMBRETABLA_NOMBRECAMPO". Quiz parezca innecesario colocar el nombre de la tabla, pero cuando empleemos varias tablas ver que es til identificar las restricciones por tipo, tabla y campo. Recuerde que cuando agregamos una restriccin a una tabla que contiene informacin, Oracle controla los datos existentes para confirmar que cumplen la condicin de la restriccin, si no los cumple, la restriccin no se aplica y aparece un mensaje de error. En el caso del ejemplo anterior, si la tabla contiene nmeros de documento duplicados, la restriccin no podr establecerse; si podr establecerse si tiene valores nulos. Oracle controla la entrada de datos en inserciones y actualizaciones evitando que se ingresen valores duplicados. Un campo que se estableci como clave primaria no puede definirse como clave nica; si una tabla tiene una clave primaria, puede tener una o varias claves nicas (aplicadas a otros campos que no sean clave primaria). Si consultamos el catlogo "user_constraints", podemos ver las restricciones "unique" (y todos los tipos de restricciones) de todas las tablas del usuario actual. El resultado es una tabla que nos informa el propietario de la restriccin (OWNER), el nombre de la restriccin (CONSTRAINT_NAME), el tipo (CONSTRAINT_TYPE, si es "unique" muestra una "U"), el nombre de la tabla en la cual se aplica (TABLE_NAME), y otra informacin que no analizaremos por el momento. Tambin podemos consultar el catlogo "user_cons_columns"; nos mostrar el propietario de la restriccin (OWNER), el nombre de la restriccin (CONSTRAINT_NAME), la tabla a la cual se aplica (TABLE_NAME), el campo (COLUMN_NAME) y la posicin (POSITION).

40 - Restriccion check
La restriccin "check" especifica los valores que acepta un campo, evitando que se ingresen valores inapropiados. La sintaxis bsica es la siguiente:
alter table NOMBRETABLA add constraint NOMBRECONSTRAINT check CONDICION;

Trabajamos con la tabla "libros" de una librera que tiene los siguientes campos: codigo, titulo, autor, editorial, preciomin (que indica el precio para los minoristas) y preciomay (que indica el precio para los mayoristas). Los campos correspondientes a los precios (minorista y mayorista) se definen de tipo number(5,2), es decir, aceptan valores entre -999.99 y 999.99. Podemos controlar que no se ingresen valores negativos para dichos campos agregando una restriccin "check":
alter table libros add constraint CK_libros_precio_positivo check (preciomin>=0 and preciomay>=0);

Este tipo de restriccin verifica los datos cada vez que se ejecuta una sentencia "insert" o "update", es decir, acta en inserciones y actualizaciones. Si la tabla contiene registros que no cumplen con la restriccin que se va a establecer, la restriccin no se puede establecer, hasta que todos los registros cumplan con dicha restriccin. La condicin puede hacer referencia a otros campos de la misma tabla. Por ejemplo, podemos controlar que el precio mayorista no sea mayor al precio minorista:
alter table libros add constraint CK_libros_preciominmay check (preciomay<=preciomin);

Por convencin, cuando demos el nombre a las restricciones "check" seguiremos la misma estructura: comenzamos con "CK", seguido del nombre de la tabla, del campo y alguna palabra con la cual podamos identificar fcilmente de qu se trata la restriccin, por si tenemos varias restricciones "check" para el mismo campo. Un campo puede tener varias restricciones "check" y una restriccin "check" puede incluir varios campos. Las condiciones para restricciones "check" tambin pueden incluir una lista de valores. Por ejemplo establecer que cierto campo asuma slo los valores que se listan:
... check (CAMPO in ('lunes','miercoles','viernes'));

Si un campo permite valores nulos, "null" es un valor aceptado aunque no est incluido en la condicin de restriccin. Si intentamos establecer una restriccin "check" para un campo que entra en conflicto con otra restriccin "check" establecida al mismo campo, Oracle no lo permite. Pero si establecemos una restriccin "check" para un campo que entra en conflicto con un valor "default" establecido para el mismo campo, Oracle lo permite; pero al intentar ingresar un registro, aparece un mensaje de error.

En las condiciones de chequeo no es posible incluir funciones (como "sysdate"). Un campo con una restriccin "primary key" o "unique" puede tener una (o varias) restricciones "check". En la condicin de una restriccin "check" se puede establecer que un campo no admita valores nulos:
alter table libros add constraint CK_libros_titulo check (titulo is not null);

41 - Restricciones: validacin y estados (validate - novalidate - enable - disable)


Sabemos que si agregamos una restriccin a una tabla que contiene datos, Oracle los controla para asegurarse que cumplen con la condicin de la restriccin, si algn registro no la cumple, la restriccin no se establecece. Es posible deshabilitar esta comprobacin estableciendo una restriccin sin comprobar los datos existentes en la tabla. Podemos hacerlo cuando agregamos la restriccin (de cualquier tipo) a una tabla para que Oracle acepte los valores ya almacenados que infringen la restriccin. Para ello debemos incluir la opcin "novalidate" en la instruccin "alter table":
alter table libros add constraint PK_libros_codigo primary key (codigo) novalidate;

La restriccin no se aplica en los datos existentes, pero si intentamos ingresar un nuevo valor que no cumpla la restriccin (o actualizarlo), Oracle no lo permite. Para saber si una restriccin est validada o no, podemos consultar el catlogo "user_constraints" y fijarnos lo que informa la columna "validated". Tambin podemos deshabilitar las restricciones para agregar o actualizar datos sin comprobarla:
alter table libros add constraint PK_libros_codigo primary key (codigo) disable;

Entonces, para evitar la comprobacin de datos existentes y futuros al crear la restriccin, la sintaxis bsica es la siguiente:
alter table TABLA add constraint NOMBRERESTRICCION TIPOdeRESTRICCION (CAMPO o CONDICION)--campo si es primary key o unique; condicin si es check disable novalidate;

Por defecto (si no especificamos) la opcin es "validate", es decir, controla los datos existentes y "enable", es decir, controla futuros ingresos y actualizaciones. Tambin es posible alterar la restriccin luego de haberla creado. Sintaxis:
alter table NOMBRETABLA ESTADO VALIDACION constraint NOMBRERESTRICCION;

En el ejemplo siguiente deshabilitamos la restriccin "PK_libros_codigo" para poder ingresar un valor que infrija la restriccin:
alter table libros disable validate constraint PK_libros_codigo;

Para habilitar una restriccin deshabilitada se ejecuta la misma instruccin pero con la clusula "enable":
alter table libros enable validate constraint PK_libros_codigo;

Para saber si una restriccin est habilitada o no, podemos consultar el catlogo "user_constraints" y fijarnos lo que informa la columna "status". Los estados "validate" y "novalidate" son relativamente independientes de los estados "enabled" y "disabled". Cuando habilitamos una restriccin "primary key" o "unique" con "enable", los datos existentes DEBEN cumplir con la restriccin; aunque coloquemos "novalidate" junto a "enable", Oracle no permite que se habilite la restricin y valida los datos existentes de todas maneras. No sucede lo mismo con una restriccin "check"; podemos habilitar una restriccin de control con "enable" y "novalidate", Oracle habilita la restriccin para futuros ingresos y actualizaciones y NO valida los datos existentes. Entonces, "enable" o "disable" activa o desactiva la restriccin para los nuevos datos ("enable" es la opcin predeterminada si no se especifica); "validate" o "novalidate" es la opcin para validar la restriccin en los datos existentes ("validate" es la predetermidada si se omite).

Una restriccin puede estar en los siguientes estados: - validate y enabled: comprueba los valores existentes y los posteriores ingresos y actualizaciones; - validate y disable: comprueba los valores existentes pero no las posteriores inserciones y actualizaciones; - novalidate y enabled: no comprueba los datos existentes, pero si los posteriores ingresos y actualizaciones; - novalidate y disabled: no comprueba los valores existentes ni los posteriores ingresos y actualizaciones.

42 - Restricciones: informacin (user_constraints - user_cons_columns)


El catlogo "user_constraints" muestra la informacin referente a todas las restricciones establecidas en las tablas del usuario actual, devuelve varias columnas, explicaremos algunas de ellas: - owner: propietario de la restriccin; - constraints_name: el nombre de la restriccin; - constraint_type: tipo de restriccin. Si es una restriccin de control muestra el caracter "C", si es "primary key" muestra "P", si es "unique" el caracter "U". - table_name: nombre de la tabla en la cual se estableci la restriccin; - search_condition: solamente es aplicable a restricciones de control; indica la condicin de chequeo a cumplirse. - status: indica si est habilitada (enabled) para futuras inserciones y actualizaciones o deshabilitada (disabled) - validated: indica si valida los datos existentes en la tabla (validated) o no (no validate) El catlogo "user_cons_columns" muestra la informacin referente a todas las restricciones establecidas en las tablas del usuario actual, devuelve las siguientes columnas:

- owner: propietario d la restriccin; - constraints_name: el nombre de la restriccin; - table_name: nombre de la tabla en la cual se estableci; - column_name: muestra cada campo en el cual la restriccin fue aplicada. - position: solamente es aplicable a restricciones "primary key" y "unique"; indica el orden en que fueron definidos los campos que componen la clave (primaria o nica).

43 - Restricciones: eliminacin (alter table - drop constraint)


Para eliminar una restriccin, la sintaxis bsica es la siguiente:
alter table NOMBRETABLA drop constraint NOMBRERESTRICCION;

Para eliminar la restriccin "PK_libros_codigo" de la tabla libros tipeamos:


alter table libros drop constraint PK_LIBROS_CODIGO;

Recuerde colocar el nombre de la restriccin en maysculas, sino Oracle no la reconocer. Cuando eliminamos una tabla, todas las restricciones que fueron establecidas en ella, se eliminan tambin. La condicin de control que debe cumplir una restriccin de control no puede modificarse, hay que eliminar la restriccin y volver a crearla; igualmente con las restricciones "primary key" y "unique", no pueden modificarse los campos.

44 - Indices.
Otros objetos de base de datos son los ndices.

Los ndices sirven para acceder a los registros de una tabla rpidamente, acelerando la localizacin de la informacin. Los ndices se emplean para facilitar la obtencin de informacin de una tabla. El indice de una tabla desempea la misma funcin que el ndice de un libro: permite encontrar datos rpidamente; en el caso de las tablas, localiza registros. Oracle accede a los datos de dos maneras: 1) recorriendo las tablas; comenzando el principio y extrayendo los registros que cumplen las condiciones de la consulta; lo cual implica posicionar las cabezas lectoras, leer el dato, controlar si coincide con lo que se busca (como si pasramos una a una las pginas de un libro buscando un tema especfico). 2) empleando ndices; recorriendo la estructura de rbol del ndice para localizar los registros y extrayendo los que cumplen las condiciones de la consulta (comparando con un libro, diremos que es como leer el ndice y luego de encontrar el tema buscado, ir directamente a la pgina indicada). Un ndice posibilita el acceso directo y rpido haciendo ms eficiente las bsquedas. Sin ndice, Oracle debe recorrer secuencialmente toda la tabla para encontrar un registro. Los ndices son estructuras asociadas a tablas, una tabla que almacena los campos indexados y se crean para acelerar las consultas. Entonces, el objetivo de un indice es acelerar la recuperacin de informacin. La indexacin es una tcnica que optimiza el acceso a los datos, mejora el rendimiento acelerando las consultas y otras operaciones. Es til cuando la tabla contiene miles de registros, cuando se realizan operaciones de ordenamiento y agrupamiento y cuando se combinan varias tablas (tema que veremos ms adelante). La desventaja es que consume espacio en el disco en disco y genera costo de mantenimiento (tiempo y recursos). Es importante identificar el o los campos por los que sera til crear un ndice, aquellos campos por los cuales se realizan bsquedas con frecuencia: claves primarias, claves externas o campos que combinan tablas. No se recomienda crear ndices sobre campos que no se usan con frecuencia en consultas o en tablas muy pequeas. Los cambios sobre la tabla, como insercin, actualizacin o eliminacin de registros, son incorporados automticamente. Cuando creamos una restriccin "primary key" o "unique" a una tabla, Oracle automticamente crea un ndice sobre el campo (o los campos) de la restriccin y le da el

mismo nombre que la restriccin. En caso que la tabla ya tenga un ndice, Oracle lo usa, no crea otro. Oracle permite crear distintos tipos de ndices. "Normal" es el standard de Oracle, son ndices tipo rbol binario; contiene una entrada por cada valor de clave que almacena la direccin donde se encuentra el dato. Es el tipo predeterminado y el ms comn (el nico que estudiaremos).

45 - Indices (Crear - Informacin)


Dijimos que el objetivo de un indice es acelerar la recuperacin de informacin y que es til cuando la tabla contiene miles de registros, cuando se realizan operaciones de ordenamiento y agrupamiento, etc. Es importante identificar el o los campos por los que sera til crear un ndice, aquellos campos por los cuales se realizan bsquedas con frecuencia: claves primarias, claves externas o campos que combinan tablas. No se recomienda crear ndices sobre campos que no se usan con frecuencia en consultas o en tablas muy pequeas. Para crear ndices empleamos la instruccin "create index". La sintaxis bsica es la siguiente:
create TIPOdeINDICE index NOMBREINDICE on NOMBRETABLA(CAMPOS);

Los ndices pueden ser: no nicos (los valores pueden estar repetidos) o nicos (los valores no pueden duplicarse). De modo predeterminado, si no se especifica el tipo de ndice, se crea uno no nico. En el siguiente ejemplo creamos un ndice nico sobre el campo "documento" de la tabla "empleados":
create unique index I_empleados_documento on empleados(documento);

Para identificar los ndices fcilmente, podemos agregar un prefijo al nombre del ndice, por ejemplo "I" y luego el nombre de la tabla y/o campo.

Si se intenta crear un ndice nico para un campo que tiene valores duplicados, Oracle no lo permite. Los campos de tipo "long" y "long raw" no pueden indexarse. Una tabla puede indexarse por un campo (o varios). Creamos un ndice compuesto para los campos "apellido" y "nombre":
create index I_empleados_apellidonombre on empleado(apellido,nombre);

Cuando creamos una restriccin "primary key" o "unique" sobre una tabla, Oracle automticamente crea un ndice sobre el campo (o los campos) de la restriccin y le da el mismo nombre que la restriccin. En caso que la tabla ya tenga un ndice, Oracle lo usa, no crea otro. Para obtener informacin sobre los ndices podemos consultar varios diccionarios. 1) "user_indexes": nos muestra las siguientes columnas (entre otras que no analizaremos):
INDEX_NAME INDEX_TYPE TABLE_NAME UNIQUENESS (nombre del ndice), (tipo de ndice, nosotros crearemos el stardart normal), (nombre de la tabla), (si es nico o no).

2) "user_ind_columns": nos muestra las siguientes columnas (entre otras que no analizaremos):
INDEX_NAME (nombre del ndice), TABLE_NAME (nombre de la tabla), COLUMN_NAME (nombre del campo), COLUMN_POSITION (posicin del campo),

3) "user_objects": en la columna "OBJECT_TYPE" muestra "index" si es un ndice. 4) "user_constraints": si la restriccin tiene un ndice asociado, aparece su nombre en la columna "INDEX_NAME".

46 - Indices (eliminar)
Los ndices se eliminan con "drop index"; la siguiente es la sintaxis bsica:

drop index NOMBREINDICE;

Eliminamos el ndice "I_empleados_documento":


drop index I_empleados_documento;

Los ndices usados por las restricciones "primary key" y "unique" no pueden eliminarse con "drop index", se eliminan automticamente cuando quitamos la restriccin. Si eliminamos una tabla, todos los ndices asociados a ella se eliminan.

47 - Varias tablas (join)


Hasta el momento hemos trabajado con una sola tabla, pero generalmente, se trabaja con ms de una. Para evitar la repeticin de datos y ocupar menos espacio, se separa la informacin en varias tablas. Cada tabla almacena parte de la informacin que necesitamos registrar. Por ejemplo, los datos de nuestra tabla "libros" podran separarse en 2 tablas, una llamada "libros" y otra "editoriales" que guardar la informacin de las editoriales. En nuestra tabla "libros" haremos referencia a la editorial colocando un cdigo que la identifique. Veamos:
create table libros( codigo number(4), titulo varchar2(40) not null, autor varchar2(30), codigoeditorial number(3) not null, precio number(5,2), primary key (codigo) ); create table editoriales( codigo number(3), nombre varchar2(20) not null, primary key(codigo) );

De esta manera, evitamos almacenar tantas veces los nombres de las editoriales en la tabla "libros" y guardamos el nombre en la tabla "editoriales"; para indicar la editorial de cada libro agregamos un campo que hace referencia al cdigo de la editorial en la tabla "libros" y en "editoriales". Al recuperar los datos de los libros con la siguiente instruccin:
select* from libros;

vemos que en el campo "editorial" aparece el cdigo, pero no sabemos el nombre de la editorial. Para obtener los datos de cada libro, incluyendo el nombre de la editorial, necesitamos consultar ambas tablas, traer informacin de las dos. Cuando obtenemos informacin de ms de una tabla decimos que hacemos un "join" (combinacin). Veamos un ejemplo:
select *from libros join editoriales on libros.codigoeditorial=editoriales.codigo;

Resumiendo: si distribuimos la informacin en varias tablas evitamos la redundancia de datos y ocupamos menos espacio fsico en el disco. Un join es una operacin que relaciona dos o ms tablas para obtener un resultado que incluya datos (campos y registros) de ambas; las tablas participantes se combinan segn los campos comunes a ambas tablas. Hay tres tipos de combinaciones. En los siguientes captulos explicamos cada una de ellas.

48 - Combinacin interna (join)


Un join es una operacin que relaciona dos o ms tablas para obtener un resultado que incluya datos (campos y registros) de ambas; las tablas participantes se combinan segn los campos comunes a ambas tablas. Hay tres tipos de combinaciones:
1) combinaciones internas (inner join o join), 2) combinaciones externas y 3) combinaciones cruzadas.

Tambin es posible emplear varias combinaciones en una consulta "select", incluso puede combinarse una tabla consigo misma.

La combinacin interna emplea "join", que es la forma abreviada de "inner join". Se emplea para obtener informacin de dos tablas y combinar dicha informacin en una salida. La sintaxis bsica es la siguiente:
select CAMPOS from TABLA1 join TABLA2 on CONDICIONdeCOMBINACION;

Ejemplo:
select *from libros join editoriales on codigoeditorial=editoriales.codigo;

Analicemos la consulta anterior. - especificamos los campos que aparecern en el resultado en la lista de seleccin; - indicamos el nombre de la tabla luego del "from" ("libros"); - combinamos esa tabla con "join" y el nombre de la otra tabla ("editoriales"); se especifica qu tablas se van a combinar y cmo; - cuando se combina informacin de varias tablas, es necesario especificar qu registro de una tabla se combinar con qu registro de la otra tabla, con "on". Se debe especificar la condicin para enlazarlas, es decir, el campo por el cual se combinarn, que tienen en comn. "on" hace coincidir registros de ambas tablas basndose en el valor de tal campo, en el ejemplo, el campo "codigoeditorial" de "libros" y el campo "codigo" de "editoriales" son los que enlazarn ambas tablas. Se emplean campos comunes, que deben tener tipos de datos iguales o similares. La condicion de combinacin, es decir, el o los campos por los que se van a combinar (parte "on"), se especifica segn las claves primarias y externas. Note que en la consulta, al nombrar el campo usamos el nombre de la tabla tambin. Cuando las tablas referenciadas tienen campos con igual nombre, esto es necesario para evitar confusiones y ambiguedades al momento de referenciar un campo. En el ejemplo, si no especificamos "editoriales.codigo" y solamente tipeamos "codigo", Oracle no sabr si nos referimos al campo "codigo" de "libros" o de "editoriales" y mostrar un mensaje de error indicando que "codigo" es ambiguo. Entonces, si las tablas que combinamos tienen nombres de campos iguales, DEBE especificarse a qu tabla pertenece anteponiendo el nombre de la tabla al nombre del campo, separado por un punto (.).

Si una de las tablas tiene clave primaria compuesta, al combinarla con la otra, en la clusula "on" se debe hacer referencia a la clave completa, es decir, la condicin referenciar a todos los campos clave que identifican al registro. Se puede incluir en la consulta join la clusula "where" para restringir los registros que retorna el resultado; tambin "order by", "distinct", etc.. Se emplea este tipo de combinacin para encontrar registros de la primera tabla que se correspondan con los registros de la otra, es decir, que cumplan la condicin del "on". Si un valor de la primera tabla no se encuentra en la segunda tabla, el registro no aparece; si en la primera tabla el valor es nulo, tampoco aparece. Para simplificar la sentencia podemos usar un alias para cada tabla:
select l.codigo,titulo,autor,nombre from libros l join editoriales e on l.codigoeditorial=e.codigo;

En algunos casos (como en este ejemplo) el uso de alias es para fines de simplificacin y hace ms legible la consulta si es larga y compleja, pero en algunas consultas es absolutamente necesario.

49 - Combinacin externa izquierda (left join)


Vimos que una combinacin interna (join) encuentra registros de la primera tabla que se correspondan con los registros de la segunda, es decir, que cumplan la condicin del "on" y si un valor de la primera tabla no se encuentra en la segunda tabla, el registro no aparece. Si queremos saber qu registros de una tabla NO encuentran correspondencia en la otra, es decir, no existe valor coincidente en la segunda, necesitamos otro tipo de combinacin, "outer join" (combinacin externa). Las combinaciones externas combinan registros de dos tablas que cumplen la condicin, ms los registros de la segunda tabla que no la cumplen; es decir, muestran todos los registros de las tablas relacionadas, an cuando no haya valores coincidentes entre ellas. Este tipo de combinacin se emplea cuando se necesita una lista completa de los datos de una de las tablas y la informacin que cumple con la condicin. Las combinaciones externas se realizan solamente entre 2 tablas.

Hay tres tipos de combinaciones externas: "left outer join", "right outer join" y "full outer join"; se pueden abreviar con "left join", "right join" y "full join" respectivamente. Vamos a estudiar las primeras. Se emplea una combinacin externa izquierda para mostrar todos los registros de la tabla de la izquierda. Si no encuentra coincidencia con la tabla de la derecha, el registro muestra los campos de la segunda tabla seteados a "null". En el siguiente ejemplo solicitamos el ttulo y nombre de la editorial de los libros:
select titulo,nombre from editoriales e left join libros l on codigoeditorial = e.codigo;

El resultado mostrar el ttulo y nombre de la editorial; las editoriales de las cuales no hay libros, es decir, cuyo cdigo de editorial no est presente en "libros" aparece en el resultado, pero con el valor "null" en el campo "titulo". Es importante la posicin en que se colocan las tablas en un "left join", la tabla de la izquierda es la que se usa para localizar registros en la tabla de la derecha. Entonces, un "left join" se usa para hacer coincidir registros en una tabla (izquierda) con otra tabla (derecha); si un valor de la tabla de la izquierda no encuentra coincidencia en la tabla de la derecha, se genera una fila extra (una por cada valor no encontrado) con todos los campos correspondientes a la tabla derecha seteados a "null". La sintaxis bsica es la siguiente:
select CAMPOS from TABLAIZQUIERDA left join TABLADERECHA on CONDICION;

En el siguiente ejemplo solicitamos el ttulo y el nombre la editorial, la sentencia es similar a la anterior, la diferencia est en el orden de las tablas:
select titulo,nombre from libros l left join editoriales e on codigoeditorial = e.codigo;

El resultado mostrar el ttulo del libro y el nombre de la editorial; los ttulos cuyo cdigo de editorial no est presente en "editoriales" aparecen en el resultado, pero con el valor "null" en el campo "nombre". Un "left join" puede tener clausula "where" que restringa el resultado de la consulta considerando solamente los registros que encuentran coincidencia en la tabla de la derecha, es decir, cuyo valor de cdigo est presente en "libros":

select titulo,nombre from editoriales e left join libros l on e.codigo=codigoeditorial where codigoeditorial is not null;

Tambin podemos mostrar las editoriales que NO estn presentes en "libros", es decir, que NO encuentran coincidencia en la tabla de la derecha:
select titulo,nombre from editoriales e left join libros l on e.codigo=codigoeditorial where codigoeditorial is null;

50 - Combinacin externa derecha (right join)


Vimos que una combinacin externa izquierda (left join) encuentra registros de la tabla izquierda que se correspondan con los registros de la tabla derecha y si un valor de la tabla izquierda no se encuentra en la tabla derecha, el registro muestra los campos correspondientes a la tabla de la derecha seteados a "null". Una combinacin externa derecha ("right outer join" o "right join") opera del mismo modo slo que la tabla derecha es la que localiza los registros en la tabla izquierda. En el siguiente ejemplo solicitamos el ttulo y nombre de la editorial de los libros empleando un "right join":
select titulo,nombre as editorial from libros l right join editoriales e on codigoeditorial = e.codigo;

El resultado mostrar el ttulo y nombre de la editorial; las editoriales de las cuales no hay libros, es decir, cuyo cdigo de editorial no est presente en "libros" aparece en el resultado, pero con el valor "null" en el campo "titulo". Es FUNDAMENTAL tener en cuenta la posicin en que se colocan las tablas en los "outer join". En un "left join" la primera tabla (izquierda) es la que busca coincidencias en la segunda tabla (derecha); en el "right join" la segunda tabla (derecha) es la que busca coincidencias en la primera tabla (izquierda). En la siguiente consulta empleamos un "left join" para conseguir el mismo resultado que el "right join" anterior":

select titulo,nombre from editoriales e left join libros l on codigoeditorial = e.codigo;

Note que la tabla que busca coincidencias ("editoriales") est en primer lugar porque es un "left join"; en el "right join" precedente, estaba en segundo lugar. Un "right join" hace coincidir registros en una tabla (derecha) con otra tabla (izquierda); si un valor de la tabla de la derecha no encuentra coincidencia en la tabla izquierda, se genera una fila extra (una por cada valor no encontrado) con todos los campos correspondientes a la tabla izquierda seteados a "null". La sintaxis bsica es la siguiente:
select CAMPOS from TABLAIZQUIERDA right join TABLADERECHA on CONDICION;

Un "right join" tambin puede tener clusula "where" que restringa el resultado de la consulta considerando solamente los registros que encuentran coincidencia en la tabla izquierda:
select titulo,nombre from libros l right join editoriales e on e.codigo=codigoeditorial where codigoeditorial is not null;

Mostramos las editoriales que NO estn presentes en "libros", es decir, que NO encuentran coincidencia en la tabla de la derecha empleando un "right join":
select titulo,nombre from libros l right join editoriales e on e.codigo=codigoeditorial where codigoeditorial is null;

51 - Combinacin externa completa (full join)


Vimos que un "left join" encuentra registros de la tabla izquierda que se correspondan con los registros de la tabla derecha y si un valor de la tabla izquierda no se encuentra en la tabla derecha, el registro muestra los campos correspondientes a la tabla de la derecha

seteados a "null". Aprendimos tambin que un "right join" opera del mismo modo slo que la tabla derecha es la que localiza los registros en la tabla izquierda. Una combinacin externa completa ("full outer join" o "full join") retorna todos los registros de ambas tablas. Si un registro de una tabla izquierda no encuentra coincidencia en la tabla derecha, las columnas correspondientes a campos de la tabla derecha aparecen seteadas a "null", y si la tabla de la derecha no encuentra correspondencia en la tabla izquierda, los campos de esta ltima aparecen conteniendo "null". Veamos un ejemplo:
select titulo,nombre from editoriales e full join libros l on codigoeditorial = e.codigo;

La salida del "full join" precedente muestra todos los registros de ambas tablas, incluyendo los libros cuyo cdigo de editorial no existe en la tabla "editoriales" y las editoriales de las cuales no hay correspondencia en "libros".

52 - Combinaciones cruzadas (cross)


Vimos que hay tres tipos de combinaciones: 1) combinaciones internas (join), 2) combinaciones externas (left, outer y full join) y 3) combinaciones cruzadas. Las combinaciones cruzadas (cross join) muestran todas las combinaciones de todos los registros de las tablas combinadas. Para este tipo de join no se incluye una condicin de enlace. Se genera el producto cartesiano en el que el nmero de filas del resultado es igual al nmero de registros de la primera tabla multiplicado por el nmero de registros de la segunda tabla, es decir, si hay 3 registros en una tabla y 4 en la otra, retorna 12 filas. La sintaxis bsica es sta:
select CAMPOS from TABLA1 cross join TABLA2;

Veamos un ejemplo. Un pequeo restaurante almacena los nombres y precios de sus comidas en una tabla llamada "comidas" y en una tabla denominada "postres" los mismos datos de sus postres. Si necesitamos conocer todas las combinaciones posibles para un men, cada comida con cada postre, empleamos un "cross join":

select c.nombre as "plato principal", p.nombre as "postre" from comidas c cross join postres p;

La salida muestra cada plato combinado con cada uno de los postres. Como cualquier tipo de "join", puede emplearse una clusula "where" que condicione la salida. Este tipo de join no es muy utilizado.

53 - Autocombinacin
Dijimos que es posible combinar una tabla consigo misma. Un pequeo restaurante tiene almacenadas sus comidas en una tabla llamada "comidas" que consta de los siguientes campos:
- nombre varchar(20), - precio decimal (4,2) y - rubro char(6)-- que indica con 'plato' si es un plato principal y 'postre' si es postre.

Podemos obtener la combinacin de todos los platos empleando un "cross join" con una sola tabla:
select c1.nombre, c2.nombre, c1.precio+c2.precio as total from comidas c1 cross join comidas c2;

En la consulta anterior aparecern filas duplicadas, para evitarlo debemos emplear un "where":
select c1.nombre as "plato principal", c2.nombre as postre, c1.precio+c2.precio as total from comidas c1 cross join comidas c2 where c1.rubro='plato' and c2.rubro='postre';

En la consulta anterior se emple un "where" que especifica que se combine "plato" con "postre".

En una autocombinacin se combina una tabla con una copia de si misma. Para ello debemos utilizar 2 alias para la tabla. Para evitar que aparezcan filas duplicadas, debemos emplear un "where". Tambin se puede realizar una autocombinacin con "join":
select c1.nombre as "plato principal", c2.nombre as postre, c1.precio+c2.precio as total from comidas c1 join comidas c2 on c1.codigo<>c2.codigo where c1.rubro='plato' and c2.rubro='postre';

Para que no aparezcan filas duplicadas se agrega un "where".

54 - Combinaciones y funciones de agrupamiento


Podemos usar "group by" y las funciones de agrupamiento con combinaciones de tablas. Para ver la cantidad de libros de cada editorial consultando la tabla "libros" y "editoriales", tipeamos:
select nombre as editorial, count(*) as cantidad from editoriales e join libros l on codigoeditorial=e.codigo group by e.nombre;

Las editoriales que no tienen libros no aparecen en la salida porque empleamos un "join". Empleamos otra funcin de agrupamiento con "left join". Para conocer el mayor precio de los libros de cada editorial usamos la funcin "max()", hacemos un "left join" y agrupamos por nombre de la editorial:
select nombre as editorial, max(precio) as "mayor precio" from editoriales e left join libros l on codigoeditorial=e.codigo group by nombre;

En la sentencia anterior, mostrar, para la editorial de la cual no haya libros, el valor "null" en la columna calculada.

55 - Combinar ms de 2 tablas
Podemos hacer un "join" con ms de dos tablas. La librera almacena los datos de sus libros en tres tablas: libros, editoriales y autores. En la tabla "libros" un campo "codigoautor" hace referencia al autor y un campo "codigoeditorial" referencia la editorial. Para recuperar todos los datos de los libros empleamos la siguiente consulta:
select titulo,a.nombre,e.nombre from autores a join libros l on codigoautor=a.codigo join editoriales e on codigoeditorial=e.codigo;

Analicemos la consulta anterior. Indicamos el nombre de la tabla luego del "from" ("autores"), combinamos esa tabla con la tabla "libros" especificando con "on" el campo por el cual se combinarn; luego debemos hacer coincidir los valores para el enlace con la tabla "editoriales" enlazndolas por los campos correspondientes. Utilizamos alias para una sentencia ms sencilla y comprensible. Note que especificamos a qu tabla pertenecen los campos cuyo nombre se repiten en las tablas, esto es necesario para evitar confusiones y ambiguedades al momento de referenciar un campo. Los libros cuyo cdigo de autor no se encuentra en "autores" y cuya editorial no existe en "editoriales", no aparecen porque realizamos una combinacin interna. Podemos combinar varios tipos de join en una misma sentencia:
select titulo,a.nombre,e.nombre from autores a right join libros l on codigoautor=a.codigo left join editoriales e on codigoeditorial=e.codigo;

En la consulta anterior solicitamos el ttulo, autor y editorial de todos los libros que encuentren o no coincidencia con "autores" ("right join") y a ese resultado lo combinamos con "editoriales", encuentren o no coincidencia.

Es posible realizar varias combinaciones para obtener informacin de varias tablas. Las tablas deben tener claves externas relacionadas con las tablas a combinar. En consultas en las cuales empleamos varios "join" es importante tener en cuenta el orden de las tablas y los tipos de "join".

56 - Otros tipos de combinaciones


Hemos aprendido que existen varios tipos de combinaciones en Oracle: 1) combinaciones internas (inner join o simplemente join), 2) combinaciones externas (left join, right join y full join) 3) combinaciones cruzadas (cross join). Tambin vimos que es posible emplear varios tipos de combinaciones en una consulta, incluso puede combinarse una tabla consigo misma. Existen otros tipos de "join" en Oracle, que veremos rpidamente, ya que se resuelven con los que vimos anteriormente, bsicamente lo que cambia es la sintaxis. 1) combinacin natural: realiza un join entre dos tablas cuando los campos por los cuales se enlazan tienen el mismo nombre. Involucra claves primarias y forneas. Sintaxis:
select CAMPOS from TABLA1 natural join TABLA2;

Ejemplo:
select titulo,nombre as editorial from libros natural join editoriales;

En el ejemplo anterior la tabla "libros" combina su campo "codigoeditorial" con el campo "codigoeditorial" de "editoriales". La clusula "on" no aparece, este "join" no necesita condicin de enlace porque Oracle busca los campos con nombres iguales de ambas tablas (ambas tablas deben tener un nico campo con idntico nombre, si tiene ms de un campo con igual nombre, Oracle no podr realizar el enlace y mostrar un mensaje de error).

2) combinacin empleando la clusula "using": permite especificar el campo (o los campos) por el cual se enlazarn las tablas; los campos de ambas tablas DEBEN tener el mismo nombre y ser de tipos compatibles. Sintaxis:
select CAMPOS from TABLA1 join TABLA2 using (CAMPOenCOMUN);

Ejemplo:
select titulo,nombre as editorial from libros join editoriales using (codigoeditorial);

En el ejemplo anterior la tabla "libros" combina su campo "codigoeditorial" con el campo "codigoeditorial" de "editoriales". La clusula "on" no aparece, es reemplazada por "using" seguido del nombre del campo en comn por el cual se enlazan. 3) combinacin izquierda empleando "join" y el operador o modificador "(+)": Podemos obtener el mismo resultado que un "left join" empleando "join" y el modificador "(+)", con lo cual se indica que se consideran los registros con valor nulo. La sintaxis es la siguiente:
select CAMPOS from TABLA1 join TABLA2 on CAMPOTABLA1=CAMPOTABLA2(+);

Es decir, se coloca el modificador "(+)" luego del campo de la tabla de la derecha para indicar que se incluyan los que tienen valor nulo. Las siguientes consultas retornan el mismo resultado. Una de ellas emplea "left join" y la otra un "join" con el modificador "(+)":
select titulo,nombre as editorial from libros l left join editoriales l on l.codigoeditorial = e.codigoeditorial; select titulo,nombre as editorial from libros l join editoriales e on l.codigoeditorial = e.codigoeditorial(+);

Ambas mostrarn el ttulo y nombre de la editorial; los libros cuyo cdigo de editorial no est presente en "editoriales" aparecern con el valor "null" en la columna "editorial".

4) combinacin derecha empleando "join" y el modificador "(+)": de modo similar al anterior, podemos obtener el mismo resultado que un "right join" empleando "join" y el modificador "(+)", con lo cual se indica que se consideren los registros con valor nulo. La sintaxis es la siguiente:
select CAMPOS from TABLA1 join TABLA2 on CAMPOTABLA1(+)=CAMPOTABLA2;

Entonces, se coloca el modificador "(+)" luego del campo de la tabla de la izquierda para indicar que se incluyan los que tienen valor nulo. Las siguientes consultas retornan el mismo resultado. Una de ellas emplea "right join" y la otra un "join" con el modificador "(+)":
select titulo,nombre as editorial from editoriales e right join libros l on e.codigoeditorial = l.codigoeditorial; select titulo,nombre as editorial from editoriales e join libros l on e.codigoeditorial(+) = l.codigoeditorial;

Ambas mostrarn el ttulo y nombre de la editorial; las editoriales que no encuentran coincidencia en "libros", aparecen con el valor "null" en la columna "titulo". Si la condicin de combinacin es compuesta (ms de un campo), DEBE colocarse el modificador "(+)" en todos los campos que forman parte del enlace. No se puede colocar el modificador en campos de distintas tablas. La siguiente combinacin producir un mensaje de error:
select titulo,nombre as editorial from libros l join editoriales e on l.codigoeditorial(+)= e.codigoeditorial(+);

57 - Clave fornea
Un campo que no es clave primaria en una tabla y sirve para enlazar sus valores con otra tabla en la cual es clave primaria se denomina clave fornea, externa o ajena.

En el ejemplo de la librera en que utilizamos las tablas "libros" y "editoriales" con estos campos:
libros: codigo (clave primaria), titulo, autor, codigoeditorial, precio y editoriales: codigo (clave primaria), nombre.

el campo "codigoeditorial" de "libros" es una clave fornea, se emplea para enlazar la tabla "libros" con "editoriales" y es clave primaria en "editoriales" con el nombre "codigo". Las claves forneas y las claves primarias deben ser del mismo tipo para poder enlazarse. Si modificamos una, debemos modificar la otra para que los valores se correspondan. Cuando alteramos una tabla, debemos tener cuidado con las claves forneas. Si modificamos el tipo, longitud o atributos de una clave fornea, sta puede quedar inhabilitada para hacer los enlaces. Entonces, una clave fornea es un campo (o varios) empleados para enlazar datos de 2 tablas, para establecer un "join" con otra tabla en la cual es clave primaria.

58 - Restricciones (foreign key)


Hemos visto que una de las alternativas que Oracle ofrece para asegurar la integridad de datos es el uso de restricciones (constraints). Aprendimos que las restricciones se establecen en tablas y campos asegurando que los datos sean vlidos y que las relaciones entre las tablas se mantengan. Vimos tres tipos de restricciones:
primary key, unique y check. Ahora veremos "foreign key".

Con la restriccin "foreign key" se define un campo (o varios) cuyos valores coinciden con la clave primaria de la misma tabla o de otra, es decir, se define una referencia a un campo con una restriccin "primary key" o "unique" de la misma tabla o de otra. La integridad referencial asegura que se mantengan las referencias entre las claves primarias y las externas. Por ejemplo, controla que si se agrega un cdigo de editorial en la tabla "libros", tal cdigo exista en la tabla "editoriales". Tambin controla que no pueda eliminarse un registro de una tabla ni modificar la clave primaria si una clave externa hace referencia al registro. Por ejemplo, que no se pueda eliminar o modificar un cdigo de "editoriales" si existen libros con dicho cdigo.

La siguiente es la sintaxis parcial general para agregar una restriccin "foreign key":
alter table NOMBRETABLA1 add constraint NOMBRERESTRICCION foreign key (CAMPOCLAVEFORANEA) references NOMBRETABLA2 (CAMPOCLAVEPRIMARIA);

Analicmosla: - NOMBRETABLA1 referencia el nombre de la tabla a la cual le aplicamos la restriccin, - NOMBRERESTRICCION es el nombre que le damos a la misma, - luego de "foreign key", entre parntesis se coloca el campo de la tabla a la que le aplicamos la restriccin que ser establecida como clave fornea, - luego de "references" indicamos el nombre de la tabla referenciada y el campo que es clave primaria en la misma, a la cual hace referencia la clave fornea. El campo de la tabla referenciada debe tener definida una restriccin "primary key" o "unique"; si no la tiene, aparece un mensaje de error. Para agregar una restriccin "foreign key" al campo "codigoeditorial" de "libros", tipeamos:
alter table libros add constraint FK_libros_codigoeditorial foreign key (codigoeditorial) references editoriales(codigo);

En el ejemplo implementamos una restriccin "foreign key" para asegurarnos que el cdigo de la editorial de la de la tabla "libros" ("codigoeditorial") est asociada con un cdigo vlido en la tabla "editoriales" ("codigo"). Cuando agregamos cualquier restriccin a una tabla que contiene informacin, Oracle controla los datos existentes para confirmar que cumplen con la restriccin, si no los cumple, la restriccin no se aplica y aparece un mensaje de error. Por ejemplo, si intentamos agregar una restriccin "foreign key" a la tabla "libros" y existe un libro con un valor de cdigo para editorial que no existe en la tabla "editoriales", la restriccin no se agrega. Acta en inserciones. Si intentamos ingresar un registro (un libro) con un valor de clave fornea (codigoeditorial) que no existe en la tabla referenciada (editoriales), Oracle muestra un mensaje de error. Si al ingresar un registro (un libro), no colocamos el valor para el campo clave fornea (codigoeditorial), almacenar "null", porque esta restriccin permite valores nulos (a menos que se haya especificado lo contrario al definir el campo). Acta en eliminaciones y actualizaciones. Si intentamos eliminar un registro o modificar un valor de clave primaria de una tabla si una clave fornea hace referencia a dicho registro, Oracle no lo permite (excepto si se permite la accin en cascada, tema que veremos

posteriormente). Por ejemplo, si intentamos eliminar una editorial a la que se hace referencia en "libros", aparece un mensaje de error. Esta restriccin (a diferencia de "primary key" y "unique") no crea ndice automticamente. La cantidad y tipo de datos de los campos especificados luego de "foreign key" DEBEN coincidir con la cantidad y tipo de datos de los campos de la clusula "references". Esta restriccin se puede definir dentro de la misma tabla (lo veremos ms adelante) o entre distintas tablas. Una tabla puede tener varias restricciones "foreign key". No se puede eliminar una tabla referenciada en una restriccin "foreign key", aparece un mensaje de error. Una restriccion "foreign key" no puede modificarse, debe eliminarse (con "alter table" y "drop constraint") y volverse a crear. Las restricciones "foreign key" se eliminan automticamente al eliminar la tabla en la que fueron definidas. Para ver informacin acerca de esta restriccin podemos consultar los diccionarios "user_constraints" y "user_cons_columns".

59 - Restricciones foreign key en la misma tabla


La restriccin "foreign key", que define una referencia a un campo con una restriccin "primary key" o "unique" se puede definir entre distintas tablas (como hemos aprendido) o dentro de la misma tabla. Veamos un ejemplo en el cual definimos esta restriccin dentro de la misma tabla. Una mutual almacena los datos de sus afiliados en una tabla llamada "afiliados". Algunos afiliados inscriben a sus familiares. La tabla contiene un campo que hace referencia al afiliado que lo incorpor a la mutual, del cual dependen. La estructura de la tabla es la siguiente:
create table afiliados(

numero number(5), documento char(8) not null, nombre varchar2(30), afiliadotitular number(5), primary key (documento), unique (numero) );

En caso que un afiliado no haya sido incorporado a la mutual por otro afiliado, el campo "afiliadotitular" almacenar "null". Establecemos una restriccin "foreign key" para asegurarnos que el nmero de afiliado que se ingrese en el campo "afiliadotitular" exista en la tabla "afiliados":
alter table afiliados add constraint FK_afiliados_afiliadotitular foreign key (afiliadotitular) references afiliados (numero);

La sintaxis es la misma, excepto que la tabla se autoreferencia. Luego de aplicar esta restriccin, cada vez que se ingrese un valor en el campo "afiliadotitular", Oracle controlar que dicho nmero exista en la tabla, si no existe, mostrar un mensaje de error. Si intentamos eliminar un afiliado que es titular de otros afiliados, no se podr hacer, a menos que se haya especificado la accin en cascada (prximo tema). Si intentamos modificar un afiliado que es titular de otros afiliados, no se podr hacer, a menos que se haya especificado la accin en cascada para actualizaciones (prximo tema).

60 - Restricciones foreign key (eliminacin)


Podemos eliminar una restriccin "foreign key" con "alter table". La sintaxis bsica es la misma que para cualquier otra restriccin:
alter table TABLA drop constraint NOMBRERESTRICCION;

Eliminamos la restriccin "foreign key" de "libros":


alter table libros drop constraint FK_libros_codigoeditorial;

No se puede eliminar una tabla si una restriccin "foreign key" hace referencia a ella. Cuando eliminamos una tabla que tiene una restriccin "foreign key", la restriccin tambin se elimina.

61 - Restricciones foreign key deshabilitar y validar


Aprendimos (cuando vimos los otros tipos de restricciones) que si agregamos una restriccin a una tabla que contiene datos, Oracle los controla para asegurarse que cumplen con la restriccin y que es posible deshabilitar esta comprobacin. Lo hacemos incluyendo la opcin "novalidate" en la instruccin "alter table"; en tal caso, La restriccin no se aplica en los datos existentes, pero si intentamos ingresar un nuevo valor que no cumpla la restriccin (o actualizarlo), Oracle no lo permite. En el siguiente ejemplo agregamos una restriccin "foreign key" sobre el campo "codigoeditorial" de "libros" especificando que no valide los datos existentes:
alter table libros add constraint FK_libros_codigoeditorial foreign key (codigoeditorial) references editoriales novalidate;

La restriccin no se aplica en los datos existentes, pero si intentamos ingresar un nuevo registro en "libros" cuyo cdigo de editorial no exista en "editoriales", Oracle no lo permitir. Para saber si una restriccin est validada o no, podemos consultar el catlogo "user_constraints" y fijarnos lo que informa la columna "validated". Tambin aprendimos que podemos deshabilitar las restricciones para agregar o actualizar datos sin comprobarla. Para evitar la comprobacin de datos en inserciones y actualizaciones agregamos "disable" en la instruccin "alter table". En el ejemplo siguiente deshabilitamos la restriccin "FK_libros_codigoeditorial" para poder ingresar un valor que infrija la restriccin:
alter table libros disable validate constraint FK_libros_codigoeditorial;

Para habilitar una restriccin "foreign key" deshabilitada se ejecuta la misma instruccin pero con la clusula "enable". Por defecto (si no se especifica) las opciones son "validate" (es decir, controla los datos existentes) y "enable" (controla futuros ingresos y actualizaciones). Para saber si una restriccin est habilitada o no, podemos consultar el catlogo "user_constraints" y fijarnos lo que informa la columna "status". Podemos habilitar una restriccin "foreign key" con "enable" y "novalidate", en tal caso Oracle habilita la restriccin para futuros ingresos y actualizaciones y NO valida los datos existentes. Entonces, "enable" o "disable" activa o desactiva la restriccin para los nuevos datos ("enable" es la opcin predeterminada si no se especifica); "validate" o "novalidate" es la opcin para validar la restriccin en los datos existentes ("validate" es la predeterminada si se omite). La sintaxis bsica al agregar la restricccin "foreign key" es la siguiente:
alter table NOMBRETABLA1 add constraint NOMBRECONSTRAINT foreign key (CAMPOCLAVEFORANEA) references NOMBRETABLA2 (CAMPOCLAVEPRIMARIA) ESTADO VALIDACION;

La sintaxis para modificar una restriccin es:


alter table NOMBRETABLA ESTADO VALIDACION constraint NOMBRERESTRICCION;

62 - Restricciones foreign key (acciones)


Continuamos con la restriccin "foreign key". Si intentamos eliminar un registro de la tabla referenciada por una restriccin "foreign key" cuyo valor de clave primaria existe referenciada en la tabla que tiene dicha restriccin, la accin no se ejecuta y aparece un mensaje de error. Esto sucede porque, por defecto, para eliminaciones, la opcin de la restriccin "foreign key" es "no action". La restriccin "foreign key" tiene la clusula "on delete", que son opcionales. Esta clusula especifica cmo debe actuar Oracle frente a eliminaciones en las tablas referenciadas en la restriccin.

Las opciones para estas clusulas son las siguientes: - "set null": indica que si eliminamos un registro de la tabla referenciada (TABLA2) cuyo valor existe en la tabla principal (TABLA1), dicho registro se elimine y los valores coincidentes en la tabla principal se seteen a "null". - "cascade": indica que si eliminamos un registro de la tabla referenciada en una "foreign key" (TABLA2), los registros coincidentes en la tabla principal (TABLA1), tambin se eliminen; es decir, si eliminamos un registro al cual una clave fornea referencia, dicha eliminacin se extiende a la otra tabla (integridad referencial en cascada). - "no action": es la predeterminada; indica que si se intenta eliminar un registro de la tabla referenciada por una "foreign key", Oracle no lo permita y muestre un mensaje de error. Se establece omitiendo la clusula "on delete" al establecer la restriccin. La sintaxis completa paar agregar esta restriccin a una tabla es la siguiente:
alter table TABLA1 add constraint NOMBRERESTRICCION foreign key (CAMPOCLAVEFORANEA) references TABLA2(CAMPOCLAVEPRIMARIA) on delete OPCION;

Veamos un ejemplo. Definimos una restriccin "foreign key" a la tabla "libros" estableciendo el campo "codigoeditorial" como clave fornea que referencia al campo "codigo" de la tabla "editoriales". La tabla "editoriales" tiene como clave primaria el campo "codigo". Especificamos la accin en cascada para las eliminaciones:
alter table libros add constraint FK_libros_codigoeditorial foreign key (codigoeditorial) references editoriales(codigo) on delete cascade;

Si luego de establecer la restriccin anterior, eliminamos una editorial de "editoriales" cuyo valor de cdigo est presente en "libros", se elimina dicha editorial y todos los libros de tal editorial. Si consultamos "user_constraints", en la columna "delete_rule" mostrar "cascade". Para definir una restriccin "foreign key" sobre la tabla "libros" estableciendo el campo "codigoeditorial" como clave fornea que referencia al campo "codigo" de la tabla "editoriales" especificando la accin de seteo a "null" tipeamos:
alter table libros add constraint FK_libros_codigoeditorial foreign key (codigoeditorial) references editoriales(codigo) on delete set null;

Si luego de establecer la restriccin anterior, eliminamos una editorial de "editoriales" cuyo valor de cdigo est presente en "libros", se elimina dicha editorial y todos los valores de libros que coinciden con tal editorial se setean a null. Si consultamos "user_constraints", en la columna "delete_rule" mostrar "set null". Sintetizando, si al agregar una restriccin "foreign key": - no se especifica accin para eliminaciones, y se intenta eliminar un registro de la tabla referenciada en la "foreign key" (editoriales) cuyo valor de clave primaria (codigo) existe en la tabla principal (libros), la accin no se realiza. - se especifica "cascade" para eliminaciones ("on delete cascade") y elimina un registro de la tabla referenciada (editoriales) cuyo valor de clave primaria (codigo) existe en la tabla principal(libros), la eliminacin de la tabla referenciada (editoriales) se realiza y se eliminan de la tabla principal (libros) todos los registros cuyo valor coincide con el registro eliminado de la tabla referenciada (editoriales). - se especifica accin para eliminaciones ("on delete set null") y se elimina un registro de la tabla referenciada en la "foreign key" (editoriales) cuyo valor de clave primaria (codigo) existe en la tabla principal (libros), la accin se realiza y se setean a "null" todos los valores coincidentes en la tabla principal (libros). La restriccin "foreign key" NO tiene una clusula para especificar acciones para actualizaciones. Si intentamos actualizar un registro de la tabla referenciada por una restriccin "foreign key" cuyo valor de clave primaria existe referenciada en la tabla que tiene dicha restriccin, la accin no se ejecuta y aparece un mensaje de error. Esto sucede porque, por defecto (y como nica opcin), para actualizaciones existe "no action".

63 - Informacin de user_constraints
El diccionario "user_constraints" devuelve mucha informacin referente a las restricciones, las que estudiamos son las siguientes columnas: - owner: propietario de la restriccin; - constraint_name: nombre de la restriccin; - constraint_type: tipo de restriccin. Si es una restriccin "primary key" aparece "P", si es de control, "C", si es nica, "U", si es una "foreign key" "R";

- table_name: nombre de la tabla sobre la cual est aplicada la restriccin; - search_condition: solamente es aplicable a restricciones de control; indica la condicin de chequeo a cumplirse. - delete_rule: solamente aplicable a restricciones "foreign key". Puede contener 3 valores: 1) "set null": indica que si eliminamos un registro de la tabla referenciada (TABLA2) cuyo valor existe en la tabla principal (TABLA1), dicho registro se elimina y los valores coincidentes en la tabla principal se seteen a "null"; 2) "cascade": indica que si eliminamos un registro de la tabla referenciada en una "foreign key" (TABLA2), los registros coincidentes en la tabla principal (TABLA1), tambin se eliminan; 3) "no action": indica que si se intenta eliminar un registro de la tabla referenciada por una "foreign key", Oracle no lo permite. - status: indica si est habilitada (enabled) para futuras inserciones y actualizaciones o deshabilitada (disabled) - validated: indica si valida los datos existentes en la tabla (validated) o no (no validate).

64 - Restricciones al crear la tabla


Hasta el momento hemos agregado restricciones a tablas existentes con "alter table"; tambin pueden establecerse al momento de crear una tabla (en la instruccin "create table"). En el siguiente ejemplo creamos la tabla "libros" con varias restricciones:
create table libros( codigo number(5), titulo varchar2(40), codigoautor number(4), codigoeditorial number(3), precio number(5,2) default 0, constraint PK_libros_codigo primary key (codigo), constraint UQ_libros_tituloautor unique (titulo,codigoautor), constraint CK_libros_codigoeditorial check (codigoeditorial is not null), constraint FK_libros_editorial foreign key (codigoeditorial) references editoriales(codigo) on delete cascade, constraint FK_libros_autores foreign key (codigoautor)

references autores(codigo) on delete set null, constraint CK_libros_preciononulo check (precio is not null) disable, constraint CK_precio_positivo check (precio>=0) );

En el ejemplo definimos las siguientes restricciones: - "primary key" sobre el campo "codigo"; - "unique" para los campos "titulo" y "codigoautor"; - de control sobre "codigoeditorial" que no permite valores nulos; - "foreign key" para establecer el campo "codigoeditorial" como clave externa que haga referencia al campo "codigo" de "editoriales y permita eliminaciones en cascada; - "foreign key" para establecer el campo "codigoautor" como clave externa que haga referencia al campo "codigo" de "autores" y permita eliminaciones "set null"; - de control sobre "precio" para que no admita valores nulos, deshabilitada; - "check" para el campo "precio" que no admita valores negativos. Las restricciones se agregan a la tabla, separadas por comas; colocando "constraint" seguido del nombre de la restriccin, el tipo y los campos (si es una "primary key", "unique" o "foreign key") o la condicin (si es de control); tambin puede especificarse el estado y la validacin de datos (por defecto es "enable" y "validate"); y en el caso de las "foreign key", la opcin para eliminaciones. Si definimos una restriccin "foreign key" al crear una tabla, la tabla referenciada debe existir y debe tener definida la clave primaria o nica a la cual hace referencia la "foreign key".

65 - Unin
Las operaciones de conjuntos combinan los resultados de dos o ms consultas "select" en un nico resultado. Se usan cuando los datos que se quieren obtener pertenecen a distintas tablas y no se puede acceder a ellos con una sola consulta.

Es necesario que las tablas referenciadas tengan tipos de datos similares, la misma cantidad de campos y el mismo orden de campos en la lista de seleccin de cada consulta. Hay tres operadores de conjuntos: union, intersect y minus. Veremos en primer lugar "union". La sintaxis para unir dos consultas con el operador "union" es la siguiente:
CONSULTA1 union CONSULTA2;

Recuerde que las consultas DEBEN tener el mismo numero de valores retornados y los valores deben ser del mismo tipo. Veamos un ejemplo. Una academia de enseanza de idiomas da clases de ingls y frances; almacena los datos de los alumnos que estudian ingls en una tabla llamada "ingles" y los que estn inscriptos en "francs" en una tabla denominada "frances". La academia necesita el nombre y domicilio de todos los alumnos, de todos los cursos para enviarles una tarjeta de felicitacin para el da del alumno. Para obtener los datos necesarios de ambas tablas en una sola consulta necesitamos realizar una unin:
select nombre, domicilio from ingles union select nombre, domicilio from frances;

El primer "select" devuelve el nombre y domicilio de todos los alumnos de "ingles"; el segundo, el nombre y domicilio de todos los alumnos de "frances". Esta sentencia de unin retornar la combinacion de los resultados de ambas consultas "select", mostrando el nombre y domicilio de los registros de ambas tablas. Los encabezados del resultado de una unin son los que se especifican en el primer "select". El operador de conjunto "union" no retorna duplicados; es decir, si un registro de la primer consulta es igual a otro registro de la segunda consulta, tal registro aparece una sola vez. Si queremos que se incluyan TODOS los registros, an duplicados, debemos emplear "union all":
select nombre,domicilio from ingles union all select nombre,domicilio from frances;

En el ejemplo anterior, si un registro de la primer consulta es igual a otro registro de la segunda consulta, tal registro aparece dos veces; es decir, si un alumno est cursando ambos idiomas, aparecer dos veces en el resultado.

"union" puede combinarse con la clusula "order by".

66 - Interseccin
Continuamos aprendiendo las operaciones de conjuntos. Aprendimos "union" y "union all", ahora veremos "intersect". Como cualquier otra operacin de conjuntos, "intersect" se emplea cuando los datos que se quieren obtener pertenecen a distintas tablas y no se puede acceder a ellos con una sola consulta. Del mismo modo, las tablas referenciadas DEBEN tener tipos de datos similares, la misma cantidad de campos y el mismo orden de campos en la lista de seleccin de cada consulta que intervenga en la interseccin. "intersect" devuelve la interseccin de las consultas involucradas; es decir, el resultado retornar los registros que se encuentran en la primera y segunda consulta (y dems si las hubiere), o sea, los registros que todas las consultas tienen en comn. Sintaxis:
SENTENCIASELECT1 intersect SENTENCIASELECT2;

No olvide que las consultas DEBEN tener el mismo numero de valores retornados y los valores deben ser del mismo tipo. Una academia de enseanza de idiomas da clases de ingls, frances y portugues; almacena los datos de los alumnos que estudian ingls en una tabla llamada "ingles", los que estn inscriptos en "francs" en una tabla denominada "frances" y los que aprenden portugues en la tabla "portugues". La academia necesita el nombre y domicilio de todos los alumnos que cursan los tres idiomas para enviarles una tarjeta de descuento. Para obtener los datos necesarios de las tres tablas en una sola consulta necesitamos realizar una intreseccin:
select nombre, domicilio from ingles intersect select nombre, domicilio from frances intersect select nombre, domicilio from portugues;

El primer "select" devuelve el nombre y domicilio de todos los estudiantes de ingls; el segundo, el nombre y domicilio de todos los inscriptos a francs y la tercera los mismos campos de los alumnos de "portugues". Esta sentencia de interseccin retornar los registros que coinciden en las tres consultas "select". "intersect" puede combinarse con la clusula "order by".

67 - Minus
Continuamos aprendiendo las operaciones de conjuntos. Aprendimos "union", "union all", "intersect", nos resta ver "minus" (resta, diferencia). Como cualquier otra operacin de conjuntos, "minus" se emplea cuando los datos que se quieren obtener pertenecen a distintas tablas y no se puede acceder a ellos con una sola consulta. Del mismo modo, las tablas referenciadas DEBEN tener tipos de datos similares, la misma cantidad de campos y el mismo orden de campos en la lista de seleccin de cada consulta que intervenga en la operacin de resta. "minus" (diferencia) devuelve los registros de la primera consulta que no se encuentran en segunda consulta, es decir, aquellos registros que no coinciden. Es el equivalente a "except" en SQL. Sintaxis:
SENTENCIASELECT1 minus SENTENCIASELECT2;

No olvide que las consultas DEBEN tener el mismo numero de valores retornados y los valores deben ser del mismo tipo. Una academia de enseanza de idiomas da clases de ingls y frances; almacena los datos de los alumnos que estudian ingls en una tabla llamada "ingles" y los que estn inscriptos en "francs" en una tabla denominada "frances". La academia necesita el nombre y domicilio de todos los alumnos que cursan solamente ingls (no presentes en la tabla "frances") para enviarles publicidad referente al curso de francs. Empleamos el operador "minus" para obtener dicha informacin:
select nombre, domicilio from ingles minus select nombre,domicilio from frances;

Obtenemos los registros de la primer consulta que NO coinciden con ningn registro de la segunda consulta. "minus" puede combinarse con la clusula "order by". Se pueden combinar ms de dos sentencias con "minus".

68 - Agregar campos (alter table- add)


"alter table" permite modificar la estructura de una tabla. Podemos utilizarla para agregar, modificar y eliminar campos de una tabla. Para agregar un nuevo campo a una tabla empleamos la siguiente sintaxis bsica:
alter table NOMBRETABLA add NOMBRENUEVOCAMPO DEFINICION;

En el siguiente ejemplo agregamos el campo "cantidad" a la tabla "libros", de tipo number(4), con el valor por defecto cero y que NO acepta valores nulos:
alter table libros add cantidad number(4) default 0 not null;

Puede verificarse la alteracin de la estructura de la tabla tipeando:


describe libros;

Para agregar un campo "not null", la tabla debe estar vaca o debe especificarse un valor por defecto. Esto es sencillo de entender, ya que si la tabla tiene registros, el nuevo campo se llenara con valores nulos; si no los admite, debe tener un valor por defecto para llenar tal campo en los registros existentes.

69 - Modificar campos (alter tablemodify)


"alter table" permite modificar la estructura de una tabla. Hemos aprendido a agregar campos, tambin podemos modificarlos.

Para modificar un campo empleamos la siguiente sintaxis:


alter table NOMBRETABLA modify NOMBRECAMPO NUEVADEFINICION;

En el siguiente ejemplo modificamos el campo "precio" de la tabla "libros" para que tome valores de 6 dgitos incluyendo 2 decimales y no acepte valores nulos:
alter table libros modify precio number(6,2) not null;

Puede verificarse la alteracin de la estructura de la tabla tipeando:


describe libros;

Podemos modificar de un campo: el tipo de dato, la escala y/o precisin, la longitud, la aceptacin de valores nulos, el valor por defecto. Se pueden modificar todos los atributos o algunos; los que no se especifican, no cambian. Algunas consideraciones para tener en cuenta al modificar los campos de una tabla: a) si se cambia el tipo de dato de un campo, la tabla debe estar vaca. Por ejemplo, de number a caracteres o viceversa. b) no puede modificarse el tipo de dato de un campo "foreign key" o referenciado por una "foreign key", a menos que el cambio no afecte la restriccin. c) no se puede cambiar el tipo de dato de un campo que es "foreign key" o que es referenciado por una "foreign key". d) para modificar un campo disminuyendo la longitud (precisin o escala) del tipo de dato, la tabla DEBE estar vaca, los registros DEBEN tener valores nulos en tal campo o los datos existentes deben ser inferiores o iguales a la nueva longitud. Para alterar la longitud (escala o precisin) aumentndola, no es necesario que la tabla est vaca. e) se puede modificar un campo definido "null" a "not null", siempre que la tabla est vaca o no contenga valores nulos. f) no puede redefinirse como "not null" un campo que es clave primaria. g) si un campo tiene un valor por defecto y se modifica el tipo de dato de tal campo, Oracle analiza que el valor por defecto pueda convertirse al nuevo tipo de dato cuando sea necesario insertarlo; si el valor por defecto no se puede convertir al nuevo tipo de dato que se intenta modificar, la modificacin del campo no se realiza. Por ejemplo, si un campo definido char(8) tiene un valor por defecto '00000000' y se modifica tal campo a tipo number(8), Oracle permite el cambio ya que al insertar el valor por defecto, lo convierte a

nmero (0) automticamente; si el valor por defecto no se puede convertir (por ejemplo 'a000000') a valor numrico, la modificacin del campo no se realiza.

70 - Eliminar campos (alter table- drop)


Vimos que "alter table" permite modificar la estructura de una tabla, agregando, modificando y eliminando campos. Para eliminar campos de una tabla la sintaxis bsica es la siguiente:
alter table NOMBRETABLA drop column NOMBRECAMPO;

En el siguiente ejemplo eliminamos el campo "precio" de la tabla "libros":


alter table libros drop column precio;

No pueden eliminarse los campos a los cuales hace referencia una restriccin "foreign key". Si eliminamos un campo que tiene una restriccin "primary key", "unique", "check" o "foreign key", la restriccin tambin se elimina. Si eliminamos un campo indexado, el ndice tambin se elimina. NO puede eliminarse un campo si es el nico en la tabla. Puede verificarse la alteracin de la estructura de la tabla tipeando:
describe libros;

71 - Agregar campos y restricciones (alter table)


Podemos agregar un campo a una tabla y en el mismo momento aplicarle una restriccin. Para agregar un campo y establecer una restriccin, la sintaxis bsica es la siguiente:

alter table TABLA add CAMPO DEFINICION constraint NOMBRERESTRICCION TIPO;

Agregamos a la tabla "libros", el campo "titulo" de tipo varchar2(30) y una restriccin "unique":
alter table libros add titulo varchar2(30) constraint UQ_libros_autor unique;

Agregamos a la tabla "libros", el campo "codigo" de tipo number(4) not null y una restriccin "primary key":
alter table libros add codigo number(4) not null constraint PK_libros_codigo primary key;

Agregamos a la tabla "libros", el campo "precio" de tipo number(6,2) y una restriccin "check":
alter table libros add precio number(6,2) constraint CK_libros_precio check (precio>=0);

72 - Subconsultas
Una subconsulta (subquery) es una sentencia "select" anidada en otra sentencia "select", "insert", "update" o "delete" (o en otra subconsulta). Las subconsultas se emplean cuando una consulta es muy compleja, entonces se la divide en varios pasos lgicos y se obtiene el resultado con una nica instruccin y cuando la consulta depende de los resultados de otra consulta. Generalmente, una subconsulta se puede reemplazar por combinaciones y estas ltimas son ms eficientes. Las subconsultas generalmente se incluyen entre parntesis. Puede haber subconsultas dentro de subconsultas. Generalmente las subconsultas se colocan en la clusula "where". Una subconsulta puede retornar:

- un solo valor, - una lista de valores de una sola columna, - un conjunto de registros de varios campos. Podemos averiguar si un valor de la consulta externa pertenece o no al conjunto devuelto por una subconsulta ("in", "not in"), si es mayor, menor o igual a todos ("all") o a algunos valores ("some", "any") del conjunto devuelto. Se pueden emplear subconsultas: - en lugar de una expresin, siempre que devuelvan un solo valor o una lista de valores. - que retornen un conjunto de registros de varios campos en lugar de una tabla o para obtener el mismo resultado que una combinacin (join). Hay varios tipos bsicos de subconsultas: - las que retornan un solo valor escalar que se utiliza con un operador de comparacin o en lugar de una expresin. - las que retornan una lista de valores, se combinan con "in", o los operadores "any", "some" y "all". - los que testean la existencia con "exists".

73 - Subconsultas como expresion


Una subconsulta puede reemplazar una expresin. Dicha subconsulta debe devolver un valor escalar (o una lista de valores de un campo). Las subconsultas que retornan un solo valor escalar se utiliza con un operador de comparacin o en lugar de una expresin:
select CAMPOS from TABLA where CAMPO OPERADOR (SUBCONSULTA); select CAMPO OPERADOR (SUBCONSULTA) from TABLA;

Si queremos saber el precio de un determinado libro y la diferencia con el precio del libro ms costoso, anteriormente debamos averiguar en una consulta el precio del libro ms costoso y luego, en otra consulta, calcular la diferencia con el valor del libro que solicitamos. Podemos conseguirlo en una sola sentencia combinando dos consultas:
select titulo,precio, precio-(select max(precio) from libros) as diferencia from libros where titulo='Uno';

En el ejemplo anterior se muestra el ttulo, el precio de un libro y la diferencia entre el precio del libro y el mximo valor de precio. Queremos saber el ttulo, autor y precio del libro ms costoso:
select titulo,autor, precio from libros where precio= (select max(precio) from libros);

Note que el campo del "where" de la consulta exterior es compatible con el valor retornado por la expresin de la subconsulta. Se pueden emplear en "select", "insert", "update" y "delete". Para actualizar un registro empleando subconsulta la sintaxis bsica es la siguiente:
update TABLA set CAMPO=NUEVOVALOR where CAMPO= (SUBCONSULTA);

Para eliminar registros empleando subconsulta empleamos la siguiente sintaxis bsica:


delete from TABLA where CAMPO=(SUBCONSULTA);

74 - Subconsultas con in
Vimos que una subconsulta puede reemplazar una expresin. Dicha subconsulta debe devolver un valor escalar o una lista de valores de un campo; las subconsultas que retornan una lista de valores reemplazan a una expresin en una clusula "where" que contiene la palabra clave "in". El resultado de una subconsulta con "in" (o "not in") es una lista. Luego que la subconsulta retorna resultados, la consulta exterior los usa.

Podemos averiguar si un valor de la consulta externa pertenece o no al conjunto devuelto por una subconsulta empleando "in" y "not in". La sintaxis bsica es la siguiente:
...where EXPRESION in (SUBCONSULTA);

Este ejemplo muestra los nombres de las editoriales que ha publicado libros de un determinado autor:
select nombre from editoriales where codigo in (select codigoeditorial from libros where autor='Richard Bach');

La subconsulta (consulta interna) retorna una lista de valores de un solo campo (codigoeditorial) que la consulta exterior luego emplea al recuperar los datos. Se averigua si el cdigo devuelto por la consulta externa se encuentra dentro del conjunto de valores retornados por la consulta interna. Podemos reemplazar por un "join" la consulta anterior:
select distinct nombre from editoriales e join libros on codigoeditorial=e.codigo where autor='Richard Bach';

Una combinacin (join) siempre puede ser expresada como una subconsulta; pero una subconsulta no siempre puede reemplazarse por una combinacin que retorne el mismo resultado. Si es posible, es aconsejable emplear combinaciones en lugar de subconsultas, son ms eficientes. Se recomienda probar las subconsultas antes de incluirlas en una consulta exterior, as puede verificar que retorna lo necesario, porque a veces resulta difcil verlo en consultas anidadas. Tambin podemos buscar valores No coincidentes con una lista de valores que retorna una subconsulta; por ejemplo, las editoriales que no han publicado libros de un autor especfico:
select nombre from editoriales where codigo not in (select codigoeditorial from libros where autor='Richard Bach');

75 - Subconsultas any- some- all


"any" y "some" son sinnimos. Chequean si alguna fila de la lista resultado de una subconsulta se encuentra el valor especificado en la condicin. Compara un valor escalar con los valores de un campo y devuelven "true" si la comparacin con cada valor de la lista de la subconsulta es verdadera, sino "false". El tipo de datos que se comparan deben ser compatibles. La sintaxis bsica es:
...VALORESCALAR OPERADORDECOMPARACION any (SUBCONSULTA);

Queremos saber los ttulos de los libros de "Borges" que pertenecen a editoriales que han publicado tambin libros de "Richard Bach", es decir, si los libros de "Borges" coinciden con ALGUNA de las editoriales que public libros de "Richard Bach":
select titulo from libros where autor='Borges' and codigoeditorial = any (select e.codigo from editoriales e join libros l on codigoeditorial=e.codigo where l.autor='Richard Bach');

La consulta interna (subconsulta) retorna una lista de valores de un solo campo (puede ejecutar la subconsulta como una consulta para probarla), luego, la consulta externa compara cada valor de "codigoeditorial" con cada valor de la lista devolviendo los ttulos de "Borges" que coinciden. "all" tambin compara un valor escalar con una serie de valores. Chequea si TODOS los valores de la lista de la consulta externa se encuentran en la lista de valores devuelta por la consulta interna. Sintaxis:
VALORESCALAR OPERADORDECOMPARACION all (SUBCONSULTA);

Queremos saber si TODAS las editoriales que publicaron libros de "Borges" coinciden con TODAS las editoriales que publicaron libros de "Richard Bach":

select titulo from libros where autor='Borges' and codigoeditorial = all (select e.codigo from editoriales e join libros l on codigoeditorial=e.codigo where l.autor='Richard Bach');

La consulta interna (subconsulta) retorna una lista de valores de un solo campo (puede ejecutar la subconsulta como una consulta para probarla), luego, la consulta externa compara cada valor de "codigoeditorial" con cada valor de la lista, si TODOS coinciden, devuelve los ttulos. Veamos otro ejemplo con un operador de comparacin diferente: Queremos saber si ALGUN precio de los libros de "Borges" es mayor a ALGUN precio de los libros de "Richard Bach":
select titulo,precio from libros where autor='Borges' and precio > any (select precio from libros where autor='Bach');

El precio de cada libro de "Borges" es comparado con cada valor de la lista de valores retornada por la subconsulta; si ALGUNO cumple la condicin, es decir, es mayor a ALGUN precio de "Richard Bach", se lista. Veamos la diferencia si empleamos "all" en lugar de "any":
select titulo,precio from libros where autor='borges' and precio > all (select precio from libros where autor='bach');

El precio de cada libro de "Borges" es comparado con cada valor de la lista de valores retornada por la subconsulta; si cumple la condicin, es decir, si es mayor a TODOS los precios de "Richard Bach" (o al mayor), se lista. Emplear "= any" es lo mismo que emplear "in". Emplear "<> all" es lo mismo que emplear "not in".

76 - Subconsultas correlacionadas
Un almacn almacena la informacin de sus ventas en una tabla llamada "facturas" en la cual guarda el nmero de factura, la fecha y el nombre del cliente y una tabla denominada "detalles" en la cual se almacenan los distintos items correspondientes a cada factura: el nombre del artculo, el precio (unitario) y la cantidad. Se necesita una lista de todas las facturas que incluya el nmero, la fecha, el cliente, la cantidad de artculos comprados y el total:
select f.*, (select count(d.numeroitem) from Detalles d where f.numero=d.numerofactura) as cantidad, (select sum(d.preciounitario*cantidad) from Detalles d where f.numero=d.numerofactura) as total from facturas f;

El segundo "select" retorna una lista de valores de una sola columna con la cantidad de items por factura (el nmero de factura lo toma del "select" exterior); el tercer "select" retorna una lista de valores de una sola columna con el total por factura (el nmero de factura lo toma del "select" exterior); el primer "select" (externo) devuelve todos los datos de cada factura. A este tipo de subconsulta se la denomina consulta correlacionada. La consulta interna se evala tantas veces como registros tiene la consulta externa, se realiza la subconsulta para cada registro de la consulta externa. El campo de la tabla dentro de la subconsulta (f.numero) se compara con el campo de la tabla externa. En este caso, especficamente, la consulta externa pasa un valor de "numero" a la consulta interna. La consulta interna toma ese valor y determina si existe en "detalles", si existe, la consulta interna devuelve la suma. El proceso se repite para el registro de la consulta externa, la consulta externa pasa otro "numero" a la consulta interna y Oracle repite la evaluacin.

77 - Exists y No Exists

Los operadores "exists" y "not exists" se emplean para determinar si hay o no datos en una lista de valores. Estos operadores pueden emplearse con subconsultas correlacionadas para restringir el resultado de una consulta exterior a los registros que cumplen la subconsulta (consulta interior). Estos operadores retornan "true" (si las subconsultas retornan registros) o "false" (si las subconsultas no retornan registros). Cuando se coloca en una subconsulta el operador "exists", Oracle analiza si hay datos que coinciden con la subconsulta, no se devuelve ningn registro, es como un test de existencia; Oracle termina la recuperacin de registros cuando por lo menos un registro cumple la condicin "where" de la subconsulta. La sintaxis bsica es la siguiente:
... where exists (SUBCONSULTA);

En este ejemplo se usa una subconsulta correlacionada con un operador "exists" en la clusula "where" para devolver una lista de clientes que compraron el artculo "lapiz":
select cliente,numero from facturas f where exists (select *from Detalles d where f.numero=d.numerofactura and d.articulo='lapiz');

Puede obtener el mismo resultado empleando una combinacin. Podemos buscar los clientes que no han adquirido el artculo "lapiz" empleando "if not exists":
select cliente,numero from facturas f where not exists (select *from Detalles d where f.numero=d.numerofactura and d.articulo='lapiz');

78 - Subconsulta simil autocombinacion


Algunas sentencias en las cuales la consulta interna y la externa emplean la misma tabla pueden reemplazarse por una autocombinacin.

Por ejemplo, queremos una lista de los libros que han sido publicados por distintas editoriales.
select distinct l1.titulo from libros l1 where l1.titulo in (select l2.titulo from libros l2 where l1.editorial <> l2.editorial);

En el ejemplo anterior empleamos una subconsulta correlacionada y las consultas interna y externa emplean la misma tabla. La subconsulta devuelve una lista de valores por ello se emplea "in" y sustituye una expresin en una clusula "where". Con el siguiente "join" se obtiene el mismo resultado:
select distinct l1.titulo from libros l1 join libros l2 on l1.titulo=l1.titulo and l1.autor=l2.autor where l1.editorial<>l2.editorial;

Otro ejemplo: Buscamos todos los libros que tienen el mismo precio que "El aleph" empleando subconsulta:
select titulo from libros where titulo<>'El aleph' and precio = (select precio from libros where titulo='El aleph');

La subconsulta retorna un solo valor. Podemos obtener la misma salida empleando "join". Buscamos los libros cuyo precio supere el precio promedio de los libros por editorial:
select l1.titulo,l1.editorial,l1.precio from libros l1 where l1.precio > (select avg(l2.precio) from libros l2 where l1.editorial= l2.editorial);

Por cada valor de l1, se evala la subconsulta, si el precio es mayor que el promedio. Se puede conseguir el mismo resultado empleando un "join" con "having".

79 - Subconsulta con update y delete


Dijimos que podemos emplear subconsultas en sentencias "insert", "update", "delete", adems de "select". La sintaxis bsica para realizar actualizaciones con subconsulta es la siguiente:
update TABLA set CAMPO=NUEVOVALOR where CAMPO= (SUBCONSULTA);

Actualizamos el precio de todos los libros de editorial "Emece":


update libros set precio=precio+(precio*0.1) where codigoeditorial= (select codigo from editoriales where nombre='Emece');

La subconsulta retorna un nico valor. Tambin podemos hacerlo con un join. La sintaxis bsica para realizar eliminaciones con subconsulta es la siguiente:
delete from TABLA where CAMPO OPERADOR (SUBCONSULTA);

Eliminamos todos los libros de las editoriales que tiene publicados libros de "Juan Perez":
delete from libros where codigoeditorial in (select e.codigo from editoriales e join libros on codigoeditorial=e.codigo where autor='Juan Perez');

La subconsulta es una combinacin que retorna una lista de valores que la consulta externa emplea al seleccionar los registros para la eliminacin.

80 - Subconsulta e insert

Aprendimos que una subconsulta puede estar dentro de un "select", "update" y "delete"; tambin puede estar dentro de un "insert". Podemos ingresar registros en una tabla empleando un subselect. La sintaxis bsica es la siguiente:
insert into TABLAENQUESEINGRESA (CAMPOSTABLA1) select (CAMPOSTABLACONSULTADA) from TABLACONSULTADA;

Un profesor almacena las notas de sus alumnos en una tabla llamada "alumnos". Tiene otra tabla llamada "aprobados", con algunos campos iguales a la tabla "alumnos" pero en ella solamente almacenar los alumnos que han aprobado el ciclo. Ingresamos registros en la tabla "aprobados" seleccionando registros de la tabla "alumnos":
insert into aprobados (documento,nota) select (documento,nota) from alumnos;

Entonces, se puede insertar registros en una tabla con la salida devuelta por una consulta a otra tabla; para ello escribimos la consulta y le anteponemos "insert into" junto al nombre de la tabla en la cual ingresaremos los registros y los campos que se cargarn (si se ingresan todos los campos no es necesario listarlos). La cantidad de columnas devueltas en la consulta debe ser la misma que la cantidad de campos a cargar en el "insert". Se pueden insertar valores en una tabla con el resultado de una consulta que incluya cualquier tipo de "join".

81 - Crear tabla a partir de otra (create table- select)


Podemos crear una tabla e insertar datos en ella en una sola sentencia consultando otra tabla (o varias) con esta sintaxis:
create table NOMBRENUEVATABLA as SUBCONSULTA;

Es decir, se crea una nueva tabla y se inserta en ella el resultado de una consulta a otra tabla.

Tenemos la tabla "libros" de una librera y queremos crear una tabla llamada "editoriales" que contenga los nombres de las editoriales. La tabla "editoriales", que no existe, contendr solamente un campo llamado "nombre". La tabla libros contiene varios registros. Podemos crear la tabla "editoriales" con el campo "nombre" consultando la tabla "libros" y en el mismo momento insertar la informacin:
create table editoriales as (select distinct editorial as nombre from libros);

La tabla "editoriales" se ha creado con el campo "nombre" seleccionado del campo "editorial" de "libros". Los campos de la nueva tabla tienen el mismo nombre, tipo de dato y valores almacenados que los campos listados de la tabla consultada; si se quiere dar otro nombre a los campos de la nueva tabla se deben especificar alias. Podemos emplear "group by", funciones de agrupamiento y "order by" en las consultas. Tambin podemos crear una tabla que contenga datos de 2 o ms tablas empleando combinaciones.

82 - Vistas (create view)


Una vista es un objeto. Una vista es una alternativa para mostrar datos de varias tablas; es como una tabla virtual que almacena una consulta. Los datos accesibles a travs de la vista no estn almacenados en la base de datos, en la base de datos se guarda la definicin de la vista y no el resultado de ella. Entonces, una vista almacena una consulta como un objeto para utilizarse posteriormente. Las tablas consultadas en una vista se llaman tablas base. En general, se puede dar un nombre a cualquier consulta y almacenarla como una vista. Una vista suele llamarse tambin tabla virtual porque los resultados que retorna y la manera de referenciarlas es la misma que para una tabla. Las vistas permiten: <="" p="">

- simplificar la administracin de los permisos de usuario: se pueden dar al usuario permisos para que solamente pueda acceder a los datos a travs de vistas, en lugar de concederle permisos para acceder a ciertos campos, as se protegen las tablas base de cambios en su estructura. - mejorar el rendimiento: se puede evitar tipear instrucciones repetidamente almacenando en una vista el resultado de una consulta compleja que incluya informacin de varias tablas. Podemos crear vistas con: un subconjunto de registros y campos de una tabla; una unin de varias tablas; una combinacin de varias tablas; un subconjunto de otra vista, combinacin de vistas y tablas. Una vista se define usando un "select". La sintaxis bsica para crear una vista es la siguiente:
create view NOMBREVISTA as SUBCONSULTA;

El contenido de una vista se muestra con un "select":


select *from NOMBREVISTA;

En el siguiente ejemplo creamos la vista "vista_empleados", que es resultado de una combinacin en la cual se muestran 4 campos:
create view vista_empleados as select (apellido||' '||e.nombre) as nombre,sexo, s.nombre as seccion, cantidadhijos from empleados e join secciones s on codigo=seccion;

Para ver la informacin contenida en la vista creada anteriormente tipeamos:


select *from vista_empleados;

Podemos realizar consultas a una vista como si se tratara de una tabla:


select seccion,count(*) as cantidad from vista_empleados;

Los nombres para vistas deben seguir las mismas reglas que cualquier identificador. Para distinguir una tabla de una vista podemos fijar una convencin para darle nombres, por ejemplo, colocar el sufijo vista y luego el nombre de las tablas consultadas en ellas. Los campos y expresiones de la consulta que define una vista DEBEN tener un nombre. Se debe colocar nombre de campo cuando es un campo calculado o si hay 2 campos con el mismo nombre. Note que en el ejemplo, al concatenar los campos "apellido" y "nombre"

colocamos un alias; si no lo hubisemos hecho aparecera un mensaje de error porque dicha expresin DEBE tener un encabezado, Oracle no lo coloca por defecto. Los nombres de los campos y expresiones de la consulta que define una vista DEBEN ser nicos (no puede haber dos campos o encabezados con igual nombre). Note que en la vista definida en el ejemplo, al campo "s.nombre" le colocamos un alias porque ya haba un encabezado (el alias de la concatenacin) llamado "nombre" y no pueden repetirse, si sucediera, aparecera un mensaje de error. Otra sintaxis es la siguiente:
create view NOMBREVISTA (NOMBRESDEENCABEZADOS) as SUBCONSULTA;

Creamos otra vista de "empleados" denominada "vista_empleados_ingreso" que almacena la cantidad de empleados por ao:
create view vista_empleados_ingreso (fecha,cantidad) as select extract(year from fechaingreso),count(*) from empleados group by extract(year from fechaingreso);

La diferencia es que se colocan entre parntesis los encabezados de las columnas que aparecern en la vista. Si no los colocamos y empleamos la sintaxis vista anteriormente, se emplean los nombres de los campos o alias (que en este caso habra que agregar) colocados en el "select" que define la vista. Los nombres que se colocan entre parntesis deben ser tantos como los campos o expresiones que se definen en la vista. Las vistas se crean en la base de datos activa. Al crear una vista, Oracle verifica que existan las tablas a las que se hacen referencia en ella; no se puede crear una vista que referencie tablas inexistentes. No se puede crear una vista si existe un objeto con ese nombre. Se aconseja probar la sentencia "select" con la cual definiremos la vista antes de crearla para asegurarnos que el resultado que retorna es el imaginado. Una vista siempre est actualizada; si modificamos las tablas base (a las cuales referencia la vista), la vista mostrar los cambios. Se pueden construir vistas sobre otras vistas.

83 - Vistas (informacin)
Las vistas son objetos, as que para obtener informacin de ellos pueden consultarse los siguientes catlogos. "user_catalog" nos muestra todos los objetos del usuario actual, incluidas las vistas. En la columna "table_type" aparece "view" si es una vista. Ejemplo:
select *from user_catalog where table_type='VIEW';

"user_objects" nos muestra informacin sobre todos los objetos del usuario actual. En la columna "OBJECT_TYPE" muestra "view" si es una vista, aparece la fecha de creacin y dems informacin que no analizaremos por el momento. Para ver todos los objetos del usuario actual que son vistas tipeamos:
select *from user_catalog where object_type='VIEW';

"user_views" nos muestra informacin referente a todas las vistas del usuario actual, el nombre de la vista, la longitud del texto, el texto que la define, etc. Con la siguiente sentencia obtenemos informacin sobre todas las vistas cuyo nombre comience con la cadena "VISTA":
select *from user_views where view_name like 'VISTA%';

84 - Vistas eliminar (drop view)


Para quitar una vista se emplea "drop view":
drop view NOMBREVISTA;

Eliminamos la vista denominada "vista_empleados":


drop view vista_empleados;

Si se elimina una tabla a la que hace referencia una vista, la vista no se elimina, hay que eliminarla explcitamente.

85 - Vistas (modificar datos a travs de ella)


Si se modifican los datos de una vista, se modifica la tabla base. Se puede insertar, actualizar o eliminar datos de una tabla a travs de una vista, teniendo en cuenta lo siguiente, las modificaciones que se realizan a las vistas: - no pueden afectar a ms de una tabla consultada. Pueden modificarse y eliminarse datos de una vista que combina varias tablas pero la modificacin o eliminacin solamente debe afectar a una sola tabla. - no se pueden cambiar los campos resultado de un clculo. - pueden generar errores si afectan a campos a las que la vista no hace referencia. Por ejemplo, si se ingresa un registro en una vista que consulta una tabla que tiene campos not null que no estn incluidos en la vista.

86 - Vistas (with read only)


Con la clusula "with read only" (slo lectura) evitamos que se puedan realizar inserciones, actualizaciones y eliminaciones mediante una vista. Sintaxis:
create view NOMBREVISTA as SUBCONSULTA with read only;

Evitamos que Oracle acepte "insert", "update" o "delete" sobre la vista si colocamos "with read only" luego de la subconsulta que define una vista. Por ejemplo, creamos la siguiente vista:
create view vista_empleados as select apellido, nombre, sexo, seccion from empleados with read only;

Oracle responde con un mensaje de error ante cualquier "insert", "update" o "delete" realizado sobre la vista.

87 - Vistas modificar (create or replace view)


Para modificar una vista puede eliminarla y volver a crearla o emplear "create or replace". Sintaxis:
create or replace view NOMBREVISTA as SUBCONSULTA;

Con "create or replace view" se modifica la definicin de una vista existente o se crea si no existe.

88 - Vistas (with check option)


Es posible obligar a todas las instrucciones de modificacin de datos que se ejecutan en una vista a cumplir ciertos criterios. Por ejemplo, creamos la siguiente vista:
create view vista_empleados as select apellido, nombre, sexo, seccion from empleados where seccion='Administracion' with check option;

La vista definida anteriormente muestra solamente algunos registros y algunos campos de "empleados", los de la seccin "Administracion". Con la clusula "with check option", no se permiten modificaciones en aquellos campos que afecten a los registros que retorna la vista. Es decir, no podemos modificar el campo

"seccin" porque al hacerlo, tal registro ya no aparecera en la vista; si podemos actualizar los dems campos. Por ejemplo, si intentamos actualizar a "Sistemas" el campo "seccion" de un registro mediante la vista, Oracle muestra un mensaje de error. La misma restriccin surge al ejecutar un "insert" sobre la vista; solamente podemos ingregar registros con el valor "Administracion" para "seccion"; si intentamos ingresar un registro con un valor diferente de "Administracion" para el campo "seccion", Oracle mostrar un mensaje de error. Sintaxis bsica:
create view NOMBREVISTA as SUBCONSULTA with check option;

89 - Vistas (otras consideraciones)


Cuando creamos una vista, Oracle verifica que las tablas a las cuales se hace referencia en ella existan. Si la vista que se intenta crear hace referencia a tablas inexistentes, Oracle muestra un mensaje de error. Podemos "forzar" a Oracle a crear una vista aunque no existan los objetos (tablas, vistas, etc.) que referenciamos en la misma. Para ello debemos agregar "force" al crearla:
create force view NOMBREVISTA as SUBCONSULTA;

De esta manera, podemos crear una vista y despus las tablas involucradas; luego, al consultar la vista, DEBEN existir las tablas. Al crear la vista la opcin predeterminada es "no force". Se recomienda crear las tablas y luego las vistas necesarias. Otra cuestin a considerar es la siguiente: si crea una vista con "select *" y luego agrega campos a la estructura de las tablas involucradas, los nuevos campos no aparecern en la vista; esto es porque los campos se seleccionan al ejecutar "create view"; debe volver a crear la vista (con "create view" o "create or replace view").

90 - Vistas materializadas (materialized view)


Una vista materializada se define como una vista comn, pero en lugar de almacenar la definicin de la vista, almacena el resultado de la consulta, es decir, la materializa, como un objeto persistente en la base de datos. Sintaxis:
create materialized view NOMBREVISTAMATERIALIZADA as SUBCONSULTA;

Existen varias clusulas que podemos agregar al crear una vista materializada, pero no las estudiaremos. En el "from" de la consulta pueden listarse tablas, vistas y vistas materializadas. Entonces, una vista materializada almacena su resultado fsicamente. Una vista materializada (materialized view) es una instantnea (snapshot), son sinnimos. Para obtener informacin acerca de las vistas materializadas podemos consultar el diccionario "user_objects", en la columna "object_type" aparecer "materialized view" si es una vista materializada. Ejemplo:
select *from user_objects where object_type='MATERIALIZED VIEW';

Tambin podemos consultar "user_mviews" para obtener informacin de todas las vistas materializadas del usuario actual:
select *from user_mviews;

Este diccionario muestra mucha informacin que no explicaremos en detalle. Para eliminar una vista materializada empleamos "drop materialized view":
drop materialized view NOMBREVISTAMATERIALIZADA;

Ejemplo:
drop materialized view vm_promedios;

No se permite realizar "insert", "update" ni "delete" en las vistas materializadas.

91 - Procedimientos almacenados
Un procedimiento almacenado es un conjunto de instrucciones a las que se les da un nombre, se almacena en la base de datos activa. Permiten agrupar y organizar tareas repetitivas. Ventajas: - comparten la lgica de la aplicacin con las otras aplicaciones, con lo cual el acceso y las modificaciones de los datos se hacen en un solo sitio. - permiten realizar todas las operaciones que los usuarios necesitan evitando que tengan acceso directo a las tablas. - reducen el trfico de red; en vez de enviar muchas instrucciones, los usuarios realizan operaciones enviando una nica instruccin, lo cual disminuye el nmero de solicitudes entre el cliente y el servidor. Un procedimiento almacenados puede hacer referencia a objetos que no existen al momento de crearlo. Los objetos deben existir cuando se ejecute el procedimiento almacenado.

92 - Procedimientos Almacenados (crearejecutar)


Al crear un procedimiento almacenado, las instrucciones que contiene se analizan para verificar si son correctas sintcticamente. Si se encuentra algn error, el procedimiento se compila, pero aparece un mensaje "con advertencias" que indica tal situacin. Un procedimiento almacenado se invoca llamndolo. En primer lugar se deben tipear y probar las instrucciones que se incluyen en el procedimiento almacenado, luego, si se obtiene el resultado esperado, se crea el procedimiento. Los procedimientos almacenados pueden hacer referencia a tablas, vistas, a funciones definidas por el usuario, a otros procedimientos almacenados.

Un procedimiento almacenado pueden incluir cualquier cantidad y tipo de instrucciones DML (de manipulacin de datos, como insert, update, delete), no instrucciones DDL (de definicin de datos, como create..., drop... alter...). Para crear un procedimiento almacenado empleamos la instruccin "create procedure". La sintaxis bsica parcial es:
create or replace procedure NOMBREPROCEDIMIENTO as begin INSTRUCCIONES end;

El bloque de instrucciones comienza luego de "begin" y acaba con "end". Si empleamos "or replace", se sobreescribe (se reemplaza) un procedimiento existente; si se omite y existe un procedimiento con el nombre que le asignamos, Oracle mostrar un mensaje de error indicando tal situacin. Para diferenciar los procedimientos almacenados del sistema de los procedimientos almacenados creados por el usuario use un prefijo, por ejemplo "pa_" cuando les de el nombre. Con las siguientes instrucciones creamos un procedimiento almacenado llamado "pa_libros_aumentar10" que incrementa en un 10% el precio de todos los libros:
create procedure pa_libros_aumentar10 as update libros set precio=precio+precio*0.1;

Entonces, creamos un procedimiento almacenado colocando "create procedure" (o "create or replace", si es que desea reemplazar el existente), luego el nombre del procedimiento y seguido de "as" las sentencias que definen el procedimiento. Para ejecutar el procedimiento almacenado creado anteriormente tipeamos:
execute pa_libros_aumentar10;

Entonces, para ejecutar un procedimiento almacenado colocamos "execute" seguido del nombre del procedimiento.

93 - Procedimientos Almacenados (eliminar)

Los procedimientos almacenados se eliminan con "drop procedure". Sintaxis:


drop procedure NOMBREPROCEDIMIENTO;

Eliminamos el procedimiento almacenado llamado "pa_libros_aumentar10":


drop procedure pa_libros_aumentar10;

Si el procedimiento que queremos eliminar no existe, aparece un mensaje de error indicando tal situacin. Podemos eliminar una tabla referenciada en un procedimiento almacenado, Oracle lo permite, pero luego, al ejecutar el procedimiento, aparecer un mensaje de error porque la tabla referenciada no existe. Si al crear un procedimiento almacenado colocamos "create or replace procedure...", el nuevo procedimiento reemplaza al anterior.

94 - Procedimientos almacenados (parmetros de entrada)


Los procedimientos almacenados pueden recibir y devolver informacin; para ello se emplean parmetros. Veamos los primeros. Los parmetros de entrada posibilitan pasar informacin a un procedimiento. Para que un procedimiento almacenado admita parmetros de entrada se deben declarar al crearlo. La sintaxis es:
create or replace procedure NOMBREPROCEDIMIENTO (PARAMETRO in TIPODEDATO) as begin INSTRUCCIONES; end;

Los parmetros se definen luego del nombre del procedimiento. Pueden declararse varios parmetros por procedimiento, se separan por comas. Cuando el procedimiento es ejecutado, deben explicitarse valores para cada uno de los parmetros (en el orden que fueron definidos), a menos que se haya definido un valor por defecto, en tal caso, pueden omitirse.

Creamos un procedimiento que recibe el nombre de una editorial como parmetro y luego lo utiliza para aumentar los precios de tal editorial:
create or replace procedure pa_libros_aumentar10(aeditorial in varchar2) as begin update libros set precio=precio+(precio*0.1) where editorial=aeditorial; end;

El procedimiento se ejecuta colocando "execute" (o "exec") seguido del nombre del procedimiento y un valor para el parmetro:
execute pa_libros_aumentar10('Planeta');

Luego de definir un parmetro y su tipo, opcionalmente, se puede especificar un valor por defecto; tal valor es el que asume el procedimiento al ser ejecutado si no recibe parmetros. Si no se coloca valor por defecto, un procedimiento definido con parmetros no puede ejecutarse sin valores para ellos. El valor por defecto puede ser "null" o una constante. Creamos otro procedimiento que recibe 2 parmetros, el nombre de una editorial y el valor de incremento (que tiene por defecto el valor 10):
create or replace procedure pa_libros_aumentar(aeditorial in varchar2,aporcentaje in number default 10) as begin update libros set precio=precio+(precio*aporcentaje/100) where editorial=aeditorial; end;

El procedimiento se ejecuta colocando "execute" (o "exec") seguido del nombre del procedimiento y los valores para los parmetros separados por comas:
execute pa_libros_aumentar('Planeta',30);

Podemos omitir el segundo parmetro al invocar el procedimiento porque tiene establecido un valor por defecto:
execute pa_libros_aumentar('Planeta');

En caso que un procedimiento tenga definidos varios parmetros con valores por defecto y al invocarlo colocamos uno solo, Oracle asume que es el primero de ellos. si son de tipos de datos diferentes, Oracle los convierte. Por ejemplo, definimos un procedimiento almacenado de la siguiente manera:
create or replace procedure pa_libros_insertar (atitulo in varchar2 default null, aautor in varchar2 default 'desconocido',

aeditorial in varchar2 default 'sin especificar', aprecio in number default 0) as begin insert into libros values (atitulo,aautor,aeditorial,aprecio); end;

Si luego llamamos al procedimiento envindoles solamente el primer y cuarto parmetro correspondientes al ttulo y precio:
execute pa_libros_insertar('Uno',100);

Oracle asume que los argumentos son el primero y segundo, el registro que se almacenar ser:
Uno,100,sin especificar,0;

95 - Procedimientos almacenados (variables)


Los procedimientos almacenados pueden contener en su definicin, variables locales, que existen durante el procedimiento. La sintaxis para declarar variables dentro de un procedimiento almacenado es la siguiente:
create or replace procedure NOMBREPROCEDIMIENTO (PARAMETRO in TIPODEDATO) as NOMBREVARIABLE TIPO; begin INSTRUCCIONES; end;

Las variables se definen antes del bloque de sentencias; pueden declararse varias. Creamos un procedimiento que recibe el nombre de un libro, en una variable guardamos el nombre del autor de tal libro, luego buscamos todos los libros de ese autor y los almacenamos en una tabla:
create or replace procedure pa_autorlibro(atitulo in varchar2) as vautor varchar2; begin vautor= select autor from libros where titulo=atitulo; drop table tabla1; create table tabla1(

titulo varchar2(40), precio number(6,2) ); insert into tabla1 select titulo,precio from libros where autor=vautor; end;

Ejecutamos el procedimiento: execute pa_autorlibro('Ilusiones'); Luego de definir un parmetro y su tipo, opcionalmente, se puede especificar un valor por defecto; tal valor es el que asume el procedimiento al ser ejecutado si no recibe parmetros. Si no se coloca valor por defecto, un procedimiento definido con parmetros no puede ejecutarse sin valores para ellos.

96 - Procedimientos Almacenados (informacion)


Los procedimientos almacenados son objetos, as que para obtener informacin de ellos pueden consultarse los siguientes diccionarios: - "user_objects": nos muestra todos los objetos de la base de datos seleccionada, incluidos los procedimientos. En la columna "object_type" aparece "procedure" si es un procedimiento almacenado. En el siguiente ejemplo solicitamos todos los objetos que son procedimientos:
select *from user_objects where object_type='PROCEDURE';

- "user_procedures": nos muestra todos los procedimientos almacenados de la base de datos actual. En el siguiente ejemplo solicitamos informacin de todos los procedimientos que comienzan con "PA":
select *from user_procedures where object_name like 'PA_%';

97 - Funciones

Oracle ofrece varios tipos de funciones para realizar distintas operaciones. Hemos empleado varias de ellas. Se pueden emplear las funciones del sistema en cualquier lugar en el que se permita una expresin en una sentencia "select". Ahora aprenderemos a crear nuestras propias funciones. Las funciones, como los procedimientos almacenados son bloques de cdigo que permiten agrupar y organizar sentencias SQL que se ejecutan al invocar la funcin. Las funciones tienen una estructura similar a la de los procedimientos. Como los procedimientos, las funciones tienen una cabecera, una seccin de declaracin de variables y el bloque "begin...end" que encierra las acciones. Una funcin, adems contiene la clusula "return". Una funcin acepta parmetros, se invoca con su nombre y retorna un valor. Para crear una funcin empleamos la instruccin "create function" o "create or replace function". Si empleamos "or replace", se sobreescribe (se reemplaza) una funcin existente; si se omite y existe una funcin con el nombre que le asignamos, Oracle mostrar un mensaje de error indicando tal situacin. La sintaxis bsica parcial es:
create o replace function NOMBREFUNCION(PARAMETRO1 TIPODATO, PARAMETRON TIPODATO) return TIPODEDATO is DECLARACION DE VARIABLES begin ACCIONES; return VALOR; end;

La siguiente funcion recibe 1 parmetro, un valor a incrementar y retorna el valor ingresado como argumento con el incremento del 10%:
create or replace function f_incremento10 (avalor number) return number is begin return avalor+(avalor*0.1); end;

Podemos emplear las funciones en cualquier lugar en el que se permita una expresin en una sentencia "select", por ejemplo:
select titulo,precio,f_incremento10(precio) from libros;

El resultado mostrar el ttulo de cada libro, el precio y el precio incrementado en un 10% devuelto por la funcin. La siguiente funcion recibe 2 parmetros, un valor a incrementar y el incremento y retorna el valor ingresado como primer argumento con el incremento especificado por el segundo argumento:
create or replace function f_incremento (avalor number, aincremento number) return number is begin return avalor+(avalor*aincremento/100); end;

Realizamos un "select" y llamamos a la funcin creada anteriormente, enviando como primer argumento el campo "precio" y como segundo argumento el valor "20", es decir, incrementar en un 20" los precios de los libros:
select titulo,precio,f_incremento(precio,20) from libros;

El resultado nos mostrar el ttulo de cada libro, el precio y el precio incrementado en un 20% devuelto por la funcin. Podemos realizar otros "select" llamando a la funcin con otro valor como segundo argumento, por ejemplo:
select titulo,precio,f_incremento(precio,50) from libros;

La siguiente funcin recibe un parmetro de tipo numrico y retorna una cadena de caracteres. Se define una variable en la zona de definicin de variables denominada "valorretornado" de tipo varchar. En el cuerpo de la funcin empleamos una estructura condicional (if) para averiguar si el valor enviado como argumento es menor o igual a 20, si lo es, almacenamos en la variable "valorretornado" la cadena "economico", en caso contrario guardamos en tal variable la cadena "costoso"; al finalizar la estructura condicional retornamos la variable "valorretornado":
create or replace function f_costoso (avalor number) return varchar is valorretornado varchar(20); begin valorretornado:=''; if avalor<=20 then valorretornado:='economico'; else valorretornado:='costoso'; end if; return valorretornado; end;

Realizamos un "select" y llamamos a la funcin creada anteriormente, enviando como argumento el campo "precio":
select titulo,precio,f_costoso(precio) from libros;

El resultado mostrar el ttulo de cada libro, el precio y el resultado devuelto por la funcin (si el precio es menor o mayor a $20, la cadena "economico" o "costoso" respectivamente). Entonces, una funcin es un bloque de cdigo que implementa acciones y que es referenciado por un nombre. Puede recibir argumentos. La diferencia con los procedimientos es que retornan un valor siempre. Para asignar un valor a una variable, dentro de una funcin DEBE usarse ":=" (dos puntos e igual). Si no se le definen parmetros a una funcin, no deben colocarse los parntesis. Podemos emplear una funcin sin incluir campos de una tabla. Por ejemplo:
select f_costoso (10) from dual;

Para almacenar los valores de un "select" debemos tipear:


select ...into VARIABLE from...

Por ejemplo:
select sum(precio) into variable from libros where autor='';

La siguiente funcin recibe dos valores numricos como parmetros y retorna el promedio:
create or replace function f_promedio (avalor1 number, avalor2 number) return number is begin return (avalor1+avalor2)/2; end;

Llamamos a la funcin "f_promedio":


exec f_promedio (10,20);

98 - Control de flujo (if)


Las estructuras de control pueden ser condicionales y repetitivas.

Estructuras de control de flujo, bifurcaciones condicionales y bucles. Veremos las condicionales. existen 2: if y case. Existen palabras especiales que pertenecen al lenguaje de control de flujo que controlan la ejecucin de las sentencias, los bloques de sentencias y procedimientos almacenados. Tales palabras son: "begin... end", "if... else", "while", "break" y "continue", "return" y "waitfor". "if... else" testea una condicin; se emplea cuando un bloque de sentencias debe ser ejecutado si una condicin se cumple y si no se cumple, se debe ejecutar otro bloque de sentencias diferente. Sintaxis:
if (CONDICION) then SENTENCIAS-- si la condicin se cumple else SENTENCIAS-- si la condicin resulta falsa end if;

99 - Control de flujo (case)


Vimos que hay dos estructuras condicionales, aprendimos "if", nos detendremos ahora en "case". Aprendimos que el "if" se empleaba cuando tenamos 2 cursos de accin, es decir, se evala una condicin y se ejecutan diferentes bloques de sentencias segn el resultado de la condicin sea verdadero o falso. La estructura "case" es similar a "if", slo que se pueden establecer varias condiciones a cumplir. Con el "if" solamente podemos obtener dos salidas, cuando la condicin resulta verdadera y cuando es falsa, si queremos ms opciones podemos usar "case". Sintaxis:
case VALORACOMPARAR when VALOR1 then SENTENCIAS; when VALOR2 then SENTENCIAS; when VALOR3 then SENTENCIAS; else SENTENCIAS; end case;

Entonces, se emplea "case" cuando tenemos varios cursos de accin; es decir, por cada valor hay un "when... then"; si encuentra un valor coincidente en algn "where" ejecuta el "then" correspondiente a ese "where", si no hay ninguna coincidencia, se ejecuta el "else". Finalmente se coloca "end case" para indicar que el "case" ha finalizado.

Necesitamos, dada una fecha, obtener el nombre del mes en espaol. Podemos utilizar la estructura condicional "case". Para ello crearemos una funcin que reciba una fecha y retorne una cadena de caracteres indicando el nombre del mes de la fecha enviada como argumento:
create or replace function f_mes(afecha date) return varchar2 is mes varchar2(20); begin mes:='enero'; case extract(month from afecha) when 1 then mes:='enero'; when 2 then mes:='febrero'; when 3 then mes:='marzo'; when 4 then mes:='abril'; when 5 then mes:='mayo'; when 6 then mes:='junio'; when 7 then mes:='julio'; when 8 then mes:='agosto'; when 9 then mes:='setiembre'; when 10 then mes:='octubre'; when 11 then mes:='noviembre'; else mes:='diciembre'; end case; return mes; end;

Si probamos la funcin anterior envindole la siguiente fecha:


select f_mes('10/10/2008') from dual;

obtendremos como resultado "octubre". La siguiente funcin recibe una fecha y retorna si se encuentra en el 1, 2, 3 4 trimestre del ao:
create or replace function f_trimestre(afecha date) return varchar2 is mes varchar2(20); trimestre number; begin mes:=extract(month from afecha); trimestre:=4; case mes when 1 then trimestre:=1; when 2 then trimestre:=1; when 3 then trimestre:=1; when 4 then trimestre:=2; when 5 then trimestre:=2; when 6 then trimestre:=2; when 7 then trimestre:=3; when 8 then trimestre:=3;

when 9 then trimestre:=3; else trimestre:=4; end case; return trimestre; end;

La clusula "else" puede omitirse, en caso que no se encuentre coincidencia con ninguno de los "where", se sale del "case" sin modificar el valor de la variable "trimestre", con lo cual, retorna el valor 4, que es que que almacenaba antes de entrar a la estructura "case". Otra diferencia con "if" es que el "case" toma valores puntuales, no expresiones. No es posible realizar comparaciones en cada "where". La siguiente sintaxis provocara un error:
... case mes when >=1 then trimestre:=1; when >=4 then trimestre:=2; when >=7 then trimestre:=3; when >=10 then trimestre:=4; end case;

Si hay ms de una sentencia en un "when...then" NO es necesario delimitarlas con "begin... end". Podemos emplear "case" dentro de un "select". Veamos un ejemplo similar a la funcin anterior:
select nombre,fechanacimiento, case extract(month from fechanacimiento) when 1 then 1 when 2 then 1 when 3 then 1 when 4 then 2 when 5 then 2 when 6 then 2 when 7 then 3 when 8 then 3 when 9 then 3 else 4 end as trimestre from empleados order by trimestre;

100 - Control de flujo (loop)


Las estructuras repetitivas permiten ejecutar una secuencia de sentencias varias veces. Hay tres estructuras repetitivas, o bucles: loop, for y while.

Comenzamos por "loop", que es la ms simple. Veremos la sintaxis del bucle "loop" que combina una condicin y la palabra "exit". Sintaxis:
loop SENTENCIAS; exit when CONDICION; SENTENCIAS; end loop;

Cuando se llega a la lnea de cdigo en la que se encuentra la condicin "exit when", se evala dicha condicin, si resulta cierta, se salta a la lnea donde se encuentra "end loop", saliendo del bucle, omitiendo las sentencias existentes antes del "end loop"; en caso contrario, si la condicin resulta falsa, se contina con las siguientes sentencias y al llegar a "end loop" se repite el bucle. La sintaxis anterior es equivalente a la siguiente:
loop SENTENCIAS if CONDICION then exit; end if; SENTENCIAS end loop;

En este ejemplo se muestra la tabla del 3. Se va incrementando la variable "multiplicador" y se almacena en una variable "resultado"; el ciclo se repite hasta que el multiplicador llega a 5, es decir, 6 veces.
set serveroutput on; declare resultado number; multiplicador number:=0; begin loop resultado:=3*multiplicador; dbms_output.put_line('3x'||to_char(multiplicador)||'='||to_char(resultado )); multiplicador:=multiplicador+1; exit when multiplicador>5; end loop; end;

En el siguiente ejemplo se muestra la tabla del 4. Se va incrementando la variable "multiplicador" y se almacena en una variable "resultado"; el ciclo se repite hasta que la variable resultado llega o supera el valor 50.
declare resultado number;

multiplicador number:=0; begin loop resultado:=4*multiplicador; exit when resultado>=50; dbms_output.put_line('4x'||to_char(multiplicador)||'='||to_char(resultado )); multiplicador:=multiplicador+1; end loop; end;

Cuando se cumple la condicin del "exit when" (supera el valor 50), no se ejecutan las sentencias siguientes (lneas de salida y de incremento de "multiplicador"), se salta a "end loop" finalizando el bucle.

101 - Control de flujo (for)


Vimos que hay tres estructuras repetitivas, o bucles, ya estudiamos "loop". Continuamos con "for". En la sentencia "for... loop" se especifican dos enteros, un lmite inferior y un lmite superior, es decir, un rango de enteros, las sentencias se ejecutan una vez por cada entero; en cada repeticin del bucle, la variable contador del "for" se incrementa en uno. Sintaxis:
for VARIABLECONTADOR in LIMITEINFERIOR..LIMITESUPERIOR loop SENTENCIAS; end loop;

"Variablecontador" debe ser una variable numrica entera; "limiteinferior" y "limitesuperior" son expresiones numricas. La variable que se emplea como contador NO se define, se define automticamente de tipo entero al iniciar el bucle y se liberar al finalizarlo. En el siguiente ejemplo se muestra la tabla del 3. La variable "f" comienza en cero (lmite inferior del for) y se va incrementando de a uno; el ciclo se repite hasta que "f" llega a 5 (lmite superior del for), cuando llega a 6, el bucle finaliza.
set serveroutput on; begin for f in 0..5 loop dbms_output.put_line('3x'||to_char(f)||'='||to_char(f*3));

end loop; end;

Si queremos que el contador se decremente en cada repeticin, en lugar de incrementarse, debemos colocar "reverse" luego de "in" y antes del lmite inferior; el contador comenzar por el valor del lmite superior y finalizar al llegar al lmite inferior decrementando de a uno. En este ejemplo mostramos la tabla del 3 desde el 5 hasta el cero:
begin for f in reverse 0..5 loop dbms_output.put_line('3*'||to_char(f)||'='||to_char(f*3)); end loop; end;

Se pueden colocar "for" dentro de otro "for". Por ejemplo, con las siguientes lneas imprimimos las tablas del 2 y del 3 del 1 al 9:
begin for f in 2..3 loop dbms_output.put_line('tabla del '||to_char(f)); for g in 1..9 loop dbms_output.put_line(to_char(f)||'x'||to_char(g)||'='||to_char(f*g)); end loop;--fin del for g end loop;--fin del for f end;

102 - Control de flujo (while loop)


Ya estudiamos dos de las tres estructuras repetitivas. Continuamos con "while". Vimos que las sentencias repetitivas permiten ejecutar una secuencia de sentencias varias veces. Se coloca la palabra "loop" antes de las sentencias y al final "end loop". "while...loop" (mientras) ejecuta repetidamente una instruccin (o bloque de instrucciones) siempre que la condicin sea verdadera. Sintaxis bsica:
while CONDICION loop SENTENCIAS end loop;

La diferencia entre "while...loop" y "for...loop" es que en la segunda se puede establecer la cantidad de repeticiones del bucle con el valor inicial y final. Adems, el segundo siempre

se ejecuta, al menos una vez, en cambio el primero puede no ejecutarse nunca, caso en el cual al evaluar la condicion por primera vez resulte falsa. En el siguiente ejemplo se muestra la tabla del 3 hasta el 5:
set server output on; execute dbms_output.enable (20000); declare numero number:=0; resultado number; begin while numero<=5 loop resultado:=3*numero; dbms_output.put_line('3*'||to_char(numero)||'='||to_char(resultado)); numero:=numero+1; end loop; end;

La condicin establece que se multiplique la variable "numero" por 3 mientras "numero" sea menor o igual a 5. En el bloque de sentencias se almacena en "resultado" la multiplicacin, luego se escribe tal valor y finalmente se incrementa la variable "numero" en 1. Hacemos el seguimiento: cuando se inicia el bucle, la variable "numero" tiene el valor 0, se ejecuta la primer linea de sentencias y "resultado" almacena el valor 0, se imprime (0) y se incrementa la variable "numero", ahora contiene el valor 1; se vuelve a la condicin, como la condicin es verdadera (1 es menor que 5), se vuelven a ejecutar las sentencias (resultado almacena 3, se imprime (3), se guarda en numero el valor 2), se vuelve a evaluar la condicin, como resulta cierta (2 es menor que 5), se vuelven a ejecutar las sentencias (resultado almacena 6, se imprime, se guarda en numero el valor 3), se vuelve a evaluar la condicin, como resulta cierta (3 es menor que 5), se vuelven a ejecutar las sentencias (resultado almacena 9, se imprime, se guarda en numero el valor 4), se vuelve a evaluar la condicin, como resulta cierta (4 es menor que 5), se vuelven a ejecutar las sentencias (resultado almacena 12, se imprime, se guarda en numero el valor 5), se vuelve a evaluar la condicin, como resulta cierta (5 es menor o igual a 5), se vuelven a ejecutar las sentencias (resultado almacena 15, se imprime, se guarda en numero el valor 6), se vuelve a evaluar la condicin, como resulta falsa (6 NO es menor ni igual a 5), se sale de la estructura.

103 - Disparador (trigger)


Un "trigger" (disparador o desencadenador) es un bloque de cdigo que se ejecuta automticamente cuando ocurre algn evento (como insercin, actualizacin o borrado) sobre una determinada tabla (o vista); es decir, cuando se intenta modificar los datos de una tabla (o vista) asociada al disparador.

Se crean para conservar la integridad referencial y la coherencia entre los datos entre distintas tablas; para registrar los cambios que se efectan sobre las tablas y la identidad de quien los realiz; para realizar cualquier accin cuando una tabla es modificada; etc. Si se intenta modificar (agregar, actualizar o eliminar) datos de una tabla asociada a un disparador, el disparador se ejecuta (se dispara) en forma automtica. La diferencia con los procedimientos almacenados del sistema es que los triggers: - no pueden ser invocados directamente; al intentar modificar los datos de una tabla asociada a un disparador, el disparador se ejecuta automticamente. - no reciben y retornan parmetros. - son apropiados para mantener la integridad de los datos, no para obtener resultados de consultas. Sintaxis general para crear un disparador:
create or replace trigger NOMBREDISPARADOR MOMENTO-- before, after o instead of EVENTO-- insert, update o delete of CAMPOS-- solo para update on NOMBRETABLA NIVEL--puede ser a nivel de sentencia (statement) o de fila (for each row) when CONDICION--opcional begin CUERPO DEL DISPARADOR--sentencias end NOMBREDISPARADOR;

Los triggers se crean con la instruccin "create trigger" seguido del nombre del disparador. Si se agrega "or replace" al momento de crearlo y ya existe un trigger con el mismo nombre, tal disparador ser borrado y vuelto a crear. "MOMENTO" indica cuando se disparar el trigger en relacin al evento, puede ser BEFORE (antes), AFTER (despus) o INSTEAD OF (en lugar de). "before" significa que el disparador se activar antes que se ejecute la operacin (insert, update o delete) sobre la tabla, que caus el disparo del mismo. "after" significa que el trigger se activar despus que se ejecute la operacin que caus el disparo. "instead of" slo puede definirse sobre vistas, anula la sentencia disparadora, se ejecuta en lugar de tal sentencia (ni antes ni despus). "EVENTO" especifica la operacin (accin, tipo de modificacin) que causa que el trigger se dispare (se active), puede ser "insert", "update" o "delete"; DEBE colocarse al menos una accin, puede ser ms de una, en tal caso se separan con "or". Si "update" lleva una lista de atributos, el trigger slo se ejecuta si se actualiza algn atributo de la lista.

"on NOMBRETABLA" indica la tabla (o vista) asociada al disparador; "NIVEL" puede ser a nivel de sentencia o de fila. "for each row" indica que el trigger es a nivel de fila, es decir, se activa una vez por cada registro afectado por la operacin sobre la tabla, cuando una sola operacin afecta a varios registros. Los triggers a nivel de sentencia, se activan una sola vez (antes o despus de ejecutar la operacin sobre la tabla). Si no se especifica, o se especifica "statement", es a nivel de sentencia. "CUERPO DEL DISPARADOR" son las acciones que se ejecutan al dispararse el trigger, las condiciones que determinan cuando un intento de insercin, actualizacin o borrado provoca las acciones que el trigger realizar. El bloque se delimita con "begin... end". Entonces, un disparador es un bloque de cdigo asociado a una tabla que se dispara automticamente antes o despus de una sentencia "insert", "update" o "delete" sobre la tabla. Se crean con la instruccin "create trigger" especificando el momento en que se disparar, qu evento lo desencadenar (insercin, actualizacin o borrado), sobre qu tabla (o vista) y las instrucciones que se ejecutarn. Los disparadores pueden clasificarse segn tres parmetros: - el momento en que se dispara: si se ejecutan antes (before) o despus (after) de la sentencia. - el evento que los dispara: insert, update o delete, segn se ejecute una de estas sentencias sobre la tabla. - nivel: dependiendo si se ejecuta para cada fila afectada en la sentencia (por cada fila) o bien una nica vez por sentencia independientemente de la filas afectadas (nivel de sentencia). Consideraciones generales: - Las siguientes instrucciones no estn permitidas en un desencadenador: create database, alter database, drop database, load database, restore database, load log, reconfigure, restore log, disk init, disk resize. - Se pueden crear varios triggers para cada evento, es decir, para cada tipo de modificacin (insercin, actualizacin o borrado) para una misma tabla. Por ejemplo, se puede crear un "insert trigger" para una tabla que ya tiene otro "insert trigger". A continuacin veremos la creacin de disparadores para los distintos sucesos (insercin, borrado, actualizacin) y todas las clusulas adicionales.

104 - Disparador (informacin)


Los triggers son objetos, as que para obtener informacin de ellos pueden consultarse los siguientes diccionarios: . - "user_objects": nos muestra todos los objetos de la base de datos seleccionada, incluidos los triggers. En la columna "object_type" aparece "trigger" si es un disparador. En el siguiente ejemplo solicitamos todos los objetos que son disparadores:
select *from user_objects where object_type='TRIGGER';

- "user_triggers": nos muestra todos los triggers de la base de datos actual. Muestra el nombre del desencadenador (trigger_name), si es before o after y si es a nivel de sentencia o por fila (trigger_type), el evento que lo desencadena (triggering_event), a qu objeto est asociado, si tabla o vista (base_object_type), el nombre de la tabla al que est asociado (table_name), los campos, si hay referencias, el estado, la descripcin, el cuerpo (trigger_body), etc. En el siguiente ejemplo solicitamos informacin de todos los disparadores que comienzan con "TR":
select trigger_name, triggering_event from user_triggers where trigger_name like 'TR%';

- "user_source": se puede visualizar el cdigo fuente almacenado en un disparador consultando este diccionario: En el siguiente ejemplo solicitamos el cdigo fuente del objeto "TR_insertar_libros":
select *from user_source where name='TR_INSERTAR_LIBROS';

105 - Disparador de insercin a nivel de sentencia


Dijimos que un disparador est asociado a una tabla y a una operacin especfica (insercin, actualizacin o borrado). A continuacin veremos la creacin de un disparador para el evento de insercin: "insert triger".

La siguiente es la sintaxis para crear un trigger de insercin que se dispare cada vez que se ejecute una sentencia "insert" sobre la tabla especificada, es decir, cada vez que se intenten ingresar datos en la tabla:
create or replace trigger NOMBREDISPARADOR MOMENTO insert on NOMBRETABLA begin CUERPO DEL TRIGGER; end NOMBREDISPARADOR;

Analizamos la sintaxis: Luego de la instruccin "create trigger" se coloca el nombre del disparador. Si se agrega "or replace" al momento de crearlo y ya existe un trigger con el mismo nombre, tal disparador ser borrado y vuelto a crear. "MOMENTO" indica cuando se disparar el trigger en relacin al evento, puede se BEFORE (antes) o AFTER (despus). Se especifica el evento que causa que el trigger se dispare, en este caso "insert", ya que el trigger se activar cada vez que se ejecute la sentencia "insert" sobre la tabla especificada luego de "on". Es un trigger a nivel de sentencia, es decir, se dispara una sola vez por cada sentencia "insert", aunque la sentencia ingrese varios registros. Es el valor por defecto si no se especifica. Finalmente se coloca el cuerpo del trigger dentro del bloque "begin.. end". Las siguientes sentencias disparan un trigger de insercin:
insert into TABLA values ...; insert into TABLA select ... from...;

Ejemplo: Creamos un desencadenador que se dispara cada vez que se ejecuta un "insert" sobre la tabla "libros":
create or replace trigger tr_ingresar_libros before insert on libros begin insert into Control values(user,sysdate); end tr_ingresar_libros;

Analizamos el trigger anterior: "create or replace trigger" junto al nombre del disparador que tiene un prefijo "tr" para reconocer que es un trigger, referencia el evento que lo disparar y la tabla asociada.

Para identificar fcilmente los disparadores de otros objetos se recomienda usar un prefijo y darles el nombre de la tabla para la cual se crean junto al tipo de accin. El disparador se activar antes ("before") del evento "insert" sobre la tabla "libros", es decir, se disparar ANTES que se realice una insercin en "libros". El trigger est definido a nivel de sentencia, se activa una vez por cada instruccin "insert" sobre "libros". El cuerpo del disparador se delimita con "begin... end", all se especifican las acciones que se realizarn al ocurrir el evento de insercin, en este caso, ingresar en la tabla "control" el nombre del usuario que alter la tabla "libros" (obtenida mediante la funcin "user") y la fecha en que lo hizo (mediante la funcin "sysdate").

106 - Disparador de insercion a nivel de fila (insert trigger for each row)
Vimos la creacin de un disparador para el evento de insercin a nivel de sentencia, es decir, se dispara una vez por cada sentencia "insert" sobre la tabla asociada. En caso que una sola sentencia "insert" ingrese varios registros en la tabla asociada, el trigger se disparar una sola vez; si queremos que se active una vez por cada registro afectado, debemos indicarlo con "for each row". La siguiente es la sintaxis para crear un trigger de insercin a nivel de fila, se dispare una vez por cada fila ingresada sobre la tabla especificada:
create or replace trigger NOMBREDISPARADOR MOMENTO insert on NOMBRETABLA for each row begin CUERPO DEL TRIGGER; end NOMBREDISPARADOR;

Creamos un desencadenador que se dispara una vez por cada registro ingresado en la tabla "ofertas":
create or replace trigger tr_ingresar_ofertas before insert on ofertas for each row begin insert into Control values(user,sysdate); end tr_ingresar_ofertas;

Si al ejecutar un "insert" sobre "ofertas" empleamos la siguiente sentencia:

insert into ofertas select titulo,autor,precio from libros where precio<30;

y se ingresan 5 registros en "ofertas", en la tabla "control" se ingresarn 5 registros, uno por cada insercin en "ofertas". Si el trigger hubiese sido definido a nivel de sentencia (statement), se agregara una sola fila en "control".

107 - Disparador de borrado (nivel de sentencia y de fila)


Dijimos que un disparador est asociado a una tabla y a una operacin especfica (insercin, actualizacin o borrado). A continuacin veremos la creacin de un disparador para el evento de borrado: "delete triger". La siguiente es la sintaxis para crear un trigger de eliminacin que se dispare cada vez que se ejecute una sentencia "delete" sobre la tabla especificada, es decir, cada vez que se eliminen registros de la tabla:
create or replace trigger NOMBREDISPARADOR MOMENTO delete on NOMBRETABLA NIVEL-- statement o for each row begin CUERPO DEL TRIGGER; end NOMBREDISPARADOR;

Luego de la instruccin "create trigger" o "create or replace trigger" se coloca el nombre del disparador. "MOMENTO" indica cuando se disparar el trigger en relacin al evento, puede se BEFORE (antes) o AFTER (despus). Se especifica el evento que causa que el trigger se dispare, en este caso "delete", ya que el trigger se activar cada vez que se ejecute la sentencia "delete" sobre la tabla especificada luego de "on". En "NIVEL" se especifica si ser un trigger a nivel de sentencia (se dispara una sola vez por cada sentencia "delete", aunque la sentencia elimine varios registros) o a nivel de fila (se dispara tantas veces como filas se eliminan en la sentencia "delete"). Finalmente se coloca el cuerpo del tigger dentro del bloque "begin.. end".

Creamos un desencadenador a nivel de fila que se dispara cada vez que se ejecuta un "delete" sobre la tabla "libros", en el cuerpo del trigger se especifican las acciones, en este caso, por cada fila eliminada de la tabla "libros", se ingresa un registro en "control" con el nombre del usuario que realiz la eliminacin y la fecha:
create or replace trigger tr_borrar_libros before delete on libros for each row begin insert into Control values(user,sysdate); end tr_borrar_libros;

108 - Disparador de actualizacion a nivel de sentencia (update trigger)


Dijimos que un disparador est asociado a una tabla y a una operacin especfica (insercin, actualizacin o borrado). A continuacin veremos la creacin de un disparador para el evento de actualizacin: "update triger". La siguiente es la sintaxis para crear un trigger de actualizacin a nivel de sentencia, que se dispare cada vez que se ejecute una sentencia "update" sobre la tabla especificada, es decir, cada vez que se intenten modificar datos en la tabla:
create or replace trigger NOMBREDISPARADOR MOMENTO update on NOMBRETABLA statement begin CUERPO DEL TRIGGER; end NOMBREDISPARADOR;

Luego de la instruccin "create trigger" se coloca el nombre del disparador. Si agregamos "or replace" al momento de crearlo y ya existe un trigger con el mismo nombre, tal disparador ser borrado y vuelto a crear. "MOMENTO" indica cuando se disparar el trigger en relacin al evento, puede ser BEFORE (antes) o AFTER (despus). Se especifica el evento que causa que el trigger se dispare, en este caso "update", ya que el trigger se activar cada vez que se ejecute la sentencia "update" sobre la tabla especificada luego de "on".

"statement" significa que es un trigger a nivel de sentencia, es decir, se dispara una sola vez por cada sentencia "update", aunque la sentencia modifique varios registros; como en cualquier trigger, es el valor por defecto si no se especifica. Finalmente se coloca el cuerpo del tigger dentro del bloque "begin.. end". Las siguientes sentencias disparan un trigger de insercin:
update TABLA set CAMPO=NUEVOVALOR; update TABLA set CAMPO=NUEVOVALOR where CONDICION;

Ejemplo: Creamos un desencadenador que se dispara cada vez que se ejecuta un "update" sobre la tabla "libros":
create or replace trigger tr_actualizar_libros before update on libros begin insert into control values(user,sysdate); end tr_actualizar_libros;

Al ocurrir el evento de actualizacin sobre "libros", se ingresa en la tabla "control" el nombre del usuario que alter la tabla "libros" (obtenida mediante la funcin "user") y la fecha en que lo hizo (mediante la funcin "sysdate").

109 - Disparador de actualizacin a nivel de fila (update trigger)


Vimos la creacin de un disparador para el evento de actualizacin a nivel de sentencia, es decir, se dispara una vez por cada sentencia "update" sobre la tabla asociada. En caso que una sola sentencia "update" modifique varios registros en la tabla asociada, el trigger se disparar una sola vez; si queremos que se active una vez por cada registro afectado, debemos indicarlo con "for each row". La siguiente es la sintaxis para crear un trigger de actualizacin a nivel de fila, se dispare una vez por cada fila modificada sobre la tabla especificada:
create or replace trigger NOMBREDISPARADOR MOMENTO update on NOMBRETABLA for each row begin CUERPO DEL TRIGGER;

end NOMBREDISPARADOR;

Creamos un desencadenador a nivel de fila, que se dispara una vez por cada fila afectada por un "update" sobre la tabla "libros". Se ingresa en la tabla "control" el nombre del usuario que altera la tabla "libros" (obtenida mediante la funcin "user") y la fecha en que lo hizo (mediante la funcin "sysdate"):
create or replace trigger tr_actualizar_libros before update on libros for each row begin insert into control values(user,sysdate); end tr_actualizar_libros;

Si al ejecutar un "update" sobre "libros" se actualizan 5 registros, en la tabla "control" se ingresarn 5 registros, uno por cada modificacin. Si el trigger hubiese sido definido a nivel de sentencia (statement), se agregara una sola fila en "control".

110 - Disparador de actualizacin - lista de campos (update trigger)


El trigger de actualizacin (a nivel de sentencia o de fila) permite incluir una lista de campos. Si se incluye el nombre de un campo (o varios) luego de "update", el trigger se disparar nicamente cuando alguno de esos campos (incluidos en la lista) es actualizado. Si se omite la lista de campos, el trigger se dispara cuando cualquier campo de la tabla asociada es modificado, es decir, por defecto toma todos los campos de la tabla. La lista de campos solamente puede especificarse en disparadores de actualizacin, nunca en disparadores de insercin o borrado. Sintaxis general:
create or replace trigger NOMBREDISPARADOR MOMENTO update of CAMPOS on TABLA NIVEL--statement o for each row begin CUERPODEL DISPARADOR; end NOMBREDISPARADOR;

"CAMPOS" son los campos de la tabla asociada que activarn el trigger si son modificados. Pueden incluirse ms de uno, en tal caso, se separan con comas.

Creamos un desencadenador a nivel de fila que se dispara cada vez que se actualiza el campo "precio" de la tabla "libros":
create or replace trigger tr_actualizar_precio_libros before update of precio on libros for each row begin insert into control values(user,sysdate); end tr_actualizar_precio_libros;

Si realizamos un "update" sobre el campo "precio" de "libros", el trigger se dispara. Pero si realizamos un "update" sobre cualquier otro campo, el trigger no se dispara, ya que est definido solamente para el campo "precio".

111 - Disparador de mltiples eventos


Hasta el momento hemos aprendido a crear un disparador (trigger) asociado a una nica operacin (insercin, actualizacin o borrado). Un trigger puede definirse sobre ms de un evento; en tal caso se separan con "or". Sintaxis para crear un disparador para mltiples eventos:
create or replace trigger NOMBREDISPARADOR MOMENTO-- before, after o instead of of CAMPO--si alguno de los eventos es update EVENTOS-- insert, update y/o delete on NOMBRETABLA NIVEL--puede ser a nivel de sentencia (statement) o de fila (for each row) begin CUERPO DEL DISPARADOR--sentencias end NOMBREDISPARADOR;

Si el trigger se define para ms de un evento desencadenante, en el cuerpo del mismo se puede emplear un condicional para controlar cul operacin dispar el trigger. Esto permite ejecutar bloques de cdigo segn la clase de accin que dispar el desencadenador. Para identificar el tipo de operacin que dispar el trigger empleamos "inserting", "updating" y "deleting". Veamos un ejemplo. El siguiente trigger est definido a nivel de sentencia, para los eventos "insert", "update" y "delete"; cuando se modifican los datos de "libros", se almacena en la tabla "control" el nombre del usuario, la fecha y el tipo de modificacin que alter la tabla:

- si se realiz una insercin, se almacena "insercin"; - si se realiz una actualizacin (update), se almacena "actualizacin" y - si se realiz una eliminacin (delete) se almacena "borrado".
create or replace trigger tr_cambios_libros before insert or update or delete on libros for each row begin if inserting then insert into control values (user, sysdate,'insercin'); end if; if updating then insert into control values (user, sysdate,'actualizacin'); end if; if deleting then insert into control values (user, sysdate,'borrado'); end if; end tr_cambios_libros;

Si ejecutamos un "insert" sobre "libros", el disparador se activa entrando por el primer "if"; si ejecutamos un "update" el trigger se dispara entrando por el segundo "if"; si ejecutamos un "delete" el desencadenador se dispara entrando por el tercer "if". Las siguientes sentencias disparan el trigger creado anteriormente:
insert insert update delete into TABLA values ...; into TABLA select ... from...; TABLA set...; from TABLA...;

112 - Disparador (old y new)


Cuando trabajamos con trigger a nivel de fila, Oracle provee de dos tablas temporales a las cuales se puede acceder, que contienen los antiguos y nuevos valores de los campos del registro afectado por la sentencia que dispar el trigger. El nuevo valor es ":new" y el viejo valor es ":old". Para referirnos a ellos debemos especificar su campo separado por un punto ":new.CAMPO" y ":old.CAMPO". El acceso a estos campos depende del evento del disparador. En un trigger disparado por un "insert", se puede acceder al campo ":new" unicamente, el campo ":old" contiene "null".

En una insercin se puede emplear ":new" para escribir nuevos valores en las columnas de la tabla. En un trigger que se dispara con "update", se puede acceder a ambos campos. En una actualizacion, se pueden comparar los valores de ":new" y ":old". En un trigger de borrado, unicamente se puede acceder al campo "old", ya que el campo ":new" no existe luego que el registro es eliminado, el campo ":new" contiene "null" y no puede ser modificado. Los valores de "old" y "new" estn disponibles en triggers after y before. El valor de ":new" puede modificarse en un trigger before, es decir, se puede acceder a los nuevos valores antes que se ingresen en la tabla y cambiar los valores asignando a ":new.CAMPO" otro valor. El valor de ":new" NO puede modificarse en un trigger after, esto es porque el trigger se activa luego que los valores de "new" se almacenaron en la tabla. El campo ":old" nunca se modifica, slo puede leerse. Pueden usarse en una clsula "when" (que veremos posteriormente). En el cuerpo el trigger, los campos "old" y "new" deben estar precedidos por ":" (dos puntos), pero si est en "when" no. Veamos un ejemplo. Creamos un trigger a nivel de fila que se dispara "antes" que se ejecute un "update" sobre el campo "precio" de la tabla "libros". En el cuerpo del disparador se debe ingresar en la tabla "control", el nombre del usuario que realiz la actualizacin, la fecha, el cdigo del libro que ha sido modificado, el precio anterior y el nuevo:
create or replace trigger tr_actualizar_precio_libros before update of precio on libros for each row begin insert into control values(user,sysdate,:new.codigo,:old.precio,:new.precio); end tr_actualizar_precio_libros;

Cuando el trigger se dispare, antes de ingresar los valores a la tabla, almacenar en "control", adems del nombre del usuario y la fecha, el precio anterior del libro y el nuevo valor.

El siguiente trigger debe controlar el precio que se est actualizando, si supera los 50 pesos, se debe redondear tal valor a entero, hacia abajo (empleando "floor"), es decir, se modifica el valor ingresado accediendo a ":new.precio" asignndole otro valor:
create or replace trigger tr_actualizar_precio_libros before update of precio on libros for each row begin if (:new.precio>50) then :new.precio:=floor(:new.precio); end if; insert into control values(user,sysdate,:new.codigo,:old.precio,:new.precio); end tr_actualizar_precio_libros;

Si al actualizar el precio de un libro colocamos un valor superior a 50, con decimales, tal valor se redondea al entero ms cercano hacia abajo. Por ejemplo, si el nuevo valor es "54.99", se almacenar "54". Podemos crear un disparador para mltiples eventos, que se dispare al ejecutar "insert", "update" y "delete" sobre "libros". En el cuerpo del trigger se realiza la siguiente accin: se almacena el nombre del usuario, la fecha y los antiguos y viejos valores del campo "precio":
create or replace trigger tr_libros before insert or update or delete on libros for each row begin insert into control values(user,sysdate,:old.codigo,:old.precio,:new.precio); end tr_libros;

Si ingresamos un registro, el campo ":old.codigo" y el campo ":old.precio" contendrn "null". Si realizamos una actualizacin del campo de un campo que no sea "precio", los campos ":old.precio" y ":new.precio" guardarn el mismo valor. Si eliminamos un registro, el campo ":new.precio" contendr "null". Entonces, se puede acceder a los valores de ":new" y ":old" en disparadores a nivel de fila (no en disparadores a nivel de sentencia). Estn disponibles en triggers after y before. Los valores de ":old" solamente pueden leerse, nunca modificarse. Los valores de ":new" pueden modificarse nicamente en triggers before (nunca en triggers after).

113 - Disparador condiciones (when)

En los triggers a nivel de fila, se puede incluir una restriccin adicional, agregando la clausula "when" con una condicin que se evala para cada fila que afecte el disparador; si resulta cierta, se ejecutan las sentencias del trigger para ese registro; si resulta falsa, el trigger no se dispara para ese registro. Limitaciones de "when": - no puede contener subconsultas, funciones agregadas ni funciones definidas por el usuario; - slo se puede hacer referencia a los parmetros del evento; - no se puede especificar en los trigers "instead of" ni en trigger a nivel de sentencia. Creamos el siguiente disparador:
create or replace trigger tr_precio_libros before insert or update of precio on libros for each row when(new.precio>50) begin :new.precio := round(:new.precio); end tr_precio_libros;

El disparador anterior se dispara ANTES (before) que se ejecute un "insert" sobre "libros" o un "update" sobre "precio" de "libros". Se ejecuta una vez por cada fila afectada (for each row) y solamente si cumple con la condicin del "when", es decir, si el nuevo precio que se ingresa o modifica es superior a 50. Si el precio es menor o igual a 50, el trigger no se dispara. Si el precio es mayor a 50, se modifica el valor ingresado redondendolo a entero. Note que cuando hacemos referencia a "new" (igualmente con "old") en la condicin "when", no se colocan los dos puntos precedindolo; pero en el cuerpo del trigger si. Si ingresamos un registro con el valor 30.80 para "precio", el trigger no se dispara. Si ingresamos un registro con el valor "55.6" para "precio", el trigger se dispara modificando tal valor a "56". Si actualizamos el precio de un libro a "40.30", el trigger no se activa. Si actualizamos el precio de un libro a "50.30", el trigger se activa y modifica el valor a "50". Si actualizamos el precio de 2 registros a valores que superen los "50", el trigger se activa 2 veces redondeando los valores a entero. Si actualizamos en una sola sentencia el precio de 2 registros y solamente uno de ellos supera los "50", el trigger se activa 1 sola vez.

El trigger anterior podra haberse creado de la siguiente manera:


create or replace trigger tr_precio_libros before insert or update of precio on libros for each row begin if :new.precio>50 then :new.precio := round(:new.precio); end if; end tr_precio_libros;

En este caso, la condicin se chequea en un "if" dentro del cuerpo del trigger. La diferencia con el primer trigger que contiene "when" es que la condicin establecida en el "when" se testea antes que el trigger se dispare y si resulta verdadera, se dispara el trigger, sino no. En cambio, si la condicin est dentro del cuerpo del disparador, el trigger se dispara y luego se controla el precio, si cumple la condicin, se modifica el precio, sino no. Por ejemplo, la siguiente sentencia:
update libros set precio=40 where...;

no dispara el primer trigger, ya que no cumple con la condicin del "when"; pero si dispara el segundo trigger, que no realiza ninguna accin ya que al evaluarse la condicin del "if", resulta falsa.

114 - Disparador de actualizacion campos (updating)


En un trigger de actualizacin a nivel de fila, se puede especificar el nombre de un campo en la condicin "updating" para determinar cul campo ha sido actualizado. Sintaxis bsica:
create or replace trigger NOMBRETRIGGER MOMENTO update... begin if updating ('CAMPO') then ... end if; end NOMBREDISPARADOR;

El siguiente trigger se dispara cuando se actualiza la tabla "libros". Dentro del cuerpo del trigger se averigua el campo que ha sido modificado; en caso de modificarse el "precio", se ingresa en la tabla "controlPrecios" la fecha, el cdigo del libro y el antiguo y nuevo precio;

en caso de actualizarse cualquier otro campo, se almacena en la tabla "control" el nombre del usuario que realiz la modificacin, la fecha y el cdigo del libro modificado.
create or replace trigger tr_actualizar_libros before update on libros for each row begin if updating ('precio') then insert into controlprecios values(sysdate,:old.codigo,:old.precio,:new.precio); else insert into control values(user,sysdate,:old.codigo); end if; end tr_actualizar_libros;

115 - Disparadores (habilitar y deshabilitar)


Un disparador puede estar en dos estados: habilitado (enabled) o deshabilitado (disabled). Cuando se crea un trigger, por defecto est habilitado. Se puede deshabilitar un trigger para que no se ejecute. Un trigger deshabilitado sigue existiendo, pero al ejecutar una instruccin que lo dispara, no se activa. Sintaxis para deshabilitar un trigger:
alter trigger NOMBREDISPARADOR disable;

Ejemplo: Deshabilitamos el trigger "tr_ingresar_empleados":


alter trigger tr_ingresar_empleados disable;

Sintaxis para habilitar un trigger que est deshabilitado:


alter trigger NOMBREDISPARADOR enable;

Ejemplo: Habilitamos el trigger "tr_actualizar_empleados":


alter trigger tr_actualizar_empleados enable;

Se pueden habilitar o deshabilitar todos los trigger establecidos sobre una tabla especifica, se emplea la siguiente sentencia;

alter table TABLA disable all triggers;--deshabilita alter table TABLA enable all triggers;-- habilita

La siguiente sentencia deshabilita todos los triggers de la tabla "empleados":


alter table empleados enable all triggers;

Podemos saber si un trigger est o no habilitado cosultando el diccionario "user_triggers", en la columna "status" aparece "enabled" si est habilitado y "disabled" si est deshabilitado.

116 - Disparador (eliminar)


Para eliminar un trigger se emplea la siguiente sentencia:
drop trigger NOMBRETRIGGER;

Ejemplo:
drop trigger tr_insertar_libros;

Si eliminamos una tabla, se eliminan todos los triggers establecidos sobre ella.

117 - Errores definidos por el usuario


Oracle permite definir a los usuarios errores especificando un nmero de error y un mensaje empleando el procedimiento "raise_application_error". Sintaxis:
raise_application_error (NUMERO,TEXTO);

El procedimiento "raise_application_error" permite emitir un mensaje de error. El NUMERO de mensaje debe ser un nmero negativo entre -20000 y -20999 y el mensaje de TEXTO una cadena de caracteres de hasta 2048 bytes. Si durante la ejecucin de un trigger se produce un error definido por el usuario, se anulan todas las actualizaciones realizadas por la accin del trigger as como el evento que la activ, es decir, se reanuda cualquier efecto retornando un mensaje y se deshace la orden ejecutada.

En caso que se incluya en el cuerpo de un disparador "after" (que se ejecuta despus de la sentencia, es decir, cuando los datos ya han sido actualizados), la sentencia ser deshecha (rollback). Si es un disparador "before" (que se ejecuta antes de la sentencia, o sea, cuando los datos an no han sido actualizados), la sentencia no se ejecuta. Veamos un ejemplo: Creamos un trigger de actualizacin a nivel de fila sobre la tabla "libros". Ante cualquier modificacin de los registros de "libros", se debe ingresar en la tabla "control", el nombre del usuario que realiz la actualizacin y la fecha; pero, controlamos que NO se permita modificar el campo "codigo", en caso de suceder, la accin no debe realizarse y debe mostrarse un mensaje de error indicndolo:
create or replace trigger tr_actualizar_libros before update on libros for each row begin if updating('codigo') then raise_application_error(-20001,'No se puede modificar el cdigo de los libros'); else insert into control values(user,sysdate); end if; end;

Si se actualiza cualquier campo de "libros", se dispara el trigger; si se actualiza el campo "codigo", aparece un mensaje de error y la actualizacin no se realiza; en caso de actualizarse cualquier otro campo, se almacenar en "control", el nombre del usuario y la fecha.

118 - Seguridad y acceso a Oracle


Una de las tareas al administrar Oracle es permitir el acceso a bases de datos y asignar permisos sobre los objetos que conforman una base de datos. Para conectarnos con un servidor Oracle necesitamos un modo de acceso que incluye los permisos que dispondremos durante la conexin; estos permisos se definen a partir de un nombre de usuario. Un USUARIO es un identificador necesario para acceder a una base de datos. Un usuario es un conjunto de permisos que se aplican a una conexin de base de datos. Un usuario es adems propietario de ciertos objetos. Los PRIVILEGIOS (permisos) especifican qu operaciones puede realizar un usuario y sobre qu objetos de la base de datos tiene autorizacin, es decir, qu tarea puede realizar

con esos objetos y si puede emitir determinadas instrucciones. Estas operaciones pueden ser de dos tipos: de sistema y sobre objeto. Un rol de base de datos es una agrupacin de permisos de sistema y de objeto. Un ROL (role) es un grupo de usuarios; permite agrupar usuarios para aplicarles permisos; as, al agregar un nuevo usuario a la base de datos, no es necesario concederle permiso para cada objeto, sino que lo agregamos a un rol; cuando asignamos permisos sobre un objeto al rol, automticamente el permiso afectar a los usuarios que pertenezcan a tal rol. Los permisos controlan el acceso a los distintos objetos de una base de datos; pueden concederse a nivel de usuario (individualmente) o a nivel de rol (a todos los usuarios de un grupo). Los permisos que un usuario tiene en una base de datos dependen de los permisos de usuario y de los roles al que pertenezca dicho usuario. Usuarios, roles y permisos son la base de los mecanismos de seguridad de Oracle.

119 - Usuarios (crear)


Puede haber varios usuarios diferentes de la base de datos. Cada uno es propietario de sus objetos. Para crear un usuario debemos conectarnos a la base datos como administradores (por ejemplo "system"). Sintaxis bsica para crear un usuario:
create user NOMBREUSUARIO identified by CONTRASEA default tablespace NOMBRETABLESPACEPORDEFECTO quota CANTIDAD on TABLEESPACE; ** [default role ROLE, ALL];

La clusula "identified by" permite indicar una contrasea. La clusula "default tablespace" ser el tablespace (espacio de tablas) por defecto en la creacin de objetos del usuario. Si se omite se utilizar el tablespace SYSTEM. Los tablespaces son unidades lgicas en las cuales de divide una base de datos, en las cuales se almacenan los objetos (tablas, secuencias, etc.); todos los objetos estn almacenados dentro de un tablespace. La clusula "quota" permite configurar un espacio en bytes, Kb o Mb en la base de datos. Si no se especifica, por defecto es cero y no podr crear objetos.

La clusula "default role" permite asignar roles de permisos durante la creacin del usuario. Ejemplo:
create user ana identified by anita;

Con la sentencia anterior se crea un usuario denominado "ana" con la clave "anita", el tablespace por defecto es "system" porque no se especific otro. Con la siguiente sentencia se crea un usuario denominado "juan" con la clave "juancito", se le asigna un espacio de 100 mb:
create user juan identified by juancito default tablespace system quota 100M on system;

Si intentamos crear un usuario que ya existe, Oracle muestra un mensaje de error indicando tal situacin. El diccionario "dba_users" muestra informacin sobre todos los usuarios; el nombre de usuario (username), contrasea (password), estado (account_status), espacio (default_tablespace), fecha de expiracin (expiry_date), fecha de creacin (created), entre otros. Luego de crear un usuario, an no podemos conectarnos, ya que no tenemos permiso para crear una sesin. Los permisos se aprendern prximamente.

120 - Permiso de conexin


Los usuarios necesitan permisos para poder acceder a la base de datos y a los objetos de la misma. Los privilegios pueden ser de dos tipos: del sistema y sobre objetos. Como mnimo, un usuario debe tener permiso para conectarse. El permiso "create session" es un privilegio de sistema. Para conceder permiso de conexin a un usuario empleamos la instruccin "grant". Sintaxis bsica:
grant create session to USUARIO;

En el siguiente ejemplo concedemos al usuario "juan" permiso para conectarse:


grant create session to juan;

Podemos consultar el diccionario "dba_sys_privs" para encontrar los privilegios concedidos a los usuarios. Nos mostrar el nombre del usuario (grantee) y el permiso (privilege), entre otra informacin que analizaremos prximamente. Luego de tener permiso para crear sesin, puede crear una sesin presionando el cono "new connection" en la solapa "connections"; se abrir una ventana en la cual deber colocar un nombre de conexin ("connection name", puede ser el mismo nombre de usuario), el nombre del usuario ("username") y la contrasea ("password"), luego presionar el botn "connect"; se abrir una nueva solapa (nueva conexin) con el nombre del usuario; no se abrir la nueva conexin si: a) el usuario para quien quiere abrir una nueva sesin no existe, b) la contrasea es incorrecta o c) el usuario existe pero no tiene permiso "create session". Si consultamos el diccionario "user_sys_privs" obtendremos la misma informacin que "dba_sys_privs" pero nicamente del usuario actual. Podemos averiguar el nombre del usuario conectado con la siguiente sentencia:
select user from dual;

121 - Privilegios del sistema (conceder)


Aprendimos que los usuarios necesitan permisos para poder acceder a la base de datos y a los objetos de la misma. Dijimos que los privilegios pueden ser de dos tipos: a) del sistema y b) sobre objetos. Hemos aprendido a conceder un privilegio de sistema: "create session", que es necesario para poder conectarse a la base de datos, es decir, para iniciar una sesin. Pero teniendo nicamente este permiso, no podemos hacer mucho, solamente iniciar una sesin, pero no podemos crear tablas, ni ningn otro objeto; por ello son importantes los permisos de creacin de objetos. Aprendamos ms sobre los privilegios de sistema.

Los privilegios de sistema son permisos para realizar ciertas operaciones en la base de datos. Los siguientes son algunos de los privilegios de sistema existentes: - create session: para conectarse a la base de datos; - create table: crear tablas; - create sequence: crear secuencias; - create view: crear vistas; - create trigger: crear disparadores en su propio esquema; - create procedure: crear procedimientos y funciones; - execute any procedure: ejecutar cualquier procedimiento en cualquier esquema; - create user: crear usuarios y especificar claves; - create role: crear roles; - drop user: eliminar usuarios. Se asignan privilegios de sistema a un usuario mediante la instruccin "grant": Sintaxis bsica:
grant PERMISODESISTEMA to USUARIO;

Oracle permite conceder mltiples privilegios a mltiples usuarios en una misma sentencia, debemos separarlos por comas. En el siguiente ejemplo se concede el permiso para crear sesin a los usuarios "juan" y "ana":
grant create sesion to juan, ana;

En el siguiente ejemplo se conceden los permisos para crear tablas y vistas al usuario "ana":
grant create table, create view to ana;

En el siguiente ejemplo se conceden 2 permisos a 2 usuarios en una sola sentencia:

grant create trigger, create procedure to juan, ana;

Consultando el diccionario "dba_sys_privs" encontramos los privilegios concedidos a los distintos usuarios; y consultando "user_sys_privs" obtendremos la misma informacin pero nicamente del usuario actual.

122 - Privilegios del sistema (with admin option)


Hemos aprendido la sintaxis bsica para conceder permisos de sistema a los usuarios, mediante la instruccin "grant". Agregando a la sentencia "grant", la clusula "with admin option" concedemos permiso para ceder a terceros los privilegios de sistema obtenidos. Es decir, la clusula "with admin option" permite que el privilegio concedido a un usuario (o rol) pueda ser otorgado a otros usuarios por el usuario al que estamos asignndoselo; es decir, se concede permiso para conceder el permiso obtenido, a otros usuarios. Sintaxis:
grant PERMISODESISTEMA to USUARIO with admin option;

En el siguiente ejemplo, concedemos el permiso de crear tablas al usuario "juan" y con "with admin option", el usuario "juan" podr conceder este permiso de crear tablas a otros usuarios:
grant create table to juan with grant option;

Podemos consultar el diccionario "dba_sys_privs" para encontrar los privilegios concedidos a los usuarios. Nos mostrar una tabla con las siguientes columnas: - grantee: el nombre del usuario, - privilege: el permiso y - admin_option: si el permiso adquirido puede ser cedido a otros o no, YES o NO.