You are on page 1of 567

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.

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

Problema:

Para probar todos los ejercicios resueltos y propuestos debemos ingresar al sqldeveloper.exe
y luego en el entorno crear una nueva conexin:

1. Elegimos File -> New y seleccionamos "New Connection" y presionamos el botn


"Aceptar".
2. Ingresamos los campos Connection Name (por ejemplo ingresamos "prueba"), en el
campo Username ingresamos el usuario SYSTEM y por ltimo en el campo Password
ingresamos la clave que creamos al instalar Oracle.
3. Luego en la ventana que aparece el mansaje "Enter SQL Statement" debemos tipear
los comandos SQL y mediante el primer botn "triangulo verde" ejecutaremos el
comando SQL donde se encuentra el cursos (tambin podemos ejecutar todos los
comando SQL mediante el segundo botn.

Veamos las tablas existentes:

select *from all_tables;


Aparece una tabla que nos muestra todas las tablas; la columna "TABLE_NAME" contiene el
nombre de cada tabla.

Vamos a crear una tabla denominada "usuarios". En primer lugar vamos a eliminar la tabla
"usuarios" porque si ya existe no podremos crear otra con el mismo nombre.

drop table usuarios;

Si la tabla no existe aparecer un mensaje indicando tal situacin.

Ahora si creamos una tabla llamada "usuarios" con dos campos:

- nombre: cadena de caracteres que no supere los 30 caracteres y


- clave: cadena que no supere los 10 caracteres:

create table USUARIOS(


nombre varchar2(30),
clave varchar2(10)
);

Aparece un mensaje que indica que la sentencia "create table" ha sido procesada.
Cada usuario ocupar un registro de esta tabla, con su respectivo nombre y clave.

Podemos verificar que se ha creado:

select *from all_tables;

La tabla "usuarios" Debe aparecer en la lista.

Veamos la estructura de la tabla "usuarios":

describe usuarios;

Aparece la siguiente informacin:

Name Null Type


-------------------------------
NOMBRE VARCHAR2(30)
CLAVE VARCHAR2(10)

Nos informa que la tabla "usuarios" tiene 2 campos, el campo "nombre" de tipo "varchar2" de
30 caracteres de longitud y el campo "clave", de tipo "varchar2" de 10 caracteres de longitud.
La columna "Null" aparece vaca y la explicaremos ms adelante.

Intentemos crear una tabla con el mismo nombre, mostrar un mensaje indicando que ya hay
un objeto llamado "usuarios" y la sentencia no se ejecutar:

create table usuarios (


nombre varchar(30),
clave varchar(10)
);

Eliminemos la tabla:

drop table usuarios;


Verifiquemos si se ha eliminado:

select *from all_tables;

no debe aparecer la tabla "usuarios".

Primer problema:

Necesita almacenar los datos de amigos en una tabla. Los datos que guardar sern: apellido,
nombre, domicilio y telfono.

1- Elimine la tabla "agenda"


Si no existe, un mensaje indicar tal situacin.

2- Intente crear una tabla llamada "*agenda"

create table *agenda(


apellido varchar2(30),
nombre varchar2(20),
domicilio varchar2(30),
telefono varchar2(11)
);
aparece un mensaje de error indicando que usamos un caracter invlido ("*") para el nombre
de la tabla.

3- Cree una tabla llamada "agenda", debe tener los siguientes campos: apellido, varchar2(30);
nombre, varchar2(20); domicilio, varchar2 (30) y telefono, varchar2(11)
Un mensaje indica que la tabla ha sido creada exitosamente.

4- Intente crearla nuevamente.


Aparece mensaje de error indicando que el nombre ya lo tiene otro objeto.

5- Visualice las tablas existentes (all_tables)


La tabla "agenda" aparece en la lista.

6- Visualice la estructura de la tabla "agenda" (describe)


Aparece la siguiente tabla:

Name Null Type


-----------------------
APELLIDO VARCHAR2(30)
NOMBRE VARCHAR2(20)
DOMICILIO VARCHAR2(30)
TELEFONO VARCHAR2(11)
Ver solucin

drop table agenda;

create table *agenda(


apellido varchar2(30),
nombre varchar2(20),
domicilio varchar2(30),
telefono varchar2(11)
);
create table agenda(
apellido varchar2(30),
nombre varchar2(20),
domicilio varchar2(30),
telefono varchar2(11)
);

create table agenda(


apellido varchar2(30),
nombre varchar2(20),
domicilio varchar2(30),
telefono varchar2(11)
);

select *from all_tables;

describe agenda;

Segundo problema:

Necesita almacenar informacin referente a los libros de su biblioteca personal. Los datos que
guardar sern: ttulo del libro, nombre del autor y nombre de la editorial.

1- Elimine la tabla "libros"


Si no existe, un mensaje indica tal situacin.

2- Verifique que la tabla "libros" no existe (all_tables)


No aparece en la lista.

3- Cree una tabla llamada "libros". Debe definirse con los siguientes campos: titulo,
varchar2(20); autor, varchar2(30) y editorial, varchar2(15)

4- Intente crearla nuevamente:


Aparece mensaje de error indicando que existe un objeto con el nombre "libros".

5- Visualice las tablas existentes

6- Visualice la estructura de la tabla "libros":


Aparece "libros" en la lista.

7- Elimine la tabla

8- Intente eliminar la tabla


Un mensaje indica que no existe.

drop table libros;

select *from all_tables;


create table libros(
titulo varchar2(20),
autor varchar2(30),
editorial varchar2(15)
);

create table libros(


titulo varchar2(20),
autor varchar2(30),
editorial varchar2(15)
);

select *from all_tables;

describe libros;

drop table libros;

drop table libros;

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');
3 - Ingresar registros (insert into- select)

Problema:

Vemos si la tabla "usuarios" existe:

select *from all_tables;

Si existe la eliminamos:

drop table usuarios;

Creamos una nueva tabla denominada "usuarios" con los siguientes campos:

create table usuarios(


nombre varchar2(30),
clave varchar2(10)
);

Veamos si tiene registros:

select *from usuarios;

No tiene, la tabla aparece vaca, solamente vemos las columnas que muestran los nombres de
sus campos.

Agregamos un registro a la tabla:

insert into usuarios (nombre, clave)


values ('Mariano','payaso');

Un mensaje indica que se ingreso una fila.

Veamos nuevamente los registros de la tabla "usuarios":

select *from usuarios;


Aparece la siguiente tabla:

NOMBRE CLAVE
-------------
Mariano payaso

La tabla contiene un solo registro, el ingresado recientemente.

Ingresamos otro registro, esta vez cambiamos el orden de los campos:

insert into usuarios (clave, nombre)


values ('River','Juan');

Ingresamos los datos en un orden distinto al orden en que se nombran los campos, no aparece
un mensaje de error y los datos se guardan de modo incorrecto:

insert into usuarios (nombre,clave)


values ('Boca','Luis');

Veamos cmo se almacenaron los datos:

select *from usuarios;

Aparece la siguiente tabla:

NOMBRE CLAVE
-------------
Mariano payaso
Juan River
Boca Luis

La tabla tiene 3 registros. Note que la clave "Boca" se guard en el campo "nombre" y el
nombre de usuario "Luis" en el campo "clave".

3 - Ingresar registros (insert into- select)

Primer problema:

Trabaje con la tabla "agenda" que almacena informacin de sus amigos.

1- Elimine la tabla "agenda"

2- Cree una tabla llamada "agenda". Debe tener los siguientes campos: apellido (cadena de
30), nombre (cadena de 20), domicilio (cadena de 30) y telefono (cadena de 11)

3- Visualice las tablas existentes para verificar la creacin de "agenda" (all_tables)

4- Visualice la estructura de la tabla "agenda" (describe)

5- Ingrese los siguientes registros:

insert into agenda (apellido, nombre, domicilio, telefono)


values ('Moreno','Alberto','Colon 123','4234567');
insert into agenda (apellido,nombre, domicilio, telefono)
values ('Torres','Juan','Avellaneda 135','4458787');
6- Seleccione todos los registros de la tabla.

7- Elimine la tabla "agenda"

8- Intente eliminar la tabla nuevamente (aparece un mensaje de error)

Ver solucin

drop table agenda;

create table agenda(


apellido varchar2(30),
nombre varchar2(20),
domicilio varchar2(30),
telefono varchar2(11)
);

select *from all_tables;

describe agenda;

insert into agenda (apellido, nombre, domicilio, telefono)


values ('Moreno','Alberto','Colon 123','4234567');
insert into agenda (apellido,nombre, domicilio, telefono)
values ('Torres','Juan','Avellaneda 135','4458787');

select *from agenda;

drop table agenda;

drop table agenda;

Segundo problema:

Trabaje con la tabla "libros" que almacena los datos de los libros de su propia biblioteca.

1- Elimine la tabla "libros"

2- Cree una tabla llamada "libros". Debe definirse con los siguientes campos: titulo (cadena de
20), autor (cadena de 30) y editorial (cadena de 15)

3- Visualice las tablas existentes.

4- Visualice la estructura de la tabla "libros"

Muestra los campos y los tipos de datos de la tabla "libros".

5- Ingrese los siguientes registros:

insert into libros (titulo,autor,editorial)


values ('El aleph','Borges','Planeta');
insert into libros (titulo,autor,editorial)
values ('Martin Fierro','Jose Hernandez','Emece');
insert into libros (titulo,autor,editorial)
values ('Aprenda PHP','Mario Molina','Emece');

6- Muestre todos los registros (select) de "libros"

drop table libros;

create table libros(


titulo varchar2(30),
autor varchar2(30),
editorial varchar2(15)
);

select *from all_tables;

describe libros;

insert into libros (titulo,autor,editorial)


values ('El aleph','Borges','Planeta');
insert into libros (titulo,autor,editorial)
values ('Martin Fierro','Jose Hernandez','Emece');
insert into libros (titulo,autor,editorial)
values ('Aprenda PHP','Mario Molina','Emece');

select *from libros;

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 x10-120 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)".

4 - Tipos de datos

Problema:

Eliminamos la tabla "libros":

drop table libros;

Vamos a crear una tabla llamada "libros" para almacenar informacin de los libros de una
librera. Necesitamos los siguientes campos:

-titulo: cadena de caracteres de 20 de longitud,


-autor: cadena de caracteres de 15 de longitud,
-editorial: caracteres de 10 de longitud,
-precio: valor numrico con 2 decimales y que no superar el valor
9999.99 y
-cantidad: valor numrico entero que no superar el valor 999.

Al crear la tabla, entonces, elegimos el tipo de dato ms adecuado para cada campo:

create table libros(


titulo varchar2(20),
autor varchar2(15),
editorial varchar2(10),
precio number(6,2),
cantidad number(3,0)
);

Vemos la estructura de la tabla:

describe libros;
Aparece la siguiente informacin:

Name Null Type


--------------------------------------
titulo varchar2(20)
autor varchar2(15)
editorial varchar2(10)
precio number(6,2)
cantidad number(3)

Ingresamos algunos registros:

insert into libros (titulo,autor,editorial,precio,cantidad)


values ('El aleph','Borges','Emece',25.50,100);
insert into libros (titulo,autor,editorial,precio,cantidad)
values ('Matematica estas ahi','Paenza','Siglo XXI',18.8,200);

Note que al ingresar valores numricos no se utilizan comillas y para el separador de


decimales se usa el caracter punto (.).

Veamos los registros cargados:

select *from libros;

Aparece la siguiente tabla:

TITULO AUTOR EDITORIAL PRECIO CANTIDAD


----------------------------------------------------------------
El Aleph Borges Emece 25,5 100
Matematica estas ahi Paenza Siglo XXI 18,8 200

Veamos lo que sucede si intentamos ingresar para el campo "titulo" una cadena de ms de 20
caracteres:

insert into libros (titulo,autor,editorial,precio,cantidad)


values ('Alicia en el pais de las maravillas','Lewis
Carroll','Atlantida',10,200);

aparece un mensaje de error y la sentencia no se ejecuta.

vamos a cortar la cadena para que SQL Server acepte el ingreso del registro:

insert into libros (titulo,autor,editorial,precio,cantidad)


values ('Alicia en el pais','Lewis Carroll','Atlantida',10,200);

Veamos los registros cargados:

select *from libros;

La tabla tiene ahora 3 registros.

Veamos qu sucede si intentamos ingresar para el campo "cantidad" un valor fuera de rango:

insert into libros (titulo,autor,editorial,precio,cantidad)


values ('El gato con botas','Anonimo','Atlantida',10,2000);
Oracle muestra un mensaje de error y la sentencia no se ejecuta, es decir, el registro no fue
ingresado.

Veamos qu sucede si intentamos ingresar en el campo "precio" un valor con ms decimales


que los permitidos:

insert into libros (titulo,autor,editorial,precio,cantidad)


values ('El gato con botas','Anonimo','Atlantida',10.123,200);

La sentencia se ejecut, el registro ha sido cargado. Veamos cmo se almacen:

select *from libros;

Oracle omiti el ltimo dgito decimal porque el campo slo admita 2 decimales.

4 - Tipos de datos

Primer problema:

Un videoclub que alquila pelculas en video almacena la informacin de sus pelculas en una
tabla llamada "peliculas"; para cada pelcula necesita los siguientes datos:

-nombre, cadena de caracteres de 20 de longitud,


-actor, cadena de caracteres de 20 de longitud,
-duracin, valor numrico entero que no supera los 3 dgitos.
-cantidad de copias: valor entero de un slo dgito (no tienen ms de 9 copias de
cada pelcula).

1- Elimine la tabla "peliculas" si ya existe.

2- Cree la tabla eligiendo el tipo de dato adecuado para cada campo.


Note que los campos "duracion" y "cantidad", que almacenarn valores sin decimales, fueron
definidos de maneras diferentes, en el primero especificamos el valor 0 como cantidad de
decimales, en el segundo no especificamos cantidad de decimales, es decir, por defecto,
asume el valor 0.

3- Vea la estructura de la tabla.

4- Ingrese los siguientes registros:

insert into peliculas (nombre, actor, duracion, cantidad)


values ('Mision imposible','Tom Cruise',128,3);
insert into peliculas (nombre, actor, duracion, cantidad)
values ('Mision imposible 2','Tom Cruise',130,2);
insert into peliculas (nombre, actor, duracion, cantidad)
values ('Mujer bonita','Julia Roberts',118,3);
insert into peliculas (nombre, actor, duracion, cantidad)
values ('Elsa y Fred','China Zorrilla',110,2);

5- Muestre todos los registros (4 registros)

6- Intente ingresar una pelcula con valor de cantidad fuera del rango permitido:

insert into peliculas (nombre, actor, duracion, cantidad)


values ('Mujer bonita','Richard Gere',1200,10);
Mensaje de error.

7- Ingrese un valor con decimales en un nuevo registro, en el campo "duracion":

insert into peliculas (nombre, actor, duracion, cantidad)


values ('Mujer bonita','Richard Gere',120.20,4);

8- Muestre todos los registros para ver cmo se almacen el ltimo registro ingresado.

9- Intente ingresar un nombre de pelcula que supere los 20 caracteres.

Ver solucin

drop table peliculas;

create table peliculas(


nombre varchar2(20),
actor varchar2(20),
duracion number(3,0),
cantidad number(1)
);

describe peliculas;

insert into peliculas (nombre, actor, duracion, cantidad)


values ('Mision imposible','Tom Cruise',128,3);
insert into peliculas (nombre, actor, duracion, cantidad)
values ('Mision imposible 2','Tom Cruise',130,2);
insert into peliculas (nombre, actor, duracion, cantidad)
values ('Mujer bonita','Julia Roberts',118,3);
insert into peliculas (nombre, actor, duracion, cantidad)
values ('Elsa y Fred','China Zorrilla',110,2);

select *from peliculas;

insert into peliculas (nombre, actor, duracion, cantidad)


values ('Mujer bonita','Richard Gere',1200,10);

insert into peliculas (nombre, actor, duracion, cantidad)


values ('Mujer bonita','Richard Gere',120.20,4);

select *from peliculas:

insert into peliculas (nombre, actor, duracion, cantidad)


values ('Alicia en el pais de las maravillas','Animados',90,3);

Segundo problema:

Una empresa almacena los datos de sus empleados en una tabla "empleados" que guarda los
siguientes datos: nombre, documento, sexo, domicilio, sueldobasico.

1- Elimine la tabla si existe.


2- Cree la tabla eligiendo el tipo de dato adecuado para cada campo:

create table empleados(


nombre varchar2(20),
documento varchar2(8),
sexo varchar2(1),
domicilio varchar2(30),
sueldobasico number(6,2)
);

3- Verifique que la tabla existe consultando "all_tables"

4- Vea la estructura de la tabla (5 campos)

5- Ingrese algunos registros:

insert into empleados (nombre, documento, sexo, domicilio, sueldobasico)


values ('Juan Perez','22333444','m','Sarmiento 123',500);
insert into empleados (nombre, documento, sexo, domicilio, sueldobasico)
values ('Ana Acosta','24555666','f','Colon 134',650);
insert into empleados (nombre, documento, sexo, domicilio, sueldobasico)
values ('Bartolome Barrios','27888999','m','Urquiza 479',800);

6- Seleccione todos los registros (3 registros)

7- Intente ingresar un registro con el valor "masculino" en el campo "sexo"


Un mensaje indica que el campo est definido para almacenar 1 solo caracter como mximo y
est intentando ingresar 9 caracteres.

8- Intente ingresar un valor fuera de rango, en un nuevo registro, para el campo


"sueldobasico"
Mensaje de error.

9- Elimine la tabla

drop table empleados;

create table empleados(


nombre varchar2(20),
documento varchar2(8),
sexo varchar2(1),
domicilio varchar2(30),
sueldobasico number(6,2)
);

select *from all_tables;

describe empleados;

insert into empleados (nombre, documento, sexo, domicilio, sueldobasico)


values ('Juan Perez','22333444','m','Sarmiento 123',500);
insert into empleados (nombre, documento, sexo, domicilio, sueldobasico)
values ('Ana Acosta','24555666','f','Colon 134',650);
insert into empleados (nombre, documento, sexo, domicilio, sueldobasico)
values ('Bartolome Barrios','27888999','m','Urquiza 479',800);
select *from empleados;

insert into empleados (nombre, documento, sexo, domicilio, sueldobasico)


values ('Carlos Caseres','33556688','masculino','Colon 235',900);

insert into empleados (nombre, documento, sexo, domicilio, sueldobasico)


values ('Carlos Caseres','33556688','m','Colon 235',10000.5);

drop table empleados;

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.

5 - Recuperar algunos campos (select)

Problema:

Trabajamos con la tabla "libros" que almacena los datos de los libros de una librera.
Eliminamos la tabla:

drop table libros;

Creamos la tabla:

create table libros(


titulo varchar2(40),
autor varchar2(30),
editorial varchar2(15),
precio number(6,2),
cantidad number(3,0)
);

Veamos la estructura de la tabla (5 campos):

describe libros;

Ingresamos algunos registros:

insert into libros (titulo,autor,editorial,precio,cantidad)


values ('El aleph','Borges','Emece',25.50,100);
insert into libros (titulo,autor,editorial,precio,cantidad)
values ('Alicia en el pais de las maravillas','Lewis
Carroll','Atlantida',10,200);
insert into libros (titulo,autor,editorial,precio,cantidad)
values ('Matematica estas ahi','Paenza','Siglo XXI',18.8,200);

Veamos todos los campos la tabla:

select *from libros;

Aparece la siguiente tabla:

TITULO AUTOR EDITORIAL


PRECIO CANTIDAD
----------------------------------------------------------------------
--------------------
El aleph Borges Emece
25.50 100
Alicia en el pais de las maravillas Lewis Carroll Atlantida 10 200
Matematica estas ahi Paenza Siglo XXI
18.8 200

Recuperamos solamente el ttulo, autor y editorial de todos los libros especificando los
nombres de los campos separados por comas:

select titulo,autor,editorial from libros;

Aparece la siguiente tabla:

TITULO AUTOR EDITORIAL


-----------------------------------------------------------------
El aleph Borges Emece
Alicia en el pais de las maravillas Lewis Carroll Atlantida
Matematica estas ahi Paenza Siglo XXI

Con la siguiente sentencia seleccionamos los ttulos y precios de todos los libros:

select titulo,precio from libros;

Aparece la siguiente tabla:

TITULO PRECIO
-----------------------------------------------
El aleph 25.50
Alicia en el pais de las maravillas 10
Matematica estas ahi 18.8

Para ver solamente la editorial y la cantidad de libros, tipeamos:

select editorial,cantidad from libros;

Aparece la siguiente tabla:

EDITORIAL CANTIDAD
-------------------------
Emece 100
Atlantida 200
Siglo XXI 200

Note que en todos los casos recuperamos TODOS los registros, pero solamente ALGUNOS
campos que especificamos.

5 - Recuperar algunos campos (select)

Primer problema:

Un videoclub que alquila pelculas en video almacena la informacin de sus pelculas en


alquiler en una tabla llamada "peliculas".

1- Elimine la tabla si existe.

2- Cree la tabla:

create table peliculas(


titulo varchar2(20),
actor varchar2(20),
duracion number(3),
cantidad number(1)
);

3- Vea la estructura de la tabla (4 campos)

4- Ingrese los siguientes registros:

insert into peliculas (titulo, actor, duracion, cantidad)


values ('Mision imposible','Tom Cruise',180,3);
insert into peliculas (titulo, actor, duracion, cantidad)
values ('Mision imposible 2','Tom Cruise',190,2);
insert into peliculas (titulo, actor, duracion, cantidad)
values ('Mujer bonita','Julia Roberts',118,3);
insert into peliculas (titulo, actor, duracion, cantidad)
values ('Elsa y Fred','China Zorrilla',110,2);

5- Realice un "select" mostrando solamente el ttulo y actor de todas las pelculas

6- Muestre el ttulo y duracin de todas las peliculas.

7- Muestre el ttulo y la cantidad de copias.

Ver solucin

drop table peliculas;

create table peliculas(


titulo varchar2(20),
actor varchar2(20),
duracion number(3),
cantidad number(1)
);
describe peliculas;

insert into peliculas (titulo, actor, duracion, cantidad)


values ('Mision imposible','Tom Cruise',180,3);
insert into peliculas (titulo, actor, duracion, cantidad)
values ('Mision imposible 2','Tom Cruise',190,2);
insert into peliculas (titulo, actor, duracion, cantidad)
values ('Mujer bonita','Julia Roberts',118,3);
insert into peliculas (titulo, actor, duracion, cantidad)
values ('Elsa y Fred','China Zorrilla',110,2);

select titulo,actor from peliculas;

select titulo,duracion from peliculas;

select titulo,cantidad from peliculas;

Segundo problema:

Una empresa almacena los datos de sus empleados en una tabla llamada "empleados".

1- Elimine la tabla si ya existe.

2- Cree la tabla:

create table empleados(


nombre varchar2(20),
documento varchar2(8),
sexo varchar2(1),
domicilio varchar2(30),
sueldobasico number(6,2)
);

3- Vea la estructura de la tabla (5 campos)

4- Ingrese algunos registros:

insert into empleados (nombre, documento, sexo, domicilio, sueldobasico)


values ('Juan Juarez','22333444','m','Sarmiento 123',500);
insert into empleados (nombre, documento, sexo, domicilio, sueldobasico)
values ('Ana Acosta','27888999','f','Colon 134',700);
insert into empleados (nombre, documento, sexo, domicilio, sueldobasico)
values ('Carlos Caseres','31222333','m','Urquiza 479',850);

5- Muestre todos los datos de los empleados.

6- Muestre el nombre, documento y domicilio de los empleados.

7- Realice un "select" mostrando el documento, sexo y sueldo bsico de todos los empleados.

drop table empleados;


create table empleados(
nombre varchar2(20),
documento varchar2(8),
sexo varchar2(1),
domicilio varchar2(30),
sueldobasico number(6,2)
);

describe empleados;

insert into empleados (nombre, documento, sexo, domicilio, sueldobasico)


values ('Juan Juarez','22333444','m','Sarmiento 123',500);
insert into empleados (nombre, documento, sexo, domicilio, sueldobasico)
values ('Ana Acosta','27888999','f','Colon 134',700);
insert into empleados (nombre, documento, sexo, domicilio, sueldobasico)
values ('Carlos Caseres','31222333','m','Urquiza 479',850);

select *from empleados;

select nombre,documento,domicilio
from empleados;

select documento,sexo,sueldobasico
from empleados;

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".

6 - Recuperar algunos registros (where)

Problema:

Trabajamos con la tabla "usuarios" que consta de 2 campos: nombre de usuario y clave.
Eliminamos la tabla si ya existe:

drop table usuarios;

Creamos la tabla:

create table usuarios (


nombre varchar2(30),
clave varchar2(10)
);

Vemos la estructura de la tabla:

describe usuarios;

Ingresamos algunos registros:

insert into usuarios (nombre, clave)


values ('Marcelo','Boca');
insert into usuarios (nombre, clave)
values ('JuanPerez','Juancito');
insert into usuarios (nombre, clave)
values ('Susana','River');
insert into usuarios (nombre, clave)
values ('Luis','River');

Realizamos una consulta especificando una condicin, queremos ver toda la informacin del
usuario cuyo nombre es "Marcelo":

select *from usuarios


where nombre='Leonardo';

Nos muestra todos los campos del registro en el cual el campo "nombre" es igual a "Marcelo".

Queremos ver el nombre de los usuarios cuya clave es "River":


select nombre from usuarios
where clave='River';

Nos muestra 2 usuarios.

Realizamos un "select" de los nombres de los usuarios cuya clave es "Santi":

select nombre from usuarios


where clave='Santi';

No se muestra ningn registro ya que ninguno cumple la condicin.

6 - Recuperar algunos registros (where)

Primer problema:

Trabaje con la tabla "agenda" en la que registra los datos de sus amigos.

1- Elimine "agenda"

2- Cree la tabla, con los siguientes campos: apellido (cadena de 30), nombre (cadena de 20),
domicilio (cadena de 30) y telefono (cadena de 11):

create table agenda(


apellido varchar2(30),
nombre varchar2(30),
domicilio varchar2(30),
telefono varchar2(11)
);

3- Visualice la estructura de la tabla "agenda" (4 campos)

4- Ingrese los siguientes registros ("insert into"):

insert into agenda(apellido,nombre,domicilio,telefono) values


('Acosta', 'Ana', 'Colon 123', '4234567');
insert into agenda(apellido,nombre,domicilio,telefono) values
('Bustamante', 'Betina', 'Avellaneda 135', '4458787');
insert into agenda(apellido,nombre,domicilio,telefono) values
('Lopez', 'Hector', 'Salta 545', '4887788');
insert into agenda(apellido,nombre,domicilio,telefono) values
('Lopez', 'Luis', 'Urquiza 333', '4545454');
insert into agenda(apellido,nombre,domicilio,telefono) values
('Lopez', 'Marisa', 'Urquiza 333', '4545454');

5- Seleccione todos los registros de la tabla (5 registros)

6- Seleccione el registro cuyo nombre sea "Marisa" (1 registro)

7- Seleccione los nombres y domicilios de quienes tengan apellido igual a "Lopez" (3 registros)

8- Seleccione los nombres y domicilios de quienes tengan apellido igual a "lopez" (en
minsculas)
No aparece ningn registro, ya que la cadena "Lopez" noe s igual a la cadena "lopez".

9- Muestre el nombre de quienes tengan el telfono "4545454" (2 registros)

drop table agenda;

create table agenda(


apellido varchar2(30),
nombre varchar2(30),
domicilio varchar2(30),
telefono varchar2(11)
);

describe agenda;

insert into agenda(apellido,nombre,domicilio,telefono) values


('Acosta', 'Ana', 'Colon 123', '4234567');
insert into agenda(apellido,nombre,domicilio,telefono) values
('Bustamante', 'Betina', 'Avellaneda 135', '4458787');
insert into agenda(apellido,nombre,domicilio,telefono) values
('Lopez', 'Hector', 'Salta 545', '4887788');
insert into agenda(apellido,nombre,domicilio,telefono) values
('Lopez', 'Luis', 'Urquiza 333', '4545454');
insert into agenda(apellido,nombre,domicilio,telefono) values
('Lopez', 'Marisa', 'Urquiza 333', '4545454');

select *from agenda;

select *from agenda


where nombre='Marisa';

select nombre,domicilio from agenda


where apellido='Lopez';

select nombre,domicilio from agenda


where apellido='lopez';

select nombre from agenda


where telefono='4545454';
Segundo problema:

Un comercio que vende artculos de computacin registra los datos de sus artculos en una
tabla llamada "articulos".

1- Elimine la tabla si existe.

2- Cree la tabla "articulos" con la siguiente estructura:

create table articulos(


codigo number(5),
nombre varchar2(20),
descripcion varchar2(30),
precio number(7,2)
);
3- Vea la estructura de la tabla:

describe articulos;

4- Ingrese algunos registros:

insert into articulos (codigo, nombre, descripcion, precio)


values (1,'impresora','Epson Stylus C45',400.80);
insert into articulos (codigo, nombre, descripcion, precio)
values (2,'impresora','Epson Stylus C85',500);
insert into articulos (codigo, nombre, descripcion, precio)
values (3,'monitor','Samsung 14',800);
insert into articulos (codigo, nombre, descripcion, precio)
values (4,'teclado','ingles Biswal',100);
insert into articulos (codigo, nombre, descripcion, precio)
values (5,'teclado','espaol Biswal',90);

5- Seleccione todos los datos de los registros cuyo nombre sea "impresora" (2 registros)

6- Muestre slo el cdigo, descripcin y precio de los teclados (2 registros)

drop table articulos;

create table articulos(


codigo number(5),
nombre varchar2(20),
descripcion varchar2(30),
precio number(7,2)
);

describe articulos;

insert into articulos (codigo, nombre, descripcion, precio)


values (1,'impresora','Epson Stylus C45',400.80);
insert into articulos (codigo, nombre, descripcion, precio)
values (2,'impresora','Epson Stylus C85',500);
insert into articulos (codigo, nombre, descripcion, precio)
values (3,'monitor','Samsung 14',800);
insert into articulos (codigo, nombre, descripcion, precio)
values (4,'teclado','ingles Biswal',100);
insert into articulos (codigo, nombre, descripcion, precio)
values (5,'teclado','espaol Biswal',90);

select *from articulos


where nombre='impresora';

select codigo,descripcion,precio from articulos


where nombre='teclado';

7 - Operadores relacionales

Los operadores son smbolos que permiten realizar operaciones matemticas, concatenar
cadenas, hacer comparaciones.

Oracle reconoce de 4 tipos de operadores:


1) relacionales (o de comparacin)
2) aritmticos
3) de concatenacin
4) 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 l

7 - Operadores relacionales
Problema:

Trabajamos con la tabla "libros" de una librera.

Eliminamos la tabla "libros":

drop table libros;

La creamos con la siguiente estructura:

create table libros(


titulo varchar2(30),
autor varchar2(30),
editorial varchar2(15),
precio number(5,2)
);

Agregamos registros a la tabla:

insert into libros (titulo,autor,editorial,precio)


values ('El aleph','Borges','Emece',24.50);
insert into libros (titulo,autor,editorial,precio)
values ('Martin Fierro','Jose Hernandez','Emece',16.00);
insert into libros (titulo,autor,editorial,precio)
values ('Aprenda PHP','Mario Molina','Emece',35.40);
insert into libros (titulo,autor,editorial,precio)
values ('Cervantes y el quijote','Borges','Paidos',50.90);

Seleccionamos los registros cuyo autor sea diferente de 'Borges':

select *from libros


where autor<>'Borges';

Seleccionamos los registros cuyo precio supere los 20 pesos, slo el ttulo y precio:

select titulo,precio
from libros
where precio>20;

Note que el valor con el cual comparamos el campo "precio", como es numrico, no se coloca
entre comillas. Los libros cuyo precio es menor a 20 pesos no aparecen en la seleccin.

Recuperamos aquellos libros cuyo precio es menor o igual a 30:

select *from libros


where precio<=30;

os nicos, existen otros que veremos mas adelante.

7 - Operadores relacionales

Primer problema:

Un comercio que vende artculos de computacin registra los datos de sus artculos en una
tabla con ese nombre.
1- Elimine "articulos"

2- Cree la tabla, con la siguiente estructura:

create table articulos(


codigo number(5),
nombre varchar2(20),
descripcion varchar2(30),
precio number(6,2),
cantidad number(3)
);

3- Vea la estructura de la tabla.

4- Ingrese algunos registros:

insert into articulos (codigo, nombre, descripcion, precio,cantidad)


values (1,'impresora','Epson Stylus C45',400.80,20);
insert into articulos (codigo, nombre, descripcion, precio,cantidad)
values (2,'impresora','Epson Stylus C85',500,30);
insert into articulos (codigo, nombre, descripcion, precio,cantidad)
values (3,'monitor','Samsung 14',800,10);
insert into articulos (codigo, nombre, descripcion, precio,cantidad)
values (4,'teclado','ingles Biswal',100,50);
insert into articulos (codigo, nombre, descripcion, precio,cantidad)
values (5,'teclado','espaol Biswal',90,50);

5- Seleccione los datos de las impresoras (2 registros)

6- Seleccione los artculos cuyo precio sea mayor o igual a 400 (3 registros)

7- Seleccione el cdigo y nombre de los artculos cuya cantidad sea menor a 30 (2 registros)

8- Selecciones el nombre y descripcin de los artculos que NO cuesten $100 (4 registros)

drop table articulos;

create table articulos(


codigo number(5),
nombre varchar2(20),
descripcion varchar2(30),
precio number(6,2),
cantidad number(3)
);

describe articulos;

insert into articulos (codigo, nombre, descripcion, precio,cantidad)


values (1,'impresora','Epson Stylus C45',400.80,20);
insert into articulos (codigo, nombre, descripcion, precio,cantidad)
values (2,'impresora','Epson Stylus C85',500,30);
insert into articulos (codigo, nombre, descripcion, precio,cantidad)
values (3,'monitor','Samsung 14',800,10);
insert into articulos (codigo, nombre, descripcion, precio,cantidad)
values (4,'teclado','ingles Biswal',100,50);
insert into articulos (codigo, nombre, descripcion, precio,cantidad)
values (5,'teclado','espaol Biswal',90,50);

select *from articulos


where nombre='impresora';

select *from articulos


where precio>=400;

select codigo,nombre
from articulos
where cantidad<30;

select nombre, descripcion


from articulos
where precio<>100;
Segundo problema:

Un video club que alquila pelculas en video almacena la informacin de sus pelculas en
alquiler en una tabla denominada "peliculas".

1- Elimine la tabla.

drop table peliculas;

2- Cree la tabla eligiendo el tipo de dato adecuado para cada campo:

create table peliculas(


titulo varchar2(20),
actor varchar2(20),
duracion number(3),
cantidad number(1)
);

3- Ingrese los siguientes registros:

insert into peliculas (titulo, actor, duracion, cantidad)


values ('Mision imposible','Tom Cruise',120,3);
insert into peliculas (titulo, actor, duracion, cantidad)
values ('Mision imposible 2','Tom Cruise',180,4);
insert into peliculas (titulo, actor, duracion, cantidad)
values ('Mujer bonita','Julia R.',90,1);
insert into peliculas (titulo, actor, duracion, cantidad)
values ('Elsa y Fred','China Zorrilla',80,2);

4- Seleccione las pelculas cuya duracin no supere los 90 minutos (2 registros)

5- Seleccione el ttulo de todas las pelculas en las que el actor NO sea "Tom Cruise" (2
registros)

6- Muestre todos los campos, excepto "duracion", de todas las pelculas de las que haya ms
de 2 copias (2 registros)

drop table peliculas;


create table peliculas(
titulo varchar2(20),
actor varchar2(20),
duracion number(3),
cantidad number(1)
);

insert into peliculas (titulo, actor, duracion, cantidad)


values ('Mision imposible','Tom Cruise',120,3);
insert into peliculas (titulo, actor, duracion, cantidad)
values ('Mision imposible 2','Tom Cruise',180,4);
insert into peliculas (titulo, actor, duracion, cantidad)
values ('Mujer bonita','Julia R.',90,1);
insert into peliculas (titulo, actor, duracion, cantidad)
values ('Elsa y Fred','China Zorrilla',80,2);

select *from peliculas


where duracion<=90;

select *from peliculas


where actor<>'Tom Cruise';

select titulo,actor,cantidad
from peliculas
where cantidad >2;

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.

8 - Borrar registros (delete)

Problema:

Trabajamos con la tabla "usuarios".


Eliminamos la tabla "usuarios":

drop table usuarios;

La creamos con la siguiente estructura:

create table usuarios(


nombre varchar2(30),
clave varchar2(10)
);

Agregamos registros a la tabla:

insert into usuarios (nombre,clave)


values ('Marcelo','River');
insert into usuarios (nombre,clave)
values ('Susana','chapita');
insert into usuarios (nombre,clave)
values ('CarlosFuentes','Boca');
insert into usuarios (nombre,clave)
values ('FedericoLopez','Boca');

Seleccionamos todos los registros:

select *from usuarios;

Vamos a eliminar el registro cuyo nombre de usuario es "Marcelo":

delete from usuarios


where nombre='Marcelo';

aparece un mensaje indicando que se ha borrado 1 fila.

Intentamos eliminarlo nuevamente:

delete from usuarios


where nombre='Marcelo';

Como ningn registro cumple con la condicin especificada (nombre igual a Marcelo),
aparecer un mensaje indicando que ningn registro fue borrado.

Eliminamos todos los registros cuya clave es 'Boca':

delete from usuarios


where clave='Boca';
Aparece un mensaje indicando que 2 registros fueron eliminados, es decir, se eliminaron los 2
registros cuyas claves eran igual a "River".

Eliminemos todos los registros:

delete from usuarios;

Veamos el contenido de la tabla:

select * from usuarios;

No hay registros.

8 - Borrar registros (delete)

Primer problema:

Trabaje con la tabla "agenda" que registra la informacin referente a sus amigos.

1- Elimine la tabla.

2- Cree la tabla con los siguientes campos: apellido (cadena de 30), nombre (cadena de 20),
domicilio (cadena de 30) y telefono (cadena de 11):

create table agenda(


apellido varchar2(30),
nombre varchar2(20),
domicilio varchar2(30),
telefono varchar2(11)
);

3- Ingrese los siguientes registros (insert into):

insert into agenda(apellido,nombre,domicilio,telefono) values


('Alvarez','Alberto','Colon 123','4234567');
insert into agenda(apellido,nombre,domicilio,telefono) values
('Juarez','Juan','Avellaneda 135','4458787');
insert into agenda(apellido,nombre,domicilio,telefono) values
('Lopez','Maria','Urquiza 333','4545454');
insert into agenda(apellido,nombre,domicilio,telefono) values
('Lopez','Jose','Urquiza 333','4545454');
insert into agenda(apellido,nombre,domicilio,telefono) values
('Salas','Susana','Gral. Paz 1234','4123456');

4- Elimine el registro cuyo nombre sea "Juan" (1 registro)

5- Elimine los registros cuyo nmero telefnico sea igual a "4545454" (2 registros)

6- Elimine todos los registros (2 registros)

drop table agenda;

create table agenda(


apellido varchar2(30),
nombre varchar2(20),
domicilio varchar2(30),
telefono varchar2(11)
);

insert into agenda(apellido,nombre,domicilio,telefono) values


('Alvarez','Alberto','Colon 123','4234567');
insert into agenda(apellido,nombre,domicilio,telefono) values
('Juarez','Juan','Avellaneda 135','4458787');
insert into agenda(apellido,nombre,domicilio,telefono) values
('Lopez','Maria','Urquiza 333','4545454');
insert into agenda(apellido,nombre,domicilio,telefono) values
('Lopez','Jose','Urquiza 333','4545454');
insert into agenda(apellido,nombre,domicilio,telefono) values
('Salas','Susana','Gral. Paz 1234','4123456');

delete from agenda


where nombre='Juan';

delete from agenda


where telefono='4545454';

delete from agenda;


Segundo problema:

Un comercio que vende artculos de computacin registra los datos de sus artculos en una
tabla con ese nombre.

1- Elimine "articulos"

2- Cree la tabla, con la siguiente estructura:

create table articulos(


codigo number(4,0),
nombre varchar2(20),
descripcion varchar2(30),
precio number(7,2),
cantidad number(3)
);

3- Vea la estructura de la tabla.

4- Ingrese algunos registros:

insert into articulos (codigo, nombre, descripcion, precio,cantidad)


values (1,'impresora','Epson Stylus C45',400.80,20);
insert into articulos (codigo, nombre, descripcion, precio,cantidad)
values (2,'impresora','Epson Stylus C85',500,30);
insert into articulos (codigo, nombre, descripcion, precio,cantidad)
values (3,'monitor','Samsung 14',800,10);
insert into articulos (codigo, nombre, descripcion, precio,cantidad)
values (4,'teclado','ingles Biswal',100,50);
insert into articulos (codigo, nombre, descripcion, precio,cantidad)
values (5,'teclado','espaol Biswal',90,50);
5- Elimine los artculos cuyo precio sea mayor o igual a 500 (2 registros)

7- Elimine todas las impresoras (1 registro)

8- Elimine todos los artculos cuyo cdigo sea diferente a 4 (1 registro)

drop table articulos;

create table articulos(


codigo number(4,0),
nombre varchar2(20),
descripcion varchar2(30),
precio number(7,2),
cantidad number(3)
);

describe libros;

insert into articulos (codigo, nombre, descripcion, precio,cantidad)


values (1,'impresora','Epson Stylus C45',400.80,20);
insert into articulos (codigo, nombre, descripcion, precio,cantidad)
values (2,'impresora','Epson Stylus C85',500,30);
insert into articulos (codigo, nombre, descripcion, precio,cantidad)
values (3,'monitor','Samsung 14',800,10);
insert into articulos (codigo, nombre, descripcion, precio,cantidad)
values (4,'teclado','ingles Biswal',100,50);
insert into articulos (codigo, nombre, descripcion, precio,cantidad)
values (5,'teclado','espaol Biswal',90,50);

delete from articulos


where precio>=500;

delete from articulos


where nombre='impresora';

delete from articulos


where codigo<>4;

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.

9 - Actualizar registros (update)

Problema:

Trabajamos con la tabla "usuarios".


Eliminamos la tabla:

drop table usuarios;

Creamos la tabla:

create table usuarios(


nombre varchar2(20),
clave varchar2(10)
);

Ingresamos algunos registros:

insert into usuarios (nombre,clave)


values ('Marcelo','River');
insert into usuarios (nombre,clave)
values ('Susana','chapita');
insert into usuarios (nombre,clave)
values ('Carlosfuentes','Boca');
insert into usuarios (nombre,clave)
values ('Federicolopez','Boca');

Cambiaremos los valores de todas las claves, por la cadena "RealMadrid":


update usuarios set clave='RealMadrid';

Un mensaje indica que se actualizaron 4 registros.

El cambio afect a todos los registros, vemoslo:

select *from usuarios;

Necesitamos cambiar el valor de la clave del usuario llamado "Federicolopez" por "Boca":

update usuarios set clave='Boca'


where nombre='Federicolopez';

Verifiquemos que la actualizacin se realiz:

select *from usuarios;

Vimos que si Oracle no encuentra registros que cumplan con la condicin del "where", un
mensaje indica que ningn registro se modifica:

update usuarios set clave='payaso'


where nombre='JuanaJuarez';

Para actualizar varios campos en una sola instruccin empleamos:

update usuarios set nombre='Marceloduarte', clave='Marce'


where nombre='Marcelo';

Verifiquemos que la actualizacin se realiz:

select *from usuarios;


9 - Actualizar registros (update)

Primer problema:

Trabaje con la tabla "agenda" que almacena los datos de sus amigos.

1- Elimine la tabla y crela con la siguiente estructura:

drop table agenda;

create table agenda(


apellido varchar2(30),
nombre varchar2(20),
domicilio varchar2(30),
telefono varchar2(11)
);

3- Ingrese los siguientes registros:

insert into agenda (apellido,nombre,domicilio,telefono)


values ('Acosta','Alberto','Colon 123','4234567');
insert into agenda (apellido,nombre,domicilio,telefono)
values ('Juarez','Juan','Avellaneda 135','4458787');
insert into agenda (apellido,nombre,domicilio,telefono)
values ('Lopez','Maria','Urquiza 333','4545454');
insert into agenda (apellido,nombre,domicilio,telefono)
values ('Lopez','Jose','Urquiza 333','4545454');
insert into agenda (apellido,nombre,domicilio,telefono)
values ('Suarez','Susana','Gral. Paz 1234','4123456');

4- Modifique el registro cuyo nombre sea "Juan" por "Juan Jose" (1 registro actualizado)

5- Actualice los registros cuyo nmero telefnico sea igual a "4545454" por "4445566" (2
registros)

6- Actualice los registros que tengan en el campo "nombre" el valor "Juan" por "Juan Jose"
(ningn registro afectado porque ninguno cumple con la condicin del "where")

drop table agenda;

create table agenda(


apellido varchar2(30),
nombre varchar2(20),
domicilio varchar2(30),
telefono varchar2(11)
);

insert into agenda (apellido,nombre,domicilio,telefono)


values ('Acosta','Alberto','Colon 123','4234567');
insert into agenda (apellido,nombre,domicilio,telefono)
values ('Juarez','Juan','Avellaneda 135','4458787');
insert into agenda (apellido,nombre,domicilio,telefono)
values ('Lopez','Maria','Urquiza 333','4545454');
insert into agenda (apellido,nombre,domicilio,telefono)
values ('Lopez','Jose','Urquiza 333','4545454');
insert into agenda (apellido,nombre,domicilio,telefono)
values ('Suarez','Susana','Gral. Paz 1234','4123456');

update agenda set nombre='Juan Jose'


where nombre='Juan';

update agenda set telefono='4445566'


where telefono='4545454';

update agenda set nombre='Juan Jose'


where nombre='Juan';
Segundo problema:

Trabaje con la tabla "libros" de una librera.

1- Elimine la tabla y crela con los siguientes campos: titulo (cadena de 30 caracteres de
longitud), autor (cadena de 20), editorial (cadena de 15) y precio (entero no mayor a 999.99):

drop table libros;

create table libros (


titulo varchar2(30),
autor varchar2(20),
editorial varchar2(15),
precio number(5,2)
);

3- Ingrese los siguientes registros:

insert into libros (titulo, autor, editorial, precio)


values ('El aleph','Borges','Emece',25.00);
insert into libros (titulo, autor, editorial, precio)
values ('Martin Fierro','Jose Hernandez','Planeta',35.50);
insert into libros (titulo, autor, editorial, precio)
values ('Aprenda PHP','Mario Molina','Emece',45.50);
insert into libros (titulo, autor, editorial, precio)
values ('Cervantes y el quijote','Borges','Emece',25);
insert into libros (titulo, autor, editorial, precio)
values ('Matematica estas ahi','Paenza','Siglo XXI',15);

4- Muestre todos los registros (5 registros)

5- Modifique los registros cuyo autor sea igual a "Paenza", por "Adrian Paenza" (1 registro)

6- Nuevamente, modifique los registros cuyo autor sea igual a "Paenza", por "Adrian Paenza"
(ningn registro afectado porque ninguno cumple la condicin)

7- Actualice el precio del libro de "Mario Molina" a 27 pesos (1 registro)

8- Actualice el valor del campo "editorial" por "Emece S.A.", para todos los registros cuya
editorial sea igual a "Emece" (3 registros)

drop table libros;

create table libros (


titulo varchar2(30),
autor varchar2(20),
editorial varchar2(15),
precio number(5,2)
);

insert into libros (titulo, autor, editorial, precio)


values ('El aleph','Borges','Emece',25.00);
insert into libros (titulo, autor, editorial, precio)
values ('Martin Fierro','Jose Hernandez','Planeta',35.50);
insert into libros (titulo, autor, editorial, precio)
values ('Aprenda PHP','Mario Molina','Emece',45.50);
insert into libros (titulo, autor, editorial, precio)
values ('Cervantes y el quijote','Borges','Emece',25);
insert into libros (titulo, autor, editorial, precio)
values ('Matematica estas ahi','Paenza','Siglo XXI',15);

select *from libros;

update libros set autor='Adrian Paenza'


where autor='Paenza';

update libros set autor='Adrian Paenza'


where autor='Paenza';
update libros set precio=27
where autor='Mario Molina';

update libros set editorial='Emece S.A.'


where editorial='Emece';

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".

11 - Valores nulos (null)

Problema:

Trabajamos con la tabla "libros" de una librera.


Eliminamos la tabla "libros":

drop table libros;

Creamos la tabla especificando que los campos "titulo" y "autor" no admitan valores nulos:

create table libros(


titulo varchar2(30) not null,
autor varchar2(30) not null,
editorial varchar2(15) null,
precio number(5,2)
);

Los campos "editorial" y "precio" si permiten valores nulos; el primero, porque lo


especificamos colocando "null" en la definicin del campo, el segundo lo asume por defecto.

Agregamos un registro a la tabla con valor nulo para el campo "precio":

insert into libros (titulo,autor,editorial,precio)


values('El aleph','Borges','Emece',null);

Veamos cmo se almacen el registro:

select *from libros;

No aparece ningn valor en la columna "precio".

Ingresamos otro registro, con valor nulo para el campo "editorial", campo que admite valores
"null":

insert into libros (titulo,autor,editorial,precio)


values('Alicia en el pais','Lewis Carroll',null,0);

Veamos cmo se almacen el registro:

select *from libros;

No aparece ningn valor en la columna "editorial".

Ingresamos otro registro, con valor nulo para los dos campos que lo admiten:

insert into libros (titulo,autor,editorial,precio)


values('Aprenda PHP','Mario Molina',null,null);

Veamos cmo se almacen el registro:

select *from libros;

No aparece ningn valor en ambas columnas.

Veamos lo que sucede si intentamos ingresar el valor "null" en campos que no lo admiten,
como "titulo":

insert into libros (titulo,autor,editorial,precio)


values(null,'Borges','Siglo XXI',25);
aparece un mensaje indicando que no se puede realizar una insercin "null" y la sentencia no
se ejecuta.

Para ver cules campos admiten valores nulos y cules no, vemos la estructura de la tabla:

describe libros;

nos muestra, en la columna "Null", que los campos "titulo" y "autor" estn definidos "not null",
es decir, no permiten valores nulos, los otros dos campos si los admiten.

Dijimos que la cadena vaca es interpretada como valor "null". Vamos a ingresar un registro
con cadena vaca para el campo "editorial":

insert into libros (titulo,autor,editorial,precio)


values('Uno','Richard Bach','',18.50);

Veamos cmo se almacen el registro:

select *from libros;

No aparece ningn valor en la columna "editorial" del libro "Uno", almacen "null".

Intentamos ingresar una cadena vaca en el campo "titulo":

insert into libros (titulo,autor,editorial,precio)


values('','Richard Bach','Planeta',22);

Mensaje de error indicando que el campo no admite valores nulos.

Dijimos que una cadena de espacios NO es igual a una cadena vaca o valor "null". Vamos a
ingresar un registro y en el campo "editorial" guardaremos una cadena de 3 espacios:

insert into libros (titulo,autor,editorial,precio)


values('Don quijote','Cervantes',' ',20);

Veamos cmo se almacen el registro:

select *from libros;

Se muestra la cadena de espacios.

Recuperamos los registros que contengan en el campo "editorial" una cadena de 3 espacios:

select *from libros where editorial=' ';


11 - Valores nulos (null)

Primer problema:

Una farmacia guarda informacin referente a sus medicamentos en una tabla llamada
"medicamentos".

1- Elimine la tabla y crela con la siguiente estructura:

drop table medicamentos;


create table medicamentos(
codigo number(5) not null,
nombre varchar2(20) not null,
laboratorio varchar2(20),
precio number(5,2),
cantidad number(3,0) not null
);

3- Visualice la estructura de la tabla "medicamentos"


note que los campos "codigo", "nombre" y "cantidad", en la columna "Null" muestra "NOT
NULL".

4- Ingrese algunos registros con valores "null" para los campos que lo admitan:

insert into medicamentos (codigo,nombre,laboratorio,precio,cantidad)


values(1,'Sertal gotas',null,null,100);
insert into medicamentos (codigo,nombre,laboratorio,precio,cantidad)
values(2,'Sertal compuesto',null,8.90,150);
insert into medicamentos (codigo,nombre,laboratorio,precio,cantidad)
values(3,'Buscapina','Roche',null,200);

5- Vea todos los registros.

6- Ingrese un registro con valor "0" para el precio y cadena vaca para el laboratorio.

7- Intente ingresar un registro con cadena vaca para el nombre (mensaje de error)

8- Intente ingresar un registro con valor nulo para un campo que no lo admite (aparece un
mensaje de error)

9- Ingrese un registro con una cadena de 1 espacio para el laboratorio.

10- Recupere los registros cuyo laboratorio contenga 1 espacio (1 registro)

11- Recupere los registros cuyo laboratorio sea distinto de ' '(cadena de 1 espacio) (1 registro)

Ver solucin

drop table medicamentos;


create table medicamentos(
codigo number(5) not null,
nombre varchar2(20) not null,
laboratorio varchar2(20),
precio number(5,2),
cantidad number(3,0) not null
);

describe medicamentos;

insert into medicamentos (codigo,nombre,laboratorio,precio,cantidad)


values(1,'Sertal gotas',null,null,100);
insert into medicamentos (codigo,nombre,laboratorio,precio,cantidad)
values(2,'Sertal compuesto',null,8.90,150);
insert into medicamentos (codigo,nombre,laboratorio,precio,cantidad)
values(3,'Buscapina','Roche',null,200);
select *from medicamentos;

insert into medicamentos (codigo,nombre, laboratorio,precio,cantidad)


values(4,'Bayaspirina','',0,150);

insert into medicamentos (codigo,nombre,laboratorio,precio,cantidad)


values(0,'','Bayer',15.60,200);

insert into medicamentos (codigo,nombre,laboratorio,precio,cantidad)


values(null,'Amoxidal jarabe','Bayer',25,120);

insert into medicamentos (codigo,nombre, laboratorio,precio,cantidad)


values(5,'Geniol',' ',0.5,200);

select *from medicamentos where laboratorio=' ';

select *from medicamentos where laboratorio<>' '

Segundo problema:

Trabaje con la tabla que almacena los datos sobre pelculas, llamada "peliculas".

1- Elimine la tabla:

2- Crela con la siguiente estructura:

create table peliculas(


codigo number(4) not null,
titulo varchar2(40) not null,
actor varchar2(20),
duracion number(3)
);

3- Visualice la estructura de la tabla.


note que el campo "codigo" y "titulo", en la columna "Null" muestran "NOT NULL".

4- Ingrese los siguientes registros:

insert into peliculas (codigo,titulo,actor,duracion)


values(1,'Mision imposible','Tom Cruise',120);
insert into peliculas (codigo,titulo,actor,duracion)
values(2,'Harry Potter y la piedra filosofal',null,180);
insert into peliculas (codigo,titulo,actor,duracion)
values(3,'Harry Potter y la camara secreta','Daniel R.',null);
insert into peliculas (codigo,titulo,actor,duracion)
values(0,'Mision imposible 2','',150);
insert into peliculas (codigo,titulo,actor,duracion)
values(4,'Titanic','L. Di Caprio',220);
insert into peliculas (codigo,titulo,actor,duracion)
values(5,'Mujer bonita','R. Gere-J. Roberts',0);

5- Recupere todos los registros para ver cmo Oracle los almacen.

6- Intente ingresar un registro con valor nulo para campos que no lo admiten (aparece un
mensaje de error)

7- Muestre todos los registros.

8- Actualice la pelcula en cuyo campo "duracion" hay 0 por "null" (1 registro)

9- Recupere todos los registros.

drop table peliculas;

create table peliculas(


codigo number(4) not null,
titulo varchar2(40) not null,
actor varchar2(20),
duracion number(3)
);

describe peliculas;

insert into peliculas (codigo,titulo,actor,duracion)


values(1,'Mision imposible','Tom Cruise',120);
insert into peliculas (codigo,titulo,actor,duracion)
values(2,'Harry Potter y la piedra filosofal',null,180);
insert into peliculas (codigo,titulo,actor,duracion)
values(3,'Harry Potter y la camara secreta','Daniel R.',null);
insert into peliculas (codigo,titulo,actor,duracion)
values(0,'Mision imposible 2','',150);
insert into peliculas (codigo,titulo,actor,duracion)
values(4,'Titanic','L. Di Caprio',220);
insert into peliculas (codigo,titulo,actor,duracion)
values(5,'Mujer bonita','R. Gere-J. Roberts',0);

select *from peliculas;

insert into peliculas (codigo,titulo,actor,duracion)


values(null,'Mujer bonita','R. Gere-J. Roberts',190);

select *from peliculas;

update peliculas set duracion=null where duracion=0;

select *from peliculas;

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;


12 - Operadores relacionales (is null)

Problema:

Trabajamos con la tabla "libros" de una librera.


Eliminamos la tabla y la creamos:

drop table libros;

create table libros(


codigo number(4) not null,
titulo varchar2(40) not null,
autor varchar2(20),
editorial varchar2(20),
precio number(6,2)
);

Ingresamos algunos registros:

insert into libros


values(1,'El aleph','Borges','Emece',15.90);
insert into libros
values(2,'Cervantes y el quijote','Borges','Paidos',null);
insert into libros
values(3,'Alicia en el pais de las maravillas','Lewis
Carroll',null,19.90);
insert into libros
values(4,'Martin Fierro','Jose Hernandez','Emece',25.90);
insert into libros (codigo,titulo,autor,precio)
values(5,'Antologa potica','Borges',25.50);
insert into libros (codigo,titulo,autor)
values(6,'Java en 10 minutos','Mario Molina');
insert into libros (codigo,titulo,autor)
values(7,'Martin Fierro','Jose Hernandez');
insert into libros (codigo,titulo,autor)
values(8,'Aprenda PHP',null);

Recuperamos los registros en los cuales est almacenado el valor "null" en el campo
"editorial":

select *from libros


where editorial is null;

Seleccionamos los libros que no contiene "null" en "autor":

select *from libros


where editorial is not null;

Dijimos que una cadena de espacios NO es igual a una cadena vaca o valor "null". Vamos a
ingresar un registro y en el campo "editorial" guardaremos una cadena de 3 espacios:

insert into libros (codigo,titulo,autor,editorial,precio)


values(9,'Don quijote','Cervantes',' ',20);

Veamos cmo se almacen el registro:

select *from libros;

Se muestra la cadena de espacios.

Recuperamos los registros que contengan el valor "null" en el campo "editorial" y luego
aquellos que tengan una cadena de 3 espacios:

select *from libros where editorial is null;


select *from libros where editorial=' ';

Con la primera sentencia veremos los libros cuya editorial es igual a "null" (desconocido); con
la segunda, los libros cuya editorial almacena una cadena de espacios.

12 - Operadores relacionales (is null)

Primer problema:

Una farmacia guarda informacin referente a sus medicamentos en una tabla llamada
"medicamentos".

1- Elimine la tabla y crela con la siguiente estructura:

drop table medicamentos;


create table medicamentos(
codigo number(5) not null,
nombre varchar2(20) not null,
laboratorio varchar2(20),
precio number(5,2),
cantidad number(3,0) not null
);

3- Visualice la estructura de la tabla "medicamentos"


note que los campos "codigo", "nombre" y "cantidad", en la columna "Null" muestra "NOT
NULL".

4- Ingrese algunos registros con valores "null" para los campos que lo admitan:

insert into medicamentos (codigo,nombre,laboratorio,precio,cantidad)


values(1,'Sertal gotas',null,null,100);
insert into medicamentos (codigo,nombre,laboratorio,precio,cantidad)
values(2,'Sertal compuesto',null,8.90,150);
insert into medicamentos (codigo,nombre,laboratorio,precio,cantidad)
values(3,'Buscapina','Roche',null,200);

5- Vea todos los registros.

6- Ingrese un registro con valor "0" para el precio y cadena vaca para el laboratorio.

7- Intente ingresar un registro con cadena vaca para el nombre (mensaje de error)

8- Intente ingresar un registro con valor nulo para un campo que no lo admite (aparece un
mensaje de error)

9- Recupere los registros que contengan valor "null" en el campo "laboratorio" (3 registros)

10- Recupere los registros que contengan valor "null" en el campo "precio", luego los que
tengan el valor 0 en el mismo campo. Note que el resultado es distinto (2 y 1 registros
respectivamente)

11- Recupere los registros cuyo laboratorio no contenga valor nulo (1 registro)

12- Recupere los registros cuyo precio sea distinto de 0, luego los que sean distintos de "null"
(1 y 2 resgistros respectivamente)
Note que la salida de la primera sentencia no muestra los registros con valor 0 y tampoco los
que tienen valor nulo; el resultado de la segunda sentencia muestra los registros con valor
para el campo precio (incluso el valor 0).

13- Ingrese un registro con una cadena de 1 espacio para el laboratorio.

14- Recupere los registros cuyo laboratorio sea "null" y luego los que contengan 1 espacio (3 y
1 registros respectivamente)

Note que la salida de la primera sentencia no muestra los registros con valores para el campo
"laboratorio" (un caracter espacio es un valor); el resultado de la segunda sentencia muestra
los registros con el valor " " para el campo precio.

15- Recupere los registros cuyo laboratorio sea distinto de ' '(cadena de 1 espacio), luego los
que sean distintos de "null" (1 y 2 registros respectivamente)
Note que la salida de la primera sentencia no muestra los registros con valor ' ' y tampoco los
que tienen valor nulo; el resultado de la segunda sentencia muestra los registros con valor
para el campo laboratorio (incluso el valor ' ')

Ver solucin
drop table medicamentos;
create table medicamentos(
codigo number(5) not null,
nombre varchar2(20) not null,
laboratorio varchar2(20),
precio number(5,2),
cantidad number(3,0) not null
);

describe medicamentos;

insert into medicamentos (codigo,nombre,laboratorio,precio,cantidad)


values(1,'Sertal gotas',null,null,100);
insert into medicamentos (codigo,nombre,laboratorio,precio,cantidad)
values(2,'Sertal compuesto',null,8.90,150);
insert into medicamentos (codigo,nombre,laboratorio,precio,cantidad)
values(3,'Buscapina','Roche',null,200);

select *from medicamentos;

insert into medicamentos (codigo,nombre, laboratorio,precio,cantidad)


values(4,'Bayaspirina','',0,150);

insert into medicamentos (codigo,nombre,laboratorio,precio,cantidad)


values(0,'','Bayer',15.60,200);

insert into medicamentos (codigo,nombre,laboratorio,precio,cantidad)


values(null,'Amoxidal jarabe','Bayer',25,120);

select *from medicamentos


where laboratorio is null;

select *from medicamentos where precio is null;


select *from medicamentos where precio=0;

select *from medicamentos where laboratorio is not null;

select *from medicamentos where precio<>0;


select *from medicamentos where precio is not null;

insert into medicamentos (codigo,nombre, laboratorio,precio,cantidad)


values(5,'Geniol',' ',0.5,200);

select *from medicamentos where laboratorio is null;


select *from medicamentos where laboratorio=' ';

select *from medicamentos where laboratorio<>' ';


select *from medicamentos where laboratorio is not null;
Segundo problema:

Trabaje con la tabla que almacena los datos sobre pelculas, llamada "peliculas".

1- Elimine la tabla:

drop table peliculas;

2- Crela con la siguiente estructura:

create table peliculas(


codigo number(4) not null,
titulo varchar2(40) not null,
actor varchar2(20),
duracion number(3)
);

3- Visualice la estructura de la tabla. note que el campo "codigo" y "titulo", en la columna


"Null" muestran "NOT NULL".

4- Ingrese los siguientes registros:

insert into peliculas (codigo,titulo,actor,duracion)


values(1,'Mision imposible','Tom Cruise',120);
insert into peliculas (codigo,titulo,actor,duracion)
values(2,'Harry Potter y la piedra filosofal',null,180);
insert into peliculas (codigo,titulo,actor,duracion)
values(3,'Harry Potter y la camara secreta','Daniel R.',null);
insert into peliculas (codigo,titulo,actor,duracion)
values(0,'Mision imposible 2','',150);
insert into peliculas (codigo,titulo,actor,duracion)
values(4,'Titanic','L. Di Caprio',220);
insert into peliculas (codigo,titulo,actor,duracion)
values(5,'Mujer bonita','R. Gere-J. Roberts',0);

5- Recupere todos los registros para ver cmo Oracle los almacen.

6- Intente ingresar un registro con valor nulo para campos que no lo admiten (aparece un
mensaje de error)

7- Muestre los registros con valor nulo en el campo "actor" (2 registros)

8- Actualice los registros que tengan valor de duracin desconocido (nulo) por "120" (1 registro
actualizado)

9- Coloque 'Desconocido' en el campo "actor" en los registros que tengan valor nulo en dicho
campo (2 registros)

10- Muestre todos los registros

11- Muestre todos los registros con valor nulo en el campo "actor" (ninguno)

12- Actualice la pelcula en cuyo campo "duracion" hay 0 por "null" (1 registro)

13- Recupere todos los registros.

14- Borre todos los registros en los cuales haya un valor nulo en "duracion" (1 registro)

15- Verifique que se elimin recuperando todos los registros.

drop table peliculas;

create table peliculas(


codigo number(4) not null,
titulo varchar2(40) not null,
actor varchar2(20),
duracion number(3)
);

describe peliculas;

insert into peliculas (codigo,titulo,actor,duracion)


values(1,'Mision imposible','Tom Cruise',120);
insert into peliculas (codigo,titulo,actor,duracion)
values(2,'Harry Potter y la piedra filosofal',null,180);
insert into peliculas (codigo,titulo,actor,duracion)
values(3,'Harry Potter y la camara secreta','Daniel R.',null);
insert into peliculas (codigo,titulo,actor,duracion)
values(0,'Mision imposible 2','',150);
insert into peliculas (codigo,titulo,actor,duracion)
values(4,'Titanic','L. Di Caprio',220);
insert into peliculas (codigo,titulo,actor,duracion)
values(5,'Mujer bonita','R. Gere-J. Roberts',0);

select *from peliculas;

insert into peliculas (codigo,titulo,actor,duracion)


values(null,'Mujer bonita','R. Gere-J. Roberts',190);

select *from peliculas where actor is null;

update peliculas set duracion=120 where duracion is null;

update peliculas set actor='Desconocido'


where actor is null;

select *from peliculas;

select *from peliculas where actor is null;

update peliculas set duracion=null where duracion=0;

select *from peliculas;

delete from peliculas


where duracion is null;

select *from peliculas;

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.

13 - Clave primaria (primary key)


Problema:

Trabajamos con la tabla "usuarios".

Eliminamos la tabla:

drop table usuarios;

Creamos la tabla definiendo el campo "nombre" como clave primaria:

create table usuarios(


nombre varchar2(20),
clave varchar2(10),
primary key (nombre)
);

Al campo "nombre" no lo definimos "not null", pero al establecerse como clave primaria,
Oracle lo convierte en "not null", veamos que en la columna "NULL" aparece "NOT NULL":

describe usuarios;

Ingresamos algunos registros:

insert into usuarios (nombre, clave)


values ('juanperez','Boca');
insert into usuarios (nombre, clave)
values ('raulgarcia','River');

Recordemos que cuando un campo es clave primaria, sus valores no se repiten. Intentamos
ingresar un valor de clave primaria existente:

insert into usuarios (nombre, clave)


values ('juanperez','payaso');

aparece un mensaje de error y la sentencia no se ejecuta.

Cuando un campo es clave primaria, sus valores no pueden ser nulos. Intentamos ingresar el
valor "null" en el campo clave primaria:

insert into usuarios (nombre, clave)


values (null,'payaso');

aparece un mensaje de error y la sentencia no se ejecuta.

Si realizamos alguna actualizacin, Oracle controla que los valores para el campo establecido
como clave primaria no estn repetidos en la tabla. Intentemos actualizar el nombre de un
usuario colocando un nombre existente:

update usuarios set nombre='juanperez'


where nombre='raulgarcia';

aparece un mensaje indicando que se viola la clave primaria y la actualizacin no se realiza.


Corroboramos que la tabla "usuarios" tiene establecido el campo "nombre" como clave
primaria realizando la siguiente consulta (Recuerde colocar el nombre de la tabla en
maysculas, sino Oracle considerar que no existe la tabla):

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';

Aparece la siguiente tabla:

TABLE_NAME COLUMN_NAME
--------------------------------------------
USUARIOS NOMBRE

indicando que la tabla "usuarios" tiene establecido el campo "nombre" como clave primaria.

13 - Clave primaria (primary key)

Primer problema:

Trabaje con la tabla "libros" de una librera.

1- Elimine la tabla:

drop table libros;

2- Crela con los siguientes campos, estableciendo como clave primaria el campo "codigo":

create table libros(


codigo number(4) not null,
titulo varchar2(40) not null,
autor varchar2(20),
editorial varchar2(15),
primary key (codigo)
);

3- Ingrese los siguientes registros:

insert into libros (codigo,titulo,autor,editorial)


values (1,'El aleph','Borges','Emece');
insert into libros (codigo,titulo,autor,editorial)
values (2,'Martin Fierro','Jose Hernandez','Planeta');
insert into libros (codigo,titulo,autor,editorial)
values (3,'Aprenda PHP','Mario Molina','Nuevo Siglo');

4- Ingrese un registro con cdigo repetido (aparece un mensaje de error)

5- Intente ingresar el valor "null" en el campo "codigo"

6- Intente actualizar el cdigo del libro "Martin Fierro" a "1" (mensaje de error)

7- Actualice el cdigo del libro "Martin Fierro" a "10"


8- Vea qu campo de la tabla "LIBROS" fue establecido como clave primaria

9- Vea qu campo de la tabla "libros" (en minsculas) fue establecido como clave primaria

La tabla aparece vaca porque Oracle no encuentra la tabla "libros", ya que almacena los
nombres de las tablas con maysculas.

drop table libros;

create table libros(


codigo number(4) not null,
titulo varchar2(40) not null,
autor varchar2(20),
editorial varchar2(15),
primary key (codigo)
);

insert into libros (codigo,titulo,autor,editorial)


values (1,'El aleph','Borges','Emece');
insert into libros (codigo,titulo,autor,editorial)
values (2,'Martin Fierro','Jose Hernandez','Planeta');
insert into libros (codigo,titulo,autor,editorial)
values (3,'Aprenda PHP','Mario Molina','Nuevo Siglo');

insert into libros (codigo,titulo,autor,editorial)


values (2,'Alicia en el pais de las maravillas','Lewis Carroll','Planeta');

insert into libros (codigo,titulo,autor,editorial)


values (null,'Alicia en el pais de las maravillas','Lewis Carroll','Planeta');

update libros set codigo=1


where titulo='Martin Fierro';

update libros set codigo=10


where titulo='Martin Fierro';

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='LIBROS';

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='libros';

Segundo problema:
Un instituto de enseanza almacena los datos de sus estudiantes en una tabla llamada
"alumnos".

1- Elimine la tabla "alumnos":

drop table alumnos;

2- Cree la tabla con la siguiente estructura intentando establecer 2 campos como clave
primaria, el campo "documento" y "legajo":

create table alumnos(


legajo varchar2(4) not null,
documento varchar2(8),
nombre varchar2(30),
domicilio varchar2(30),
primary key(codigo),
primary key(documento)
);

Un mensaje indica la tabla solamente puede tener UNA clave primaria.

3- Cree la tabla estableciendo como clave primaria el campo "documento":

create table alumnos(


legajo varchar2(4) not null,
documento varchar2(8),
nombre varchar2(30),
domicilio varchar2(30),
primary key(documento)
);

4- Verifique que el campo "documento" no admite valores nulos

5- Ingrese los siguientes registros:

insert into alumnos (legajo,documento,nombre,domicilio)


values('A233','22345345','Perez Mariana','Colon 234');
insert into alumnos (legajo,documento,nombre,domicilio)
values('A567','23545345','Morales Marcos','Avellaneda 348');

6- Intente ingresar un alumno con nmero de documento existente (no lo permite)

7- Intente ingresar un alumno con documento nulo (no lo permite)

8- Vea el campo clave primaria de "ALUMNOS".

drop table alumnos;

create table alumnos(


legajo varchar2(4) not null,
documento varchar2(8),
nombre varchar2(30),
domicilio varchar2(30),
primary key(codigo),
primary key(documento)
);

create table alumnos(


legajo varchar2(4) not null,
documento varchar2(8),
nombre varchar2(30),
domicilio varchar2(30),
primary key(documento)
);

describe alumnos;

insert into alumnos (legajo,documento,nombre,domicilio)


values('A233','22345345','Perez Mariana','Colon 234');
insert into alumnos (legajo,documento,nombre,domicilio)
values('A567','23545345','Morales Marcos','Avellaneda 348');

insert into alumnos (legajo,documento,nombre,domicilio)


values('A642','23545345','Gonzalez Analia','Caseros 444');

insert into alumnos (legajo,documento,nombre,domicilio)


values('A685',null,'Miranda Carmen','Uspallata 999');

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='ALUMNOS';

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).
14 - Vaciar la tabla (truncate table)

Problema:

Trabajamos con la tabla "libros" que almacena los datos de los libros de una librera.

Eliminamos la tabla:

drop table libros;

Creamos la tabla:

create table libros(


codigo number(4),
titulo varchar2(30),
autor varchar2(20),
editorial varchar2(15),
precio number(5,2)
);

Agregamos algunos registros:

insert into libros (codigo,titulo,autor,editorial,precio)


values (1,'El aleph','Borges','Emece',25.60);
insert into libros (codigo,titulo,autor,editorial,precio)
values (2,'Uno','Richard Bach','Planeta',18);

Seleccionamos todos los registros:

select *from libros;

Truncamos la tabla:

truncate table libros;

Si consultamos la tabla, vemos que an existe pero ya no tiene registros:

select *from libros;

Ingresamos nuevamente algunos registros:

insert into libros (codigo,titulo,autor,editorial,precio)


values (1,'El aleph','Borges','Emece',25.60);
insert into libros (codigo,titulo,autor,editorial,precio)
values (2,'Uno','Richard Bach','Planeta',18);

Eliminemos todos los registros con "delete":

delete from libros;

Si consultamos la tabla, vemos que an existe pero ya no tiene registros:

select *from libros;

Ingresamos nuevamente algunos registros:


insert into libros (codigo,titulo,autor,editorial,precio)
values (1,'El aleph','Borges','Emece',25.60);
insert into libros (codigo,titulo,autor,editorial,precio)
values (2,'Uno','Richard Bach','Planeta',18);

Eliminamos la tabla:

drop table libros;

Intentamos seleccionar todos los registros:

select *from libros;

Aparece un mensaje de error, la tabla no existe.

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".

15 - Tipos de datos alfanumricos

Problema:

Un comercio que tiene un stand en una feria registra en una tabla llamada "visitantes" algunos
datos de las personas que visitan o compran en su stand para luego enviarle publicidad de sus
productos.

Eliminamos la tabla "visitantes":

drop table visitantes;

Creamos con la siguiente estructura:

create table visitantes(


nombre varchar2(30),
edad number(2),
sexo char(1),
domicilio varchar2(30),
ciudad varchar2(20),
telefono varchar2(11)
);

Los campos "nombre", "domicilio" y "ciudad" almacenarn valores cuya longitud vara, por ello
elegimos el tipo "varchar2" y le damos a cada uno una longitud mxima estimando su tamao.
El campo "sexo" se define de tipo "char", porque necesitamos solamente 1 caracter "f" o "m",
que siempre ser fijo. El campo "telefono" tambin se define como varchar2 porque no todos
los nmeros telefnicos tienen la misma longitud.

Ingresamos un registro:

insert into visitantes (nombre,edad,sexo,domicilio,ciudad,telefono)


values ('Ana Acosta',25,'f','Avellaneda 123','Cordoba','4223344');

Intentamos ingresar una cadena de mayor longitud que la definida en el campo "sexo":

insert into visitantes (nombre,edad,sexo,domicilio,ciudad,telefono)


values ('Betina Bustos',32,'fem','Bulnes 234','Cordoba','4515151');

aparece un mensaje de error y la sentencia no se ejecuta.

Ingresamos el mismo registro, esta vez con un slo caracter para el campo "sexo":

insert into visitantes (nombre,edad,sexo,domicilio,ciudad,telefono)


values ('Betina Bustos',32,'f','Bulnes 234','Cordoba','4515151');

Ingresamos un nmero telefnico olvidando las comillas, es decir, como un valor numrico:

insert into visitantes (nombre,edad,sexo,domicilio,ciudad,telefono)


values ('Carlos Caseres',43,'m','Colon 345','Cordoba',03514555666);

lo convierte a cadena, vemoslo:

select *from visitantes;


15 - Tipos de datos alfanumricos

Primer problema:

Una concesionaria de autos vende autos usados y almacena los datos de los autos en una tabla
llamada "autos".

1- Elimine la tabla "autos"

2- Cree la tabla eligiendo el tipo de dato adecuado para cada campo, estableciendo el campo
"patente" como clave primaria:

create table autos(


patente char(6),
marca varchar2(20),
modelo char(4),
precio number(8,2),
primary key (patente)
);
Hemos definido el campo "patente" de tipo "char" y no "varchar2" porque la cadena de
caracteres siempre tendr la misma longitud (6 caracteres). Lo mismo sucede con el campo
"modelo", en el cual almacenaremos el ao, necesitamos 4 caracteres fijos.

3- Ingrese los siguientes registros:

insert into autos (patente,marca,modelo,precio)


values('ABC123','Fiat 128','1970',15000);
insert into autos (patente,marca,modelo,precio)
values('BCD456','Renault 11','1990',40000);
insert into autos (patente,marca,modelo,precio)
values('CDE789','Peugeot 505','1990',80000);
insert into autos (patente,marca,modelo,precio)
values('DEF012','Renault Megane','1998',95000);

4- Ingrese un registro omitiendo las comillas en el valor de "modelo"


Oracle convierte el valor a cadena.

5- Vea cmo se almacen.

6- Seleccione todos los autos modelo "1990"

7- Intente ingresar un registro con un valor de patente de 7 caracteres

8- Intente ingresar un registro con valor de patente repetida.

drop table autos;

create table autos(


patente char(6),
marca varchar2(20),
modelo char(4),
precio number(8,2),
primary key (patente)
);

insert into autos (patente,marca,modelo,precio)


values('ABC123','Fiat 128','1970',15000);
insert into autos (patente,marca,modelo,precio)
values('BCD456','Renault 11','1990',40000);
insert into autos (patente,marca,modelo,precio)
values('CDE789','Peugeot 505','1990',80000);
insert into autos (patente,marca,modelo,precio)
values('DEF012','Renault Megane','1998',95000);

insert into autos (patente,marca,modelo,precio)


values('HIJ678','Renault Clio',1990,70000);

select *from autos;

select *from autos


where modelo='1990';

insert into autos (patente,marca,modelo,precio)


values('FGH3457','Fiat 128','1975',20000);

insert into autos (patente,marca,modelo,precio)


values('HIJ678','Fiat 128','1975',20000);

Segundo problema:

Una empresa almacena los datos de sus clientes en una tabla llamada "clientes".

1- Elimine la tabla "clientes"

2- Crela eligiendo el tipo de dato ms adecuado para cada campo:

create table clientes(


documento char(8) not null,
apellido varchar2(20),
nombre varchar2(20),
domicilio varchar2(30),
telefono varchar2 (11)
);

3- Analice la definicin de los campos. Se utiliza char(8) para el documento porque siempre
constar de 8 caracteres. Para el nmero telefnico se usar "varchar2" y no un tipo numrico
porque si bien es un nmero, con l no se realizarn operaciones matemticas.

4- Ingrese algunos registros:

insert into clientes (documento,apellido,nombre,domicilio,telefono)


values('22333444','Perez','Juan','Sarmiento 980','4223344');
insert into clientes (documento,apellido,nombre,domicilio,telefono)
values('23444555','Perez','Ana','Colon 234',null);
insert into clientes (documento,apellido,nombre,domicilio,telefono)
values('30444555','Garcia','Luciana','Caseros 634',null);

5- Intente ingresar un registro con ms caracteres que los permitidos para el campo "telefono"

6- Intente ingresar un registro con ms caracteres que los permitidos para el campo
"documento"

7- Intente ingresar un registro omitiendo las comillas en el campo "apellido"

8- Seleccione todos los clientes de apellido "Perez" (2 registros)

drop table clientes;

create table clientes(


documento char(8) not null,
apellido varchar2(20),
nombre varchar2(20),
domicilio varchar2(30),
telefono varchar2 (11)
);

insert into clientes (documento,apellido,nombre,domicilio,telefono)


values('22333444','Perez','Juan','Sarmiento 980','4223344');
insert into clientes (documento,apellido,nombre,domicilio,telefono)
values('23444555','Perez','Ana','Colon 234',null);
insert into clientes (documento,apellido,nombre,domicilio,telefono)
values('30444555','Garcia','Luciana','Caseros 634',null);

insert into clientes (documento,apellido,nombre,domicilio,telefono)


values('24555666','Juarez','Ana','Urquiza 444','035145566778');

insert into clientes (documento,apellido,nombre,domicilio,telefono)


values('256667778','Garcia','Luis','Avellaneda 1454','4558877');

insert into clientes (documento,apellido,nombre,domicilio,telefono)


values('25666777',Garcia,'Luis','Avellaneda 1454','4558877');

select *from clientes


where apellido='Perez';

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.

16 - Tipos de datos numricos

Problema:

Trabajamos con la tabla "libros" de una librera.

Eliminamos la tabla:

drop table libros;

Creamos la tabla con la siguiente estructura:

create table libros(


codigo number(5) not null,
titulo varchar2(40) not null,
autor varchar2(30),
editorial varchar2(15),
precio number(6,2),
cantidad number(4)
);

Note que definimos el campo "codigo" de tipo "number(5)", esto es porque estimamos que no
tendremos ms de 99999 libros, y no colocamos decimales porque necesitamos nmeros
enteros.
Como en el campo "precio" no almacenaremos valores mayores a 9999.99, definimos el campo
de tipo "number(6,2)".

El tipo "float" no es adecuado para representar precios porque no es exacto.

Como los valores para el campo "cantidad" no superarn los 9999, definimos el campo de tipo
"number(4)", no colocamos decimales porque necesitamos valores enteros.

Analicemos la insercin de datos numricos.

Intentemos ingresar un valor para "cantidad" fuera del rango definido:


insert into libros (codigo,titulo,autor,editorial,precio,cantidad)
values(1,'El aleph','Borges','Emece',25.60,50000);

aparece un mensaje de error y la insercin no se ejecuta.

Ingresamos un valor para "cantidad" con decimales:

insert into libros (codigo,titulo,autor,editorial,precio,cantidad)


values(1,'El aleph','Borges','Emece',25.60,100.2);

Lo acepta, veamos qu se almacen:

select *from libros;

Trunc el valor.

Ingresamos un precio con 3 decimales:

insert into libros (codigo,titulo,autor,editorial,precio,cantidad)


values(2,'Don quijote','Cervantes','Emece',25.123,100);

Lo acepta, veamos qu se almacen:

select *from libros;

Trunc el valor.

Intentamos ingresar un cdigo con comillas (una cadena):

insert into libros (codigo,titulo,autor,editorial,precio,cantidad)


values(4,'Uno','Richard Bach','Planeta','50',100);

Oracle lo convierte a nmero.

Intentamos ingresar una cadena que Oracle no pueda convertir a valor numrico en el campo
"precio":

insert into libros (codigo,titulo,autor,editorial,precio,cantidad)


values(5,'Alicia en el pais...','Lewis
Carroll','Planeta','50.30',200);

Error.

16 - Tipos de datos numricos

Primer problema:

Un banco tiene registrados las cuentas corrientes de sus clientes en una tabla llamada
"cuentas".
La tabla contiene estos datos:

Nmero de Cuenta Documento Nombre Saldo


___________________________________________________________
___
1234 25666777 Pedro Perez 500000.60
2234 27888999 Juan Lopez -250000
3344 27888999 Juan Lopez 4000.50
3346 32111222 Susana Molina 1000

1- Elimine la tabla "cuentas":

drop table cuentas;

2- Cree la tabla eligiendo el tipo de dato adecuado para almacenar los datos descriptos
arriba:

- Nmero de cuenta: entero hasta 9999, no nulo, no puede haber valores repetidos, clave
primaria;

- Documento del propietario de la cuenta: cadena de caracteres de 8 de longitud (siempre 8),


no nulo;

- Nombre del propietario de la cuenta: cadena de caracteres de 30 de longitud,

- Saldo de la cuenta: valores que no superan 999999.99

create table cuentas(


numero number(4) not null,
documento char(8),
nombre varchar2(30),
saldo number(8,2),
primary key (numero)
);

3- Ingrese los siguientes registros:

insert into cuentas(numero,documento,nombre,saldo)


values('1234','25666777','Pedro Perez',500000.60);
insert into cuentas(numero,documento,nombre,saldo)
values('2234','27888999','Juan Lopez',-250000);
insert into cuentas(numero,documento,nombre,saldo)
values('3344','27888999','Juan Lopez',4000.50);
insert into cuentas(numero,documento,nombre,saldo)
values('3346','32111222','Susana Molina',1000);

Note que hay dos cuentas, con distinto nmero de cuenta, de la misma persona.

4- Seleccione todos los registros cuyo saldo sea mayor a "4000" (2 registros)

5- Muestre el nmero de cuenta y saldo de todas las cuentas cuyo propietario sea "Juan
Lopez" (2 registros)

6- Muestre las cuentas con saldo negativo (1 registro)

7- Muestre todas las cuentas cuyo nmero es igual o mayor a "3000" (2 registros)
drop table cuentas;

create table cuentas(


numero number(4) not null,
documento char(8),
nombre varchar2(30),
saldo number(8,2),
primary key (numero)
);

insert into cuentas(numero,documento,nombre,saldo)


values('1234','25666777','Pedro Perez',500000.60);
insert into cuentas(numero,documento,nombre,saldo)
values('2234','27888999','Juan Lopez',-250000);
insert into cuentas(numero,documento,nombre,saldo)
values('3344','27888999','Juan Lopez',4000.50);
insert into cuentas(numero,documento,nombre,saldo)
values('3346','32111222','Susana Molina',1000);

select *from cuentas


where saldo<4000;

select numero,saldo from cuentas


where nombre='Juan Lopez';

select *from cuentas


where saldo<0;

select *from cuentas


where numero>=3000;

Segundo problema:

Una empresa almacena los datos de sus empleados en una tabla "empleados" que guarda los
siguientes datos: nombre, documento, sexo, domicilio, sueldobasico.

1- Elimine la tabla:

drop table empleados;

2- Cree la tabla eligiendo el tipo de dato adecuado para cada campo:

create table empleados(


nombre varchar2(30),
documento char(8),
sexo char(1),
domicilio varchar2(30),
sueldobasico numberl(7,2),--mximo estimado 99999.99
cantidadhijos number(2)--no superar los 99
);

3- Ingrese algunos registros:


insert into empleados
(nombre,documento,sexo,domicilio,sueldobasico,cantidadhijos)
values ('Juan Perez','22333444','m','Sarmiento 123',500,2);
insert into empleados
(nombre,documento,sexo,domicilio,sueldobasico,cantidadhijos)
values ('Ana Acosta','24555666','f','Colon 134',850,0);
insert into empleados
(nombre,documento,sexo,domicilio,sueldobasico,cantidadhijos)
values ('Bartolome Barrios','27888999','m','Urquiza 479',10000.80,4);

4- Ingrese un valor de "sueldobasico" con ms decimales que los definidos (redondea los
decimales al valor ms cercano 800.89)

5- Intente ingresar un sueldo que supere los 7 dgitos (no lo permite)

6- Muestre todos los empleados cuyo sueldo no supere los 900 pesos

7- Seleccione los nombres de los empleados que tengan hijos (3 registros)

drop table empleados;

create table empleados(


nombre varchar2(30),
documento char(8),
sexo char(1),
domicilio varchar2(30),
sueldobasico numberl(7,2),--mximo estimado 99999.99
cantidadhijos number(2)--no superar los 99
);

insert into empleados


(nombre,documento,sexo,domicilio,sueldobasico,cantidadhijos)
values ('Juan Perez','22333444','m','Sarmiento 123',500,2);
insert into empleados
(nombre,documento,sexo,domicilio,sueldobasico,cantidadhijos)
values ('Ana Acosta','24555666','f','Colon 134',850,0);
insert into empleados
(nombre,documento,sexo,domicilio,sueldobasico,cantidadhijos)
values ('Bartolome Barrios','27888999','m','Urquiza 479',10000.80,4);

insert into empleados


(nombre,documento,sexo,domicilio,sueldobasico,cantidadhijos)
values ('Susana Molina','29000555','f','Salta 876',800.888,3);

insert into empleados


(nombre,documento,sexo,domicilio,sueldobasico,cantidadhijos)
values ('Marta Juarez','32444555','f','Sucre 1086',5000000,2);

select *from empleados


where sueldobasico<=900;

select *from empleados


where cantidadhijos>0;
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.

17 - Ingresar algunos campos

Problema:

Trabajamos con la tabla "libros" que almacena los datos de los libros de una librera.

Eliminamos la tabla:

drop table libros;

Creamos la tabla:

create table libros(


codigo number(5) not null,
titulo varchar2(40) not null,
autor varchar2(30),
editorial varchar2(15)
);

Si ingresamos valores para todos los campos, podemos omitir la lista de campos:
insert into libros
values (1,'Uno','Richard Bach','Planeta');

Podemos ingresar valores para algunos de los campos:

insert into libros (codigo, titulo, autor)


values (2,'El aleph','Borges');

Veamos cmo Oracle almacen los registros:

select *from libros;

En el campo "editorial", para el cual no ingresamos valor, se almacen "null".

No podemos omitir el valor para un campo declarado "not null", como el campo "codigo":

insert into libros (titulo, autor,editorial)


values ('Alicia en el pais de las maravillas','Lewis
Carroll','Planeta');

aparece un mensaje y la insercin no se realiza.

Veamos cmo Oracle almacen los registros:

select *from libros;


17 - Ingresar algunos campos

Primer problema:

Un banco tiene registrados las cuentas corrientes de sus clientes en una tabla llamada
"cuentas".

1- Elimine la tabla "cuentas":

drop table cuentas;

2- Cree la tabla :

create table cuentas(


numero number(10) not null,
documento char(8) not null,
nombre varchar2(30),
saldo number(9,2)
);

3- Ingrese un registro con valores para todos sus campos, omitiendo la lista de campos.

4- Ingrese un registro omitiendo algn campo que admita valores nulos.

5- Verifique que en tal campo se almacen "null"

6- Intente ingresar un registro listando 3 campos y colocando 4 valores. Un mensaje indica


que hay demasiados valores.
7- Intente ingresar un registro listando 3 campos y colocando 2 valores. Un mensaje indica
que no hay suficientes valores.

8- Intente ingresar un registro sin valor para un campo definido "not null".

9- Vea los registros ingresados.

drop table cuentas;

create table cuentas(


numero number(10) not null,
documento char(8) not null,
nombre varchar2(30),
saldo number(9,2)
);

insert into cuentas


values (12345,'30111111','Juan Perez',2500.50);

insert into cuentas (numero,documento,saldo)


values (23456,'28999777',-5500);

select *from cuentas;

insert into cuentas (numero,documento,nombre)


values (44444,'28999777','Luis Lopez',34000);

insert into cuentas (numero,documento,nombre)


values (44444,'28999777');

insert into cuentas (numero,nombre,saldo)


values (555,'Luis Lopez',34000);

select *from cuentas;

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.

18 - Valores por defecto (default)

Problema:

Trabajamos con la tabla "libros" de una librera.

Eliminamos la tabla:

drop table libros;

Creamos la tabla estableciendo valores por defecto para los campos "autor" y "cantidad":

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
);

Ingresamos un registro omitiendo los valores para el campo "autor" y "cantidad":

insert into libros (titulo,editorial,precio)


values('Java en 10 minutos','Paidos',50.40);

Oracle ingresar el registro con el ttulo, editorial y precio especificados, en "autor" colocar
"Desconocido" y en cantidad "0", vemoslo:

select *from libros;

Si ingresamos un registro sin valor para el campo "precio", que admite valores nulos, se
ingresar "null" en ese campo:

insert into libros (titulo,editorial)


values('Aprenda PHP','Siglo XXI');

Veamos cmo se almacen el registro ingresado anteriormente:

select *from libros;

Veamos si los campos de la tabla "libros" tiene definidos valores por defecto y cules son:

select column_name,nullable,data_default
from user_tab_columns where TABLE_NAME = 'LIBROS';

Muestra la siguiente tabla:

COLUMN_NAME NULLABLE DATA_DEFAULT


---------------------------------------------
TITULO N
AUTOR N 'Desconocido'
EDITORIAL Y
PRECIO Y
CANTIDAD Y 0

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 permite valores nulos.

Podemos emplear "default" para dar el valor por defecto a algunos campos al ingresar un
registro:

insert into libros (titulo,autor,editorial,precio,cantidad)


values ('El gato con botas',default,default,default,default);

Veamos cmo se almacen el registro:

select *from libros where titulo='El gato con botas';

Todos los campos, excepto "titulo" almacenaron su valor predeterminado.

Que un campo tenga valor por defecto no significa que no admita valores nulos, puede o no
admitirlos. Podemos ingresar el valor "null" en el campo "cantidad":

insert into libros (titulo,autor,cantidad)


values ('Alicia en el pais de las maravillas','Lewis Carroll',null);

Recuperamos el registro ingresado anteriormente:

select *from libros where autor='Lewis Carroll';

En "cantidad" se almacen "null".

18 - Valores por defecto (default)

Primer problema:

Un comercio que tiene un stand en una feria registra en una tabla llamada "visitantes" algunos
datos de las personas que visitan o compran en su stand para luego enviarle publicidad de sus
productos.

1- Elimine la tabla "visitantes"

2- Cree la tabla con la siguiente estructura:

create table visitantes(


nombre varchar2(30),
edad number(2),
sexo char(1) default 'f',
domicilio varchar2(30),
ciudad varchar2(20) default 'Cordoba',
telefono varchar(11),
mail varchar(30) default 'no tiene',
montocompra number (6,2)
);

4- Analice la informacin que retorna la siguiente consulta:


select column_name,nullable,data_default
from user_tab_columns where TABLE_NAME = 'VISITANTES';

Todos los campos admiten valores nulos; hay 3 campos con valores predeterminados.

5- Ingrese algunos registros sin especificar valores para algunos campos para ver cmo opera
la clusula "default":

insert into visitantes (domicilio,ciudad,telefono,mail,montocompra)


values ('Colon 123','Cordoba','4334455','juanlopez@hotmail.com',59.80);
insert into visitantes (nombre,edad,sexo,telefono,mail,montocompra)
values ('Marcos Torres',29,'m','4112233','marcostorres@hotmail.com',60);
insert into visitantes (nombre,edad,sexo,domicilio,ciudad)
values ('Susana Molina',43,'f','Bulnes 345','Carlos Paz');

6- Recupere todos los registros.

Los campos de aquellos registros para los cuales no se ingres valor almacenaron el valor por
defecto ("null" o el especificado con "default").

7- Use la palabra "default" para ingresar valores en un "insert"

8- Recupere el registro anteriormente ingresado.

drop table visitantes;

create table visitantes(


nombre varchar2(30),
edad number(2),
sexo char(1) default 'f',
domicilio varchar2(30),
ciudad varchar2(20) default 'Cordoba',
telefono varchar(11),
mail varchar(30) default 'no tiene',
montocompra number (6,2)
);

select column_name,nullable,data_default
from user_tab_columns where TABLE_NAME = 'VISITANTES';

insert into visitantes (domicilio,ciudad,telefono,mail,montocompra)


values ('Colon 123','Cordoba','4334455','juanlopez@hotmail.com',59.80);
insert into visitantes (nombre,edad,sexo,telefono,mail,montocompra)
values ('Marcos Torres',29,'m','4112233','marcostorres@hotmail.com',60);
insert into visitantes (nombre,edad,sexo,domicilio,ciudad)
values ('Susana Molina',43,'f','Bulnes 345','Carlos Paz');

select *from visitantes;

insert into visitantes


values ('Marcela Morales',default,default,'Avellaneda
292',default,'4255232',default,default);
select *from visitantes where nombre='Marcela Morales';

Segundo problema:

Una pequea biblioteca de barrio registra los prstamos de sus libros en una tabla llamada
"prestamos". En ella almacena la siguiente informacin: ttulo del libro, documento de
identidad del socio a quien se le presta el libro, fecha de prstamo, fecha en que tiene que
devolver el libro y si el libro ha sido o no devuelto.

1- Elimine la tabla "prestamos"

2- Cree la tabla:

create table prestamos(


titulo varchar2(40) not null,
documento char(8) not null,
fechaprestamo date not null,
fechadevolucion date,
devuelto char(1) default 'n'
);

3- Consulte "user_tab_columns" y analice la informacin.


Hay 3 campos que no admiten valores nulos y 1 solo campo con valor por defecto.

4- Ingrese algunos registros omitiendo el valor para los campos que lo admiten.

5- Seleccione todos los registros.

6- Ingrese un registro colocando "default" en los campos que lo admiten y vea cmo se
almacen.

7- Intente ingresar un registro colocando "default" como valor para un campo que no admita
valores nulos y no tenga definido un valor por defecto.

drop table prestamos;

create table prestamos(


titulo varchar2(40) not null,
documento char(8) not null,
fechaprestamo date not null,
fechadevolucion date,
devuelto char(1) default 'n'
);

select column_name,nullable,data_default
from user_tab_columns where TABLE_NAME = 'PRESTAMOS';

insert into prestamos (titulo,documento,fechaprestamo,fechadevolucion)


values ('Manual de 1 grado','23456789','15/12/2007','18/12/2007');
insert into prestamos (titulo,documento,fechaprestamo)
values ('Alicia en el pais de las maravillas','23456789','16/12/2007');

select *from prestamos;

insert into prestamos


values('Manual de historia','32555666','25/10/2007',default,default);

select *from prestamos;

insert into prestamos values('Manual de


aritmetica',default,'10/10/2007','12/10/2007','s');

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;
19 - Operadores aritmticos y de concatenacin (columnas
calculadas)

Problema:

Trabajamos con la tabla "libros" de una librera.

Eliminamos la tabla:

drop table libros;

Creamos la tabla:

create table libros(


codigo number(5),
titulo varchar2(40) not null,
autor varchar2(20) default 'Desconocido',
editorial varchar2(20),
precio number(6,2),
cantidad number(4) default 0,
primary key (codigo)
);

Ingresamos algunos registros:

insert into libros (codigo,titulo,autor,editorial,precio)


values(1,'El aleph','Borges','Emece',25);
insert into libros
values(2,'Java en 10 minutos','Mario Molina','Siglo XXI',50.40,100);
insert into libros (codigo,titulo,autor,editorial,precio,cantidad)
values(3,'Alicia en el pais de las maravillas','Lewis
Carroll','Emece',15,50);

Queremos saber el monto total en dinero de cada libro:

select titulo, precio,cantidad,


precio*cantidad
from libros;

Queremos saber el precio de cada libro con un 10% de descuento:

select titulo,precio,
precio-(precio*0.1)
from libros;

Actualizamos los precios con un 10% de descuento y vemos el resultado:

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


select *from libros;

Queremos una columna con el ttulo y autor de cada libro:

select titulo||'-'||autor
from libros;

Mostramos el ttulo y precio de cada libro concatenados:

select titulo||' $'||precio


from libros;
19 - Operadores aritmticos y de concatenacin (columnas
calculadas)

Primer problema:

Un comercio que vende artculos de computacin registra los datos de sus artculos en una
tabla con ese nombre.

1- Elimine la tabla:

drop table articulos;

2- Cree la tabla:

create table articulos(


codigo number(4),
nombre varchar2(20),
descripcion varchar2(30),
precio number(8,2),
cantidad number(3) default 0,
primary key (codigo)
);

3- Ingrese algunos registros:

insert into articulos


values (101,'impresora','Epson Stylus C45',400.80,20);
insert into articulos
values (203,'impresora','Epson Stylus C85',500,30);
insert into articulos
values (205,'monitor','Samsung 14',800,10);
insert into articulos
values (300,'teclado','ingles Biswal',100,50);

4- El comercio quiere aumentar los precios de todos sus artculos en un 15%. Actualice todos
los precios empleando operadores aritmticos.

5- Vea el resultado.
6- Muestre todos los artculos, concatenando el nombre y la descripcin de cada uno de ellos
separados por coma.

7- Reste a la cantidad de todas las impresoras, el valor 5, empleando el operador aritmtico


menos ("-")

8- Recupere todos los datos de las impresoras para verificar que la actualizacin se realiz.

9- Muestre todos los artculos concatenado los campos para que aparezcan de la siguiente
manera "Cod. 101: impresora Epson Stylus C45 $460,92 (15)"

drop table articulos;

create table articulos(


codigo number(4),
nombre varchar2(20),
descripcion varchar2(30),
precio number(8,2),
cantidad number(3) default 0,
primary key (codigo)
);

insert into articulos


values (101,'impresora','Epson Stylus C45',400.80,20);
insert into articulos
values (203,'impresora','Epson Stylus C85',500,30);
insert into articulos
values (205,'monitor','Samsung 14',800,10);
insert into articulos
values (300,'teclado','ingles Biswal',100,50);

update articulos set precio=precio+(precio*0.15);

select *from articulos;


select nombre||','||descripcion
from articulos;

update articulos set cantidad=cantidad-5


where nombre='impresora';

select *from articulos where nombre='impresora';

select 'Cod. '||codigo||': '||nombre||' '||descripcion||' $'||precio||' ('||cantidad||')';


from articulos;

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.

20 - Alias (encabezados de columnas)

Problema:

Trabajamos con nuestra tabla "libros".

Eliminamos la tabla:

drop table libros;

Creamos la tabla:

create table libros(


titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(5,2),
cantidad number(4)
);

Ingresamos algunos registros:

insert into libros


values('Uno','Richard Bach','Planeta',15,100);
insert into libros
values('El aleph','Borges','Emece',24,150);
insert into libros
values('Matematica estas ahi','Paenza','Nuevo siglo',12.5,200);
Mostramos la informacin con el encabezado "stock" para el campo "cantidad":

select titulo,
cantidad as stock,
precio
from libros;

Mostramos la informacin con el encabezado "stock disponible" para el campo "cantidad",


necesitamos emplear comillas dobles:

select titulo,
cantidad as "stock disponible",
precio
from libros;

Recuperamos el ttulo, autor, precio, descuento del 10% y precio final con descuento,
empleando un alias para las 2 ltimas columnas:

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

La palabra clave "as" es opcional, podemos obviarla:

select titulo,precio,
precio-(precio*0.1) "precio con descuento"
from libros;
20 - Alias (encabezados de columnas)

Primer problema:

Un comercio que vende artculos de computacin registra los datos de sus artculos en una
tabla con ese nombre.

1- Elimine la tabla:

drop table articulos;

2- Cree la tabla:

create table articulos(


codigo number(4),
nombre varchar2(20),
descripcion varchar2(30),
precio number(8,2),
cantidad number(3) default 0,
primary key (codigo)
);

3- Ingrese algunos registros:

insert into articulos


values (101,'impresora','Epson Stylus C45',400.80,20);
insert into articulos
values (203,'impresora','Epson Stylus C85',500,30);
insert into articulos
values (205,'monitor','Samsung 14',800,10);
insert into articulos
values (300,'teclado','ingles Biswal',100,50);

4- El comercio hace un descuento del 15% en ventas mayoristas. Necesitamos recuperar el


cdigo, nombre, decripcin de todos los artculos con una columna extra que muestre el
precio de cada artculo para la venta mayorista con el siguiente encabezado "precio
mayorista"

5- Muestre los precios de todos los artculos, concatenando el nombre y la descripcin con el
encabezado "artculo" (sin emplear "as" ni comillas)

6- Muestre todos los campos de los artculos y un campo extra, con el encabezado "monto
total" en la que calcule el monto total en dinero de cada artculo (precio por cantidad)

7- Muestre la descripcin de todas las impresoras junto al precio con un 20% de recargo con
un encabezado que lo especifique.

drop table articulos;

create table articulos(


codigo number(4),
nombre varchar2(20),
descripcion varchar2(30),
precio number(8,2),
cantidad number(3) default 0,
primary key (codigo)
);

insert into articulos


values (101,'impresora','Epson Stylus C45',400.80,20);
insert into articulos
values (203,'impresora','Epson Stylus C85',500,30);
insert into articulos
values (205,'monitor','Samsung 14',800,10);
insert into articulos
values (300,'teclado','ingles Biswal',100,50);

select codigo, nombre, descripcion, precio-(precio*.15) as "precio mayorista"


from articulos;

select nombre||' '||descripcion artculo, precio


from articulos;

select codigo,nombre,descripcion, precio, cantidad,


precio*cantidad "Monto Total"
from articulos;

select descripcion, precio+(precio*.2) as recargado


from articulos;
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.

21 - Funciones string

Problema:

Trabajamos con la tabla "libros" de una librera.

Eliminamos la tabla:

drop table libros;

Creamos la tabla:

create table libros(


codigo number(5),
titulo varchar2(40) not null,
autor varchar2(20) default 'Desconocido',
editorial varchar2(20),
precio number(6,2),
cantidad number(3)
);

Ingresamos algunos registros:

insert into libros


values(1,'El aleph','Borges','Emece',25,100);
insert into libros
values(2,'Java en 10 minutos','Mario Molina','Siglo XXI',50.40,100);
insert into libros
values(3,'Alicia en el pais de las maravillas','Lewis
Carroll','Emece',15.50,200);
insert into libros
values(4,'El pais de las hadas',default,'Emece',25.50,150);

Mostramos slo los 12 primeros caracteres de los ttulos de los libros y sus autores, empleando
la funcin "substr":

select substr(titulo,1,12) as titulo


from libros;

Mostramos slo los 20 primeros caracteres de los ttulos de los libros y rellenando los espacios
restantes con "*", empleando la funcin "rpad":

select rpad(titulo,20,'*') as titulo


from libros;

Mostramos los ttulos de los libros empleando la funcin "initcap":

select initcap(titulo) as titulo


from libros;
Note que cada palabra comienza con maysculas.

Mostramos los ttulos de los libros y sus autores en maysculas:

select titulo,upper(autor) as autor


from libros;

Concatenamos ttulo y autor empleando "concat":

select concat(titulo, autor)


from libros;

Mostramos el ttulo y el precio de todos los libros concatenando el signo "$" a los precios:

select titulo,concat('$ ',precio) as precio


from libros;

Recuperamos el ttulo y editorial de "libros" reemplazando "Emece" por "Sudamericana":

select titulo,replace(editorial,'Emece','Sudamericana')
from libros;

Recuperamos el autor de todos los libros reemplazando las letras "abc" por "ABC"
respectivamente (empleando "translate"):

select translate(autor,'abc','ABC') from libros;

Note que cada caracter individual es reemplazado por el especificado.

Mostramos la posicin de la primera ocurrencia de la cadena "pais" en los ttulos de los libros:

select instr(titulo,'pais') from libros;

Note que los ttulos que no contienen la subcadena "pais" muestran el valor cero.

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 trunc(1234.5678,2) from dual;--retorna 1234.56


select trunc(1234.5678,-2) from dual;--retorna 1200
select trunc(1234.5678,-1) from dual;--retorna 1230
select 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.
22 - Funciones matemticas.

Problema:

Una empresa almacena los datos de sus empleados en una tabla denominada "empleados".

Eliminamos la tabla:

drop table empleados;

Creamos la tabla:

create table empleados(


legajo number(5),
documento char(8) not null,
nombre varchar2(30) not null,
domicilio varchar2(30),
sueldo number(6,2),
hijos number(2),
primary key (legajo)
);

Ingresamos algunos registros:

insert into empleados


values(1,'22333444','Ana Acosta','Avellaneda 213',870.79,2);
insert into empleados
values(20,'27888999','Betina Bustos','Bulnes 345',950.85,1);
insert into empleados
values(31,'30111222','Carlos Caseres','Caseros 985',1190,0);
insert into empleados
values(39,'33444555','Daniel Duarte','Dominicana 345',1250.56,3);

Vamos a mostrar los sueldos de los empleados redondeando el valor hacia abajo y luego hacia
arriba (empleamos "floor" y "ceil"):

select floor(sueldo) as "sueldo hacia abajo",


ceil(sueldo) as "sueldo hacia arriba"
from empleados;

Mostramos los nombre de cada empleado, su respectivo sueldo, y el sueldo redondeando el


valor a entero ("round") y truncado a entero ("trunc"):

select nombre, sueldo, round(sueldo) as "sueldo redondeado",


trunc(sueldo) as "sueldo truncado"
from empleados;

Note que los valores devueltos segn la funcin empleada, son diferentes.

Mostramos el resultado de "2 elevado a la potencia 5" ("power"):

select power(2,5) from dual;

Retorna el valor 32.

Mostramos el resto de la divisin "1234 / 5" ("mod"):


select mod(1234,5) from dual;

Devuelve el valor 4.

Calculamos la raz cuadrada de 81:

select sqrt(81) from dual;

Retorna 9.

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.

23 - Funciones de fechas y horas

Problema:

Trabajamos con la tabla "libros" de una librera.

Eliminamos la tabla:

drop table libros;

Creamos la tabla:

create table libros(


titulo varchar2(40) not null,
autor varchar2(20) default 'Desconocido',
editorial varchar2(20),
edicion date,
precio number(6,2)
);
Ingresamos algunos registros:

insert into libros values('El


aleph','Borges','Emece','10/10/1980',25.33);
insert into libros values('Java en 10 minutos','Mario Molina','Siglo
XXI','05/05/2000',50.65);
insert into libros
values('Alicia en el pais de las maravillas','Lewis
Carroll','Emece','08/09/2000',19.95);
insert into libros values('Aprenda PHP','Mario Molina','Siglo
XXI','02/04/2000',45);

Mostramos el ttulo del libro y el ao de edicin:

select titulo, extract (year from edicion) from libros;

Mostramos el ttulo del libro y el mes de edicin:

select titulo, extract (month from edicion) from libros;

Mostramos el ttulo del libro y los aos que tienen de editados:

select titulo, extract(year from sysdate)-extract(year from edicion)


as "aos de editado"
from libros;

Mostramos los ttulos de los libros que se editaron en el ao 2000:

select titulo from libros


where extract(year from edicion)=2000;

Calcule 3 meses luego de la fecha actual empleando ""add_months":

select add_months(sysdate,3) from dual;

Muestre la fecha del primer martes desde la fecha actual:

select next_day(sysdate,'martes') from dual;

Muestre la fecha que ser 15 das despus de "24/08/2007" empleando el operador "+":

select to_date('24/08/2007')+15 from dual;

Retorna 08/09/07.

Muestre la fecha que 20 das antes del "12/08/2007" empleando el operador "-":

select to_date('12/08/2007')-20 from dual;

Retorna 23/07/07.

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.

24 - Ordenar registros (order by)

Primer problema:

En una pgina web se guardan los siguientes datos de las visitas: nombre, mail, pais y fecha.
1- Elimine la tabla "visitas" y crela con la siguiente estructura:

drop table visitas;


create table visitas (
nombre varchar2(30) default 'Anonimo',
mail varchar2(50),
pais varchar2(20),
fecha date
);

3- Ingrese algunos registros:

insert into visitas values ('Ana Maria


Lopez','AnaMaria@hotmail.com','Argentina','10/10/2006 10:10');
insert into visitas values ('Gustavo
Gonzalez','GustavoGGonzalez@hotmail.com','Chile','10/10/2006 21:30');
insert into visitas values
('Juancito','JuanJosePerez@hotmail.com','Argentina','11/10/2006 15:45');
insert into visitas values ('Fabiola
Martinez','MartinezFabiola@hotmail.com','Mexico','12/10/2006 08:15');
insert into visitas values ('Fabiola
Martinez','MartinezFabiola@hotmail.com','Mexico','12/09/2006 20:45');
insert into visitas values
('Juancito','JuanJosePerez@hotmail.com','Argentina','12/09/2006 16:20');
insert into visitas values
('Juancito','JuanJosePerez@hotmail.com','Argentina','15/09/2006 16:25');

4- Ordene los registros por fecha, en orden descendente.

5- Muestre el nombre del usuario, pais y el mes, ordenado por pais (ascendente) y el mes
(descendente)

6- Muestre los mail, pas, ordenado por pas, de todos los que visitaron la pgina en octubre
(4 registros)

drop table visitas;


create table visitas (
nombre varchar2(30) default 'Anonimo',
mail varchar2(50),
pais varchar2(20),
fecha date
);

insert into visitas values ('Ana Maria


Lopez','AnaMaria@hotmail.com','Argentina','10/10/2006 10:10');
insert into visitas values ('Gustavo
Gonzalez','GustavoGGonzalez@hotmail.com','Chile','10/10/2006 21:30');
insert into visitas values
('Juancito','JuanJosePerez@hotmail.com','Argentina','11/10/2006 15:45');
insert into visitas values ('Fabiola
Martinez','MartinezFabiola@hotmail.com','Mexico','12/10/2006 08:15');
insert into visitas values ('Fabiola
Martinez','MartinezFabiola@hotmail.com','Mexico','12/09/2006 20:45');
insert into visitas values
('Juancito','JuanJosePerez@hotmail.com','Argentina','12/09/2006 16:20');
insert into visitas values
('Juancito','JuanJosePerez@hotmail.com','Argentina','15/09/2006 16:25');

select *from visitas


order by fecha desc;

select nombre,pais,extract(month from fecha)


from visitas
order by 1,3 desc;

select mail, pais


from visitas
where extract(month from fecha)=10
order by 2;

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 con

25 - Operadores lgicos (and - or - not)

Problema:

Trabajamos con la tabla "libros" de una librera.

Eliminamos la tabla y la creamos:

drop table libros;

create table libros(


codigo number(5),
titulo varchar2(40) not null,
autor varchar2(20) default 'Desconocido',
editorial varchar2(20),
precio number(6,2)
);

Ingresamos algunos registros:

insert into libros


values(1,'El aleph','Borges','Emece',15.90);
insert into libros
values(2,'Antologa potica','Borges','Planeta',39.50);
insert into libros
values(3,'Java en 10 minutos','Mario Molina','Planeta',50.50);
insert into libros
values(4,'Alicia en el pais de las maravillas','Lewis
Carroll','Emece',19.90);
insert into libros
values(5,'Martin Fierro','Jose Hernandez','Emece',25.90);
insert into libros
values(6,'Martin Fierro','Jose Hernandez','Paidos',16.80);
insert into libros
values(7,'Aprenda PHP','Mario Molina','Emece',19.50);
insert into libros
values(8,'Cervantes y el quijote','Borges','Paidos',18.40);

Recuperamos los libros cuyo autor sea igual a "Borges" y cuyo precio no supere los 20 pesos:

select *from libros


where (autor='Borges') and
(precio<=20);

Aparecen 2 libros, los nicos que cumplen con ambas condiciones.

Seleccionamos los libros cuyo autor es "Borges" y/o cuya editorial es "Planeta":

select *from libros


where autor='Borges' or
editorial='Planeta';

Note que aparecen todos los libros de "Borges" y todos los libros de "Planeta", algunos
cumplen ambas condiciones.

Recuperamos los libros cuya editorial NO es "Planeta":

select *from libros


where not editorial='Planeta';

Veamos un ejemplo de cmo el empleo de parntesis permite a Oracle evaluar en forma


diferente ciertas consultas aparentemente iguales:

select *from libros


where (autor='Borges') or
(editorial='Paidos' and precio<20);

select *from libros


where (autor='Borges' or editorial='Paidos') and
(precio<20);

Note que el primer resultado retorna todos los libros de "Borges" (primera condicin) y todos
los libros de "Paidos" con precio inferior a 20 (segunda condicin) (registros 1,2,6 y 8); la
segunda recupera todos los libros de "Borges" o de "Paidos" (primera condicin) cuyo precio
sea inferior a 20 (segunda condicin) (registros 1,6 y 8).

dicin especificada.

25 - Operadores lgicos (and - or - not)

Primer problema:

Trabaje con la tabla llamada "medicamentos" de una farmacia.

1- Elimine la tabla y crela con la siguiente estructura:

drop table medicamentos;


create table medicamentos(
codigo number(5),
nombre varchar2(20),
laboratorio varchar2(20),
precio number(5,2),
cantidad number(3),
primary key(codigo)
);

3- Ingrese algunos registros:

insert into medicamentos values(100,'Sertal','Roche',5.2,100);


insert into medicamentos values(102,'Buscapina','Roche',4.10,200);
insert into medicamentos values(205,'Amoxidal 500','Bayer',15.60,100);
insert into medicamentos values(230,'Paracetamol 500','Bago',1.90,200);
insert into medicamentos values(345,'Bayaspirina','Bayer',2.10,150);
insert into medicamentos values(347,'Amoxidal jarabe','Bayer',5.10,250);

4- Recupere los cdigos y nombres de los medicamentos cuyo laboratorio sea "Roche' y cuyo
precio sea menor a 5 (1 registro cumple con ambas condiciones)

5- Recupere los medicamentos cuyo laboratorio sea "Roche" o cuyo precio sea menor a 5 (4
registros)

6- Muestre todos los medicamentos cuyo laboratorio NO sea "Bayer" y cuya cantidad sea=100.
Luego muestre todos los medicamentos cuyo laboratorio sea "Bayer" y cuya cantidad NO
sea=100

7- Recupere los nombres de los medicamentos cuyo precio est entre 2 y 5 inclusive (2
registros)

8- Elimine todos los registros cuyo laboratorio sea igual a "Bayer" y su precio sea mayor a 10 (1
registro eliminado)

9- Cambie la cantidad por 200, de todos los medicamentos de "Roche" cuyo precio sea mayor
a 5 (1 registro afectado)

10- Muestre todos los registros para verificar el cambio.

11- Borre los medicamentos cuyo laboratorio sea "Bayer" o cuyo precio sea menor a 3 (3
registros borrados)
Ver solucin

Segundo problema:

Trabajamos con la tabla "peliculas" de un video club que alquila pelculas en video.

1- Elimine la tabla y crela con la siguiente estructura:

drop table peliculas;

create table peliculas(


codigo number(4),
titulo varchar2(40) not null,
actor varchar2(20),
duracion number(3),
primary key (codigo)
);

3- Ingrese algunos registros:

insert into peliculas


values(1020,'Mision imposible','Tom Cruise',120);
insert into peliculas
values(1021,'Harry Potter y la piedra filosofal','Daniel R.',180);
insert into peliculas
values(1022,'Harry Potter y la camara secreta','Daniel R.',190);
insert into peliculas
values(1200,'Mision imposible 2','Tom Cruise',120);
insert into peliculas
values(1234,'Mujer bonita','Richard Gere',120);
insert into peliculas
values(900,'Tootsie','D. Hoffman',90);
insert into peliculas
values(1300,'Un oso rojo','Julio Chavez',100);
insert into peliculas
values(1301,'Elsa y Fred','China Zorrilla',110);

4- Recupere los registros cuyo actor sea "Tom Cruise" o "Richard Gere" (3 registros)

5- Recupere los registros cuyo actor sea "Tom Cruise" y duracin menor a 100 (ninguno cumple
ambas condiciones)

6- Recupere los nombres de las pelculas cuya duracin se encuentre entre 100 y 120
minutos(5 registros)

7- Cambie la duracin a 200, de las pelculas cuyo actor sea "Daniel R." y cuya duracin sea
180 (1 registro afectado)

8- Recupere todos los registros para verificar la actualizacin anterior

9- Borre todas las pelculas donde el actor NO sea "Tom Cruise" y cuya duracin sea mayor o
igual a 100 (2 registros eliminados)
drop table peliculas;

create table peliculas(


codigo number(4),
titulo varchar2(40) not null,
actor varchar2(20),
duracion number(3),
primary key (codigo)
);

insert into peliculas


values(1020,'Mision imposible','Tom Cruise',120);
insert into peliculas
values(1021,'Harry Potter y la piedra filosofal','Daniel R.',180);
insert into peliculas
values(1022,'Harry Potter y la camara secreta','Daniel R.',190);
insert into peliculas
values(1200,'Mision imposible 2','Tom Cruise',120);
insert into peliculas
values(1234,'Mujer bonita','Richard Gere',120);
insert into peliculas
values(900,'Tootsie','D. Hoffman',90);
insert into peliculas
values(1300,'Un oso rojo','Julio Chavez',100);
insert into peliculas
values(1301,'Elsa y Fred','China Zorrilla',110);

select *from peliculas


where actor='Tom Cruise' or
actor='Richard Gere';

select *from peliculas


where actor='Tom Cruise' and
duracion<100;

select titulo from peliculas


where duracion>=100 and
duracion<=120;

update peliculas set duracion=200


where actor='Daniel R.' and
duracion=180;

select *from peliculas;

delete from peliculas


where not actor='Tom Cruise' and
duracion<=100;

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".

26 - Otros operadores relacionales (between)

Problema:

Trabajamos con la tabla "libros" de una librera.

Eliminamos la tabla y la creamos con la siguiente estructura:

drop table libros;

create table libros(


codigo number(5) not null,
titulo varchar2(40) not null,
autor varchar2(20) default 'Desconocido',
editorial varchar2(20),
edicion date,
precio number(6,2)
);
Ingresamos algunos registros:

insert into libros


values(1,'El aleph','Borges','Emece','15/01/2000',15.90);
insert into libros
values(2,'Cervantes y el quijote','Borges','Paidos',null,null);
insert into libros
values(3,'Alicia en el pais de las maravillas','Lewis
Carroll',null,'25/03/2000',19.90);
insert into libros
values(4,'Martin Fierro','Jose
Hernandez','Emece','18/05/2000',25.90);
insert into libros (codigo,titulo,autor,edicion,precio)
values(5,'Antologa potica','Borges','25/08/2000',32);
insert into libros (codigo,titulo,autor,edicion,precio)
values(6,'Java en 10 minutos','Mario Molina','11/02/2007',45.80);
insert into libros (codigo,titulo,autor,edicion,precio)
values(7,'Martin Fierro','Jose Hernandez','23/11/2006',40);
insert into libros (codigo,titulo,autor,edicion,precio)
values(8,'Aprenda PHP','Mario Molina','01/06/2007',56.50);

Recuperamos los registros cuyo precio est entre 20 y 40 empleando "between":

select *from libros


where precio between 20 and 40;

Note que si el campo tiene el valor "null", no aparece en la seleccin.

Para seleccionar los libros cuyo precio NO est entre un intervalo de valores antecedemos
"not" al "between":

select *from libros


where precio not between 20 and 40;

Note que si el campo tiene el valor "null", no aparece en la seleccin.

Recuperamos los ttulos y edicin de los libros cuya fecha de edicin se encuentre entre
'01/05/2000' y '01/05/2007', ordenados por fecha de edicin:

select titulo, edicion from libros


where edicion between '01/05/2000' and '01/05/2007'
order by edicion;
26 - Otros operadores relacionales (between)

Primer problema:

En una pgina web se guardan los siguientes datos de las visitas: nmero de visita, nombre,
mail, pais, fechayhora de la visita.

1- Elimine la tabla "visitas" y crela con la siguiente estructura:

drop table visitas;

create table visitas (


nombre varchar2(30) default 'Anonimo',
mail varchar2(50),
pais varchar2(20),
fecha date
);

2- Ingrese algunos registros:

insert into visitas


values ('Ana Maria Lopez','AnaMaria@hotmail.com','Argentina','10/10/2006');
insert into visitas
values ('Gustavo
Gonzalez','GustavoGGonzalez@gotmail.com','Chile','10/10/2006');
insert into visitas
values ('Juancito','JuanJosePerez@hotmail.com','Argentina','11/10/2006');
insert into visitas
values ('Fabiola Martinez','MartinezFabiola@hotmail.com','Mexico','12/10/2006');
insert into visitas
values ('Fabiola Martinez','MartinezFabiola@hotmail.com','Mexico','12/09/2006');
insert into visitas
values ('Juancito','JuanJosePerez@gmail.com','Argentina','12/09/2006');
insert into visitas
values ('Juancito','JuanJosePerez@hotmail.com','Argentina','15/09/2006');
insert into visitas
values ('Federico1','federicogarcia@xaxamail.com','Argentina',null);

3- Seleccione los usuarios que visitaron la pgina entre el '12/09/2006' y '11/10/2006' (6


registros)
Note que incluye los de fecha mayor o igual al valor mnimo y menores o iguales al valor
mximo, y que los valores nulos no se incluyen.

drop table visitas;

create table visitas (


nombre varchar2(30) default 'Anonimo',
mail varchar2(50),
pais varchar2(20),
fecha date
);

insert into visitas


values ('Ana Maria Lopez','AnaMaria@hotmail.com','Argentina','10/10/2006');
insert into visitas
values ('Gustavo
Gonzalez','GustavoGGonzalez@gotmail.com','Chile','10/10/2006');
insert into visitas
values ('Juancito','JuanJosePerez@hotmail.com','Argentina','11/10/2006');
insert into visitas
values ('Fabiola Martinez','MartinezFabiola@hotmail.com','Mexico','12/10/2006');
insert into visitas
values ('Fabiola Martinez','MartinezFabiola@hotmail.com','Mexico','12/09/2006');
insert into visitas
values ('Juancito','JuanJosePerez@gmail.com','Argentina','12/09/2006');
insert into visitas
values ('Juancito','JuanJosePerez@hotmail.com','Argentina','15/09/2006');
insert into visitas
values ('Federico1','federicogarcia@xaxamail.com','Argentina',null);

select *from visitas


where fecha between '12/09/2006' and '11/10/2006';

Segundo problema:

Trabaje con la tabla llamada "medicamentos" de una farmacia.

1- Elimine la tabla y crela con la siguiente estructura:

drop table medicamentos;

create table medicamentos(


codigo number(6) not null,
nombre varchar2(20),
laboratorio varchar2(20),
precio number(6,2),
cantidad number(4),
fechavencimiento date not null,
primary key(codigo)
);

2- Ingrese algunos registros:

insert into medicamentos


values(102,'Sertal','Roche',5.2,10,'01/02/2010');
insert into medicamentos
values(120,'Buscapina','Roche',4.10,200,'01/12/2007');
insert into medicamentos
values(230,'Amoxidal 500','Bayer',15.60,100,'28/12/2007');
insert into medicamentos
values(250,'Paracetamol 500','Bago',1.90,20,'01/02/2008');
insert into medicamentos
values(350,'Bayaspirina','Bayer',2.10,150,'01/12/2009');
insert into medicamentos
values(456,'Amoxidal jarabe','Bayer',5.10,250,'01/10/2010');

3- Recupere los nombres y precios de los medicamentos cuyo precio est entre 5 y 15 (2
registros)

4- Seleccione los registros cuya cantidad se encuentre entre 100 y 200 (3 registros)

5- Recupere los remedios cuyo vencimiento se encuentre entre la fecha actual y '01/01/2008'
inclusive (2 registros)

6- Elimine los remedios cuyo vencimiento se encuentre entre el ao 2007 y 2008 inclusive (3
registros)
drop table medicamentos;

create table medicamentos(


codigo number(6) not null,
nombre varchar2(20),
laboratorio varchar2(20),
precio number(6,2),
cantidad number(4),
fechavencimiento date not null,
primary key(codigo)
);

insert into medicamentos


values(102,'Sertal','Roche',5.2,10,'01/02/2010');
insert into medicamentos
values(120,'Buscapina','Roche',4.10,200,'01/12/2007');
insert into medicamentos
values(230,'Amoxidal 500','Bayer',15.60,100,'28/12/2007');
insert into medicamentos
values(250,'Paracetamol 500','Bago',1.90,20,'01/02/2008');
insert into medicamentos
values(350,'Bayaspirina','Bayer',2.10,150,'01/12/2009');
insert into medicamentos
values(456,'Amoxidal jarabe','Bayer',5.10,250,'01/10/2010');

select nombre,precio from medicamentos


where precio between 5 and 15;

select *from medicamentos


where cantidad between 100 and 200;

select *from medicamentos


where fechavencimiento between sysdate and '01/01/2008';

delete from medicamentos


where extract(year from fechavencimiento) between '2007' and '2008';

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.

27 - Otros operadores relacionales (in)

Problema:

Trabajamos con la tabla "libros" de una librera.

Eliminamos la tabla:

drop table libros;

Creamos la tabla:

create table libros(


codigo number (5),
titulo varchar2(40) not null,
autor varchar2(20),
editorial varchar2(20),
precio number(6,2)
);

Ingresamos algunos registros:

insert into libros


values(1,'El aleph','Borges','Emece',15.90);
insert into libros
values(2,'Cervantes y el quijote','Borges','Paidos',null);
insert into libros
values(3,'Alicia en el pais de las maravillas','Lewis
Carroll',null,19.90);
insert into libros
values(4,'Matematica estas ahi','Paenza','Siglo XXI',15);
insert into libros
values(5,'Antologa potica',default,default,32);
insert into libros
values(6,'Martin Fierro','Jose Hernandez',default,40);
insert into libros
values(7,'Aprenda PHP','Mario Molina',default,56.50);

Recuperamos los libros cuyo autor es "Paenza" o "Borges":


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

Note que los valores "null" no se consideran.

Recuperamos los libros cuyo autor NO es "Paenza" ni "Borges":

select *from libros


where autor not in ('Borges','Paenza');

Note que los valores "null" no se consideran.

Recuperamos los libros cuyo cdigo se encuentre en la siguiente lista de valores (1,3,5,7,9):

select *from libros


where codigo in (1,3,5,7,9);
27 - Otros operadores relacionales (in)

Primer problema:

Trabaje con la tabla llamada "medicamentos" de una farmacia.

1- Elimine la tabla y crela con la siguiente estructura:

drop table medicamentos;

create table medicamentos(


codigo number(5),
nombre varchar2(20),
laboratorio varchar2(20),
precio number(6,2),
cantidad number(3) not null,
fechavencimiento date not null,
primary key(codigo)
);

3- Ingrese algunos registros:

insert into medicamentos


values(100,'Sertal','Roche',5.2,1,'01/02/2005');
insert into medicamentos
values(230,'Buscapina',null,4.10,3,'01/03/2006');
insert into medicamentos
values(280,'Amoxidal 500','Bayer',15.60,100,'01/05/2007');
insert into medicamentos
values(301,'Paracetamol 500','Bago',1.90,10,'01/02/2008');
insert into medicamentos
values(400,'Bayaspirina','Bayer',2.10,150,'01/08/2009');
insert into medicamentos
values(560,'Amoxidal jarabe','Bayer',5.10,250,'01/10/2010');

4- Recupere los nombres y precios de los medicamentos cuyo laboratorio sea "Bayer" o "Bago"
empleando el operador "in" (4 registros)
5- Recupere los nombres y precios de los medicamentos cuyo laboratorio NO sea "Bayer" o
"Bago" empleando el operador "in" (1 registro)
Note que los valores nulos no se incluyen.

6- Seleccione los remedios cuya cantidad se encuentre entre 1 y 5 empleando el operador


"between" y luego el operador "in" (2 registros)
Note que es ms conveniente emplear, en este caso, el operador "between", simplifica la
consulta.

7- Recupere los registros cuyas fechas de vencimiento se encuentra entre enero de 2005 y
enero del 2007 (emplee el operador apropiado) (2 registros)

8- Recupere los registros cuyo ao de vencimiento sea 2005 o 2006 (emplee el operador
apropiado) (2 registros)

drop table medicamentos;

create table medicamentos(


codigo number(5),
nombre varchar2(20),
laboratorio varchar2(20),
precio number(6,2),
cantidad number(3) not null,
fechavencimiento date not null,
primary key(codigo)
);

insert into medicamentos


values(100,'Sertal','Roche',5.2,1,'01/02/2005');
insert into medicamentos
values(230,'Buscapina',null,4.10,3,'01/03/2006');
insert into medicamentos
values(280,'Amoxidal 500','Bayer',15.60,100,'01/05/2007');
insert into medicamentos
values(301,'Paracetamol 500','Bago',1.90,10,'01/02/2008');
insert into medicamentos
values(400,'Bayaspirina','Bayer',2.10,150,'01/08/2009');
insert into medicamentos
values(560,'Amoxidal jarabe','Bayer',5.10,250,'01/10/2010');

select nombre,precio from medicamentos


where laboratorio in ('Bayer','Bago');

select nombre,precio from medicamentos


where laboratorio not in ('Bayer','Bago');

select *from medicamentos


where cantidad between 1 and 5;
select *from medicamentos
where cantidad in (1,2,3,4,5);

select *from medicamentos


where fechavencimiento between '01/01/2005' and '01/01/2007';
select *from medicamentos
where extract(year from fechavencimiento) in (2005,2006);

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".

28 - Bsqueda de patrones (like - not like)

Problema:

Trabajamos con la tabla "libros" de una librera.

Eliminamos la tabla:

drop table libros;

Creamos la tabla:

create table libros(


titulo varchar2(40),
autor varchar2(20) default 'Desconocido',
editorial varchar2(20),
edicion date,
precio number(6,2)
);

Ingresamos algunos registros:

insert into libros


values('El aleph','Borges','Emece','12/05/2005',15.90);
insert into libros
values('Antologa potica','J. L.
Borges','Planeta','16/08/2000',null);
insert into libros
values('Alicia en el pais de las maravillas','Lewis
Carroll',null,'25/04/2000',19.90);
insert into libros
values('Matematica estas ahi','Paenza','Siglo XXI','21/12/2006',15);
insert into libros
values('Martin Fierro','Jose Hernandez',default,'22/09/2001',40);
insert into libros
values('Aprenda PHP','Mario Molina','Nuevo
siglo','22/05/1999',56.50);
insert into libros
values(null,'Mario Molina','Nuevo siglo',null,45);

Recuperamos todos los libros que contengan en el campo "autor" la cadena "Borges":

select *from libros


where autor like '%Borges%';

Seleccionamos los libros cuyos ttulos comienzan con la letra "M":

select *from libros


where titulo like 'M%';

Note que los valores nulos no se incluyen en la bsqueda.

Seleccionamos todos los ttulos que NO comienzan con "M":

select *from libros


where titulo not like 'M%';

Si queremos ver los libros de "Lewis Carroll" pero no recordamos si se escribe "Carroll" o
"Carrolt", podemos emplear el comodn "_" (guin bajo) y establecer la siguiente condicin:

select *from libros


where autor like '%Carrol_';

Recuperamos todos los libros que contengan en el campo "edicion", en la parte


correspondiente al mes, la cadena "05":

select titulo,edicion from libros


where edicion like '__/05%';

Note que especificamos que los 2 primeros caracteres (2 guiones bajos) pueden ser cualquier
caracter, luego una barra seguida de "05" y que finalice con cualquier nmero de caracteres.

Recuperamos todos los libros cuyo precio se encuentra entre 10.00 y 19.99:

select titulo,precio from libros


where precio like '1_,%';

Note que especificamos que el segundo caracter (1 guin bajo) puede ser cualquier valor,
luego una coma y que finalice con cualquier nmero de caracteres.

Recuperamos los libros que NO incluyen centavos en sus precios:

select titulo,precio from libros


where precio not like '%,%';
28 - Bsqueda de patrones (like - not like)

Primer problema:
Una empresa almacena los datos de sus empleados en una tabla "empleados".

1- Elimine la tabla:

drop table empleados;

2- Cree la tabla:

create table empleados(


nombre varchar2(30),
documento char(8) not null,
domicilio varchar2(30),
fechaingreso date,
seccion varchar2(20),
sueldo number(6,2),
primary key(documento)
);

3- Ingrese algunos registros:

insert into empleados


values('Juan Perez','22333444','Colon 123','08/10/1990','Gerencia',900.50);
insert into empleados
values('Ana Acosta','23444555','Caseros 987','18/12/1995','Secretaria',590.30);
insert into empleados
values('Lucas Duarte','25666777','Sucre 235','15/05/2005','Sistemas',790);
insert into empleados
values('Pamela Gonzalez','26777888','Sarmiento
873','12/02/1999','Secretaria',550);
insert into empleados
values('Marcos Juarez','30000111','Rivadavia
801','22/09/2002','Contaduria',630.70);
insert into empleados
values('Yolanda perez','35111222','Colon 180','08/10/1990','Administracion',400);
insert into empleados
values('Rodolfo perez','35555888','Coronel Olmedo
588','28/05/1990','Sistemas',800);

4- Muestre todos los empleados con apellido "Perez" empleando el operador "like" (1 registro)
Note que no incluye los "perez" (que comienzan con minscula).

5- Muestre todos los empleados cuyo domicilio comience con "Co" y tengan un "8" (2 registros)

6- Seleccione todos los empleados cuyo documento finalice en 0 4 (2 registros)

7- Seleccione todos los empleados cuyo documento NO comience con 2 y cuyo nombre finalice
en "ez" (1 registro)

8- Recupere todos los nombres que tengan una "G" o una "J" en su nombre o apellido (3
registros)

9- Muestre los nombres y seccin de los empleados que pertenecen a secciones que
comiencen con "S" o "G" y tengan 8 caracteres (3 registros)

10- Muestre los nombres y seccin de los empleados que pertenecen a secciones que NO
comiencen con "S" (3 registros)
11- Muestre todos los nombres y sueldos de los empleados cuyos sueldos se encuentren entre
500,00 y 599,99 empleando "like" (2 registros)

12- Muestre los empleados que hayan ingresado en la dcada del 90 (5 registros)

13- Agregue 50 centavos a todos los sueldos que no tengan centavos (4 registros) y verifique
recuperando todos los registros.

14- Elimine todos los empleados cuyos apellidos comiencen con "p" (minscula) (2 registros)

drop table empleados;

create table empleados(


nombre varchar2(30),
documento char(8) not null,
domicilio varchar2(30),
fechaingreso date,
seccion varchar2(20),
sueldo number(6,2),
primary key(documento)
);

insert into empleados


values('Juan Perez','22333444','Colon 123','08/10/1990','Gerencia',900.50);
insert into empleados
values('Ana Acosta','23444555','Caseros 987','18/12/1995','Secretaria',590.30);
insert into empleados
values('Lucas Duarte','25666777','Sucre 235','15/05/2005','Sistemas',790);
insert into empleados
values('Pamela Gonzalez','26777888','Sarmiento
873','12/02/1999','Secretaria',550);
insert into empleados
values('Marcos Juarez','30000111','Rivadavia
801','22/09/2002','Contaduria',630.70);
insert into empleados
values('Yolanda perez','35111222','Colon 180','08/10/1990','Administracion',400);
insert into empleados
values('Rodolfo perez','35555888','Coronel Olmedo
588','28/05/1990','Sistemas',800);

select *from empleados


where nombre like '%Perez%';

select *from empleados


where domicilio like 'Co%8%';

select *from empleados


where documento like '%1' or
documento like '%4';

select *from empleados


where documento not like '2%' and
nombre like '%ez';
select nombre from empleados
where nombre like '%G%' or
nombre like '%J%';

select nombre,seccion from empleados


where seccion like 'S_______' or
seccion like 'G_______';

select nombre,seccion from empleados


where seccion not like 'S%';

select nombre,sueldo from empleados


where sueldo like '5__%';

select *from empleados


where fechaingreso like '%9_';

update empleados set sueldo=sueldo+0.50


where sueldo not like '%,%';
select sueldo from empleados;

delete from empleados


where nombre like '% p%';

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.

29 - Contar registros (count)

Problema:

Trabajamos con la tabla "libros" de una librera.

Eliminamos la tabla:

drop table libros;

Creamos la tabla:

create table libros(


titulo varchar2(40) not null,
autor varchar2(20) default 'Desconocido',
editorial varchar(20),
precio number(6,2)
);

Ingresamos algunos registros:

insert into libros


values('El aleph','Borges','Emece',15.90);
insert into libros
values('Antologa potica',null,'Planeta',null);
insert into libros
values('Alicia en el pais de las maravillas','Lewis
Carroll',null,19.90);
insert into libros
values('Matematica estas ahi','Paenza','Siglo XXI',15);
insert into libros
values('Martin Fierro','Jose Hernandez',default,40);
insert into libros
values('Aprenda PHP',default,'Nuevo siglo',null);
insert into libros
values('Uno','Richard Bach','Planeta',20);

Averiguemos la cantidad de libros usando la funcin "count()":

select count(*)
from libros;

Note que incluye todos los libros aunque tengan valor nulo en algn campo.

Contamos los libros de editorial "Planeta":

select count(*)
from libros
where editorial='Planeta';
Existen 2 libros de editorial "Planeta".

Contamos los registros que tienen precio (sin tener en cuenta los que tienen valor nulo),
usando la funcin "count(precio)":

select count(precio)
from libros;

La consulta nos retorna el valor 5.

Contamos los registros que tienen valor diferente de "null" en "editorial":

select count(editorial)
from libros;

La consulta nos retorna el valor 5.

29 - Contar registros (count)

Primer problema:

Trabaje con la tabla llamada "medicamentos" de una farmacia.

1- Elimine la tabla:

drop table medicamentos;

2- Cree la tabla con la siguiente estructura:

create table medicamentos(


codigo number(5),
nombre varchar2(20),
laboratorio varchar2(20),
precio number(6,2),
cantidad number(3),
fechavencimiento date not null,
numerolote number(6) default null,
primary key(codigo)
);

3- Ingrese algunos registros:

insert into medicamentos


values(120,'Sertal','Roche',5.2,1,'01/02/2005',123456);
insert into medicamentos
values(220,'Buscapina','Roche',4.10,3,'01/02/2006',null);
insert into medicamentos
values(228,'Amoxidal 500','Bayer',15.60,100,'01/05/2007',null);
insert into medicamentos
values(324,'Paracetamol 500','Bago',1.90,20,'01/02/2008',null);
insert into medicamentos
values(587,'Bayaspirina',null,2.10,null,'01/12/2009',null);
insert into medicamentos
values(789,'Amoxidal jarabe','Bayer',null,null,'15/12/2009',null);
4- Muestre la cantidad de registros empleando la funcin "count(*)" (6 registros)

5- Cuente la cantidad de medicamentos que tienen laboratorio conocido (5 registros)

6- Cuente la cantidad de medicamentos que tienen precio y cantidad, con alias (5 y 4


respectivamente)

7- Cuente la cantidad de remedios con precio conocido, cuyo laboratorio comience con "B" (2
registros)

8- Cuente la cantidad de medicamentos con nmero de lote distinto de "null" (1 registro)

9- Cuente la cantidad de medicamentos con fecha de vencimiento conocida (6 registros)

drop table medicamentos;

create table medicamentos(


codigo number(5),
nombre varchar2(20),
laboratorio varchar2(20),
precio number(6,2),
cantidad number(3),
fechavencimiento date not null,
numerolote number(6) default null,
primary key(codigo)
);

insert into medicamentos


values(120,'Sertal','Roche',5.2,1,'01/02/2005',123456);
insert into medicamentos
values(220,'Buscapina','Roche',4.10,3,'01/02/2006',null);
insert into medicamentos
values(228,'Amoxidal 500','Bayer',15.60,100,'01/05/2007',null);
insert into medicamentos
values(324,'Paracetamol 500','Bago',1.90,20,'01/02/2008',null);
insert into medicamentos
values(587,'Bayaspirina',null,2.10,null,'01/12/2009',null);
insert into medicamentos
values(789,'Amoxidal jarabe','Bayer',null,null,'15/12/2009',null);

select count(*)
from medicamentos;

select count(laboratorio)
from medicamentos;

select count(precio) as "Con precio",


count(cantidad) as "Con cantidad"
from medicamentos;

select count(precio)
from medicamentos
where laboratorio like 'B%';
select count(numerolote) from medicamentos;

select count(fechavencimiento)
from medicamentos;

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".

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

Problema:

Trabajamos con la tabla "libros" de una librera.

Eliminamos la tabla:

drop table libros;

Creamos la tabla:

create table libros(


codigo number(4) not null,
titulo varchar2(40) not null,
autor varchar2(30) default 'Desconocido',
editorial varchar2(15),
edicion date,
precio number(5,2),
cantidad number(3),
primary key(codigo)
);

Ingresamos algunos registros:

insert into libros


values(1562,'El aleph','Borges','Planeta','10/10/1980',15,null);
insert into libros
values(1878,'Martin Fierro','Jose
Hernandez','Emece',null,22.20,200);
insert into libros
values(2587,'Antologia poetica','J.L.
Borges','Planeta',null,null,150);
insert into libros
values(3654,'Aprenda PHP','Mario
Molina',null,'05/05/1999',18.20,null);
insert into libros
values(3921,'Cervantes y el
quijote',default,'Paidos','15/02/2000',null,null);
insert into libros
values(4582,'Manual de PHP', 'J.C. Paez', 'Siglo
XXI','21/04/2005',31.80,120);
insert into libros
values(5963,'Harry Potter y la piedra filosofal','J.K.
Rowling',default,null,45.00,90);
insert into libros
values(6211,'Harry Potter y la camara secreta','J.K.
Rowling','Emece',null,0,100);
insert into libros
values(8851,'Alicia en el pais de las maravillas','Lewis
Carroll',null,null,null,220);
insert into libros
values(9920,'PHP de la A a la Z',default,default,default,null,0);

Para conocer la cantidad total de libros, sumamos las cantidades de cada uno:

select sum(cantidad)
from libros;

Retorna 880; verifique la suma, sumando los valores de todos los registros del campo
"cantidad".

Queremos saber cuntos libros tenemos de la editorial "Emece":

select sum(cantidad)
from libros
where editorial='Emece';

retorna 300.

Queremos saber el precio del libro ms costoso; usamos la funcin "max()":

select max(precio)
from libros;

retorna 45.

Para conocer el precio mnimo de los libros de "Rowling" tipeamos:

select min(precio)
from libros
where autor like '%Rowling%';

retorna 0 (cero).

Queremos saber el promedio del precio de los libros referentes a "PHP":

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

Devuelve 25. Note que hay 3 libros sobre "PHP", pero uno de ellos tiene precio nulo entonces
Oracle no lo incluye para calcular el promedio.

Averiguamos el mnimo valor del campo "edicion":

select min(edicion)
from libros;

Retorna 10/10/80.
Necesitamos conocer el mayor valor de "codigo":

select max(codigo)
from libros;

Retorna 9920.

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

Primer problema:

Una empresa almacena los datos de sus empleados en una tabla "empleados".

1- Elimine la tabla y crela con la siguiente estructura:

drop table empleados;

create table empleados(


nombre varchar2(30),
documento char(8),
domicilio varchar2(30),
seccion varchar2(20),
sueldo number(6,2),
cantidadhijos number(2),
fechaingreso date,
primary key(documento)
);

3- Ingrese algunos registros:

insert into empleados


values('Juan Perez','22333444','Colon 123','Gerencia',5000,2,'10/10/1980');
insert into empleados
values('Ana Acosta','23444555','Caseros 987','Secretaria',2000,0,'15/08/1998');
insert into empleados
values('Lucas Duarte','25666777','Sucre 235','Sistemas',4000,1,null);
insert into empleados
values('Pamela Gonzalez','26777888','Sarmiento 873','Secretaria',2200,3,null);
insert into empleados
values('Marcos Juarez','30000111','Rivadavia
801','Contaduria',3000,0,'26/08/2000');
insert into empleados
values('Yolanda Perez','35111222','Colon
180','Administracion',3200,1,'25/09/2001');
insert into empleados
values('Rodolfo Perez','35555888','Coronel Olmedo 588','Sistemas',4000,3,null);
insert into empleados
values('Martina Rodriguez','30141414','Sarmiento
1234','Administracion',3800,4,'14/12/2000');
insert into empleados
values('Andres Costa','28444555',default,'Secretaria',null,null,'08/08/1990');

4- Muestre la cantidad de empleados usando "count" (9 empleados)

5- Muestre la cantidad de empleados con fecha de ingreso conocida (6 empleados)


6- Muestre la cantidad de empleados con sueldo (8 empleados)

7- Muestre la cantidad de empleados con sueldo de la seccin "Secretaria" (2 empleados)

8- Muestre el sueldo ms alto y el ms bajo colocando un alias (5000 y 2000 respectivamente)

9- Muestre el valor mayor de "cantidadhijos" de los empleados "Perez" (3 hijos)

10- Muestre la fecha de ingreso ms reciente (max) y la ms lejana (min) (25/09/01 y


10/10/80 respectivamente)

11- Muestre el documento menor (22333444)

12- Muestre el promedio de sueldos de todo los empleados (3400. Note que hay un sueldo nulo
y no es tenido en cuenta)

13- Muestre el promedio de sueldos de los empleados de la seccin "Secretara" (2100. Note
que hay 3 registros de la seccin solicitada, pero como uno de ellos tiene sueldo nulo, no es
tenido en cuenta)

14- Muestre el promedio de hijos de todos los empleados de "Sistemas" (retorna 2)

15- Muestre la cantidad de empleados, la cantidad de empleados con domicilio conocido, la


suma de los hijos, el promedio de los sueldos y los valores mnimo y mximo del campo
"fechaingreso" de todos los empleados. Empleamos todas las funciones de grupo en una sola
consulta y nos retorna 9, 8, 14, 3400, 10/10/80 y 25/09/01.

16- Realice la misma consulta anterior pero ahora de los empleados de la seccin "Recursos".
Al no existir tal seccin, "count(*)" y "count(domicilio)" retornan 0 (cero) y las dems
funciones de grupo retornan "null".

drop table empleados;

create table empleados(


nombre varchar2(30),
documento char(8),
domicilio varchar2(30),
seccion varchar2(20),
sueldo number(6,2),
cantidadhijos number(2),
fechaingreso date,
primary key(documento)
);

insert into empleados


values('Juan Perez','22333444','Colon 123','Gerencia',5000,2,'10/10/1980');
insert into empleados
values('Ana Acosta','23444555','Caseros 987','Secretaria',2000,0,'15/08/1998');
insert into empleados
values('Lucas Duarte','25666777','Sucre 235','Sistemas',4000,1,null);
insert into empleados
values('Pamela Gonzalez','26777888','Sarmiento 873','Secretaria',2200,3,null);
insert into empleados
values('Marcos Juarez','30000111','Rivadavia
801','Contaduria',3000,0,'26/08/2000');
insert into empleados
values('Yolanda Perez','35111222','Colon
180','Administracion',3200,1,'25/09/2001');
insert into empleados
values('Rodolfo Perez','35555888','Coronel Olmedo 588','Sistemas',4000,3,null);
insert into empleados
values('Martina Rodriguez','30141414','Sarmiento
1234','Administracion',3800,4,'14/12/2000');
insert into empleados
values('Andres Costa','28444555',default,'Secretaria',null,null,'08/08/1990');

select count(*)
from empleados;

select count(fechaingreso)
from empleados;

select count(sueldo)
from empleados;

select count(sueldo)
from empleados
where seccion='Secretaria';

select max(sueldo) as "Mayor sueldo",


min(sueldo) as "Menor sueldo"
from empleados;

select max(cantidadhijos)
from empleados
where nombre like '%Perez%';

select max(fechaingreso),min(fechaingreso)
from empleados;

select min(documento) from empleados;

select avg(sueldo)
from empleados;

select avg(sueldo)
from empleados
where seccion='Secretaria';

select avg(cantidadhijos)
from empleados
where seccion='Sistemas';

select
count(*),count(domicilio),sum(cantidadhijos),avg(sueldo),min(fechaingreso),max(f
echaingreso)
from empleados;
select
count(*),count(domicilio),sum(cantidadhijos),avg(sueldo),min(fechaingreso),max(f
echaingreso)
from empleados where seccion='Recursos';

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 count(*) from libros


where editorial='Emece';
select count(*) from libros
where 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.

31 - Agrupar registros (group by)

Problema:

Trabajamos con la tabla "libros" de una librera.

Eliminamos la tabla:

drop table libros;

Creamos la tabla:

create table libros(


codigo number(5),
titulo varchar2(40),
autor varchar2(30) default 'Desconocido',
editorial varchar2(15),
precio number(5,2),
cantidad number(3),
primary key(codigo)
);

Ingresamos algunos registros:

insert into libros


values(100,'El aleph','Borges','Planeta',15,null);
insert into libros
values(234,'Martin Fierro','Jose Hernandez','Emece',22.20,200);
insert into libros
values(354,'Antologia poetica',default,'Planeta',null,150);
insert into libros
values(478,'Aprenda PHP','Mario Molina','Emece',18.20,null);
insert into libros
values(512,'Cervantes y el quijote','Bioy Casares- J.L.
Borges','Paidos',28,100);
insert into libros
values(643,'Manual de PHP', default, 'Siglo XXI',31.80,120);
insert into libros
values(646,'Harry Potter y la piedra filosofal','J.K.
Rowling',default,45.00,90);
insert into libros
values(753,'Harry Potter y la camara secreta','J.K.
Rowling','Emece',null,100);
insert into libros
values(889,'Alicia en el pais de las maravillas','Lewis
Carroll','Paidos',22.50,200);
insert into libros
values(893,'PHP de la A a la Z',null,null,55.90,0);

Queremos saber la cantidad de libros de cada editorial, utilizando la clusula "group by":
select editorial, count(*)
from libros
group by editorial;

Aparece el siguiente resultado:

EDITORIAL COUNT(*)
--------------------------
Paidos 2
2
Planeta 2
Emece 3
Siglo XXI 1

El resultado muestra los nombres de las editoriales y la cantidad de registros para cada valor
del campo. Note que los valores nulos se procesan como otro grupo.

Obtenemos la cantidad libros con precio no nulo de cada editorial:

select editorial, count(precio)


from libros
group by editorial;

La salida es la siguiente:

EDITORIAL COUNT(PRECIO)
------------------------------
Paidos 2
2
Planeta 1
Emece 2
Siglo XXI 1

Aparecen los nombres de las editoriales y la cantidad de registros de cada una, sin contar los
que tienen precio nulo.

Para conocer el total de libros agrupados por editorial, tipeamos:

select editorial, sum(cantidad)


from libros
group by editorial;

Obtenemos el mximo y mnimo valor de los libros agrupados por editorial, en una sola
sentencia:

select editorial,
max(precio) as mayor,
min(precio) as menor
from libros
group by editorial;

Calculamos 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". Vamos a contar y agrupar por editorial
considerando solamente los libros cuyo precio es 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 (sus precios superan
los 30 pesos), no aparecen en la salida.

31 - Agrupar registros (group by)

Primer problema:

Un comercio que tiene un stand en una feria registra en una tabla llamada "visitantes" algunos
datos de las personas que visitan o compran en su stand para luego enviarle publicidad de sus
productos.

1- Elimine la tabla "visitantes" y crela con la siguiente estructura:

drop table visitantes;


create table visitantes(
nombre varchar2(30),
edad number(2),
sexo char(1) default 'f',
domicilio varchar2(30),
ciudad varchar2(20) default 'Cordoba',
telefono varchar2(11),
mail varchar2(30) default 'no tiene',
montocompra number(6,2)
);

3- Ingrese algunos registros:

insert into visitantes


values ('Susana Molina',35,default,'Colon 123',default,null,null,59.80);
insert into visitantes
values ('Marcos Torres',29,'m',default,'Carlos
Paz',default,'marcostorres@hotmail.com',150.50);
insert into visitantes
values ('Mariana Juarez',45,default,default,'Carlos Paz',null,default,23.90);
insert into visitantes (nombre, edad,sexo,telefono, mail)
values ('Fabian Perez',36,'m','4556677','fabianperez@xaxamail.com');
insert into visitantes (nombre, ciudad, montocompra)
values ('Alejandra Gonzalez','La Falda',280.50);
insert into visitantes (nombre, edad,sexo, ciudad, mail,montocompra)
values ('Gaston Perez',29,'m','Carlos Paz','gastonperez1@gmail.com',95.40);
insert into visitantes
values ('Liliana Torres',40,default,'Sarmiento 876',default,default,default,85);
insert into visitantes
values ('Gabriela Duarte',21,null,null,'Rio
Tercero',default,'gabrielaltorres@hotmail.com',321.50);
4- Queremos saber la cantidad de visitantes de cada ciudad utilizando la clusula "group by"
(4 filas devueltas)

5- Queremos la cantidad visitantes con telfono no nulo, de cada ciudad (4 filas devueltas)

6- Necesitamos el total del monto de las compras agrupadas por sexo (3 filas)
Note que los registros con valor nulo en el campo "sexo" se procesan como un grupo diferente.

7- Se necesita saber el mximo y mnimo valor de compra agrupados por sexo y ciudad (6
filas)

8- Calcule el promedio del valor de compra agrupados por ciudad (4 filas)

9- Cuente y agrupe por ciudad sin tener en cuenta los visitantes que no tienen mail (3 filas)

drop table visitantes;

create table visitantes(


nombre varchar2(30),
edad number(2),
sexo char(1) default 'f',
domicilio varchar2(30),
ciudad varchar2(20) default 'Cordoba',
telefono varchar2(11),
mail varchar2(30) default 'no tiene',
montocompra number(6,2)
);

insert into visitantes


values ('Susana Molina',35,default,'Colon 123',default,null,null,59.80);
insert into visitantes
values ('Marcos Torres',29,'m',default,'Carlos
Paz',default,'marcostorres@hotmail.com',150.50);
insert into visitantes
values ('Mariana Juarez',45,default,default,'Carlos Paz',null,default,23.90);
insert into visitantes (nombre, edad,sexo,telefono, mail)
values ('Fabian Perez',36,'m','4556677','fabianperez@xaxamail.com');
insert into visitantes (nombre, ciudad, montocompra)
values ('Alejandra Gonzalez','La Falda',280.50);
insert into visitantes (nombre, edad,sexo, ciudad, mail,montocompra)
values ('Gaston Perez',29,'m','Carlos Paz','gastonperez1@gmail.com',95.40);
insert into visitantes
values ('Liliana Torres',40,default,'Sarmiento 876',default,default,default,85);
insert into visitantes
values ('Gabriela Duarte',21,null,null,'Rio
Tercero',default,'gabrielaltorres@hotmail.com',321.50);

select ciudad, count(*)


from visitantes
group by ciudad;

select ciudad, count(telefono)


from visitantes
group by ciudad;

select sexo, sum(montocompra)


from visitantes
group by sexo;

select sexo,ciudad,
max(montocompra) as mayor,
min(montocompra) as menor
from visitantes
group by sexo,ciudad;

select ciudad,
avg(montocompra) as "promedio de compras"
from visitantes
group by ciudad;

select ciudad,
count(*) as "cantidad con mail"
from visitantes
where mail is not null and
mail<>'no tiene'
group by ciudad;

Segundo problema:

Una empresa almacena los datos de sus empleados en una tabla "empleados".

1- Elimine la tabla y luego crela con la estructura definida a continuacin:

drop table empleados;


create table empleados(
nombre varchar2(30),
documento char(8),
domicilio varchar2(30),
seccion varchar2(20),
sueldo number(6,2),
cantidadhijos number(2),
fechaingreso date,
primary key(documento)
);

3- Ingrese algunos registros:

insert into empleados


values('Juan Perez','22333444','Colon 123','Gerencia',5000,2,'10/05/1980');
insert into empleados
values('Ana Acosta','23444555','Caseros 987','Secretaria',2000,0,'12/10/1980');
insert into empleados
values('Lucas Duarte','25666777','Sucre 235','Sistemas',4000,1,'25/05/1985');
insert into empleados
values('Pamela Gonzalez','26777888','Sarmiento
873','Secretaria',2200,3,'25/06/1990');
insert into empleados
values('Marcos Juarez','30000111','Rivadavia
801','Contaduria',3000,0,'01/05/1996');
insert into empleados
values('Yolanda Perez','35111222','Colon
180','Administracion',3200,1,'01/05/1996');
insert into empleados
values('Rodolfo Perez','35555888','Coronel Olmedo
588','Sistemas',4000,3,'01/05/1996');
insert into empleados
values('Martina Rodriguez','30141414','Sarmiento
1234','Administracion',3800,4,'01/09/2000');
insert into empleados
values('Andres Costa','28444555',default,'Secretaria',null,null,null);

4- Cuente la cantidad de empleados agrupados por seccin (5 filas)

5- Calcule el promedio de hijos por seccin (5 filas)

6- Cuente la cantidad de empleados agrupados por ao de ingreso (6 filas)

7- Calcule el promedio de sueldo por seccin de los empleados con hijos (4 filas)

drop table empleados;


create table empleados(
nombre varchar2(30),
documento char(8),
domicilio varchar2(30),
seccion varchar2(20),
sueldo number(6,2),
cantidadhijos number(2),
fechaingreso date,
primary key(documento)
);

insert into empleados


values('Juan Perez','22333444','Colon 123','Gerencia',5000,2,'10/05/1980');
insert into empleados
values('Ana Acosta','23444555','Caseros 987','Secretaria',2000,0,'12/10/1980');
insert into empleados
values('Lucas Duarte','25666777','Sucre 235','Sistemas',4000,1,'25/05/1985');
insert into empleados
values('Pamela Gonzalez','26777888','Sarmiento
873','Secretaria',2200,3,'25/06/1990');
insert into empleados
values('Marcos Juarez','30000111','Rivadavia
801','Contaduria',3000,0,'01/05/1996');
insert into empleados
values('Yolanda Perez','35111222','Colon
180','Administracion',3200,1,'01/05/1996');
insert into empleados
values('Rodolfo Perez','35555888','Coronel Olmedo
588','Sistemas',4000,3,'01/05/1996');
insert into empleados
values('Martina Rodriguez','30141414','Sarmiento
1234','Administracion',3800,4,'01/09/2000');
insert into empleados
values('Andres Costa','28444555',default,'Secretaria',null,null,null);

select seccion, count(*)


from empleados
group by seccion;

select seccion, avg(cantidadhijos) as "promedio de hijos"


from empleados
group by seccion;

select datepart(year,fechaingreso) as ingreso, count(*)


from empleados
group by datepart(year,fechaingreso);

select seccion, avg(sueldo) as "promedio de sueldo"


from empleados
where cantidadhijos>0 and
cantidadhijos is not null
group by seccion;

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.

32 - Seleccionar grupos (Having)

Problema:

Trabajamos con la tabla "libros" de una librera.

Eliminamos la tabla:

drop table libros;

Creamos la tabla:

create table libros(


titulo varchar2(40),
autor varchar2(30),
editorial varchar2(15),
precio number(5,2),
cantidad number(3)
);

Ingresamos algunos registros:

insert into libros


values('El aleph','Borges','Planeta',35,null);
insert into libros
values('Martin Fierro','Jose Hernandez','Emece',22.20,200);
insert into libros
values('Martin Fierro','Jose Hernandez','Planeta',40,200);
insert into libros
values('Antologia poetica','J.L. Borges','Planeta',null,150);
insert into libros
values('Aprenda PHP','Mario Molina','Emece',18,null);
insert into libros
values('Manual de PHP', 'J.C. Paez', 'Siglo XXI',56,120);
insert into libros
values('Cervantes y el quijote','Bioy Casares- J.L.
Borges','Paidos',null,100);
insert into libros
values('Harry Potter y la piedra filosofal','J.K.
Rowling',default,45.00,90);
insert into libros
values('Harry Potter y la camara secreta','J.K.
Rowling','Emece',null,100);
insert into libros
values('Alicia en el pais de las maravillas','Lewis
Carroll','Paidos',42,80);
insert into libros
values('PHP de la A a la Z',null,null,110,0);
insert into libros
values('Uno','Richard Bach','Planeta',25,null);

Queremos saber la cantidad de libros agrupados por editorial:


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

Nos devuelve:

EDITORIAL COUNT(*)
------------------------
Paidos 2
2
Planeta 4
Emece 3
Siglo XXI 1

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;

La salida es la siguiente:

EDITORIAL COUNT(*)
-------------------------
Planeta 4
Emece 3

Compare esta salida con la de la sentencia anterior.

Queremos el promedio de los precios de los libros 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;

Queremos la cantidad de libros, sin considerar los que tienen precio nulo (where), agrupados
por editorial (group by), sin considerar la editorial "Planeta" (having):

select editorial, count(*) from libros


where precio is not null
group by editorial
having editorial<>'Planeta';

Necesitamos 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;

Buscamos el mayor valor de los libros agrupados y ordenados por editorial y seleccionamos las
filas que tienen un valor menor a 100 y mayor a 30:

select editorial, max(precio) as mayor


from libros
group by editorial
having max(precio)<100 and
max(precio)>30
order by editorial;
32 - Seleccionar grupos (Having)

Primer problema:

Una empresa tiene registrados sus clientes en una tabla llamada "clientes".

1- Elimine la tabla "clientes":

drop table clientes;

2- Crela con la siguiente estructura:

create table clientes (


nombre varchar2(30) not null,
domicilio varchar2(30),
ciudad varchar2(20),
provincia varchar2(20),
telefono varchar2(11)
);

3- Ingrese algunos registros:

insert into clientes


values ('Lopez Marcos','Colon 111','Cordoba','Cordoba','null');
insert into clientes
values ('Perez Ana','San Martin 222','Cruz del Eje','Cordoba','4578585');
insert into clientes
values ('Garcia Juan','Rivadavia 333','Villa del Rosario','Cordoba','4578445');
insert into clientes
values ('Perez Luis','Sarmiento 444','Rosario','Santa Fe',null);
insert into clientes
values ('Pereyra Lucas','San Martin 555','Cruz del Eje','Cordoba','4253685');
insert into clientes
values ('Gomez Ines','San Martin 666','Santa Fe','Santa Fe','0345252525');
insert into clientes
values ('Torres Fabiola','Alem 777','Villa del Rosario','Cordoba','4554455');
insert into clientes
values ('Lopez Carlos',null,'Cruz del Eje','Cordoba',null);
insert into clientes
values ('Ramos Betina','San Martin 999','Cordoba','Cordoba','4223366');
insert into clientes
values ('Lopez Lucas','San Martin 1010','Posadas','Misiones','0457858745');

4- Obtenga el total de los registros agrupados por ciudad y provincia (6 filas)

5- Obtenga el total de los registros agrupados por ciudad y provincia sin considerar los que
tienen menos de 2 clientes (3 filas)

6- Obtenga el total de los clientes que viven en calle "San Martin" (where), agrupados por
provincia (group by), de aquellas ciudades que tengan menos de 2 clientes (having) y
omitiendo la fila correspondiente a la ciudad de "Cordoba" (having) (2 filas devueltas)
drop table clientes;

create table clientes (


nombre varchar2(30) not null,
domicilio varchar2(30),
ciudad varchar2(20),
provincia varchar2(20),
telefono varchar2(11)
);

insert into clientes


values ('Lopez Marcos','Colon 111','Cordoba','Cordoba','null');
insert into clientes
values ('Perez Ana','San Martin 222','Cruz del Eje','Cordoba','4578585');
insert into clientes
values ('Garcia Juan','Rivadavia 333','Villa del Rosario','Cordoba','4578445');
insert into clientes
values ('Perez Luis','Sarmiento 444','Rosario','Santa Fe',null);
insert into clientes
values ('Pereyra Lucas','San Martin 555','Cruz del Eje','Cordoba','4253685');
insert into clientes
values ('Gomez Ines','San Martin 666','Santa Fe','Santa Fe','0345252525');
insert into clientes
values ('Torres Fabiola','Alem 777','Villa del Rosario','Cordoba','4554455');
insert into clientes
values ('Lopez Carlos',null,'Cruz del Eje','Cordoba',null);
insert into clientes
values ('Ramos Betina','San Martin 999','Cordoba','Cordoba','4223366');
insert into clientes
values ('Lopez Lucas','San Martin 1010','Posadas','Misiones','0457858745');

select ciudad, provincia,


count(*) as cantidad
from clientes
group by ciudad,provincia;

select ciudad, provincia,


count(*) as cantidad
from clientes
group by ciudad,provincia
having count(*)>1;

select ciudad, count(*)


from clientes
where domicilio like '%San Martin%'
group by all ciudad
having count(*)<2 and
ciudad <> 'Cordoba';

Segundo problema:
Un comercio que tiene un stand en una feria registra en una tabla llamada "visitantes" algunos
datos de las personas que visitan o compran en su stand para luego enviarle publicidad de sus
productos.

1- Elimine la tabla "visitantes":

drop table visitantes;

2- Crela con la siguiente estructura:

create table visitantes(


nombre varchar2(30),
edad number(2),
sexo char(1),
domicilio varchar2(30),
ciudad varchar2(20),
telefono varchar2(11),
montocompra number(6,2) not null
);

3- Ingrese algunos registros:

insert into visitantes


values ('Susana Molina',28,'f',null,'Cordoba',null,45.50);
insert into visitantes
values ('Marcela Mercado',36,'f','Avellaneda 345','Cordoba','4545454',22.40);
insert into visitantes
values ('Alberto Garcia',35,'m','Gral. Paz 123','Alta Gracia','03547123456',25);
insert into visitantes
values ('Teresa Garcia',33,'f',default,'Alta Gracia','03547123456',120);
insert into visitantes
values ('Roberto Perez',45,'m','Urquiza 335','Cordoba','4123456',33.20);
insert into visitantes
values ('Marina Torres',22,'f','Colon 222','Villa Dolores','03544112233',95);
insert into visitantes
values ('Julieta Gomez',24,'f','San Martin 333','Alta Gracia',null,53.50);
insert into visitantes
values ('Roxana Lopez',20,'f','null','Alta Gracia',null,240);
insert into visitantes
values ('Liliana Garcia',50,'f','Paso 999','Cordoba','4588778',48);
insert into visitantes
values ('Juan Torres',43,'m','Sarmiento 876','Cordoba',null,15.30);

4- Obtenga el total de las compras agrupados por ciudad y sexo de aquellas filas que
devuelvan un valor superior a 50 (3 filas)

5- Obtenga el total de las compras agrupados por ciudad y sexo (group by), considerando slo
los montos de compra superiores a 50 (where), los visitantes con telfono (where), sin
considerar la ciudad de "Cordoba" (having), ordenados por ciudad (order by) (2 filas)

6- Muestre el monto mayor de compra agrupado por ciudad, siempre que dicho valor supere
los 50 pesos (having), considerando slo los visitantes de sexo femenino y domicilio conocido
(where) (2 filas)
7- Agrupe por ciudad y sexo, muestre para cada grupo el total de visitantes, la suma de sus
compras y el promedio de compras, ordenado por la suma total y considerando las filas con
promedio superior a 30 (3 filas)

drop table visitantes;

create table visitantes(


nombre varchar2(30),
edad number(2),
sexo char(1),
domicilio varchar2(30),
ciudad varchar2(20),
telefono varchar2(11),
montocompra number(6,2) not null
);

insert into visitantes


values ('Susana Molina',28,'f',null,'Cordoba',null,45.50);
insert into visitantes
values ('Marcela Mercado',36,'f','Avellaneda 345','Cordoba','4545454',22.40);
insert into visitantes
values ('Alberto Garcia',35,'m','Gral. Paz 123','Alta Gracia','03547123456',25);
insert into visitantes
values ('Teresa Garcia',33,'f',default,'Alta Gracia','03547123456',120);
insert into visitantes
values ('Roberto Perez',45,'m','Urquiza 335','Cordoba','4123456',33.20);
insert into visitantes
values ('Marina Torres',22,'f','Colon 222','Villa Dolores','03544112233',95);
insert into visitantes
values ('Julieta Gomez',24,'f','San Martin 333','Alta Gracia',null,53.50);
insert into visitantes
values ('Roxana Lopez',20,'f','null','Alta Gracia',null,240);
insert into visitantes
values ('Liliana Garcia',50,'f','Paso 999','Cordoba','4588778',48);
insert into visitantes
values ('Juan Torres',43,'m','Sarmiento 876','Cordoba',null,15.30);

select ciudad,sexo,
sum(montocompra) as Total
from visitantes
group by ciudad,sexo
having sum(montocompra)>50;

select ciudad, sexo,


sum(montocompra) as total
from visitantes
where montocompra>50 and
telefono is not null
group by ciudad,sexo
having ciudad<>'Cordoba'
order by ciudad;

select ciudad,max(montocompra) as maximo


from visitantes
where domicilio is not null and
sexo='f'
group by all ciudad
having max(montocompra)>50;

select ciudad,sexo, count(*) as cantidad,


sum(montocompra) as total,
avg(montocompra) as promedio
from visitantes
group by ciudad,sexo
having avg(montocompra)>30
order by total;

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.

33 - Registros duplicados (Distinct)

Problema:

Trabajamos con la tabla "libros" de una librera.

Eliminamos la tabla:

drop table libros;

Creamos la tabla:

create table libros(


titulo varchar2(40),
autor varchar2(30),
editorial varchar2(15)
);

Ingresamos algunos registros:

insert into libros


values('El aleph','Borges','Planeta');
insert into libros
values('Martin Fierro','Jose Hernandez','Emece');
insert into libros
values('Martin Fierro','Jose Hernandez','Planeta');
insert into libros
values('Antologia poetica','Borges','Planeta');
insert into libros
values('Aprenda PHP','Mario Molina','Emece');
insert into libros
values('Aprenda PHP','Lopez','Emece');
insert into libros
values('Manual de PHP', 'J. Paez', null);
insert into libros
values('Cervantes y el quijote',null,'Paidos');
insert into libros
values('Harry Potter y la piedra filosofal','J.K. Rowling','Emece');
insert into libros
values('Harry Potter y la camara secreta','J.K. Rowling','Emece');
insert into libros
values('Alicia en el pais de las maravillas','Lewis
Carroll','Paidos');
insert into libros
values('Alicia en el pais de las maravillas','Lewis
Carroll','Planeta');
insert into libros
values('PHP de la A a la Z',null,null);
insert into libros
values('Uno','Richard Bach','Planeta');

Para obtener la lista de autores sin repeticin tipeamos:

select distinct autor from libros;

Note que aparece "null" como un valor para "autor" Para obtener la lista de autores
conocidos, es decir, no incluyendo "null" en la lista:

select distinct autor from libros


where autor is not null;

Contamos los distintos autores:

select count(distinct autor)


from libros;

Queremos los nombres de las editoriales sin repetir:

select distinct editorial from libros;

Queremos saber la cantidad de editoriales distintas:

select count(distinct editorial) from libros;

La combinamos con "where" para obtener los distintos autores de la editorial "Planeta":

select distinct autor from libros


where editorial='Planeta';

Contamos los distintos autores que tiene cada editorial empleando "group by":

select editorial,count(distinct autor)


from libros
group by editorial;

Mostramos los ttulos y editoriales de los libros sin repetir ttulos ni editoriales:

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.

33 - Registros duplicados (Distinct)


Primer problema:

Una empresa tiene registrados sus clientes en una tabla llamada "clientes".

1- Elimine la tabla "clientes" y crela con la siguiente estructura:

drop table clientes;

create table clientes (


nombre varchar2(30) not null,
domicilio varchar2(30),
ciudad varchar2(20),
provincia varchar2(20)
);

2- Ingrese algunos registros:

insert into clientes


values ('Lopez Marcos','Colon 111','Cordoba','Cordoba');
insert into clientes
values ('Perez Ana','San Martin 222','Cruz del Eje','Cordoba');
insert into clientes
values ('Garcia Juan','Rivadavia 333','Villa del Rosario','Cordoba');
insert into clientes
values ('Perez Luis','Sarmiento 444','Rosario','Santa Fe');
insert into clientes
values ('Pereyra Lucas','San Martin 555','Cruz del Eje','Cordoba');
insert into clientes
values ('Gomez Ines','San Martin 666','Santa Fe','Santa Fe');
insert into clientes
values ('Torres Fabiola','Alem 777','Villa del Rosario','Cordoba');
insert into clientes
values ('Lopez Carlos',null,'Cruz del Eje','Cordoba');
insert into clientes
values ('Ramos Betina','San Martin 999','Cordoba','Cordoba');
insert into clientes
values ('Lopez Lucas','San Martin 1010','Posadas','Misiones');

3- Obtenga las provincias sin repetir (3 registros)

4- Cuente las distintas provincias (retorna 3)

5- Se necesitan los nombres de las ciudades sin repetir (6 registros)

6- Obtenga la cantidad de ciudades distintas (devuelve 6)

7- Combine con "where" para obtener las distintas ciudades de la provincia de Cordoba (3
registros)

8- Contamos las distintas ciudades de cada provincia empleando "group by" (3 filas)
drop table clientes;

create table clientes (


nombre varchar2(30) not null,
domicilio varchar2(30),
ciudad varchar2(20),
provincia varchar2(20)
);

insert into clientes


values ('Lopez Marcos','Colon 111','Cordoba','Cordoba');
insert into clientes
values ('Perez Ana','San Martin 222','Cruz del Eje','Cordoba');
insert into clientes
values ('Garcia Juan','Rivadavia 333','Villa del Rosario','Cordoba');
insert into clientes
values ('Perez Luis','Sarmiento 444','Rosario','Santa Fe');
insert into clientes
values ('Pereyra Lucas','San Martin 555','Cruz del Eje','Cordoba');
insert into clientes
values ('Gomez Ines','San Martin 666','Santa Fe','Santa Fe');
insert into clientes
values ('Torres Fabiola','Alem 777','Villa del Rosario','Cordoba');
insert into clientes
values ('Lopez Carlos',null,'Cruz del Eje','Cordoba');
insert into clientes
values ('Ramos Betina','San Martin 999','Cordoba','Cordoba');
insert into clientes
values ('Lopez Lucas','San Martin 1010','Posadas','Misiones');

select distinct provincia from clientes;

select count(distinct provincia) as cantidad


from clientes;

select distinct ciudad from clientes;

select count(distinct ciudad) from clientes;

select distinct ciudad from clientes


where provincia='Cordoba';

select provincia,count(distinct ciudad)


from clientes
group by provincia;

Segundo problema:

La provincia almacena en una tabla llamada "inmuebles" los siguientes datos de los inmuebles
y sus propietarios para cobrar impuestos:

1- Elimine la tabla:
drop table inmuebles;

2- Crela con la siguiente estructura:

create table inmuebles (


documento varchar2(8) not null,
apellido varchar2(30),
nombre varchar2(30),
domicilio varchar2(20),
barrio varchar2(20),
ciudad varchar2(20),
tipo char(1),--b=baldio, e: edificado
superficie number(8,2)
);

3- Ingrese algunos registros:

insert into inmuebles


values ('11000000','Perez','Alberto','San Martin 800','Centro','Cordoba','e',100);
insert into inmuebles
values ('11000000','Perez','Alberto','Sarmiento 245','Gral. Paz','Cordoba','e',200);
insert into inmuebles
values ('12222222','Lopez','Maria','San Martin 202','Centro','Cordoba','e',250);
insert into inmuebles
values ('13333333','Garcia','Carlos','Paso 1234','Alberdi','Cordoba','b',200);
insert into inmuebles
values ('13333333','Garcia','Carlos','Guemes 876','Alberdi','Cordoba','b',300);
insert into inmuebles
values ('14444444','Perez','Mariana','Caseros 456','Flores','Cordoba','b',200);
insert into inmuebles
values ('15555555','Lopez','Luis','San Martin 321','Centro','Carlos Paz','e',500);
insert into inmuebles
values ('15555555','Lopez','Luis','Lopez y Planes 853','Flores','Carlos Paz','e',350);
insert into inmuebles
values ('16666666','Perez','Alberto','Sucre 1877','Flores','Cordoba','e',150);

4- Muestre los distintos apellidos de los propietarios, sin repetir (3 registros)

5- Recupere los distintos documentos de los propietarios y luego muestre los distintos
documentos de los propietarios, sin repetir y vea la diferencia (9 y 6 registros
respectivamente)

6- Cuente, sin repetir, la cantidad de propietarios de inmuebles de la ciudad de Cordoba (5)

7- Cuente la cantidad de inmuebles con domicilio en 'San Martin' (3)

8- Cuente la cantidad de inmuebles con domicilio en 'San Martin', sin repetir la ciudad (2
registros). Compare con la sentencia anterior.

9- Muestre los apellidos y nombres de todos los registros(9 registros)

10- Muestre los apellidos y nombres, sin repetir (5 registros)

Note que si hay 2 personas con igual nombre y apellido aparece una sola vez.
11- Muestre la cantidad de inmuebles que tiene cada propietario en barrios conocidos,
agrupando por documento (6 registros)

12- Realice la misma consulta anterior pero en esta oportunidad, sin repetir barrio (6
registros)

Compare los valores con los obtenidos en el punto 11.

drop table inmuebles;

create table inmuebles (


documento varchar2(8) not null,
apellido varchar2(30),
nombre varchar2(30),
domicilio varchar2(20),
barrio varchar2(20),
ciudad varchar2(20),
tipo char(1),--b=baldio, e: edificado
superficie number(8,2)
);

insert into inmuebles


values ('11000000','Perez','Alberto','San Martin 800','Centro','Cordoba','e',100);
insert into inmuebles
values ('11000000','Perez','Alberto','Sarmiento 245','Gral. Paz','Cordoba','e',200);
insert into inmuebles
values ('12222222','Lopez','Maria','San Martin 202','Centro','Cordoba','e',250);
insert into inmuebles
values ('13333333','Garcia','Carlos','Paso 1234','Alberdi','Cordoba','b',200);
insert into inmuebles
values ('13333333','Garcia','Carlos','Guemes 876','Alberdi','Cordoba','b',300);
insert into inmuebles
values ('14444444','Perez','Mariana','Caseros 456','Flores','Cordoba','b',200);
insert into inmuebles
values ('15555555','Lopez','Luis','San Martin 321','Centro','Carlos Paz','e',500);
insert into inmuebles
values ('15555555','Lopez','Luis','Lopez y Planes 853','Flores','Carlos Paz','e',350);
insert into inmuebles
values ('16666666','Perez','Alberto','Sucre 1877','Flores','Cordoba','e',150);

select distinct apellido from inmuebles;

select distinct documento from inmuebles;

select count(distinct documento)


from inmuebles
where ciudad='Cordoba';

select count(ciudad)
from inmuebles
where domicilio like 'San Martin %';

select count(distinct ciudad)


from inmuebles
where domicilio like 'San Martin %';
select apellido,nombre
from inmuebles;

select distinct apellido,nombre


from inmuebles;

select documento,count(barrio) as cantidad


from inmuebles
group by documento;

select documento,count(distinct barrio) as cantidad


from inmuebles
group by documento;

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.

34 - Clave primaria compuesta

Problema:

Una playa de estacionamiento almacena cada da los datos de los vehculos que ingresan en la
tabla llamada "vehiculos".

Seteamos el formato de "date" para que nos muestre nicamente la hora y los minutos, ya que
en esta playa, se almacenan los datos de los vehculos diariamente:

ALTER SESSION SET NLS_DATE_FORMAT = 'HH24:MI';

Eliminamos la tabla:

drop table vehiculos;

Creamos la tabla estableciendo dos campos como clave primaria:

create table vehiculos(


patente char(6) not null,
tipo char(1),--'a'=auto, 'm'=moto
horallegada date,
horasalida date,
primary key(patente,horallegada)
);

Ingresamos algunos registros:

insert into vehiculos values('AIC124','a','8:05','12:30');


insert into vehiculos values('CAA258','a','8:05',null);
insert into vehiculos values('DSE367','m','8:30','18:00');
insert into vehiculos values('FGT458','a','9:00',null);
insert into vehiculos values('AIC124','a','16:00',null);
insert into vehiculos values('LOI587','m','18:05','19:55');
Si intentamos ingresar un registro con clave primaria repetida:

insert into vehiculos values('LOI587','m','18:05',null);

aparece un mensaje de error y la insercin no se realiza.

Si ingresamos un registro repitiendo el valor de uno de los campos que forman parte de la
clave, si lo acepta:

insert into vehiculos values('LOI587','m','21:30',null);

Recuperamos todos los registros:

select *from vehiculos;

Note que cada registro es nico, dos de ellos tienen la misma patente, pero diferente hora de
llegada.

Si intentamos actualizar un registro repitiendo la clave primaria:

update vehiculos set horallegada='8:05'


where patente='AIC124' and horallegada='16:00';

aparece un mensaje de error y la actualizacin no se realiza.

Recordemos que los campos que forman parte de la clave primaria no aceptan valores nulos,
aunque no se haya aclarado en la definicin de la tabla:

insert into vehiculos values('HUO690','m',null,null);

Si mostramos la estructura de la tabla:

describe vehiculos;

vemos que los campos que forman parte de la clave primaria (patente y horallegada) tienen
"NOT NULL" en la columna "Null", es decir, no admiten valores nulos.

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';

Nos retorna la siguiente informacin:

TABLE_NAME COLUMN_NAME POSITION


----------------------------------------
VEHICULOS PATENTE 1
VEHICULOS HORALLEGADA 2

Los dos campos son clave primaria, "POSITION" indica el orden en que fueron definidos los
campos.
34 - Clave primaria compuesta

Primer problema:

Un consultorio mdico en el cual trabajan 3 mdicos registra las consultas de los pacientes en
una tabla llamada "consultas".

1- Elimine la tabla:

drop table consultas;

2- La tabla contiene los siguientes datos:

- fechayhora: date not null, fecha y hora de la consulta,


- medico: varchar2(30), not null, nombre del mdico (Perez,Lopez,Duarte),
- documento: char(8) not null, documento del paciente,
- paciente: varchar2(30), nombre del paciente,
- obrasocial: varchar2(30), nombre de la obra social (IPAM,PAMI, etc.).

3- Setee el formato de "date" para que nos muestre da, mes, ao, hora y minutos:

ALTER SESSION SET NLS_DATE_FORMAT = 'DD/MM/YYYY HH24:MI';

4- Un mdico slo puede atender a un paciente en una fecha y hora determinada. En una
fecha y hora determinada, varios mdicos atienden a distintos pacientes. Cree la tabla
definiendo una clave primaria compuesta:

create table consultas(


fechayhora date not null,
medico varchar2(30) not null,
documento char(8) not null,
paciente varchar2(30),
obrasocial varchar2(30),
primary key(fechayhora,medico)
);

4- Ingrese varias consultas para un mismo mdico en distintas horas el mismo da:

insert into consultas


values ('05/11/2006 8:00','Lopez','12222222','Acosta Betina','PAMI');
insert into consultas
values ('05/11/2006 8:30','Lopez','23333333','Fuentes Carlos','PAMI');

5- Ingrese varias consultas para diferentes mdicos en la misma fecha y hora:

insert into consultas


values ('05/11/2006 8:00','Perez','34444444','Garcia Marisa','IPAM');
insert into consultas
values ('05/11/2006 8:00','Duarte','45555555','Pereyra Luis','PAMI');

6- Intente ingresar una consulta para un mismo mdico en la misma hora el mismo da
(mensaje de error)
7- Intente cambiar la hora de la consulta de "Acosta Betina" por una no disponible ("8:30")
(error)

8- Cambie la hora de la consulta de "Acosta Betina" por una disponible ("9:30")

9- Ingrese una consulta para el da "06/11/2006" a las 10 hs. para el doctor "Perez"

10- Recupere todos los datos de las consultas de "Lopez" (3 registros)

11- Recupere todos los datos de las consultas programadas para el "05/11/2006 8:00" (2
registros)

12- Muestre da y mes de todas las consultas de "Lopez"

drop table consultas;

ALTER SESSION SET NLS_DATE_FORMAT = 'DD/MM/YYYY HH24:MI';

create table consultas(


fechayhora date not null,
medico varchar2(30) not null,
documento char(8) not null,
paciente varchar2(30),
obrasocial varchar2(30),
primary key(fechayhora,medico)
);

insert into consultas


values ('05/11/2006 8:00','Lopez','12222222','Acosta Betina','PAMI');
insert into consultas
values ('05/11/2006 8:30','Lopez','23333333','Fuentes Carlos','PAMI');

insert into consultas


values ('05/11/2006 8:00','Perez','34444444','Garcia Marisa','IPAM');
insert into consultas
values ('05/11/2006 8:00','Duarte','45555555','Pereyra Luis','PAMI');

insert into consultas


values ('05/11/2006 8:00','Perez','25555555','Mercado Marcos','PAMI');

update consultas set fechayhora='05/11/2006 8:30' where paciente='Acosta


Betina';

update consultas set fechayhora='05/11/2006 9:30' where paciente='Acosta


Betina';

insert into consultas


values ('06/11/2006 10:00','Lopez','25555555','Mercado Marcos','PAMI');

select *from consultas


where medico='Lopez';

select *from consultas


where fechayhora='05/11/2006 8:00';

select extract(day from fechayhora) as dia,


extract(month from fechayhora) as mes
from consultas
where medico='Lopez';

Segundo problema:

Un club dicta clases de distintos deportes. En una tabla llamada "inscriptos" almacena la
informacin necesaria.

1- Elimine la tabla "inscriptos":

drop table inscriptos;

2- La tabla contiene los siguientes campos:

- documento del socio alumno: char(8) not null


- nombre del socio: varchar2(30),
- nombre del deporte (tenis, futbol, natacin, basquet): varchar2(15) not null,
- ao de inscripcion: date,
- matrcula: si la matrcula ha sido o no pagada ('s' o 'n').

3- Necesitamos una clave primaria que identifique cada registro. Un socio puede inscribirse
en varios deportes en distintos aos. Un socio no puede inscribirse en el mismo deporte el
mismo ao. Varios socios se inscriben en un mismo deporte en distintos aos. Cree la tabla
con una clave compuesta:

create table inscriptos(


documento char(8) not null,
nombre varchar2(30),
deporte varchar2(15) not null,
ao date,
matricula char(1),
primary key(documento,deporte,ao)
);

4- Setee el formato de "date" para que nos muestre solamente el ao (no necesitamos las
otras partes de la fecha ni la hora)

5- Inscriba a varios alumnos en el mismo deporte en el mismo ao:

insert into inscriptos


values ('12222222','Juan Perez','tenis','2005','s');
insert into inscriptos
values ('23333333','Marta Garcia','tenis','2005','s');
insert into inscriptos
values ('34444444','Luis Perez','tenis','2005','n');

6- Inscriba a un mismo alumno en varios deportes en el mismo ao:


insert into inscriptos
values ('12222222','Juan Perez','futbol','2005','s');
insert into inscriptos
values ('12222222','Juan Perez','natacion','2005','s');
insert into inscriptos
values ('12222222','Juan Perez','basquet','2005','n');

7- Ingrese un registro con el mismo documento de socio en el mismo deporte en distintos


aos:

insert into inscriptos


values ('12222222','Juan Perez','tenis','2006','s');
insert into inscriptos
values ('12222222','Juan Perez','tenis','2007','s');

8- Intente inscribir a un socio alumno en un deporte en el cual ya est inscripto en un ao en


el cual ya se haya inscripto (mensaje de error)

9- Intente actualizar un registro para que la clave primaria se repita (error)

10- Muestre los nombres y aos de los inscriptos en "tenis" (5 registros)

11- Muestre los nombres y deportes de los inscriptos en el ao 2005 (6 registros)

12- Muestre el deporte y ao de todas las incripciones del socio documento "12222222" (6
registros)

drop table inscriptos;

create table inscriptos(


documento char(8) not null,
nombre varchar2(30),
deporte varchar2(15) not null,
ao date,
matricula char(1),
primary key(documento,deporte,ao)
);

ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY';

insert into inscriptos


values ('12222222','Juan Perez','tenis','2005','s');
insert into inscriptos
values ('23333333','Marta Garcia','tenis','2005','s');
insert into inscriptos
values ('34444444','Luis Perez','tenis','2005','n');

insert into inscriptos


values ('12222222','Juan Perez','futbol','2005','s');
insert into inscriptos
values ('12222222','Juan Perez','natacion','2005','s');
insert into inscriptos
values ('12222222','Juan Perez','basquet','2005','n');
insert into inscriptos
values ('12222222','Juan Perez','tenis','2006','s');
insert into inscriptos
values ('12222222','Juan Perez','tenis','2007','s');

insert into inscriptos


values ('12222222','Juan Perez','tenis','2005','s');

update inscriptos set deporte='tenis'


where documento='12222222' and
deporte='futbol' and
ao='2005';

select nombre,ao from inscriptos


where deporte='tenis';

select nombre,deporte from inscriptos


where ao='2005';

select deporte,ao from inscriptos


where documento='12222222';

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;


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

Problema:

Veamos las secuencias existentes:

select *from all_sequences;

Aparece una tabla que nos muestra todas las secuencias; la columna "SEQUENCE_NAME"
contiene el nombre de cada secuencia; las dems columnas nos informan sobre cada una de
las secuencias de la base de datos actual (propietario, valores mnimo y mximo, valor de
incremento, si es circular o no, etc.).

Vamos a crear una secuencia denominada "sec_codigolibros" para utilizarla en la clave


primaria de la tabla "libros".

En primer lugar vamos a eliminar la secuencia "sec_codigolibros" porque si ya existe no


podremos crear otra con el mismo nombre:

drop sequence sec_codigolibros;

Si la secuencia no existe aparecer un mensaje indicando tal situacin.

Creamos la 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;

Para acceder a las secuencias (que son tablas) empleamos "select" y la tabla "dual".

En primer lugar, debemos inicializar la secuencia:

select sec_codigolibros.nextval from dual;

Nos retorna el valor 1.

Recuperamos el valor actual de nuestra secuencia:

select sec_codigolibros.currval from dual;

Retorna 1.

Eliminamos la tabla "libros" y la creamos con la siguiente estructura:


drop table libros;
create table libros(
codigo number(5) not null,
titulo varchar2(40) not null,
autor varchar2(30),
editorial varchar2(20),
primary key(codigo)
);

Note que al crear la tabla no se hace referencia en ningn momento a la secuencia que luego
servir para dar valores secuenciales a su clave primaria.

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');

Recuerde que "nextval" incrementa la secuencia y retorna el nuevo valor.

Recuperamos todos los registros para ver qu se ha almacenado en "codigo":

select *from libros;

Veamos todos los objetos de la base de datos actual que contengan en su nombre la cadena
"LIBROS":

select object_name,object_type
from all_objects
where object_name like '%LIBROS%';

En la tabla resultado aparecen la tabla "libros" y la secuencia "sec_codigolibros".

Eliminamos la secuencia creada:

drop sequence sec_codigolibros;

Un mensaje indica que la secuencia ha sido eliminada.

Si consultamos todos los objetos de la base de datos veremos que tal secuencia ya no existe:

select object_name,object_type
from all_objects
where object_name like '%LIBROS%';
35 - Secuencias (create sequence - currval - nextval - drop sequence)

Primer problema:
Una empresa registra los datos de sus empleados en una tabla llamada "empleados".

1- Elimine la tabla "empleados":

drop table empleados;

2- Cree la tabla:

create table empleados(


legajo number(3),
documento char(8) not null,
nombre varchar2(30) not null,
primary key(legajo)
);

3- Elimine la secuencia "sec_legajoempleados" y luego crela estableciendo el valor mnimo


(1), mximo (999), valor inicial (100), valor de incremento (2) y no circular. Finalmente
inicialice la secuencia.

4- Ingrese algunos registros, empleando la secuencia creada para los valores de la clave
primaria:

insert into empleados


values (sec_legajoempleados.currval,'22333444','Ana Acosta');
insert into empleados
values (sec_legajoempleados.nextval,'23444555','Betina Bustamante');
insert into empleados
values (sec_legajoempleados.nextval,'24555666','Carlos Caseros');
insert into empleados
values (sec_legajoempleados.nextval,'25666777','Diana Dominguez');
insert into empleados
values (sec_legajoempleados.nextval,'26777888','Estela Esper');

5- Recupere los registros de "libros" para ver los valores de clave primaria.

Note que los valores se incrementaron en 2, porque as se estableci el valor de incremento al


crear la secuencia.

6- Vea el valor actual de la secuencia empleando la tabla "dual". Retorna 108.

7- Recupere el valor siguiente de la secuencia empleando la tabla "dual" Retorna 110.

8- Ingrese un nuevo empleado (recuerde que la secuencia ya tiene el prximo valor, emplee
"currval" para almacenar el valor de legajo)

9- Recupere los registros de "libros" para ver el valor de clave primaria ingresado
anteriormente.

10- Incremente el valor de la secuencia empleando la tabla "dual" (retorna 112)

11- Ingrese un empleado con valor de legajo "112".

12- Intente ingresar un registro empleando "currval":

insert into empleados


values (sec_legajoempleados.currval,'29000111','Hector Huerta');

Mensaje de error porque el legajo est repetido y la clave primaria no puede repetirse.

13- Incremente el valor de la secuencia. Retorna 114.

14- Ingrese el registro del punto 11.

Ahora si lo permite, pues el valor retornado por "currval" no est repetido en la tabla
"empleados".

15- Recupere los registros.

16- Vea las secuencias existentes y analice la informacin retornada.

Debe aparecer "sec_legajoempleados".

17- Vea todos los objetos de la base de datos actual que contengan en su nombre la cadena
"EMPLEADOS".

Debe aparacer la tabla "empleados" y la secuencia "sec_legajoempleados".

18- Elimine la secuencia creada.

19- Consulte todos los objetos de la base de datos que sean secuencias y verifique que
"sec_legajoempleados" ya no existe.

drop table empleados;

create table empleados(


legajo number(3),
documento char(8) not null,
nombre varchar2(30) not null,
primary key(legajo)
);

drop sequence sec_legajoempleados;

create sequence sec_legajoempleados


start with 100
increment by 2
maxvalue 999
minvalue 1;

select sec_legajoempleados.nextval from dual;

insert into empleados


values (sec_legajoempleados.currval,'22333444','Ana Acosta');
insert into empleados
values (sec_legajoempleados.nextval,'23444555','Betina Bustamante');
insert into empleados
values (sec_legajoempleados.nextval,'24555666','Carlos Caseros');
insert into empleados
values (sec_legajoempleados.nextval,'25666777','Diana Dominguez');
insert into empleados
values (sec_legajoempleados.nextval,'26777888','Estela Esper');

select *from empleados;

select sec_legajoempleados.currval from dual;

select sec_legajoempleados.nextval from dual;

insert into empleados


values (sec_legajoempleados.currval,'27888999','Federico Fuentes');

select *from empleados;

select sec_legajoempleados.nextval from dual;

insert into empleados


values (112,'28999000','Gaston Gonzalez');

insert into empleados


values (sec_legajoempleados.currval,'29000111','Hector Huerta');

select sec_legajoempleados.nextval from dual;

insert into empleados


values (sec_legajoempleados.currval,'29000111','Hector Huerta');

select *from empleados;

select *from all_sequences;

select object_name,object_type
from all_objects
where object_name like '%EMPLEADOS%';

drop sequence sec_legajoempleados;

select object_name,object_type
from all_objects
where object_type='SEQUENCE';

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.

36 - Alterar secuencia (alter sequence)

Problema:

Eliminamos la secuencia "sec_codigolibros":

drop sequence sec_codigolibros;

La creamos definiendo 1 como valor de inicio, 1 de incremento, 999 como valor mximo, 1
como mnimo valor y no circular:

create sequence sec_codigolibros


start with 1
increment by 1
maxvalue 999
minvalue 1
nocycle;

Vemos la informacin sobre la secuencia creada anteriormente:

select *from all_sequences where sequence_name='SEC_CODIGOLIBROS';

Alteramos la secuencia para que el mximo valor sea 99999 y se incremente de a 2:

alter sequence sec_codigolibros


increment by 2
maxvalue 99999;

Veamos la informacin de la secuencia modificada consultando "all_sequences":

select *from all_sequences where sequence_name='SEC_CODIGOLIBROS';

Ahora el valor de incremento es 2 y el mximo 99999, los dems valores permanecen como
fueron definidos.

36 - Alterar secuencia (alter sequence)

Primer problema:

Una empresa registra los datos de sus empleados en una tabla llamada "empleados".
1- Elimine la tabla "empleados":

drop table empleados;

2- Cree la tabla:

create table empleados(


legajo number(3),
documento char(8) not null,
nombre varchar2(30) not null,
primary key(legajo)
);

3- Elimine la secuencia "sec_legajoempleados" y luego crela estableciendo el valor mnimo


(1), mximo (210), valor inicial (206), valor de incremento (2) y no circular. Finalmente
inicialice la secuencia.

4- Ingrese algunos registros, empleando la secuencia creada para los valores de la clave
primaria.

insert into empleados


values (sec_legajoempleados.currval,'22333444','Ana Acosta');
insert into empleados
values (sec_legajoempleados.nextval,'23444555','Betina Bustamante');
insert into empleados
values (sec_legajoempleados.nextval,'24555666','Carlos Caseros');

5- Recupere los registros de "libros" para ver los valores de clave primaria.

6- Vea el valor actual de la secuencia empleando la tabla "dual"

7- Intente ingresar un registro empleando "nextval":

insert into empleados


values (sec_legajoempleados.nextval,'25666777','Diana Dominguez');

Oracle muestra un mensaje de error indicando que la secuencia ha llegado a su valor mximo.

8- Altere la secuencia modificando el atributo "maxvalue" a 999.

9- Obtenga informacin de la secuencia.

10- Ingrese el registro del punto 7.

11- Recupere los registros.

12- Modifique la secuencia para que sus valores se incrementen en 1.

13- Ingrese un nuevo registro:

insert into empleados


values (sec_legajoempleados.nextval,'26777888','Federico Fuentes');

14- Recupere los registros.


15- Elimine la secuencia creada.

16- Consulte todos los objetos de la base de datos que sean secuencias y verifique que
"sec_legajoempleados" ya no existe.

drop table empleados;

create table empleados(


legajo number(3),
documento char(8) not null,
nombre varchar2(30) not null,
primary key(legajo)
);

drop sequence sec_legajoempleados;

create sequence sec_legajoempleados


start with 206
increment by 2
maxvalue 210
minvalue 1;

select sec_legajoempleados.nextval from dual;

insert into empleados


values (sec_legajoempleados.currval,'22333444','Ana Acosta');
insert into empleados
values (sec_legajoempleados.nextval,'23444555','Betina Bustamante');
insert into empleados
values (sec_legajoempleados.nextval,'24555666','Carlos Caseros');

select *from empleados;

select sec_legajoempleados.currval from dual;

insert into empleados


values (sec_legajoempleados.nextval,'25666777','Diana Dominguez');

alter sequence sec_legajoempleados maxvalue 999;

select *from all_sequences where sequence_name='SEC_LEGAJOEMPLEADOS';

insert into empleados


values (sec_legajoempleados.nextval,'25666777','Diana Dominguez');

select *from empleados;

alter sequence sec_legajoempleados increment by 1;

insert into empleados


values (sec_legajoempleados.nextval,'26777888','Federico Fuentes');

select *from empleados;


drop sequence sec_legajoempleados;

select object_name,object_type
from all_objects
where object_type='SEQUENCE';

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).

38 - Restriccin primary key

Problema:

Trabajamos con la tabla "libros" de una librera.


Eliminamos la tabla:

drop table libros;

La creamos estableciendo el campo cdigo como clave primaria:

create table libros(


codigo number(5),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(15),
primary key (codigo)
);

Veamos la restriccin "primary key" que cre automticamente Oracle:

select *from user_constraints where table_name='LIBROS';

Aparece la siguiente informacin simplificada:

OWNER CONSTRAINT_NAME CONSTRAINT_TYPE TABLE_NAME


------------------------------------------------------------------
SYSTEM SYS_C004427 P LIBROS

Nos informa que la tabla "libros" (TABLE_NAME) tiene una restriccin de tipo "primary key"
(muestra "P" en "CONSTRAINT_TYPE") creada por "SYSTEM" (OWNER) cuyo nombre es
"SYS_C004427" (nombre dado por Oracle).

Vamos a eliminar la tabla y la crearemos nuevamente, sin establecer la clave primaria:


drop table libros;
create table libros(
codigo number(5),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(15)
);

Ingresamos 2 registros con valor de cdigo repetido:

insert into libros values(1,'El aleph','Borges','Emece');


insert into libros values(1,'Ilusiones','Bach','Planeta');

Si intentamos agregar una restriccin "primary key" a la tabla, aparecer un mensaje


indicando que la clave primaria se viola y proponiendo que se elimine la clave repetida.

Modificamos el cdigo repetido:

update libros set codigo=2 where titulo='Ilusiones';

Ahora si podremos definir la restriccin "primary key" para nuestra tabla "libros":

alter table libros


add constraint PK_libros_codigo
primary key(codigo);

Veamos la informacin respecto a ella:

select *from user_constraints where table_name='LIBROS';

Aparece la siguiente informacin simplificada:

OWNER CONSTRAINT_NAME CONSTRAINT_TYPE TABLE_NAME


------------------------------------------------------------------
SYSTEM PK_LIBROS_CODIGO P LIBROS

Nos informa que la tabla "libros" (TABLE_NAME) tiene una restriccin de tipo "primary key"
(muestra "P" en "CONSTRAINT_TYPE") creada por "SYSTEM" (OWNER) cuyo nombre es
"PK_libros_codigo" (nombre dado por nosotros al agregarla).

Si intentamos ingresar un registro con un valor para el campo "codigo" que ya existe, no lo
permite:

insert into libros values(1,'El quijote de la


mancha','Cervantes','Emece');

Tampoco permite modificar un cdigo colocando uno existente:

update libros set codigo=1 where titulo='Ilusiones';

Tampoco podemos ingresar en "codigo" un valor nulo:

insert into libros values(null,'El quijote de la


mancha','Cervantes','Emece');
El campo, luego de agregarse la restriccin "primary key" se estableci como "not null";
podemos verificarlo:

describe libros;

Si intentamos agregar otra restriccin "primary key", Oracle no lo permite:

alter table libros


add constraint PK_libros_titulo
primary key(titulo);

Un mensaje nos indica que la tabla solamente puede tener UNA clave primaria.

Veamos lo que nos informa el catlogo "user_const_columns":

select *from user_cons_columns where table_name='LIBROS';

Nos muestra la siguiente informacin:

OWNER CONSTRAINT_NAME TABLE_NAME COLUMN_NAME POSITION


----------------------------------------------------------------------
---
SYSTEM PK_LIBROS_CODIGO LIBROS CODIGO 1
38 - Restriccin primary key

Primer problema:

Una empresa tiene registrados datos de sus empleados en una tabla llamada "empleados".

1- Elimine la tabla:

drop table empleados;

2- Crela con la siguiente estructura:

create table empleados (


documento char(8),
nombre varchar2(30),
seccion varchar2(20)
);

3- Ingrese algunos registros, dos de ellos con el mismo nmero de documento:

4- Intente establecer una restriccin "primary key" para la tabla para que el documento no se
repita ni admita valores nulos.
No lo permite porque la tabla contiene datos que no cumplen con la restriccin, debemos
eliminar (o modificar) el registro que tiene documento duplicado.

5- Establecezca la restriccin "primary key" del punto 4

6- Intente actualizar un documento para que se repita.


No lo permite porque va contra la restriccin.

7-Intente establecer otra restriccin "primary key" con el campo "nombre".


8- Vea las restricciones de la tabla "empleados" consultando el catlogo "user_constraints" (1
restriccin "P")

9- Consulte el catlogo "user_cons_columns"

drop table empleados;

create table empleados (


documento char(8),
nombre varchar2(30),
seccion varchar2(20)
);

insert into empleados


values ('22222222','Alberto Lopez','Sistemas');
insert into empleados
values ('23333333','Beatriz Garcia','Administracion');
insert into empleados
values ('23333333','Carlos Fuentes','Administracion');

alter table empleados


add constraint PK_empleados_documento
primary key(documento);

delete from empleados


where nombre='Carlos Fuentes';

alter table empleados


add constraint PK_empleados_documento
primary key(documento);

update empleados set documento='22222222'


where documento='23333333';

alter table empleados


add constraint PK_empleados_nombre
primary key(nombre);

select *from user_constraints where table_name='EMPLEADOS';

select *from user_cons_columns where table_name='EMPLEADOS';

Segundo problema:

Una empresa de remises tiene registrada la informacin de sus vehculos en una tabla llamada
"remis".

1- Elimine la tabla:
drop table remis;

2- Cree la tabla con la siguiente estructura:

create table remis(


numero number(5),
patente char(6),
marca varchar2(15),
modelo char(4)
);

3- Ingrese algunos registros sin repetir patente y repitiendo nmero.

4- Ingrese un registro con patente nula.

5- Intente definir una restriccin "primary key" para el campo "numero".

6- Intente establecer una restriccin "primary key" para el campo "patente".

7- Modifique el valor "null" de la patente.

8- Establezca una restriccin "primary key" del punto 6.

9- Vea la informacin de las restricciones consultando "user_constraints" (1 restriccin "P")

10- Consulte el catlogo "user_cons_columns" y analice la informacin retornada (1


restriccin)

drop table remis;

create table remis(


numero number(5),
patente char(6),
marca varchar2(15),
modelo char(4)
);

insert into remis values(1,'ABC123','Renault 12','1990');


insert into remis values(1,'DEF456','Fiat Duna','1995');

insert into remis values(2,null,'Renault Clio','1990');

alter table remis


add constraint PK_remis_numero
primary key(numero);

alter table remis


add constraint PK_remis_patente
primary key(patente);

update remis set patente='AIC222' where patente is null;

alter table remis


add constraint PK_remis_patente
primary key(patente);

select *from user_constraints where table_name='REMIS';

select *from user_cons_columns where table_name='REMIS';

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).

39 - Restriccin unique

Problema:

Trabajamos con la tabla "alumnos".


Eliminamos la tabla:

drop table alumnos;

Creamos la tabla:

create table alumnos(


legajo char(4),
apellido varchar2(20),
nombre varchar2(20),
documento char(8)
);

Agregamos una restriccin "primary" para el campo "legajo":

alter table alumnos


add constraint PK_alumnos_legajo
primary key(legajo);

Agregamos una restriccin "unique" para el campo "documento":

alter table alumnos


add constraint UQ_alumnos_documento
unique (documento);

Ingresamos algunos registros:

insert into alumnos values('A111','Lopez','Ana','22222222');


insert into alumnos values('A123','Garcia','Maria','23333333');

Intentamos ingresar un documento repetido:

insert into alumnos values('A230','Perez','Juan','23333333');


aparece un mensaje de error indicando que se viola la restriccin nica.

Intentamos ingresar un legajo repetido:

insert into alumnos values('A123','Suarez','Silvana','30111222');

aparece un mensaje de error indicando que se viola la restriccin "primary key".

Veamos las restricciones de la tabla "alumnos" consultando el catlogo "user_constraints":

select *from user_constraints where table_name='ALUMNOS';

Aparecen las dos restricciones creadas anteriormente:

OWNER CONSTRAINT_NAME CONSTRAINT_TYPE


TABLE_NAME
----------------------------------------------------------------------
----
SYSTEM PK_ALUMNOS_LEGAJO P ALUMNOS
SYSTEM UQ_ALUMNOS_DOCUMENTO U ALUMNOS

Veamos la informacin de "user_cons_columns":

select *from user_cons_columns where table_name='ALUMNOS';

Nos informa:

OWNER CONSTRAINT_NAME TABLE_NAME COLUMN_NAME


POSITION
----------------------------------------------------------------------
----------
SYSTEM UQ_ALUMNOS_DOCUMENTO ALUMNOS DOCUMENTO 1
SYSTEM PK_ALUMNOS_LEGAJO ALUMNOS LEGAJO 1
39 - Restriccin unique

Primer problema:

Una empresa de remises tiene registrada la informacin de sus vehculos en una tabla llamada
"remis".

1- Elimine la tabla:

drop table remis;

2- Cree la tabla con la siguiente estructura:

create table remis(


numero number(5),
patente char(6),
marca varchar2(15),
modelo char(4)
);

3- Ingrese algunos registros, 2 de ellos con patente repetida y alguno con patente nula.
4- Agregue una restriccin "primary key" para el campo "numero".

5- Intente agregar una restriccin "unique" para asegurarse que la patente del remis no
tomar valores repetidos.

No se puede porque hay valores duplicados, un mensaje indica que se encontraron claves
duplicadas.

6- Elimine el registro con patente duplicada y establezca la restriccin.

Note que hay 1 registro con valor nulo en "patente".

7- Intente ingresar un registro con patente repetida (no lo permite)

8- Ingrese un registro con valor nulo para el campo "patente".

9- Muestre la informacin de las restricciones consultando "user_constraints" y


"user_cons_columns" y analice la informacin retornada (2 filas en cada consulta)

drop table remis;

create table remis(


numero number(5),
patente char(6),
marca varchar2(15),
modelo char(4)
);

insert into remis values(1,'ABC123','Renault clio','1990');


insert into remis values(2,'DEF456','Peugeot 504','1995');
insert into remis values(3,'DEF456','Fiat Duna','1998');
insert into remis values(4,'GHI789','Fiat Duna','1995');
insert into remis values(5,null,'Fiat Duna','1995');

alter table remis


add constraint PK_remis_numero
primary key(numero);

alter table remis


add constraint UQ_remis_patente
unique(patente);

delete from remis where numero=3;

alter table remis


add constraint UQ_remis_patente
unique(patente);

insert into remis values(6,'ABC123','Renault 11','1995');

insert into remis values(7,null,'Renault 11','1995');

select *from user_constraints where table_name='REMIS';


select *from user_cons_columns where table_name='REMIS';

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);

40 - Restriccion check

Problema:

Trabajamos con la tabla "libros" de una librera.


Eliminamos la tabla:

drop table libros;

La creamos e ingresamos algunos registros:

create table libros(


codigo number(5),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(15),
preciomin number(5,2),
preciomay number(5,2)
);

insert into libros values (1,'Uno','Bach','Planeta',22,20);


insert into libros values (2,'El quijote','Cervantes','Emece',15,13);
insert into libros values (3,'Aprenda PHP','Mario Molina','Siglo
XXI',53,48);
insert into libros values (4,'Java en 10 minutos','Garcia','Siglo
XXI',35,40);

Agregamos una restriccin "primary key" para el campo "codigo":

alter table libros


add constraint PK_libros_codigo
primary key (codigo);
Agregamos una restriccin nica, la clave nica consta de 3 campos, "titulo", "autor" y
"editorial":

alter table libros


add constraint UQ_libros
unique (titulo,codigo,editorial);

Agregamos una restriccin "check" para asegurar que los valores de los campos
correspondientes a precios no puedan ser negativos:

alter table libros


add constraint CK_libros_precios_positivo
check (preciomin>=0 and preciomay>=0);

Intentamos ingresar un valor invlido para algn campo correspondiente al precio, que vaya
en contra de la restriccin (por ejemplo el valor "-15"):

insert into libros values (5,'Matematica estas ahi','Paenza','Siglo


XXI',-15,30);

aparecer un mensaje de error indicando que hay conflicto con la restriccin de control
creada anteriormente y la insercin no se realiza.

Igualmente si intentamos actualizar un precio, que vaya en contra de la restriccin:

update libros set preciomay=-20 where titulo='Uno';

Si intentamos agregar una restriccin que no permita que el precio mayorista supere el precio
minorista:

alter table libros


add constraint CK_libros_preciominmay
check (preciomay<=preciomin);

aparece un mensaje de error y la sentencia no se ejecuta, porque hay un registro que no


cumple con la restriccin que intentamos establecer. Podemos modificar los datos que no
cumplen la condicin de la restriccin:

update libros set preciomay=30


where titulo='Java en 10 minutos';

Ahora Oracle si nos permite agregar la restriccin "check" que impida que se ingresen valores
para "preciomay" superiores a "preciomin":

alter table libros


add constraint CK_libros_preciominmay
check (preciomay<=preciomin);

Veamos las restricciones de la tabla:

select *from user_constraints where table_name='LIBROS';

Aparece la siguiente tabla (simplificada) resultado:

OWNER CONSTRAINT_NAME CONSTRAINT_TYPE


TABLE_NAME SEARCH_CONDITION
----------------------------------------------------------------------
----------------------------
SYSTEM PK_LIBROS_CODIGO P LIBROS
SYSTEM UQ_LIBROS U LIBROS
SYSTEM CK_LIBROS_PRECIOS_POSITIVO C LIBROS preciomin
SYSTEM CK_LIBROS_PRECIOMINMAY C LIBROS preciomay

Note que en el caso de las restricciones de control, en las cuales muestra "C" en el tipo de
constraint, la columna "SEARCH_CONDITION" muestra la regla que debe cumplirse; en caso de
ser una restriccin "primary key" o unique", esa columna queda vaca.

Intentamos ingresar un registro que infrinja la restriccin "CK_libros_preciominmax":

insert into libros values (6,'El gato con


botas',null,'Planeta',25,30);

Mensaje de error.

Consultamos "user_cons_columns":

select *from user_cons_columns where table_name='LIBROS';

Aparece la siguiente informacin simplificada:

OWNER CONSTRAINT_NAME TABLE_NAME


COLUMN_NAME POSITION
----------------------------------------------------------------------
-------------------
SYSTEM PK_LIBROS_CODIGO LIBROS CODIGO 1
SYSTEM UQ_LIBROS LIBROS EDITORIAL 3
SYSTEM UQ_LIBROS LIBROS CODIGO 2
SYSTEM UQ_LIBROS LIBROS TITULO 1
SYSTEM CK_LIBROS_PRECIOS_POSITIVO LIBROS PRECIOMAY
SYSTEM CK_LIBROS_PRECIOS_POSITIVO LIBROS PRECIOMIN
SYSTEM CK_LIBROS_PRECIOMINMAY LIBROS PRECIOMAY
SYSTEM CK_LIBROS_PRECIOMINMAY LIBROS PRECIOMIN

Analizamos la informacin: la tabla tiene 4 restricciones, 1 "primary key", 1 "unique" y 2


"check". La restriccin "primarykey" ocupa una sola fila porque fue definida para 1 solo
campo, por ello, en la columna "POSITION" aparece "1". La restriccin nica ocupa tres filas
porque fue definida con 3 campos cuyo orden est indicado en la columna "POSITION". La
columna "POSITION" muestra informacin si la restriccin es "primary key" o "unique"
indicando el orden de los campos. La restriccin de control "CK_libros_precios_positivo" ocupa
2 filas porque en su definicin se nombran 2 campos (indicados en "COLUMN_NAME"). La
restriccin de control "CK_libros_preciominmax" ocupa 2 filas porque en su definicin se
nombran 2 campos (indicados en "COLUMN_NAME").

40 - Restriccion check

Primer problema:

Una empresa tiene registrados datos de sus empleados en una tabla llamada "empleados".
1- Elimine la tabla:

drop table empleados;


2- Crela con la siguiente estructura:

create table empleados (


documento char(8),
nombre varchar2(30),
cantidadhijos number(2),
seccion varchar2(20),
sueldo number(6,2) default -1
);

3- Agregue una restriccin "check" para asegurarse que no se ingresen valores negativos para
el sueldo.

Note que el campo "sueldo" tiene establecido un valor por defecto (el valor -1) que va contra
la restriccin; Oracle no controla esto, permite establecer la restriccin, pero al intentar
ingresar un registro con el valor por defecto en tal campo, muestra un mensaje de error.

4- Intente ingresar un registro con la palabra clave "default" en el campo "sueldo" (mensaje de
error)

5- Ingrese algunos registros vlidos:

insert into empleados values ('22222222','Alberto Lopez',1,'Sistemas',1000);


insert into empleados values ('33333333','Beatriz Garcia',2,'Administracion',3000);
insert into empleados values ('34444444','Carlos Caseres',0,'Contadura',6000);

6- Intente agregar otra restriccin "check" al campo sueldo para asegurar que ninguno supere
el valor 5000.
La sentencia no se ejecuta porque hay un sueldo que no cumple la restriccin.

7- Elimine el registro infractor y vuelva a crear la restriccin

8- Establezca una restriccin "check" para "seccion" que permita solamente los valores
"Sistemas", "Administracion" y "Contadura".

9- Ingrese un registro con valor "null" en el campo "seccion".

10- Establezca una restriccin "check" para "cantidadhijos" que permita solamente valores
entre 0 y 15.

11- Vea todas las restricciones de la tabla (4 filas)

12- Intente agregar un registro que vaya contra alguna de las restricciones al campo "sueldo".
Mensaje de error porque se infringe la restriccin "CK_empleados_sueldo_positivo".

13- Intente modificar un registro colocando en "cantidadhijos" el valor "21".

14- Intente modificar el valor de algn registro en el campo "seccion" cambindolo por uno
que no est incluido en la lista de permitidos.

15- Intente agregar una restriccin al campo seccin para aceptar solamente valores que
comiencen con la letra "B".

Note que NO se puede establecer esta restriccin porque va en contra de la establecida


anteriormente para el mismo campo, si lo permitiera, no podramos ingresar ningn valor
para "seccion".
16- Agregue un registro con documento nulo.

17- Intente agregar una restriccin "primary key" para el campo "documento".
No lo permite porque existe un registro con valor nulo en tal campo.

18- Elimine el registro que infringe la restriccin y establezca la restriccin del punto 17.

19- Consulte "user_constraints", mostrando los campos "constraint_name", "constraint_type" y


"search_condition" de la tabla "empleados" (5 filas)

20- Consulte el catlogo "user_cons_colums" recuperando el nombre de las restricciones


establecidas en el campo sueldo de la tabla "empleados" (2 filas)

drop table empleados;

create table empleados (


documento char(8),
nombre varchar2(30),
cantidadhijos number(2),
seccion varchar2(20),
sueldo number(6,2) default -1
);

alter table empleados


add constraint CK_empleados_sueldo_positivo
check (sueldo>0);

insert into empleados values ('33555888','Juan Pereyra',1,'Sistemas',default);

insert into empleados values ('22222222','Alberto Lopez',1,'Sistemas',1000);


insert into empleados values ('33333333','Beatriz Garcia',2,'Administracion',3000);
insert into empleados values ('34444444','Carlos Caseres',0,'Contadura',6000);

alter table empleados


add constraint CK_empleados_sueldo_maximo
check (sueldo<=5000);

delete from empleados where sueldo=6000;

alter table empleados


add constraint CK_empleados_sueldo_maximo
check (sueldo<=5000);

alter table empleados


add constraint CK_empleados_seccion_lista
check (seccion in ('Sistemas','Administracion','Contaduria'));

insert into empleados


values ('31111222','Roberto Sanchez',1,null,1500);

alter table empleados


add constraint CK_cantidadhijos
check (cantidadhijos between 0 and 15);
select *from user_constraints where table_name='EMPLEADOS';

insert into empleados


values ('24444444','Carlos Fuentes',2,'Administracion',-1500);

update empleados set cantidadhijos=21 where documento='22222222';

update empleados set seccion='Recursos' where documento='22222222';

alter table empleados


add constraint CK_seccion_letrainicial
check (seccion like '%B');

insert into empleados values(null,'Federico Torres',1,'Sistemas',1800);

alter table empleados


add constraint PK_empleados_documento
primary key (documento);

delete from empleados where nombre='Federico Torres';


alter table empleados
add constraint PK_empleados_documento
primary key (documento);

select constraint_name, constraint_type, search_condition


from user_constraints
where table_name='EMPLEADOS';

select constraint_name
from user_cons_columns
where table_name='EMPLEADOS' and
column_name='SUELDO';

Segundo problema:

Una playa de estacionamiento almacena los datos de los vehculos que ingresan en la tabla
llamada "vehiculos".

1- Setee el formato de "date" para que nos muestre da, mes, ao, hora y minutos:

alter session set NLS_DATE_FORMAT = 'DD/MM/YYYY HH24:MI';

2- Elimine la tabla "vehiculos" y crela con la siguiente estructura:

drop table vehiculos;

create table vehiculos(


numero number(5),
patente char(6),
tipo char(4),
fechahoraentrada date,
fechahorasalida date
);

3- Ingrese algunos registros:

insert into vehiculos values(1,'AIC124','auto','17/01/2007 8:05','17/01/2007


12:30');
insert into vehiculos values(2,'CAA258','auto','17/01/2007 8:10',null);
insert into vehiculos values(3,'DSE367','moto','17/01/2007 8:30','17/01/2007
18:00');

4- Agregue una restriccin de control que especifique que el campo "tipo" acepte solamente
los valores "auto" y "moto":

alter table vehiculos


add constraint CK_vehiculos_tipo_valores
check (tipo in ('auto','moto'));

5- Intente modificar el valor del campo "tipo" ingresando un valor inexistente en la lista de
valores permitidos por la restriccin establecida a dicho campo.

6- Ingrese un registro con valor nulo para "tipo".

7- Agregue una restriccin de control al campo "fechahoraentrada" que establezca que sus
valores no sean posteriores a "fechahorasalida".

8- Intente modificar un registro para que la salida sea anterior a la entrada.

9- Vea todas las restricciones para la tabla "vehiculos".

10- Ingrese un registro con valor nulo para "fechahoraentrada".

11- Vea todos los registros.

12- Consulte "user_cons_columns" y analice la informacin retornada.

alter session set NLS_DATE_FORMAT = 'DD/MM/YYYY HH24:MI';

drop table vehiculos;

create table vehiculos(


numero number(5),
patente char(6),
tipo char(4),
fechahoraentrada date,
fechahorasalida date
);

insert into vehiculos values(1,'AIC124','auto','17/01/2007 8:05','17/01/2007


12:30');
insert into vehiculos values(2,'CAA258','auto','17/01/2007 8:10',null);
insert into vehiculos values(3,'DSE367','moto','17/01/2007 8:30','17/01/2007
18:00');
alter table vehiculos
add constraint CK_vehiculos_tipo_valores
check (tipo in ('auto','moto'));

update vehiculos set tipo='bici' where patente='AIC124';

insert into vehiculos values(4,'SDF134',null,null,null);

alter table vehiculos


add constraint CK_vehiculos_entradasalida
check (fechahoraentrada<=fechahorasalida);

update vehiculos set fechahorasalida='17/01/2007 7:30'


where patente='CAA258';

select *from user_constraints where table_name='VEHICULOS';

insert into vehiculos values(8,'DFR156','moto',null,default);

select *from vehiculos;

select *from user_cons_columns where table_name='VEHICULOS';

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.

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


- disable)

Problema:

Trabajamos con la tabla "libros" de una librera.


Eliminamos la tabla:

drop table libros;

La creamos e ingresamos algunos registros:

create table libros(


codigo number(5),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(15),
precio number(5,2)
);

insert into libros values (1,'Uno','Bach','Planeta',22);


insert into libros values (2,'El quijote','Cervantes','Emece',15);
insert into libros values (2,'Aprenda PHP','Mario Molina','Siglo
XXI',-40);

Intentamos agregar una restriccin "primary key" para asegurar que los cdigos no se repitan,
pero como ya tenemos almacenado registros que infringen la restriccin, Oracle nos mostrar
un mensaje de error:

alter table libros


add constraint PK_libros_codigo
primary key (codigo);

Vamos a especificar que no haya comprobacin de datos existentes agregando "disable" y


"novalidate":

alter table libros


add constraint PK_libros_codigo
primary key (codigo) disable novalidate;

Veamos lo que nos informa "user_constraints":

select constraint_name, constraint_type, status, validated


from user_constraints
where table_name='LIBROS';

Aparece la siguiente tabla:

CONSTRAINT_NAME CONSTRAINT_TYPE STATUS VALIDATED


----------------------------------------------------------------------
----
PK_LIBROS_CODIGO P DISABLED NOT
VALIDATED

La columna "status" nos informa que est deshabilitada (Disabled).

Si ingresamos un registro con cdigo existente, Oracle lo permite, porque la restriccin est
en estado "disabled":

insert into libros values (2,'Momo','Michael Ende','Alfaragua',25);

Intentamos habilitar la restriccin sin verificar los datos ya almacenados:

alter table libros


enable novalidate constraint PK_libros_codigo;

No lo permite, aun cuando especificamos que no valide los datos existentes, Oracle realiza la
verificacin igualmente.

Eliminamos los registros con clave duplicada:

delete libros where titulo='El quijote';


delete libros where titulo='Momo';

Ahora Oracle permite habilitar la restriccin:

alter table libros


enable novalidate constraint PK_libros_codigo;

Si intentamos actualizar un registro repitiendo la clave primaria, Oracle no lo permite:

insert into libros values (2,'Momo','Michael Ende','Alfaragua',25);

Veamos lo que nos informa "user_constraints":

select constraint_name, constraint_type, status, validated


from user_constraints
where table_name='LIBROS';

Aparece la siguiente tabla:

CONSTRAINT_NAME CONSTRAINT_TYPE STATUS VALIDATED


----------------------------------------------------------------------
----
PK_LIBROS_CODIGO P ENABLED NOT
VALIDATED

Intentamos agregamos una restriccin "check" que no permita valores negativos para el
precio:

alter table libros


add constraint CK_libros_precio
check(precio>=0);
Oracle no lo permite porque, por defecto, la opcin es "validate" y existen precios que violan
la restriccin que intentamos establecer.

Agregamos la restriccin especificando que no valide los datos almacenados:

alter table libros


add constraint CK_libros_precio
check(precio>=0) novalidate;

Veamos el estado de la restriccin de control:

select constraint_type, status, validated


from user_constraints
where table_name='LIBROS' and
constraint_name='CK_LIBROS_PRECIO';

El resultado es el siguiente:

CONSTRAINT_TYPE STATUS VALIDATED


-----------------------------------------------------
C ENABLED NOT VALIDATED

Si intentamos ingresar un valor negativo para el precio, aparecer un mensaje de error,


porque la restriccin de control creada est habilitada:

insert into libros values (3,'Momo','Michael Ende','Alfaragua',-25);

Deshabilitamos la restriccin "CK_libros_precio":

alter table libros


disable constraint CK_libros_precio;

Veamos el estado actual:

select constraint_type, status, validated


from user_constraints
where table_name='LIBROS' and
constraint_name='CK_LIBROS_PRECIO';

Nos muestra que est deshabilitada y no valida los datos existentes.

Ahora si podemos ingresar el registro:

insert into libros values (3,'Momo','Michael Ende','Alfaragua',-25);

Habilitamos la restriccin para futuros ingresos pero no para los existentes:

alter table libros


enable novalidate constraint CK_libros_precio;

Note que Oracle lo permite, no valida los datos existentes, pero si fuera otro tipo de
restriccin, no lo permitira.

Consultamos "user_constraints":

select constraint_type, status, validated


from user_constraints
where table_name='LIBROS' and
constraint_name='CK_LIBROS_PRECIO';

Nos muestra que est habilitada y no valida los datos existentes.

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


- disable)

Primer problema:

Una empresa tiene registrados datos de sus empleados en una tabla llamada "empleados".
1- Elimine la tabla:

drop table empleados;

2- Crela con la siguiente estructura e ingrese los registros siguientes:

create table empleados (


codigo number(6),
documento char(8),
nombre varchar2(30),
seccion varchar2(20),
sueldo number(6,2)
);

insert into empleados


values (1,'22222222','Alberto Acosta','Sistemas',-10);
insert into empleados
values (2,'33333333','Beatriz Benitez','Recursos',3000);
insert into empleados
values (3,'34444444','Carlos Caseres','Contaduria',4000);

3- Intente agregar una restriccin "check" para asegurarse que no se ingresen valores
negativos para el sueldo sin especificar validacin ni estado:

alter table empleados


add constraint CK_empleados_sueldo_positivo
check (sueldo>=0);

No se permite porque hay un valor negativo almacenado y por defecto la opcin es "validate".

5- Vuelva a intentarlo agregando la opcin "novalidate".

6- Intente ingresar un valor negativo para sueldo.

7- Deshabilite la restriccin e ingrese el registro anterior.

8- Intente establecer una restriccin "check" para "seccion" que permita solamente los valores
"Sistemas", "Administracion" y "Contadura" sin especificar validacin:

alter table empleados


add constraint CK_empleados_seccion_lista
check (seccion in ('Sistemas','Administracion','Contaduria'));
No lo permite porque existe un valor fuera de la lista.

9- Establezca la restriccin anterior evitando que se controlen los datos existentes.

10- Vea si las restricciones de la tabla estn o no habilitadas y validadas.


Muestra 2 filas, una por cada restriccin; ambas son de control, ninguna valida los datos
existentes, "CK_empleados_sueldo_positivo" est deshabilitada, la otra habilitada.

11- Habilite la restriccin deshabilitada.


Note que existe un sueldo que infringe la condicin.

12- Intente modificar la seccin del empleado "Carlos Caseres" a "Recursos"


No lo permite.

13- Deshabilite la restriccin para poder realizar la actualizacin del punto precedente.

14- Agregue una restriccin "primary key" para el campo "codigo" deshabilitada.

15- Ingrese un registro con cdigo existente.

16- Intente habilitar la restriccin.


No se permite porque aun cuando se especifica que no lo haga, Oracle verifica los datos
existentes, y existe un cdigo repetido.

17- Modifique el registro con clave primaria repetida.

18- Habilite la restriccin "primary key"

19- Agregue una restriccin "unique" para el campo "documento"

20- Vea todas las restricciones de la tabla "empleados"


Muestra las 4 restricciones: 2 de control (1 habilitada y la otra no, no validan datos
existentes), 1 "primary key" (habilitada y no valida datos existentes) y 1 nica (habilitada y
valida los datos anteriores).

21- Deshabilite todas las restricciones de "empleados"

22- Ingrese un registro que viole todas las restricciones.

23- Habilite la restriccin "CK_empleados_sueldo_positivo" sin validar los datos existentes.

24- Habilite la restriccin "CK_empleados_seccion_lista" sin validar los datos existentes.

25- Intente habilitar la restriccin "PK_empleados_codigo" sin validar los datos existentes.

26- Intente habilitar la restriccin "UQ_empleados_documento" sin validar los datos


existentes.

27- Elimine el registro que infringe con las restricciones "primary key" y "unique".

28- Habilite las restricciones "PK_empleados_codigo" y "UQ_empleados_documento" sin validar


los datos existentes.

29- Consulte el catlogo "user_constraints" y analice la informacin.


drop table empleados;

create table empleados (


codigo number(6),
documento char(8),
nombre varchar2(30),
seccion varchar2(20),
sueldo number(6,2)
);

insert into empleados


values (1,'22222222','Alberto Acosta','Sistemas',-10);
insert into empleados
values (2,'33333333','Beatriz Benitez','Recursos',3000);
insert into empleados
values (3,'34444444','Carlos Caseres','Contaduria',4000);

alter table empleados


add constraint CK_empleados_sueldo_positivo
check (sueldo>=0);

alter table empleados


add constraint CK_empleados_sueldo_positivo
check (sueldo>=0) novalidate;

insert into empleados


values (4,'35555555','Daniel Duarte','Administracion',-2000);

alter table empleados


disable novalidate
constraint CK_empleados_sueldo_positivo;

insert into empleados


values (4,'35555555','Daniel Duarte','Administracion',-2000);

alter table empleados


add constraint CK_empleados_seccion_lista
check (seccion in ('Sistemas','Administracion','Contaduria'));

alter table empleados


add constraint CK_empleados_seccion_lista
check (seccion in ('Sistemas','Administracion','Contaduria')) novalidate;

select constraint_name, constraint_type, status, validated


from user_constraints
where table_name='EMPLEADOS';

alter table empleados


enable novalidate constraint CK_empleados_sueldo_positivo;

update empleados set seccion='Recursos' where nombre='Carlos Caseres';

alter table empleados


disable novalidate constraint CK_empleados_seccion_lista;
update empleados set seccion='Recursos' where nombre='Carlos Caseres';

alter table empleados


add constraint PK_empleados_codigo
primary key (codigo) disable;

insert into empleados


values (4,'22333444','Federico Fuentes',null,null);

alter table empleados


enable novalidate constraint PK_empleados_codigo;

update empleados set codigo=5 where nombre='Federico Fuentes';

alter table empleados


enable novalidate constraint PK_empleados_codigo;

alter table empleados


add constraint UQ_empleados_documento
unique(documento);

select constraint_name, constraint_type, status, validated


from user_constraints
where table_name='EMPLEADOS';

alter table empleados


disable constraint PK_empleados_codigo;
alter table empleados
disable constraint UQ_empleados_documento;
alter table empleados
disable constraint CK_empleados_sueldo_positivo;
alter table empleados
disable constraint CK_empleados_seccion_lista;

insert into empleados


values (1,'33333333','Federico Fuentes','Gerencia',-1500);

alter table empleados


enable novalidate constraint CK_empleados_sueldo_positivo;

alter table empleados


enable novalidate constraint CK_empleados_seccion_lista;

alter table empleados


enable novalidate constraint PK_empleados_codigo;

alter table empleados


enable novalidate constraint UQ_empleados_documento;

delete empleados where seccion='Gerencia';

alter table empleados


enable novalidate constraint PK_empleados_codigo;
alter table empleados
enable novalidate constraint UQ_empleados_documento;
select constraint_name, constraint_type, status, validated
from user_constraints
where table_name='EMPLEADOS';

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.

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

Problema:

Trabajamos con la tabla "libros" de una librera.


Eliminamos la tabla:

drop table libros;

La creamos estableciendo el campo cdigo como clave primaria:

create table libros(


codigo number(5) not null,
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(15),
precio number(6,2)
);

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);

Definimos una restriccin "check" para asegurarnos que el precio no ser negativo:

alter table libros


add constraint CK_libros_precio
check (precio>=0);

Definimos una restriccin "unique" para los campos "titulo", "autor" y "editorial":

alter table libros


add constraint UQ_libros
unique(titulo,autor,editorial);

Vemos las restricciones:

select *from user_constraints where table_name='LIBROS';


Aparecen 4 restricciones:

- 1 "check" que controla que el precio sea positivo;

- 1 "check" , que se cre al definir "not null" el campo "codigo", el nombre le fue dado por
Oracle;

- 1 "primary key" y

- 1 "unique".

Eliminamos la restriccin "PK_libros_codigo":

alter table libros


drop constraint PK_LIBROS_CODIGO;

Eliminamos la restriccin de control "CK_libros_precio":

alter table libros


drop constraint CK_LIBROS_PRECIO;

Vemos si se eliminaron:

select *from user_constraints where table_name='LIBROS';

Aparecen 2 restricciones.

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

Primer problema:

Una playa de estacionamiento almacena cada da los datos de los vehculos que ingresan en la
tabla llamada "vehiculos".
1- Setee el formato de "date" para que nos muestre hora y minutos:

ALTER SESSION SET NLS_DATE_FORMAT = 'HH24:MI';

2- Elimine la tabla y crela con la siguiente estructura:

drop table vehiculos;

create table vehiculos(


patente char(6) not null,
tipo char(1),--'a'=auto, 'm'=moto
horallegada date not null,
horasalida date
);

3- Establezca una restriccin "check" que admita solamente los valores "a" y "m" para el
campo "tipo":

alter table vehiculos


add constraint CK_vehiculos_tipo
check (tipo in ('a','m'));
4- Agregue una restriccin "primary key" que incluya los campos "patente" y "horallegada"

5- Ingrese un vehculo.

6- Intente ingresar un registro repitiendo la clave primaria.

7- Ingrese un registro repitiendo la patente pero no la hora de llegada.

8- Ingrese un registro repitiendo la hora de llegada pero no la patente.

9- Vea todas las restricciones para la tabla "vehiculos"


aparecen 4 filas, 3 correspondientes a restricciones "check" y 1 a "primary key". Dos de las
restricciones de control tienen nombres dados por Oracle.

12- Elimine la restriccin "primary key"

13- Vea si se ha eliminado.


Ahora aparecen 3 restricciones.

14- Elimine la restriccin de control que establece que el campo "patente" no sea nulo
(busque el nombre consultando "user_constraints").

15- Vea si se han eliminado.

16- Vuelva a establecer la restriccin "primary key" eliminada.

17- La playa quiere incluir, para el campo "tipo", adems de los valores permitidos "a" (auto) y
"m" (moto), el caracter "c" (camin). No puede modificar la restriccin, debe eliminarla y
luego redefinirla con los 3 valores.

18- Consulte "user_constraints" para ver si la condicin de chequeo de la restriccin


"CK_vehiculos_tipo" se ha modificado.

ALTER SESSION SET NLS_DATE_FORMAT = 'HH24:MI';

drop table vehiculos;

create table vehiculos(


patente char(6) not null,
tipo char(1),--'a'=auto, 'm'=moto
horallegada date not null,
horasalida date
);

alter table vehiculos


add constraint CK_vehiculos_tipo
check (tipo in ('a','m'));

alter table vehiculos


add constraint PK_vehiculos
primary key(patente,horallegada);

insert into vehiculos values('SDR456','a','10:10',null);


insert into vehiculos values('SDR456','m','10:10',null);

insert into vehiculos values('SDR456','m','12:20',null);

insert into vehiculos values('SDR111','m','10:10',null);

select constraint_name, constraint_type, search_condition from user_constraints


where table_name='VEHICULOS';

alter table vehiculos


drop constraint PK_vehiculos;

select constraint_name, constraint_type, search_condition from user_constraints


where table_name='VEHICULOS';

select constraint_name, constraint_type, search_condition from user_constraints


where table_name='VEHICULOS';

alter table vehiculos


add constraint PK_vehiculos
primary key(patente,horallegada);

alter table vehiculos


drop constraint CK_vehiculos_tipo;

alter table vehiculos


add constraint CK_vehiculos_tipo
check (tipo in ('a','m','c'));

select search_condition from user_constraints


where table_name='VEHICULOS' and
constraint_name='CK_VEHICULOS_TIPO';

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 (nombre del ndice),


- INDEX_TYPE (tipo de ndice, nosotros crearemos el stardart normal),
- TABLE_NAME (nombre de la tabla),
- UNIQUENESS (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

45 - Indices (Crear - Informacin)


Problema:

Trabajamos con la tabla "empleados" de una librera.


Eliminamos la tabla y la creamos:

drop table empleados;


create table empleados(
legajo number(5),
documento char(8),
apellido varchar2(25),
nombre varchar2(25),
domicilio varchar2(30)
);

Agregamos una restriccin "primary key" sobre el campo "legajo":

alter table empleados


add constraint PK_empleados_legajo
primary key (legajo);

Consultamos "user_constraints":

select constraint_name, constraint_type, index_name


from user_constraints
where table_name='EMPLEADOS';

Note que Oracle cre un ndice con el mismo nombre de la restriccin.

Veamos los ndices de "empleados":

select index_name, index_type, uniqueness


from user_indexes
where table_name='EMPLEADOS';

Aparece 1 fila, mostrando el nombre del ndice, indicando que es normal y nico.

Creamos un ndice nico sobre el campo "documento":

create unique index I_empleados_documento


on empleados(documento);

Verificamos que se cre el ndice:

select index_name, index_type, uniqueness


from user_indexes where table_name='EMPLEADOS';

Aparecen 2 filas, una por cada ndice.

Agregamos a la tabla una restriccin nica sobre el campo "documento":

alter table empleados


add constraint UQ_empleados_documento
unique(documento);

Analicemos la informacin que nos muestra "user_constraints":


select constraint_name, constraint_type, index_name
from user_constraints
where table_name='EMPLEADOS';

En la columna "index_name" correspondiente a la restriccin nica, aparece


"I_empleados_documento", Oracle usa para esta restriccin el ndice existente, no crea otro
nuevo.

Creamos un ndice no nico, compuesto (para los campos "apellido" y "nombre"):

create index I_empleados_apellidonombre


on empleados(apellido,nombre);

Consultamos el diccionario "user_indexes":

select index_name, index_type, uniqueness


from user_indexes
where table_name='EMPLEADOS';

Nos muestra informacin sobre los 3 ndices de la tabla.

Veamos todos los ndices de la base de datos activa consultando "user_objects":

select *from user_objects


where object_type='INDEX';

Aparecen varios ndices, entre ellos, los de nuestra tabla "empleados".

Obtenemos informacin de "user_ind_columns":

select index_name,column_name,column_position
from user_ind_columns
where table_name='EMPLEADOS';

Nos muestra la siguiente tabla:

INDEX_NAME COLUMN_NAME COLUMN_POSITION


-----------------------------------------------------------------
PK_EMPLEADOS_LEGAJO LEGAJO 1
I_EMPLEADOS_DOCUMENTO DOCUMENTO 1
I_EMPLEADOS_APELLIDONOMBRE APELLIDO 1
I_EMPLEADOS_APELLIDONOMBRE NOMBRE 2

La tabla tiene 3 ndices, 2 filas corresponden al ndice compuesto


"I_empleados_apellidonombre"; la columna "position" indica el orden de los campos
indexados.

Agregamos algunos registros:

insert into empleados values(1,'22333444','Lopez','Juan','Colon


123');
insert into empleados values(1,'23444555','Lopez','Luis','Lugones
1234');
insert into empleados
values(1,'24555666','Garcia','Pedro','Avellaneda 987');
insert into empleados values(1,'25666777','Garcia','Ana','Caseros
678');
Si intentamos crear un ndice nico para el campo "apellido" (que contiene valores
duplicados") Oracle no lo permite:

create unique index I_empleados_apellido


on empleados(apellido);

Igualmente, si hay un ndice nico sobre un campo y luego intentamos ingresar un registro con
un valor repetido para el campo indexado, Oracle no lo permite.

Creamos un ndice nico sobre el campo "nombre":

create unique index I_empleados_nombre


on empleados(nombre);

Oracle lo permite porque no hay valores duplicados.

Intentamos agregamos un registro que repita un nombre:

insert into empleados values(5,'30111222','Perez','Juan','Bulnes


233');

Oracle no lo permite.

"INDEX_NAME".

45 - Indices (Crear - Informacin)

Primer problema:

Un profesor guarda algunos datos de sus alumnos en una tabla llamada "alumnos".

1- Elimine la tabla y crela con la siguiente estructura:

drop table alumnos;


create table alumnos(
legajo char(5) not null,
documento char(8) not null,
nombre varchar2(30),
curso char(1),
materia varchar2(30),
notafinal number(4,2)
);

2- Ingresamos algunos registros:

insert into alumnos values ('A123','22222222','Perez Patricia','5','Matematica',9);


insert into alumnos values ('A234','23333333','Lopez Ana','5','Matematica',9);
insert into alumnos values ('A345','24444444','Garcia Carlos','6','Matematica',8.5);
insert into alumnos values ('A348','25555555','Perez Patricia','6','Lengua',7.85);
insert into alumnos values ('A457','26666666','Perez Fabian','6','Lengua',3.2);

3- Intente crear un ndice nico para el campo "nombre".


No lo permite porque hay valores duplicados.
4- Cree un ndice no nico, para el campo "nombre".

5- Cree un ndice nico, para el campo "lejago".

6- Establezca una restriccin "primary key" sobre el campo "legajo".

7- Verifique que Oracle no cre un ndice al agregar la restriccin, utiliz el ndice


"I_alumnos_legajo" existente.

8- Agregue una restriccin nica sobre el campo "documento".

9- Verifique que Oracle cre un ndice al agregar la restriccin y le dio el nombre de la


restriccin.

10- Intente crear un ndice nico para la tabla "alumnos" sobre el campo "notafinal"

11- Indexe la tabla "alumnos" por el campo "notafinal" (ndice no nico)

12- Indexe la tabla "alumnos" por los campos "curso" y "materia" (ndice no nico)

13- Intente crear un ndice nico sobre "materia" (error pues hay datos duplicados)

14- Vea los indices de "alumnos"

15- Consulte el diccionario "user_ind_columns" y analice la informacin retornada.

16- Vea todos los ndices de la base de datos activa que contengan en su nombre el patrn
"%EMPLEADOS%" (5 filas retornadas)

drop table alumnos;


create table alumnos(
legajo char(5) not null,
documento char(8) not null,
nombre varchar(30),
curso char(1),
materia varchar2(30),
notafinal number(4,2)
);

insert into alumnos values ('A123','22222222','Perez Patricia','5','Matematica',9);


insert into alumnos values ('A234','23333333','Lopez Ana','5','Matematica',9);
insert into alumnos values ('A345','24444444','Garcia Carlos','6','Matematica',8.5);
insert into alumnos values ('A348','25555555','Perez Patricia','6','Lengua',7.85);
insert into alumnos values ('A457','26666666','Perez Fabian','6','Lengua',3.2);

create unique index I_alumnos_nombre


on alumnos(nombre);

create index I_alumnos_nombre


on alumnos(nombre);

create index I_alumnos_legajo


on alumnos(legajo);
alter table alumnos
add constraint PK_alumnos_legajo
primary key (legajo);

select constraint_name, constraint_type, index_name


from user_constraints
where table_name='ALUMNOS';

alter table alumnos


add constraint UQ_alumnos_documento
unique (documento);

select constraint_name, constraint_type, index_name


from user_constraints
where table_name='ALUMNOS';

create unique index I_alumnos_notafinal


on alumnos(notafinal);

create index I_alumnos_notafinal


on alumnos(notafinal);

create index I_alumnos_cursomateria


on alumnos(curso,materia);

create unique index I_alumnos_materia


on alumnos(materia);

select index_name, index_type, uniqueness


from user_indexes
where table_name='ALUMNOS';

select index_name,column_name,column_position
from user_ind_columns
where table_name='ALUMNOS';

select *from user_objects


where object_type='INDEX' and
object_name like '%ALUMNOS%';

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.


46 - Indices (eliminar)

Problema:

Trabajamos con la tabla "empleados".


Eliminamos la tabla y la creamos:

drop table empleados;

create table empleados(


legajo number (5),
documento char(8),
apellido varchar2(40),
nombre varchar2(40)
);

Creamos un ndice nico para el campo "legajo":

create unique index I_empleados_legajo


on empleados(legajo);

Agregamos una restriccin "unique" sobre "legajo":

alter table empleados


add constraint UQ_empleados_legajo
unique (legajo);

Verificamos que la restriccin usa el ndice creado anteriormente, no crea otro:

select constraint_name, constraint_type, index_name


from user_constraints
where table_name='EMPLEADOS';

Agregamos una restriccin "primary key" sobre "documento":

alter table empleados


add constraint PK_empleados_documento
primary key(documento);

Verificamos que Oracle cre un ndice para el campo "documento":

select constraint_name, constraint_type, index_name


from user_constraints
where table_name='EMPLEADOS';

Consultamos todos los ndices y sus tipos consultando "user_indexes":

select index_name,uniqueness
from user_indexes
where table_name='EMPLEADOS';

Creamos un ndice no nico sobre "nombre":

create index I_empleados_nombre


on empleados(nombre);
Creamos un ndice no nico sobre "apellido":

create index I_empleados_apellido


on empleados(apellido);

Si intentamos eliminar un ndice que utiliza una restriccin Oracle no lo permite:

drop index I_empleados_legajo;

Verificamos que tal ndice es utilizado por una restriccin:

select constraint_name, constraint_type, index_name


from user_constraints
where index_name='I_EMPLEADOS_LEGAJO';

Eliminamos el ndice "I_empleados_nombre":

drop index I_empleados_nombre;

Corroboremos que se elimin:

select *from user_objects


where object_type='INDEX';

No aparece en la lista.

Eliminamos la tabla:

drop table empleados;

Verificamos que se eliminaron todos los ndices establecidos sobre la tabla:

select *from user_indexes where table_name='EMPLEADOS';

No aparece ninguno cuyo nombre de la tabla sea "empleados".

Lo verificamos nuevamente consultando el diccionario de todos los objetos:

select *from user_objects


where object_type='INDEX';

No aparecen los ndices.

46 - Indices (eliminar)

Primer problema:

Un profesor guarda algunos datos de sus alumnos en una tabla llamada "alumnos".

1- Elimine la tabla y crela con la siguiente estructura:

drop table alumnos;


create table alumnos(
legajo char(5) not null,
documento char(8) not null,
nombre varchar2(30),
curso char(1) not null,
materia varchar2(20) not null,
notafinal number(4,2)
);

2- Cree un ndice no nico para el campo "nombre".

3- Establezca una restriccin "primary key" para el campo "legajo"

4- Verifique que se cre un ndice con el nombre de la restriccin.

5- Verifique que se cre un ndice nico con el nombre de la restriccin consultando el


diccionario de ndices.

6- Intente eliminar el ndice "PK_alumnos_legajo" con "drop index".

7- Cree un ndice nico para el campo "documento".

8- Agregue a la tabla una restriccin nica sobre el campo "documento" y verifique que no se
cre un ndice, Oracle emplea el ndice creado en el punto anterior.

9- Intente eliminar el ndice "I_alumnos_documento" (no se puede porque una restriccin lo


est utilizando)

10- Elimine la restriccin nica establecida sobre "documento".

11- Verifique que el ndice "I_alumnos_documento" an existe.

12- Elimine el ndice "I_alumnos_documento", ahora puede hacerlo porque no hay restriccin
que lo utilice.

13-Elimine el ndice "I_alumnos_nombre".

14- Elimine la restriccin "primary key"/

15- Verifique que el ndice "PK_alumnos_legajo" fue eliminado (porque fue creado por Oracle
al establecerse la restriccin)

16- Cree un ndice compuesto por los campos "curso" y "materia", no nico.

17- Verifique su existencia.

18- Elimine la tabla "alumnos" y verifique que todos los ndices han sido eliminados junto con
ella.

drop table alumnos;


create table alumnos(
legajo char(5) not null,
documento char(8) not null,
nombre varchar(30),
curso char(1) not null,
materia varchar2(20) not null,
notafinal number(4,2)
);

create index I_alumnos_nombre


on alumnos(nombre);

alter table alumnos


add constraint PK_alumnos_legajo
primary key (legajo);

select constraint_name, constraint_type, index_name


from user_constraints
where table_name='ALUMNOS';

select index_name,uniqueness
from user_indexes
where table_name='ALUMNOS';

drop index PK_alumnos_legajo;

create unique index I_alumnos_documento


on alumnos(documento);

alter table alumnos


add constraints UQ_alumnos_documento
unique (documento);

select constraint_name, constraint_type, index_name


from user_constraints
where table_name='ALUMNOS';

drop index I_alumnos_documento;

alter table alumnos


drop constraint UQ_ALUMNOS_DOCUMENTO;

select index_name,uniqueness
from user_indexes
where table_name='ALUMNOS';

drop index I_alumnos_documento;

drop index I_alumnos_nombre;

alter table alumnos


drop constraint PK_ALUMNOS_LEGAJO;

select index_name,uniqueness
from user_indexes
where table_name='ALUMNOS';

create index I_alumnos_cursomateria


on alumnos(curso,materia);

select index_name,uniqueness
from user_indexes
where table_name='ALUMNOS';

drop table alumnos;

select index_name,uniqueness
from user_indexes
where table_name='ALUMNOS';

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.

48 - Combinacin interna (join)

Problema:

Una librera almacena la informacin de sus libros para la venta en dos tablas, "libros" y
"editoriales".
Eliminamos ambas tablas:

drop table libros;


drop table editoriales;

Creamos las tablas:

create table libros(


codigo number(5),
titulo varchar2(40),
autor varchar2(30),
codigoeditorial number(3)
);
create table editoriales(
codigo number(3),
nombre varchar2(20),
primary key (codigo)
);

Ingresamos algunos registros en ambas tablas:

insert into editoriales values(1,'Planeta');


insert into editoriales values(2,'Emece');
insert into editoriales values(3,'Siglo XXI');

insert into libros values(100,'El aleph','Borges',1);


insert into libros values(200,'Martin Fierro','Jose Hernandez',2);
insert into libros values(300,'Aprenda PHP','Mario Molina',3);
insert into libros values(400,'Java en 10 minutos',null,5);
insert into libros values(500,'Matematica estas ahi','Paenza',null);

Recuperamos los datos de libros:

select *from libros;

vemos que en el campo "editorial" aparece el cdigo, pero no sabemos el nombre de la


editorial. Realizamos un join para obtener datos de ambas tablas (titulo, autor y nombre de
la editorial):

select titulo, autor, nombre


from libros
join editoriales
on codigoeditorial=editoriales.codigo;

Note que los libros cuyo cdigo de editorial NO se encuentra en "editoriales" no aparecen en
el resultado de la consulta. El libro "Java en 10 minutos" tiene cdigo de editorial 5, y ese
cdigo no est presente en "editoriales"; el libro "Matemtica estas ahi" tiene valor nulo en
"codigoeditorial", por lo tanto, tampoco se muestra en el join.

Mostramos el cdigo del libro, ttulo, autor y nombre de la editorial realizando un join y
empleando alias:

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

Note que al listar el campo "codigo" especificamos a qu tabla pertenece; si no lo hacemos


Oracle no sabr si nos referimos al de la tabla "libros" o "editoriales". Los dems campos no
tienen referencia a la tabla porque tienen nombres que no se repiten.

Realizamos la misma consulta anterior agregando un "where" para obtener solamente los
libros de la editorial "Siglo XXI":

select l.codigo,titulo,autor,nombre
from libros l
join editoriales e
on codigoeditorial=e.codigo
where e.nombre='Siglo XXI';

Obtenemos ttulo, autor y nombre de la editorial, esta vez ordenados por ttulo:

select titulo,autor,nombre
from libros l
join editoriales e
on codigoeditorial=e.codigo
order by titulo;
48 - Combinacin interna (join)

Primer problema:

Una empresa tiene registrados sus clientes en una tabla llamada "clientes", tambin tiene una
tabla "provincias" donde registra los nombres de las provincias.

1- Elimine las tablas "clientes" y "provincias":

drop table clientes;


drop table provincias;

2- Crelas con las siguientes estructuras:

create table clientes (


codigo number(5),
nombre varchar2(30),
domicilio varchar2(30),
ciudad varchar2(20),
codigoprovincia number(2)
);

create table provincias(


codigo number(2),
nombre varchar2(20)
);

3- Ingrese algunos registros para ambas tablas:

insert into provincias values(1,'Cordoba');


insert into provincias values(2,'Santa Fe');
insert into provincias values(3,'Corrientes');
insert into provincias values(null,'La Pampa');

insert into clientes values (1,'Lopez Marcos','Colon 111','Crdoba',1);


insert into clientes values (2,'Perez Ana','San Martin 222','Cruz del Eje',1);
insert into clientes values (3,'Garcia Juan','Rivadavia 333','Villa Maria',null);
insert into clientes values (4,'Perez Luis','Sarmiento 444','Rosario',2);
insert into clientes values (5,'Pereyra Lucas','San Martin 555','Cruz del Eje',1);
insert into clientes values (6,'Gomez Ines','San Martin 666','Santa Fe',2);
insert into clientes values (7,'Torres Fabiola','Alem 777','Ibera',3);
insert into clientes values (8,'Garcia Paco','Avellaneda 888','Rawson',5);

4- Obtenga los datos de ambas tablas, usando alias.


Note que los registros de "clientes" cuyo valor de "codigoprovincia" que NO encuentran
coincidencia con "codigo" de "provincias" no aparecen en el resultado de la consulta; caso de
"Garcia Juan", que cdigo de provincia nulo y "Garcia Paco", que tiene un cdigo de provincia
que no est presente en "provincias".

5- Obtenga la misma informacin anterior pero ordenada por nombre de provincia (join y
order by)

6- Recupere todos los datos de los clientes de la provincia "Santa Fe" (join con where) (2
registros devueltos)

drop table clientes;


drop table provincias;

create table clientes (


codigo number(5),
nombre varchar2(30),
domicilio varchar2(30),
ciudad varchar2(20),
codigoprovincia number(2)
);

create table provincias(


codigo number(2),
nombre varchar2(20)
);

insert into provincias values(1,'Cordoba');


insert into provincias values(2,'Santa Fe');
insert into provincias values(3,'Corrientes');
insert into provincias values(null,'La Pampa');

insert into clientes values (1,'Lopez Marcos','Colon 111','Crdoba',1);


insert into clientes values (2,'Perez Ana','San Martin 222','Cruz del Eje',1);
insert into clientes values (3,'Garcia Juan','Rivadavia 333','Villa Maria',null);
insert into clientes values (4,'Perez Luis','Sarmiento 444','Rosario',2);
insert into clientes values (5,'Pereyra Lucas','San Martin 555','Cruz del Eje',1);
insert into clientes values (6,'Gomez Ines','San Martin 666','Santa Fe',2);
insert into clientes values (7,'Torres Fabiola','Alem 777','Ibera',3);
insert into clientes values (8,'Garcia Paco','Avellaneda 888','Rawson',5);

select c.nombre,domicilio,ciudad,p.nombre
from clientes c
join provincias p
on c.codigoprovincia=p.codigo;

select c.nombre,domicilio,ciudad,p.nombre
from clientes c
join provincias p
on c.codigoprovincia=p.codigo
order by p.nombre;

select c.nombre,domicilio,ciudad
from clientes c
join provincias p
on c.codigoprovincia=p.codigo
where p.nombre='Santa Fe';

Segundo problema:

Un club dicta clases de distintos deportes. Almacena la informacin en una tabla llamada
"inscriptos" que incluye el documento, el nombre, el deporte y si la matricula esta paga o no y
una tabla llamada "inasistencias" que incluye el documento, el deporte y la fecha de la
inasistencia.

1- Elimine las tablas y crelas:

drop table inscriptos;


drop table inasistencias;

create table inscriptos(


nombre varchar2(30),
documento char(8),
deporte varchar2(15),
matricula char(1), --'s'=paga; 'n'=impaga
primary key(documento,deporte)
);

create table inasistencias(


documento char(8),
deporte varchar2(15),
fecha date
);

2- Ingrese algunos registros para ambas tablas:

insert into inscriptos values('Juan Perez','22222222','tenis','s');


insert into inscriptos values('Maria Lopez','23333333','tenis','s');
insert into inscriptos values('Agustin Juarez','24444444','tenis','n');
insert into inscriptos values('Marta Garcia','25555555','natacion','s');
insert into inscriptos values('Juan Perez','22222222','natacion','s');
insert into inscriptos values('Maria Lopez','23333333','natacion','n');

insert into inasistencias values('22222222','tenis','01/12/2006');


insert into inasistencias values('22222222','tenis','08/12/2006');
insert into inasistencias values('23333333','tenis','01/12/2006');
insert into inasistencias values('24444444','tenis','08/12/2006');
insert into inasistencias values('22222222','natacion','02/12/2006');
insert into inasistencias values('23333333','natacion','02/12/2006');

3- Muestre el nombre, el deporte y las fechas de inasistencias, ordenado por nombre y


deporte.

Note que la condicin es compuesta porque para identificar los registros de la tabla
"inasistencias" necesitamos ambos campos.
Note que la persona con documento '25555555' no aparece en la consulta porque no est
presente en "inasistencias".

4- Obtenga el nombre, deporte y las fechas de inasistencias de un determinado inscripto en


un determinado deporte (3 registros).

5- Obtenga el nombre, deporte y las fechas de inasistencias de todos los inscriptos que
pagaron la matrcula (4 registros)

drop table inscriptos;


drop table inasistencias;

create table inscriptos(


nombre varchar2(30),
documento char(8),
deporte varchar2(15),
matricula char(1), --'s'=paga; 'n'=impaga
primary key(documento,deporte)
);

create table inasistencias(


documento char(8),
deporte varchar2(15),
fecha date
);

insert into inscriptos values('Juan Perez','22222222','tenis','s');


insert into inscriptos values('Maria Lopez','23333333','tenis','s');
insert into inscriptos values('Agustin Juarez','24444444','tenis','n');
insert into inscriptos values('Marta Garcia','25555555','natacion','s');
insert into inscriptos values('Juan Perez','22222222','natacion','s');
insert into inscriptos values('Maria Lopez','23333333','natacion','n');

insert into inasistencias values('22222222','tenis','01/12/2006');


insert into inasistencias values('22222222','tenis','08/12/2006');
insert into inasistencias values('23333333','tenis','01/12/2006');
insert into inasistencias values('24444444','tenis','08/12/2006');
insert into inasistencias values('22222222','natacion','02/12/2006');
insert into inasistencias values('23333333','natacion','02/12/2006');

select nombre,insc.deporte,ina.fecha
from inscriptos insc
join inasistencias ina
on insc.documento=ina.documento and
insc.deporte=ina.deporte
order by nombre, insc.deporte;

select nombre,insc.deporte, ina.fecha


from inscriptos insc
join inasistencias ina
on insc.documento=ina.documento and
insc.deporte=ina.deporte
where insc.documento='22222222';

select nombre,insc.deporte, ina.fecha


from inscriptos insc
join inasistencias ina
on insc.documento=ina.documento and
insc.deporte=ina.deporte
where insc.matricula='s';

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;
49 - Combinacin externa izquierda (left join)

Problema:

Una librera almacena la informacin de sus libros para la venta en dos tablas, "libros" y
"editoriales".
Eliminamos ambas tablas, las creamos y agregamos a cada una de ellas restricciones nicas
para los campos "codigo" de ambas tablas:

drop table libros;


drop table editoriales;

create table libros(


codigo number(5),
titulo varchar2(40),
autor varchar2(30),
codigoeditorial number(3)
);
create table editoriales(
codigo number(3),
nombre varchar2(20)
);

alter table editoriales


add constraints UQ_editoriales_codigo
unique (codigo);

alter table libros


add constraints UQ_libros_codigo
unique (codigo);

Ingresamos algunos registros en ambas tablas:

insert into editoriales values(1,'Planeta');


insert into editoriales values(2,'Emece');
insert into editoriales values(3,'Siglo XXI');
insert into editoriales values(null,'Sudamericana');
insert into editoriales values(null,'Norma');

insert into libros values(100,'El aleph','Borges',1);


insert into libros values(200,'Martin Fierro','Jose Hernandez',1);
insert into libros values(300,'Aprenda PHP','Mario Molina',2);
insert into libros values(400,'Java en 10 minutos',default,4);
insert into libros values(500,'El quijote de la
mancha','Cervantes',null);

Realizamos una combinacin izquierda para obtener los ttulos de los libros, incluyendo el
nombre de la editorial:

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

Las editoriales de las cuales no hay libros, es decir, cuyo cdigo de editorial no est presente
en "libros" o tienen valor nulo, aparece en el resultado, pero con el valor "null" en el campo
"titulo" (caso de "Siglo XXI", "Sudamericana" y "Norma").

Realizamos la misma consulta anterior pero cambiamos 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" o tienen valor nulo, aparecen en el resultado, pero
con el valor "null" en el campo "nombre" (caso de los libros "El quijote..." y "Java...").

Restringimos el resultado de una 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;

Mostramos las editoriales que NO estn presentes en "libros", es decir, que NO encuentran
coincidencia en la tabla de la derecha:

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

Aparecen 3 editoriales.

49 - Combinacin externa izquierda (left join)

Primer problema:

Una empresa tiene registrados sus clientes en una tabla llamada "clientes", tambin tiene una
tabla "provincias" donde registra los nombres de las provincias.
1- Elimine las tablas "clientes" y "provincias", crelas y agregue restricciones nicas para los
campos "codigo" de ambas tablas:

drop table clientes;


drop table provincias;

create table clientes (


codigo number(5),
nombre varchar2(30),
domicilio varchar2(30),
ciudad varchar2(20),
codigoprovincia number(3)
);

create table provincias(


codigo number(3),
nombre varchar2(20)
);

alter table clientes


add constraints UQ_clientes_codigo
unique (codigo);

alter table provincias


add constraints UQ_provincias_codigo
unique (codigo);

2- Ingrese algunos registros para ambas tablas. Incluya valores nulos para el campo "codigo"
de "provincias" y valores nulos para el campo "codigoprovincia" de "clientes". Incluya en
"clientes" un cdigo de provincia que no exista en "provincias":

insert into provincias values(1,'Cordoba');


insert into provincias values(2,'Santa Fe');
insert into provincias values(3,'Corrientes');
insert into provincias values(4,'Santa Cruz');
insert into provincias values(null,'Salta');
insert into provincias values(null,'Jujuy');

insert into clientes values (100,'Lopez Marcos','Colon 111','Crdoba',1);


insert into clientes values (200,'Perez Ana','San Martin 222','Cruz del Eje',1);
insert into clientes values (300,'Garcia Juan','Rivadavia 333','Villa Maria',null);
insert into clientes values (400,'Perez Luis','Sarmiento 444','Rosario',2);
insert into clientes values (500,'Gomez Ines','San Martin 666','Santa Fe',2);
insert into clientes values (600,'Torres Fabiola','Alem 777','La Plata',5);
insert into clientes values (700,'Garcia Luis','Sucre 475','Santa Rosa',null);
3- Muestre todos los datos de los clientes, incluido el nombre de la provincia

Note que los clientes de "Santa Rosa", "Villa Maria" y "La Plata" se muestran seteados a null en
la columna corespondiente al nombre de la provincia porque tienen valores nulos o
inexistentes.

4- Realice la misma consulta anterior pero alterando el orden de las tablas.

5- Muestre solamente los clientes de las provincias que existen en "provincias" (4 registros)

Note que los clientes de "Jujuy", "Salta", "Santa Cruz" y "Corrientes" se muestran seteados a
null en los campos pertenecientes a la tabla "clientes" porque tienen valores nulos o
inexistentes en dicha tabla.

6- Muestre todos los clientes cuyo cdigo de provincia NO existe en "provincias" ordenados por
nombre del cliente (3 registros)

7- Obtenga todos los datos de los clientes de "Cordoba" (2 registros)

drop table clientes;


drop table provincias;

create table clientes (


codigo number(5),
nombre varchar2(30),
domicilio varchar2(30),
ciudad varchar2(20),
codigoprovincia number(3)
);

create table provincias(


codigo number(3),
nombre varchar2(20)
);

alter table clientes


add constraints UQ_clientes_codigo
unique (codigo);

alter table provincias


add constraints UQ_provincias_codigo
unique (codigo);

insert into provincias values(1,'Cordoba');


insert into provincias values(2,'Santa Fe');
insert into provincias values(3,'Corrientes');
insert into provincias values(4,'Santa Cruz');
insert into provincias values(null,'Salta');
insert into provincias values(null,'Jujuy');

insert into clientes values (100,'Lopez Marcos','Colon 111','Crdoba',1);


insert into clientes values (200,'Perez Ana','San Martin 222','Cruz del Eje',1);
insert into clientes values (300,'Garcia Juan','Rivadavia 333','Villa Maria',null);
insert into clientes values (400,'Perez Luis','Sarmiento 444','Rosario',2);
insert into clientes values (500,'Gomez Ines','San Martin 666','Santa Fe',2);
insert into clientes values (600,'Torres Fabiola','Alem 777','La Plata',5);
insert into clientes values (700,'Garcia Luis','Sucre 475','Santa Rosa',null);

select c.nombre,domicilio,ciudad, p.nombre as provincia


from clientes c
left join provincias p
on codigoprovincia = p.codigo;

select c.nombre,domicilio,ciudad, p.nombre


from provincias p
left join clientes c
on codigoprovincia = p.codigo;

select c.nombre,domicilio,ciudad, p.nombre as provincia


from clientes c
left join provincias p
on codigoprovincia = p.codigo
where p.codigo is not null;

select c.nombre,domicilio,ciudad, p.nombre as provincia


from clientes c
left join provincias p
on codigoprovincia = p.codigo
where p.codigo is null
order by c.nombre;

select c.nombre,domicilio,ciudad, p.nombre as provincia


from clientes c
left join provincias p
on codigoprovincia = p.codigo
where p.nombre='Cordoba';

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;
50 - Combinacin externa derecha (right join)

Problema:

Una librera almacena la informacin de sus libros para la venta en dos tablas, "libros" y
"editoriales".
Eliminamos ambas tablas, las creamos y agregamos dos restricciones "primary key" sobre los
campos "codigo" de las dos tablas:

drop table libros;


drop table editoriales;

create table libros(


codigo number(5),
titulo varchar2(40),
autor varchar2(30),
codigoeditorial number(3)
);
create table editoriales(
codigo number(3),
nombre varchar2(20)
);

alter table libros


add constraint PK_libros
primary key(codigo);

alter table editoriales


add constraint PK_editoriales
primary key(codigo);

Ingresamos algunos registros en ambas tablas:

insert into editoriales values(1,'Planeta');


insert into editoriales values(2,'Emece');
insert into editoriales values(3,'Siglo XXI');
insert into editoriales values(4,'Norma');

insert into libros values(100,'El aleph','Borges',1);


insert into libros values(101,'Martin Fierro','Jose Hernandez',1);
insert into libros values(102,'Aprenda PHP','Mario Molina',2);
insert into libros values(103,'Java en 10 minutos',null,4);
insert into libros values(104,'El anillo del hechicero','Carol
Gaskin',4);

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;

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"; caso de la
editorial "Siglo XXI".

Realizamos la misma consulta anterior agregando un "where" que restringa el resultado


considerando solamente los registros que encuentran coincidencia en la tabla izquierda:

select titulo,nombre as editorial


from libros l
right join editoriales e
on e.codigo=codigoeditorial
where codigoeditorial is not null;

Ya no aparece la editorial "Siglo XXI".

Mostramos las editoriales que NO estn presentes en "libros" (que NO encuentran coincidencia
en "editoriales"):

select nombre
from libros l
right join editoriales e
on e.codigo=codigoeditorial
where codigoeditorial is null;

Solamente aparece la editorial "Siglo XXI".

50 - Combinacin externa derecha (right join)

Primer problema:

Una empresa tiene registrados sus clientes en una tabla llamada "clientes", tambin tiene una
tabla "provincias" donde registra los nombres de las provincias.

1- Elimine las tablas "clientes" y "provincias" y crelas:

drop table clientes;


drop table provincias;

create table clientes (


codigo number(5),
nombre varchar2(30),
domicilio varchar2(30),
ciudad varchar2(20),
codigoprovincia number(2),
primary key(codigo)
);

create table provincias(


codigo number(2),
nombre varchar2(20),
primary key (codigo)
);

2- Ingrese algunos registros para ambas tablas:

insert into provincias values(1,'Cordoba');


insert into provincias values(2,'Santa Fe');
insert into provincias values(3,'Corrientes');

insert into clientes values (101,'Lopez Marcos','Colon 111','Crdoba',1);


insert into clientes values (102,'Perez Ana','San Martin 222','Cruz del Eje',1);
insert into clientes values (103,'Garcia Juan','Rivadavia 333','Villa Maria',1);
insert into clientes values (104,'Perez Luis','Sarmiento 444','Rosario',2);
insert into clientes values (105,'Gomez Ines','San Martin 666','Santa Fe',2);
insert into clientes values (106,'Torres Fabiola','Alem 777','La Plata',4);
insert into clientes values (107,'Garcia Luis','Sucre 475','Santa Rosa',5);

3- Muestre todos los datos de los clientes, incluido el nombre de la provincia empleando un
"right join".

4- Obtenga la misma salida que la consulta anterior pero empleando un "left join".

5- Empleando un "right join", muestre solamente los clientes de las provincias que existen en
"provincias" (5 registros)
6- Muestre todos los clientes cuyo cdigo de provincia NO existe en "provincias" ordenados por
ciudad (2 registros)

drop table clientes;


drop table provincias;

create table clientes (


codigo number(5),
nombre varchar2(30),
domicilio varchar2(30),
ciudad varchar2(20),
codigoprovincia number(2),
primary key(codigo)
);

create table provincias(


codigo number(2),
nombre varchar2(20),
primary key (codigo)
);

insert into provincias values(1,'Cordoba');


insert into provincias values(2,'Santa Fe');
insert into provincias values(3,'Corrientes');

insert into clientes values (101,'Lopez Marcos','Colon 111','Crdoba',1);


insert into clientes values (102,'Perez Ana','San Martin 222','Cruz del Eje',1);
insert into clientes values (103,'Garcia Juan','Rivadavia 333','Villa Maria',1);
insert into clientes values (104,'Perez Luis','Sarmiento 444','Rosario',2);
insert into clientes values (105,'Gomez Ines','San Martin 666','Santa Fe',2);
insert into clientes values (106,'Torres Fabiola','Alem 777','La Plata',4);
insert into clientes values (107,'Garcia Luis','Sucre 475','Santa Rosa',5);

select c.nombre,domicilio,ciudad, p.nombre


from provincias p
right join clientes c
on codigoprovincia = p.codigo;

select c.nombre,domicilio,ciudad, p.nombre


from clientes c
left join provincias p
on codigoprovincia = p.codigo;

select c.nombre,domicilio,ciudad, p.nombre


from provincias p
right join clientes c
on codigoprovincia = p.codigo
where p.codigo is not null;

select c.nombre,domicilio,ciudad, p.nombre


from provincias p
right join clientes c
on codigoprovincia = p.codigo
where p.codigo is null
order by ciudad;

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 cor

51 - Combinacin externa completa (full join)

Problema:

Una librera almacena la informacin de sus libros para la venta en dos tablas, "libros" y
"editoriales".

Eliminamos ambas tablas, las creamos y agregamos dos claves nicas sobre los campos
"codigo" de ambas tablas:

drop table libros;


drop table editoriales;

create table libros(


codigo number(5),
titulo varchar2(40),
autor varchar2(30),
codigoeditorial number(3)
);
create table editoriales(
codigo number(3),
nombre varchar2(20)
);

alter table libros


add constraint UQ_libros_codigo
unique (codigo);
alter table editoriales
add constraint UQ_editoriales_codigo
unique (codigo);

Ingresamos algunos registros en ambas tablas:

insert into editoriales values(1,'Alfaragua');


insert into editoriales values(2,'Emece');
insert into editoriales values(3,'Siglo XXI');
insert into editoriales values(4,'Norma');
insert into editoriales values(null,'Sudamericana');

insert into libros values(100,'El aleph','Borges',null);


insert into libros values(101,'Martin Fierro','Jose Hernandez',1);
insert into libros values(102,'Aprenda PHP','Mario Molina',2);
insert into libros values(103,'Java en 10 minutos',default,4);
insert into libros values(104,'El anillo del hechicero','Carol
Gaskin',1);

Realizamos una combinacin externa completa para obtener 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":

select titulo,nombre as editorial


from editoriales e
full join libros l
on codigoeditorial = e.codigo;

Note que el libro "El aleph" cuyo valor de "codigoeditorial" es null, muestra "null" en la
columna "editorial" y las editoriales "Sudamericana" y "Siglo XXI" muestran "null" en el campo
"titulo".

respondencia en "libros".

51 - Combinacin externa completa (full join)

Primer problema:

Un club dicta clases de distintos deportes. Almacena la informacin en una tabla llamada
"deportes" en la cual incluye el nombre del deporte y el nombre del profesor y en otra tabla
llamada "inscriptos" que incluye el documento del socio que se inscribe, el deporte y si la
matricula est paga o no.

1- Elimine las tablas, crelas y agregue dos restricciones, una "primary key" sobre el campo
"codigo" de "deportes" y otra compuesta por "documento" y "codigodeporte" de "inscriptos":

drop table deportes;


drop table inscriptos;

create table deportes(


codigo number(2),
nombre varchar2(30),
profesor varchar2(30)
);

create table inscriptos(


documento char(8),
codigodeporte number(2),
matricula char(1) --'s'=paga; 'n'=impaga
);

alter table deportes


add constraint PK_deportes
primary key(codigo);

alter table inscriptos


add constraint PK_inscriptos
primary key(documento,codigodeporte);

2- Ingrese algunos registros para ambas tablas:

insert into deportes values(1,'tenis','Marcelo Roca');


insert into deportes values(2,'natacion','Marta Torres');
insert into deportes values(3,'basquet','Luis Garcia');
insert into deportes values(4,'futbol','Marcelo Roca');

insert into inscriptos values('22222222',3,'s');


insert into inscriptos values('23333333',3,'s');
insert into inscriptos values('24444444',3,'n');
insert into inscriptos values('22222222',2,'s');
insert into inscriptos values('23333333',2,'s');
insert into inscriptos values('22222222',4,'n');
insert into inscriptos values('22222222',5,'n');

3- Muestre todos la informacin de la tabla "inscriptos", y consulte la tabla "deportes" para


obtener el nombre de cada deporte (6 registros)

Note que uno de los registros tiene seteado a null la columna "deporte".

4- Empleando un "left join" con "deportes" obtenga todos los datos de los inscriptos (7
registros)

5- Obtenga la misma salida anterior empleando un "rigth join"

Note que se cambia el orden de las tablas y "right" por "left".

6- Muestre los deportes para los cuales no hay inscriptos, empleando un "left join" (1 registro)

7- Muestre los documentos de los inscriptos a deportes que no existen en la tabla "deportes"
(1 registro)

8- Emplee un "full join" para obtener todos los datos de ambas tablas, incluyendo las
inscripciones a deportes inexistentes en "deportes" y los deportes que no tienen inscriptos (8
registros)

Note que uno de los registros con documento "22222222" tiene seteado a "null" los campos
correspondientes a "deportes" porque el cdigo "5" no est presente en "deportes"; otro
registro, que muestra "tenis" y "Marcelo Roca", tiene valores nulos en los campos
correspondientes a la tabla "inscriptos", ya que, para el deporte con cdigo 1, no hay
inscriptos.
drop table deportes;
drop table inscriptos;

create table deportes(


codigo number(2),
nombre varchar2(30),
profesor varchar2(30)
);

create table inscriptos(


documento char(8),
codigodeporte number(2),
matricula char(1) --'s'=paga; 'n'=impaga
);

alter table deportes


add constraint PK_deportes
primary key(codigo);

alter table inscriptos


add constraint PK_inscriptos
primary key(documento,codigodeporte);

insert into deportes values(1,'tenis','Marcelo Roca');


insert into deportes values(2,'natacion','Marta Torres');
insert into deportes values(3,'basquet','Luis Garcia');
insert into deportes values(4,'futbol','Marcelo Roca');

insert into inscriptos values('22222222',3,'s');


insert into inscriptos values('23333333',3,'s');
insert into inscriptos values('24444444',3,'n');
insert into inscriptos values('22222222',2,'s');
insert into inscriptos values('23333333',2,'s');
insert into inscriptos values('22222222',4,'n');
insert into inscriptos values('22222222',5,'n');

select documento,d.nombre as deporte,matricula


from inscriptos i
join deportes d
on codigodeporte=codigo;

select documento,d.nombre as deporte,matricula


from inscriptos i
left join deportes d
on codigodeporte=codigo;

select documento,d.nombre as deporte,matricula


from deportes d
right join inscriptos i
on codigodeporte=codigo;

select nombre
from deportes d
left join inscriptos i
on codigodeporte=codigo
where codigodeporte is null;

select documento
from inscriptos i
left join deportes d
on codigodeporte=codigo
where codigo is null;

select documento,nombre as deporte,profesor,matricula


from inscriptos i
full join deportes d
on codigodeporte=codigo;

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.

52 - Combinaciones cruzadas (cross)

Problema:

Un pequeo restaurante tiene almacenados los nombres y precios de sus comidas en una tabla
llamada "comidas" y en una tabla denominada "postres" los mismos datos de sus postres.
Eliminamos las tablas:

drop table comidas;


drop table postres;

Creamos las tablas:

create table comidas(


codigo number(2),
nombre varchar2(30),
precio number(4,2)
);

create table postres(


codigo number(2),
nombre varchar2(30),
precio number(4,2)
);

Ingresamos algunos registros:

insert into comidas values(1,'ravioles',5);


insert into comidas values(2,'tallarines',4);
insert into comidas values(3,'milanesa',7);
insert into comidas values(4,'cuarto de pollo',6);

insert into postres values(1,'flan',2.5);


insert into postres values(2,'porcion torta',3.5);

El restaurante quiere combinar los registros de ambas tablas para mostrar los distintos
menes que ofrece. Lo hacemos usando 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. Se obtienen 8 registros.

En la siguiente combinacin cruzada, agregamos una columna que calcula el precio total de
cada men:

select c.nombre as "plato principal",


p.nombre as "postre",
c.precio+p.precio as "total"
from comidas c
cross join postres p;

La salida muestra cada plato combinado con cada uno de los postres y el precio total de cada
men. Se obtienen 8 registros.

52 - Combinaciones cruzadas (cross)

Primer problema:
Una agencia matrimonial almacena la informacin de sus clientes de sexo femenino en una
tabla llamada "mujeres" y en otra la de sus clientes de sexo masculino llamada "varones".

1- Elimine las tablas y crelas con las siguientes estructuras:

drop table mujeres;


drop table varones;

create table mujeres(


nombre varchar2(30),
domicilio varchar2(30),
edad number(2)
);

create table varones(


nombre varchar2(30),
domicilio varchar2(30),
edad number(2)
);

2- Ingrese los siguientes registros:

insert into mujeres values('Maria Lopez','Colon 123',45);


insert into mujeres values('Liliana Garcia','Sucre 456',35);
insert into mujeres values('Susana Lopez','Avellaneda 98',41);

insert into varones values('Juan Torres','Sarmiento 755',44);


insert into varones values('Marcelo Oliva','San Martin 874',56);
insert into varones values('Federico Pereyra','Colon 234',38);
insert into varones values('Juan Garcia','Peru 333',50);

3- La agencia necesita la combinacin de todas las personas de sexo femenino con las de sexo
masculino. Use un "cross join" (12 filas)

4- Realice la misma combinacin pero considerando solamente las personas mayores de 40


aos (6 filas)

5- Forme las parejas pero teniendo en cuenta que no tengan una diferencia superior a 10 aos
(8 filas)

drop table mujeres;


drop table varones;

create table mujeres(


nombre varchar2(30),
domicilio varchar2(30),
edad number(2)
);

create table varones(


nombre varchar2(30),
domicilio varchar2(30),
edad number(2)
);

insert into mujeres values('Maria Lopez','Colon 123',45);


insert into mujeres values('Liliana Garcia','Sucre 456',35);
insert into mujeres values('Susana Lopez','Avellaneda 98',41);

insert into varones values('Juan Torres','Sarmiento 755',44);


insert into varones values('Marcelo Oliva','San Martin 874',56);
insert into varones values('Federico Pereyra','Colon 234',38);
insert into varones values('Juan Garcia','Peru 333',50);

select m.nombre,m.edad,v.nombre,v.edad
from mujeres m
cross join varones v;

select m.nombre,m.edad,v.nombre,v.edad
from mujeres m
cross join varones v
where m.edad>40 and
v.edad>40;

select m.nombre,m.edad,v.nombre,v.edad
from mujeres m
cross join varones v
where m.edad-v.edad between -10 and 10;

Segundo problema:

Una empresa de seguridad almacena los datos de sus guardias de seguridad en una tabla
llamada "guardias". tambin almacena los distintos sitios que solicitaron sus servicios en una
tabla llamada "tareas".

1- Elimine las tablas "guardias" y "tareas":

drop table guardias;


drop table tareas;

2- Cree las tablas:

create table guardias(


documento char(8),
nombre varchar2(30),
sexo char(1), /* 'f' o 'm' */
domicilio varchar2(30),
primary key (documento)
);

create table tareas(


codigo number(2),
domicilio varchar2(30),
descripcion varchar2(30),
horario char(2), /* 'AM' o 'PM'*/
primary key (codigo)
);

3- Ingrese los siguientes registros:

insert into guardias values('22333444','Juan Perez','m','Colon 123');


insert into guardias values('24333444','Alberto Torres','m','San Martin 567');
insert into guardias values('25333444','Luis Ferreyra','m','Chacabuco 235');
insert into guardias values('23333444','Lorena Viale','f','Sarmiento 988');
insert into guardias values('26333444','Irma Gonzalez','f','Mariano Moreno 111');

insert into tareas values(1,'Colon 1111','vigilancia exterior','AM');


insert into tareas values(2,'Urquiza 234','vigilancia exterior','PM');
insert into tareas values(3,'Peru 345','vigilancia interior','AM');
insert into tareas values(4,'Avellaneda 890','vigilancia interior','PM');

4- La empresa quiere que todos sus empleados realicen todas las tareas. Realice un "cross
join" (20 filas)

5- En este caso, la empresa quiere que todos los guardias de sexo femenino realicen las tareas
de "vigilancia interior" y los de sexo masculino de "vigilancia exterior". Realice una "cross join"
con un "where" que controle tal requisito (10 filas)

drop table guardias;


drop table tareas;

create table guardias(


documento char(8),
nombre varchar2(30),
sexo char(1), /* 'f' o 'm' */
domicilio varchar2(30),
primary key (documento)
);

create table tareas(


codigo number(2),
domicilio varchar2(30),
descripcion varchar2(30),
horario char(2), /* 'AM' o 'PM'*/
primary key (codigo)
);

insert into guardias values('22333444','Juan Perez','m','Colon 123');


insert into guardias values('24333444','Alberto Torres','m','San Martin 567');
insert into guardias values('25333444','Luis Ferreyra','m','Chacabuco 235');
insert into guardias values('23333444','Lorena Viale','f','Sarmiento 988');
insert into guardias values('26333444','Irma Gonzalez','f','Mariano Moreno 111');

insert into tareas values(1,'Colon 1111','vigilancia exterior','AM');


insert into tareas values(2,'Urquiza 234','vigilancia exterior','PM');
insert into tareas values(3,'Peru 345','vigilancia interior','AM');
insert into tareas values(4,'Avellaneda 890','vigilancia interior','PM');

select nombre,t.domicilio,descripcion
from guardias
cross join tareas t;

select nombre,t.domicilio,descripcion
from guardias g
cross join tareas t
where (g.sexo='f' and t.descripcion='vigilancia interior') or
(g.sexo='m' and t.descripcion='vigilancia exterior');

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".

53 - Autocombinacin

Problema:

Un pequeo restaurante tiene almacenados los nombres, precios y rubro de sus comidas en
una tabla llamada "comidas".

Eliminamos la tabla:

drop table comidas;

Creamos la tabla:

create table comidas(


codigo number(2),
nombre varchar2(30),
precio number(4,2),
rubro char(6),-- 'plato'=plato principal', 'postre'=postre
primary key(codigo)
);

Ingresamos algunos registros:

insert into comidas values(1,'ravioles',5,'plato');


insert into comidas values(2,'tallarines',4,'plato');
insert into comidas values(3,'milanesa',7,'plato');
insert into comidas values(4,'cuarto de pollo',6,'plato');
insert into comidas values(5,'flan',2.5,'postre');
insert into comidas values(6,'porcion torta',3.5,'postre');

Realizamos un "cross join":

select c1.nombre,
c2.nombre,
c1.precio+c2.precio as total
from comidas c1
cross join comidas c2;

Note que aparecen filas duplicadas, por ejemplo, "ravioles" se combina con "ravioles" y la
combinacin "ravioles- flan" se repite como "flan- ravioles". Debemos especificar que combine
el rubro "plato" con "postre":

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';

La salida muestra cada plato combinado con cada postre, y una columna extra que calcula el
total del men.
Tambin se puede realizar una autocombinacin con "join":

select c1.nombre as "plato principal",


c2.nombre as postre,
c1.precio+c2.precio 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".

53 - Autocombinacin

Primer problema:

Una agencia matrimonial almacena la informacin de sus clientes en una tabla llamada
"clientes".

1- Elimine la tabla y crela:

drop table clientes;

create table clientes(


nombre varchar2(30),
sexo char(1),--'f'=femenino, 'm'=masculino
edad number(2),
domicilio varchar2(30)
);

2- Ingrese los siguientes registros:

insert into clientes values('Maria Lopez','f',45,'Colon 123');


insert into clientes values('Liliana Garcia','f',35,'Sucre 456');
insert into clientes values('Susana Lopez','f',41,'Avellaneda 98');
insert into clientes values('Juan Torres','m',44,'Sarmiento 755');
insert into clientes values('Marcelo Oliva','m',56,'San Martin 874');
insert into clientes values('Federico Pereyra','m',38,'Colon 234');
insert into clientes values('Juan Garcia','m',50,'Peru 333');

3- La agencia necesita la combinacin de todas las personas de sexo femenino con las de sexo
masculino. Use un "cross join" (12 filas)

4- Obtenga la misma salida anterior pero realizando un "join"

5- Realice la misma autocombinacin que el punto 3 pero agregue la condicin que las parejas
no tengan una diferencia superior a 5 aos (5 filas)

drop table clientes;

create table clientes(


nombre varchar2(30),
sexo char(1),--'f'=femenino, 'm'=masculino
edad number(2),
domicilio varchar2(30)
);

insert into clientes values('Maria Lopez','f',45,'Colon 123');


insert into clientes values('Liliana Garcia','f',35,'Sucre 456');
insert into clientes values('Susana Lopez','f',41,'Avellaneda 98');
insert into clientes values('Juan Torres','m',44,'Sarmiento 755');
insert into clientes values('Marcelo Oliva','m',56,'San Martin 874');
insert into clientes values('Federico Pereyra','m',38,'Colon 234');
insert into clientes values('Juan Garcia','m',50,'Peru 333');

select cm.nombre,cm.edad,cv.nombre,cv.edad
from clientes cm
cross join clientes cv
where cm.sexo='f' and cv.sexo='m';

select cm.nombre,cm.edad,cv.nombre,cv.edad
from clientes cm
join clientes cv
on cm.nombre<>cv.nombre
where cm.sexo='f' and cv.sexo='m';

select cm.nombre,cm.edad,cv.nombre,cv.edad
from clientes cm
cross join clientes cv
where cm.sexo='f' and cv.sexo='m' and
cm.edad-cv.edad between -5 and 5;

Segundo problema:

Varios clubes de barrio se organizaron para realizar campeonatos entre ellos. La tabla
llamada "equipos" guarda la informacin de los distintos equipos que jugarn.

1- Elimine la tabla y crela nuevamente:

drop table equipos;

create table equipos(


nombre varchar2(30),
barrio varchar2(20),
domicilio varchar2(30),
entrenador varchar2(30)
);

2- Ingrese los siguientes registros:

insert into equipos values('Los tigres','Gral. Paz','Sarmiento 234','Juan Lopez');


insert into equipos values('Los leones','Centro','Colon 123','Gustavo Fuentes');
insert into equipos values('Campeones','Pueyrredon','Guemes 346','Carlos
Moreno');
insert into equipos values('Cebollitas','Alberdi','Colon 1234','Luis Duarte');

4- Cada equipo jugar con todos los dems 2 veces, una vez en cada sede. Realice un "cross
join" para combinar los equipos teniendo en cuenta que un equipo no juega consigo mismo (12
filas)

5- Obtenga el mismo resultado empleando un "join".

6- Realice un "cross join" para combinar los equipos para que cada equipo juegue con cada
uno de los otros una sola vez (6 filas)

drop table equipos;

create table equipos(


nombre varchar2(30),
barrio varchar2(20),
domicilio varchar2(30),
entrenador varchar2(30)
);

insert into equipos values('Los tigres','Gral. Paz','Sarmiento 234','Juan Lopez');


insert into equipos values('Los leones','Centro','Colon 123','Gustavo Fuentes');
insert into equipos values('Campeones','Pueyrredon','Guemes 346','Carlos
Moreno');
insert into equipos values('Cebollitas','Alberdi','Colon 1234','Luis Duarte');

select e1.nombre,e2.nombre,e1.barrio as sede


from equipos e1
cross join equipos e2
where e1.nombre<>e2.nombre;
5- Obtenga el mismo resultado empleando un "join":
select e1.nombre,e2.nombre,e1.barrio as 'sede'
from equipos e1
join equipos e2
on e1.nombre<>e2.nombre;

select e1.nombre,e2.nombre,e1.barrio as sede


from equipos e1
cross join equipos e2
where e1.nombre>e2.nombre;

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.

54 - Combinaciones y funciones de agrupamiento

Problema:

Una librera almacena la informacin de sus libros para la venta en dos tablas, "libros" y
"editoriales".

Eliminamos ambas tablas y las creamos:

drop table libros;


drop table editoriales;

create table libros(


codigo number(5),
titulo varchar2(40),
autor varchar2(30),
codigoeditorial number(3),
precio number(5,2),
primary key(codigo)
);

create table editoriales(


codigo number(3),
nombre varchar2(20),
primary key (codigo)
);

Ingresamos algunos registros en ambas tablas:

insert into editoriales values(1,'Planeta');


insert into editoriales values(2,'Emece');
insert into editoriales values(3,'Siglo XXI');

insert into libros values(100,'El aleph','Borges',1,20);


insert into libros values(200,'Martin Fierro','Jose Hernandez',1,30);
insert into libros values(300,'Aprenda PHP','Mario Molina',3,50);
insert into libros values(400,'Uno','Richard Bach',3,15);
insert into libros values(500,'Java en 10 minutos',default,4,45);

Contamos la cantidad de libros de cada editorial consultando ambas tablas:

select nombre as editorial,


count(*) as cantidad
from editoriales e
join libros l
on codigoeditorial=e.codigo
group by e.nombre;

Note que las editoriales que no tienen libros no aparecen en la salida porque empleamos un
"join".

Buscamos el libro ms costoso de cada editorial con un "left join":

select nombre as editorial,


max(precio) as "mayor precio"
from editoriales e
left join libros l
on codigoeditorial=e.codigo
group by nombre;

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

54 - Combinaciones y funciones de agrupamiento

Primer problema:

Un comercio que tiene un stand en una feria registra en una tabla llamada "visitantes" algunos
datos de las personas que visitan o compran en su stand para luego enviarle publicidad de sus
productos y en otra tabla llamada "ciudades" los nombres de las ciudades.

1- Elimine las tablas:

drop table visitantes;


drop table ciudades;

2- Cree las tablas:

create table visitantes(


nombre varchar2(30),
edad number(2),
sexo char(1) default 'f',
domicilio varchar2(30),
codigociudad number(2),
mail varchar(30),
montocompra decimal (6,2)
);

create table ciudades(


codigo number(2),
nombre varchar(20)
);
3- Ingrese algunos registros:

insert into ciudades values(1,'Cordoba');


insert into ciudades values(2,'Carlos Paz');
insert into ciudades values(3,'La Falda');
insert into ciudades values(4,'Cruz del Eje');

insert into visitantes values ('Susana Molina', 35,'f','Colon 123', 1, null,59.80);


insert into visitantes values ('Marcos Torres', 29,'m','Sucre 56', 1,
'marcostorres@hotmail.com',150.50);
insert into visitantes values ('Mariana Juarez', 45,'f','San Martin 111',2,null,23.90);
insert into visitantes values ('Fabian Perez',36,'m','Avellaneda
213',3,'fabianperez@xaxamail.com',0);
insert into visitantes values ('Alejandra Garcia',28,'f',null,2,null,280.50);
insert into visitantes values ('Gaston
Perez',29,'m',null,5,'gastonperez1@gmail.com',95.40);
insert into visitantes values ('Mariana Juarez',33,'f',null,2,null,90);

4- Cuente la cantidad de visitas por ciudad mostrando el nombre de la ciudad (3 filas)

5- Muestre el promedio de gastos de las visitas agrupados por ciudad y sexo (4 filas)

6- Muestre la cantidad de visitantes con mail, agrupados por ciudad (3 filas)

7- Obtenga el monto de compra ms alto de cada ciudad (3 filas)

8- Realice la misma consulta anterior pero con "left join" (4 filas)

Note que aparece el monto "95,4" con valor nulo en el campo correspondiente a la ciudad, ya
que ese registro tiene un valor inexistente en "ciudades".

drop table visitantes;


drop table ciudades;

create table visitantes(


nombre varchar2(30),
edad number(2),
sexo char(1) default 'f',
domicilio varchar2(30),
codigociudad number(2),
mail varchar(30),
montocompra decimal (6,2)
);

create table ciudades(


codigo number(2),
nombre varchar(20)
);

insert into ciudades values(1,'Cordoba');


insert into ciudades values(2,'Carlos Paz');
insert into ciudades values(3,'La Falda');
insert into ciudades values(4,'Cruz del Eje');
insert into visitantes values ('Susana Molina', 35,'f','Colon 123', 1, null,59.80);
insert into visitantes values ('Marcos Torres', 29,'m','Sucre 56', 1,
'marcostorres@hotmail.com',150.50);
insert into visitantes values ('Mariana Juarez', 45,'f','San Martin 111',2,null,23.90);
insert into visitantes values ('Fabian Perez',36,'m','Avellaneda
213',3,'fabianperez@xaxamail.com',0);
insert into visitantes values ('Alejandra Garcia',28,'f',null,2,null,280.50);
insert into visitantes values ('Gaston
Perez',29,'m',null,5,'gastonperez1@gmail.com',95.40);
insert into visitantes values ('Mariana Juarez',33,'f',null,2,null,90);

select c.nombre,
count(*) as cantidad
from ciudades c
join visitantes v
on codigociudad=c.codigo
group by c.nombre;

select c.nombre,sexo,
avg(montocompra) as "promedio de compra"
from ciudades c
join visitantes v
on codigociudad=c.codigo
group by c.nombre,sexo;

select c.nombre,
count(mail) as "tienen mail"
from ciudades c
join visitantes v
on codigociudad=c.codigo
group by c.nombre;

select c.nombre,
max(montocompra)
from visitantes v
join ciudades c
on codigociudad=c.codigo
group by c.nombre;

select c.nombre,
max(montocompra)
from visitantes v
left join ciudades c
on codigociudad=c.codigo
group by c.nombre;

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".

55 - Combinar ms de 2 tablas

Problema:

Una librera almacena la informacin de sus libros para la venta en tres tablas, "libros",
"autores" y "editoriales".

Eliminamos ambas tablas y las creamos:

drop table libros;


drop table autores;
drop table editoriales;

create table libros(


codigo number(5),
titulo varchar2(40),
codigoautor number(4) not null,
codigoeditorial number(3),
primary key(codigo)
);

create table autores(


codigo number(4),
nombre varchar2(20),
primary key (codigo)
);

create table editoriales(


codigo number(3),
nombre varchar2(20),
primary key (codigo)
);

Ingresamos algunos registros:

insert into editoriales values(1,'Planeta');


insert into editoriales values(2,'Emece');
insert into editoriales values(3,'Siglo XXI');
insert into editoriales values(4,'Norma');

insert into autores values (1,'Richard Bach');


insert into autores values (2,'Borges');
insert into autores values (3,'Jose Hernandez');
insert into autores values (4,'Mario Molina');
insert into autores values (5,'Paenza');

insert into libros values(100,'El aleph',2,2);


insert into libros values(101,'Martin Fierro',3,1);
insert into libros values(102,'Aprenda PHP',4,3);
insert into libros values(103,'Uno',1,1);
insert into libros values(104,'Java en 10 minutos',0,3);
insert into libros values(105,'Matematica estas ahi',10,null);
insert into libros values(106,'Java de la A a la Z',4,0);

Recuperamos todos los datos de los libros consultando las tres tablas:

select titulo,a.nombre as autor,e.nombre as editorial


from autores a
join libros l
on codigoautor=a.codigo
join editoriales e
on codigoeditorial=e.codigo;

Note que no aparecen los libros cuyo cdigo de autor no se encuentra en "autores" (caso de
"Java en 10 minutos" y "Matematica estas ahi") y cuya editorial no existe en "editoriales" (caso
de "Matematica estas ahi" y "Java de la A a la Z"), esto es porque realizamos una combinacin
interna.

Podemos combinar varios tipos de join en una misma sentencia:

select titulo,a.nombre as autor,e.nombre as editorial


from autores a
right join libros l
on codigoautor=a.codigo
left join editoriales e
on codigoeditorial=e.codigo;
55 - Combinar ms de 2 tablas

Primer problema:

Un club dicta clases de distintos deportes. En una tabla llamada "socios" guarda los datos de
los socios, en una tabla llamada "deportes" la informacin referente a los diferentes deportes
que se dictan y en una tabla denominada "inscriptos", las inscripciones de los socios a los
distintos deportes.

Un socio puede inscribirse en varios deportes el mismo ao. Un socio no puede inscribirse en
el mismo deporte el mismo ao. Distintos socios se inscriben en un mismo deporte en el
mismo ao.

1- Elimine las tablas:

drop table socios;


drop table deportes;
drop table inscriptos;

2- Cree las tablas con las siguientes estructuras:

create table socios(


documento char(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
primary key(documento)
);
create table deportes(
codigo number(2),
nombre varchar2(20),
profesor varchar2(15),
primary key(codigo)
);
create table inscriptos(
documento char(8) not null,
codigodeporte number(2) not null,
ao char(4),
matricula char(1),--'s'=paga, 'n'=impaga
primary key(documento,codigodeporte,ao)
);

3- Ingrese algunos registros en "socios":

insert into socios values('22222222','Ana Acosta','Avellaneda 111');


insert into socios values('23333333','Betina Bustos','Bulnes 222');
insert into socios values('24444444','Carlos Castro','Caseros 333');
insert into socios values('25555555','Daniel Duarte','Dinamarca 44');

4- Ingrese algunos registros en "deportes":

insert into deportes values(1,'basquet','Juan Juarez');


insert into deportes values(2,'futbol','Pedro Perez');
insert into deportes values(3,'natacion','Marina Morales');
insert into deportes values(4,'tenis','Marina Morales');

5- Inscriba a varios socios en el mismo deporte en el mismo ao:

insert into inscriptos values ('22222222',3,'2006','s');


insert into inscriptos values ('23333333',3,'2006','s');
insert into inscriptos values ('24444444',3,'2006','n');

6- Inscriba a un mismo socio en el mismo deporte en distintos aos:

insert into inscriptos values ('22222222',3,'2005','s');


insert into inscriptos values ('22222222',3,'2007','n');

7- Inscriba a un mismo socio en distintos deportes el mismo ao:

insert into inscriptos values ('24444444',1,'2006','s');


insert into inscriptos values ('24444444',2,'2006','s');

8- Ingrese una inscripcin con un cdigo de deporte inexistente y un documento de socio que
no exista en "socios":

insert into inscriptos values ('26666666',0,'2006','s');

9- Muestre el nombre del socio, el nombre del deporte en que se inscribi y el ao empleando
diferentes tipos de join (8 filas):

10- Muestre todos los datos de las inscripciones (excepto los cdigos) incluyendo aquellas
inscripciones cuyo cdigo de deporte no existe en "deportes" y cuyo documento de socio no se
encuentra en "socios" (10 filas)

11- Muestre todas las inscripciones del socio con documento "22222222" (3 filas)

drop table socios;


drop table deportes;
drop table inscriptos;

create table socios(


documento char(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
primary key(documento)
);
create table deportes(
codigo number(2),
nombre varchar2(20),
profesor varchar2(15),
primary key(codigo)
);
create table inscriptos(
documento char(8) not null,
codigodeporte number(2) not null,
ao char(4),
matricula char(1),--'s'=paga, 'n'=impaga
primary key(documento,codigodeporte,ao)
);

insert into socios values('22222222','Ana Acosta','Avellaneda 111');


insert into socios values('23333333','Betina Bustos','Bulnes 222');
insert into socios values('24444444','Carlos Castro','Caseros 333');
insert into socios values('25555555','Daniel Duarte','Dinamarca 44');

insert into deportes values(1,'basquet','Juan Juarez');


insert into deportes values(2,'futbol','Pedro Perez');
insert into deportes values(3,'natacion','Marina Morales');
insert into deportes values(4,'tenis','Marina Morales');

insert into inscriptos values ('22222222',3,'2006','s');


insert into inscriptos values ('23333333',3,'2006','s');
insert into inscriptos values ('24444444',3,'2006','n');

insert into inscriptos values ('22222222',3,'2005','s');


insert into inscriptos values ('22222222',3,'2007','n');

insert into inscriptos values ('24444444',1,'2006','s');


insert into inscriptos values ('24444444',2,'2006','s');

insert into inscriptos values ('26666666',0,'2006','s');

select s.nombre,d.nombre,ao
from deportes d
right join inscriptos i
on codigodeporte=d.codigo
left join socios s
on i.documento=s.documento;

select s.nombre,d.nombre,ao,matricula
from deportes d
full join inscriptos i
on codigodeporte=d.codigo
full join socios s
on s.documento=i.documento;

select s.nombre,d.nombre,ao,matricula
from deportes d
join inscriptos i
on codigodeporte=d.codigo
join socios s
on s.documento=i.documento
where s.documento='22222222';

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(+);

56 - Otros tipos de combinaciones

Problema:

Una librera almacena la informacin de sus libros para la venta en dos tablas, "libros" y
"editoriales".

Eliminamos ambas tablas y las creamos:

drop table libros;


drop table editoriales;

create table libros(


codigo number(5),
titulo varchar2(40),
autor varchar2(30),
codigoeditorial number(3)
);
create table editoriales(
codigoeditorial number(3),
nombre varchar2(20)
);

Ingresamos algunos registros en ambas tablas:

insert into editoriales values(1,'Planeta');


insert into editoriales values(2,'Emece');
insert into editoriales values(3,'Siglo XXI');
insert into editoriales values(null,'Norma');

insert into libros values(100,'El aleph','Borges',1);


insert into libros values(101,'Martin Fierro','Jose Hernandez',1);
insert into libros values(102,'Aprenda PHP','Mario Molina',2);
insert into libros values(103,'Java en 10 minutos',null,4);
insert into libros values(104,'El anillo del hechicero','Carol
Gaskin',null);

Realizamos un natural join entre las dos tablas:

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".

Realizamos una combinacin empleando la clusula "using":

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".

Realizamos una combinacin izquierda y luego un "join" con el modificador "(+)"; ambas
consultas retornan el mismo resultado:

select titulo,nombre as editorial


from libros l
left join editoriales e
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".

Realizamos una combinacin derecha y luego obtenemos el mismo resultado empleando "join"
y 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 intentamos emplear el modificador en campos de distintas tablas Oracle mostrar un


mensaje de error:

select titulo,nombre as editorial


from libros l
join editoriales e
on l.codigoeditorial(+)= e.codigoeditorial(+);
56 - Otros tipos de combinaciones

Primer problema:

Una empresa tiene registrados sus clientes en una tabla llamada "clientes", tambin tiene una
tabla "provincias" donde registra los nombres de las provincias.

1- Elimine las tablas "clientes" y "provincias" y crelas:

drop table clientes;


drop table provincias;
create table clientes (
codigo number(5),
nombre varchar2(30),
domicilio varchar2(30),
ciudad varchar2(20),
codigoprovincia number(2)
);

create table provincias(


codigoprovincia number(2),
nombre varchar2(20)
);

2- Ingrese algunos registros para ambas tablas:

insert into provincias values(1,'Cordoba');


insert into provincias values(2,'Santa Fe');
insert into provincias values(3,'Corrientes');
insert into provincias values(null,'Salta');

insert into clientes values (100,'Lopez Marcos','Colon 111','Crdoba',1);


insert into clientes values (101,'Perez Ana','San Martin 222','Cruz del Eje',1);
insert into clientes values (102,'Garcia Juan','Rivadavia 333','Villa Maria',1);
insert into clientes values (103,'Perez Luis','Sarmiento 444','Rosario',2);
insert into clientes values (104,'Gomez Ines','San Martin 666','Santa Fe',2);
insert into clientes values (105,'Torres Fabiola','Alem 777','La Plata',4);
insert into clientes values (106,'Garcia Luis','Sucre 475','Santa Rosa',null);

3- Muestre todos los datos de los clientes, incluido el nombre de la provincia empleando un
"left join" (7 filas)

4- Obtenga la misma salida que la consulta anterior pero empleando un "join" con el
modificador (+)

Note que en los puntos 3 y 4, los registros "Garcia Luis" y "Torres Fabiola" aparecen aunque no
encuentran coincidencia en "provincias", mostrando "null" en la columna "provincia".

5- Muestre todos los datos de los clientes, incluido el nombre de la provincia empleando un
"right join" para que las provincias de las cuales no hay clientes tambin aparezcan en la
consulta (7 filas)

6- Obtenga la misma salida que la consulta anterior pero empleando un "join" con el
modificador (+)

Note que en los puntos 5 y 6, las provincias "Salta" y "Corrientes" aparecen aunque no
encuentran coincidencia en "clientes", mostrando "null" en todos los campos de tal tabla.

7- Intente colocar en una consulta "join", el modificador "(+)" en ambos campos del enlace
(mensaje de error)

8- Intente realizar un natural join entre ambas tablas mostrando el nombre del cliente, la
ciudad y nombre de la provincia (las tablas tienen 2 campos con igual nombre
"codigoprovincia" y "nombre"; mensaje de error)

9- Realice una combinacin entre ambas tablas empleando la clusula "using" (5 filas)
drop table clientes;
drop table provincias;

create table clientes (


codigo number(5),
nombre varchar2(30),
domicilio varchar2(30),
ciudad varchar2(20),
codigoprovincia number(2)
);

create table provincias(


codigoprovincia number(2),
nombre varchar2(20)
);

insert into provincias values(1,'Cordoba');


insert into provincias values(2,'Santa Fe');
insert into provincias values(3,'Corrientes');
insert into provincias values(null,'Salta');

insert into clientes values (100,'Lopez Marcos','Colon 111','Crdoba',1);


insert into clientes values (101,'Perez Ana','San Martin 222','Cruz del Eje',1);
insert into clientes values (102,'Garcia Juan','Rivadavia 333','Villa Maria',1);
insert into clientes values (103,'Perez Luis','Sarmiento 444','Rosario',2);
insert into clientes values (104,'Gomez Ines','San Martin 666','Santa Fe',2);
insert into clientes values (105,'Torres Fabiola','Alem 777','La Plata',4);
insert into clientes values (106,'Garcia Luis','Sucre 475','Santa Rosa',null);

select c.nombre,domicilio,ciudad, p.nombre as provincia


from clientes c
left join provincias p
on c.codigoprovincia = p.codigoprovincia;

select c.nombre,domicilio,ciudad, p.nombre as provincia


from clientes c
join provincias p
on c.codigoprovincia = p.codigoprovincia(+);

select c.nombre,domicilio,ciudad, p.nombre as provincia


from clientes c
right join provincias p
on c.codigoprovincia = p.codigoprovincia;

select c.nombre,domicilio,ciudad, p.nombre as provincia


from clientes c
join provincias p
on c.codigoprovincia(+)= p.codigoprovincia;

select c.nombre,domicilio,ciudad, p.nombre as provincia


from clientes c
join provincias p
on codigoprovincia(+)= p.codigo(+);
select c.nombre,ciudad,p.nombre as provincia
from clientes c
natural join
provincias p;

select c.nombre,ciudad,p.nombre as provincia


from clientes c
join provincias p
using (codigoprovincia);

Segundo problema:

Un club dicta clases de distintos deportes. Almacena la informacin en una tabla llamada
"inscriptos" que incluye el documento, el nombre, el deporte y si la matricula esta paga o no y
una tabla llamada "inasistencias" que incluye el documento, el deporte y la fecha de la
inasistencia.

1- Elimine las tablas y crelas:

drop table inscriptos;


drop table inasistencias;

create table inscriptos(


nombre varchar2(30),
documento char(8),
deporte varchar2(15),
matricula char(1), --'s'=paga; 'n'=impaga
primary key(documento,deporte)
);

create table inasistencias(


documento char(8),
deporte varchar2(15),
fecha date
);

2- Ingrese algunos registros para ambas tablas:

insert into inscriptos values('Juan Perez','22222222','tenis','s');


insert into inscriptos values('Maria Lopez','23333333','tenis','s');
insert into inscriptos values('Agustin Juarez','24444444','tenis','n');
insert into inscriptos values('Marta Garcia','25555555','natacion','s');
insert into inscriptos values('Juan Perez','22222222','natacion','s');
insert into inscriptos values('Maria Lopez','23333333','natacion','n');

insert into inasistencias values('22222222','tenis','01/12/2006');


insert into inasistencias values('22222222','tenis','08/12/2006');
insert into inasistencias values('23333333','tenis','01/12/2006');
insert into inasistencias values('24444444','tenis','08/12/2006');
insert into inasistencias values('22222222','natacion','02/12/2006');
insert into inasistencias values('23333333','natacion','02/12/2006');
3- Muestre toda la informacin de "inscriptos", realizando una combinacin con
"inasistencias". Realice un "left join" para incluir todos los "inscriptos" aunque no se
encuentren en "inasistencias" (7 filas)

Note que la condicin es compuesta porque para identificar los registros necesitamos ambos
campos. Note que la persona con documento '25555555' aparece en la consulta an cuando no
est presente en "inasistencias".

4- Obtenga el mismo resultado anterior empleando un "join" y el modificador "(+)" (7 filas)

Note que se coloca el modificador en ambos campos. Si se omite en alguno de ellos, el


resultado ser diferente (6 filas)

5- Intente realizar un natural join entre ambas tablas mostrando el nombre del inscripto, el
deporte y la fecha de inasistencia (mensaje de error porque hay 2 campos con igual nombre)

6- Realice una combinacin entre ambas tablas mostrando toda la informacin y empleando la
clusula "using" (6 filas)

drop table inscriptos;


drop table inasistencias;

create table inscriptos(


nombre varchar2(30),
documento char(8),
deporte varchar2(15),
matricula char(1), --'s'=paga; 'n'=impaga
primary key(documento,deporte)
);

create table inasistencias(


documento char(8),
deporte varchar2(15),
fecha date
);

insert into inscriptos values('Juan Perez','22222222','tenis','s');


insert into inscriptos values('Maria Lopez','23333333','tenis','s');
insert into inscriptos values('Agustin Juarez','24444444','tenis','n');
insert into inscriptos values('Marta Garcia','25555555','natacion','s');
insert into inscriptos values('Juan Perez','22222222','natacion','s');
insert into inscriptos values('Maria Lopez','23333333','natacion','n');

insert into inasistencias values('22222222','tenis','01/12/2006');


insert into inasistencias values('22222222','tenis','08/12/2006');
insert into inasistencias values('23333333','tenis','01/12/2006');
insert into inasistencias values('24444444','tenis','08/12/2006');
insert into inasistencias values('22222222','natacion','02/12/2006');
insert into inasistencias values('23333333','natacion','02/12/2006');

select ins.documento,nombre,ins.deporte,ina.fecha
from inscriptos ins
left join inasistencias ina
on ins.documento=ina.documento and
ins.deporte=ina.deporte;

select ins.documento,nombre,ins.deporte,ina.fecha
from inscriptos ins
join inasistencias ina
on ins.documento=ina.documento(+) and
ins.deporte=ina.deporte(+);

select ins.documento,nombre,ins.deporte,ina.fecha
from inscriptos ins
join inasistencias ina
on ins.documento=ina.documento(+) and
ins.deporte=ina.deporte;

select nombre,ins.deporte,fecha
from inscriptos ins
natural join
inasistencias ina;

select * from inscriptos ins


join inasistencias ina
using (documento,deporte);

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".

58 - Restricciones (foreign key)

Problema:

Una librera almacena la informacin de sus libros para la venta en dos tablas, "libros" y
"editoriales".

Eliminamos ambas tablas:

drop table libros;


drop table editoriales;

Creamos las tablas:

create table libros(


codigo number(5),
titulo varchar2(40),
autor varchar2(30),
codigoeditorial number(3)
);
create table editoriales(
codigo number(3),
nombre varchar2(20)
);

Ingresamos algunos registros en ambas tablas:

insert into editoriales values(1,'Emece');


insert into editoriales values(2,'Planeta');
insert into editoriales values(3,'Siglo XXI');

insert into libros values(100,'El aleph','Borges',1);


insert into libros values(101,'Martin Fierro','Jose Hernandez',2);
insert into libros values(102,'Aprenda PHP','Mario Molina',5);

Intentamos establecer una restriccin "foreign key" sobre "codigoeditorial":

alter table libros


add constraint FK_libros_codigoeditorial
foreign key (codigoeditorial)
references editoriales(codigo);

Mensaje de error; pues el campo "codigo" de la tabla "editoriales" no fue definida clave
primaria ni nica.

Agregamos una restriccin "primary key" sobre "codigo" de "editoriales":

alter table editoriales


add constraint PK_editoriales
primary key (codigo);

Intentamos nuevamente establecer una restriccin "foreign key" sobre "codigoeditorial":

alter table libros


add constraint FK_libros_codigoeditorial
foreign key (codigoeditorial)
references editoriales(codigo);

Mensaje de error. Oracle controla que los datos existentes no violen la restriccin que
intentamos establecer, como existe un valor de "codigoeditorial" inexistente en "editoriales",
la restriccin no puede establecerse.

Eliminamos el registro que infringe la regla:

delete from libros where codigoeditorial=5;

Ahora si podemos establecer una restriccin "foreign key" sobre "codigoeditorial":

alter table libros


add constraint FK_libros_codigoeditorial
foreign key (codigoeditorial)
references editoriales(codigo);

Veamos las restricciones de "libros" consultando "user_constraints":

select constraint_name, constraint_type


from user_constraints
where table_name='LIBROS';
aparece la restriccin "FK_libros_codigoeditorial" indicando que es una "foreign key" con el
caracter "R" en el tipo de restriccin.

Consultamos "user_cons_columns":

select constraint_name, column_name


from user_cons_columns
where table_name='LIBROS';

Aparece la siguiente tabla:

CONSTRAINT_NAME COLUMN_NAME
-------------------------------------------
FK_LIBROS_CODIGOEDITORIAL EDITORIALEDITORIAL

Veamos las restricciones de "editoriales":

select constraint_name, constraint_type


from user_constraints
where table_name='EDITORIALES';

aparece la restriccin "primary key".

Ingresamos un libro sin especificar un valor para el cdigo de editorial:

insert into libros values(103,'El experto en


laberintos','Gaskin',default);

Veamos todos los registros de "libros":

select *from libros;

Note que en "codigoeditorial" almacen "null", porque esta restriccin permite valores nulos
(a menos que se haya especificado lo contrario al definir el campo).

Intentamos agregar un libro con un cdigo de editorial inexistente en "editoriales":

insert into libros values(104,'El anillo del hechicero','Gaskin',8);

Nos muestra un mensaje indicando que la restriccin FK_LIBROS_EDITORIAL est siendo


violada, que no encuentra el valor de clave primaria en "editoriales".

Intentamos eliminar una editorial cuyo cdigo est presente en "libros":

delete from editoriales where codigo=2;

Un mensaje nos informa que la restriccin de clave externa est siendo violada, existen
registros que hacen referencia al que queremos eliminar.

Intente eliminar la tabla "editoriales":

drop table editoriales;

Un mensaje de error indica que la accin no puede realizarse porque la tabla es referenciada
por una "foreign key".
58 - Restricciones (foreign key)

Primer problema:

Una empresa tiene registrados sus clientes en una tabla llamada "clientes", tambin tiene una
tabla "provincias" donde registra los nombres de las provincias.

1- Elimine las tablas "clientes" y "provincias" y crelas:

drop table clientes;


drop table provincias;

create table clientes (


codigo number(5),
nombre varchar2(30),
domicilio varchar2(30),
ciudad varchar2(20),
codigoprovincia number(2)
);

create table provincias(


codigo number(2),
nombre varchar2(20)
);

En este ejemplo, el campo "codigoprovincia" de "clientes" es una clave fornea, se emplea


para enlazar la tabla "clientes" con "provincias".

2- Intente agregar una restriccin "foreign key" a la tabla "clientes" que haga referencia al
campo "codigo" de "provincias"

No se puede porque "provincias" no tiene restriccin "primary key" ni "unique".

3- Establezca una restriccin "unique" al campo "codigo" de "provincias"

4- Ingrese algunos registros para ambas tablas:

insert into provincias values(1,'Cordoba');


insert into provincias values(2,'Santa Fe');
insert into provincias values(3,'Misiones');
insert into provincias values(4,'Rio Negro');

insert into clientes values(100,'Perez Juan','San Martin 123','Carlos Paz',1);


insert into clientes values(101,'Moreno Marcos','Colon 234','Rosario',2);
insert into clientes values(102,'Acosta Ana','Avellaneda 333','Posadas',3);
insert into clientes values(103,'Luisa Lopez','Juarez 555','La Plata',6);

5- Intente agregar la restriccin "foreign key" del punto 2 a la tabla "clientes"

No se puede porque hay un registro en "clientes" cuyo valor de "codigoprovincia" no existe en


"provincias".

6- Elimine el registro de "clientes" que no cumple con la restriccin y establezca la restriccin


nuevamente.
7- Intente agregar un cliente con un cdigo de provincia inexistente en "provincias"

8- Intente eliminar el registro con cdigo 3, de "provincias".


No se puede porque hay registros en "clientes" al cual hace referencia.

9- Elimine el registro con cdigo "4" de "provincias"


Se permite porque en "clientes" ningn registro hace referencia a l.

10- Intente modificar el registro con cdigo 1, de "provincias"


No se puede porque hay registros en "clientes" al cual hace referencia.

11- Vea las restricciones de "clientes" consultando "user_constraints"

12- Vea las restricciones de "provincias"

13- Intente eliminar la tabla "provincias" (mensaje de error)

14- Elimine la restriccin "foreign key" de "clientes" y luego elimine la tabla "provincias"

drop table clientes;


drop table provincias;

create table clientes (


codigo number(5),
nombre varchar2(30),
domicilio varchar2(30),
ciudad varchar2(20),
codigoprovincia number(2)
);

create table provincias(


codigo number(2),
nombre varchar2(20)
);

alter table clientes


add constraint FK_clientes_codigoprovincia
foreign key (codigoprovincia)
references provincias(codigo);

alter table provincias


add constraint UQ_provincias_codigo
unique (codigo);

insert into provincias values(1,'Cordoba');


insert into provincias values(2,'Santa Fe');
insert into provincias values(3,'Misiones');
insert into provincias values(4,'Rio Negro');

insert into clientes values(100,'Perez Juan','San Martin 123','Carlos Paz',1);


insert into clientes values(101,'Moreno Marcos','Colon 234','Rosario',2);
insert into clientes values(102,'Acosta Ana','Avellaneda 333','Posadas',3);
insert into clientes values(103,'Luisa Lopez','Juarez 555','La Plata',6);
alter table clientes
add constraint FK_clientes_codigoprovincia
foreign key (codigoprovincia)
references provincias(codigo);

delete from clientes where codigoprovincia=6;

alter table clientes


add constraint FK_clientes_codigoprovincia
foreign key (codigoprovincia)
references provincias(codigo);

insert into clientes values(104,'Garcia Marcos','Colon 877','Lules',9);


Oracle no lo permite.

delete from provincias where codigo=3;

delete from provincias where codigo=4;

update provincias set codigo=7 where codigo=1;

select constraint_name, constraint_type


from user_constraints
where table_name='CLIENTES';

select constraint_name, constraint_type


from user_constraints
where table_name='PROVINCIAS';

drop table provincias;

alter table clientes


drop constraint FK_CLIENTES_CODIGOPROVINCIA;

drop table provincias;

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).

59 - Restricciones foreign key en la misma tabla

Problema:

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.

Eliminamos la tabla "afiliados" y la creamos:

drop table afiliados;

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);

Ingresamos algunos registros:

insert into afiliados values(1,'22222222','Perez Juan',null);


insert into afiliados values(2,'23333333','Garcia Maria',null);
insert into afiliados values(3,'24444444','Lopez Susana',null);
insert into afiliados values(4,'30000000','Perez Marcela',1);
insert into afiliados values(5,'31111111','Garcia Luis',2);
insert into afiliados values(6,'32222222','Garcia Maria',2);

Podemos eliminar un afiliado, siempre que no haya otro afiliado que haga referencia a l en
"afiliadotitular", es decir, si el "numero" del afiliado est presente en algn registro en el
campo "afiliadotitular":

delete from afiliados where numero=5;

Veamos la informacin referente a "afiliados":

select constraint_name, constraint_type,search_condition


from user_constraints
where table_name='AFILIADOS';

Aparece la siguiente tabla:

CONSTRAINT_NAME CONSTRAINT_TYPE SEARCH_CONDITION


----------------------------------------------------------------------
-----------
SYS_C004816 C "DOCUMENTO" IS
NOT NULL
SYS_C004817 P
SYS_C004818 U
FK_AFILIADOS_AFILIADOTITULAR R

Los nombres de las tres primeras restricciones son dadas por Oracle.

La tabla tiene una restriccin "check", una "primary key", una "unique" y una "foreign key".

Veamos sobre qu campos estn establecidas:

select *from user_cons_columns


where table_name='AFILIADOS';

Aparece la siguiente tabla:

CONSTRAINT_NAME COLUMN_NAME POSITION


----------------------------------------------------------
SYS_C004818 NUMERO 1
SYS_C004817 DOCUMENTO 1
SYS_C004816 DOCUMENTO
FK_AFILIADOS_AFILIADOTITULAR AFILIADOTITULAR 1

Nos informa que la restriccin nica est establecida sobre "numero"; la "primary key" sobre
"documento", la restriccin de chequeo sobre "documento" y la "foreign key" sobre
"afiliadotitular".
Ingresamos un nuevo registro con un valor para "afiliadotitular" existente:

insert into afiliados values(7,'33333333','Lopez Juana',3);

Intentamos ingresar un nuevo registro con un valor para "afiliadotitular" inexistente:

insert into afiliados values(8,'34555666','Marconi Julio',9);

Oracle no lo permite porque se violara la restriccin "foreign key".

Igresamos un nuevo registro con el valor "null" para "afiliadotitular":

insert into afiliados values(8,'34555666','Marconi Julio',null);


59 - Restricciones foreign key en la misma tabla

Primer problema:

Una empresa registra los datos de sus clientes en una tabla llamada "clientes". Dicha tabla
contiene un campo que hace referencia al cliente que lo recomend denominado
"referenciadopor". Si un cliente no ha sido referenciado por ningn otro cliente, tal campo
almacena "null".

1- Elimine la tabla y crela:

drop table clientes;

create table clientes(


codigo number(5),
nombre varchar2(30),
domicilio varchar2(30),
ciudad varchar2(20),
referenciadopor number(5),
primary key(codigo)
);

2- Ingresamos algunos registros:

insert into clientes values (50,'Juan Perez','Sucre 123','Cordoba',null);


insert into clientes values(90,'Marta Juarez','Colon 345','Carlos Paz',null);
insert into clientes values(110,'Fabian Torres','San Martin 987','Cordoba',50);
insert into clientes values(125,'Susana Garcia','Colon 122','Carlos Paz',90);
insert into clientes values(140,'Ana Herrero','Colon 890','Carlos Paz',9);

3- Intente agregar una restriccin "foreign key" para evitar que en el campo "referenciadopor"
se ingrese un valor de cdigo de cliente que no exista.
No se permite porque existe un registro que no cumple con la restriccin que se intenta
establecer.

4- Cambie el valor invlido de "referenciadopor" del registro que viola la restriccin por uno
vlido:

update clientes set referenciadopor=90 where referenciadopor=9;

5- Agregue la restriccin "foreign key" que intent agregar en el punto 3


6- Vea la informacin referente a las restricciones de la tabla "clientes"
La tabla tiene 2 restricciones.

7- Intente agregar un registro que infrinja la restriccin.

8- Intente modificar el cdigo de un cliente que est referenciado en "referenciadopor"

9- Intente eliminar un cliente que sea referenciado por otro en "referenciadopor"

10- Cambie el valor de cdigo de un cliente que no referenci a nadie.

11- Elimine un cliente que no haya referenciado a otros.

drop table clientes;

create table clientes(


codigo number(5),
nombre varchar2(30),
domicilio varchar2(30),
ciudad varchar2(20),
referenciadopor number(5),
primary key(codigo)
);

insert into clientes values (50,'Juan Perez','Sucre 123','Cordoba',null);


insert into clientes values(90,'Marta Juarez','Colon 345','Carlos Paz',null);
insert into clientes values(110,'Fabian Torres','San Martin 987','Cordoba',50);
insert into clientes values(125,'Susana Garcia','Colon 122','Carlos Paz',90);
insert into clientes values(140,'Ana Herrero','Colon 890','Carlos Paz',9);

alter table clientes


add constraint FK_clientes_referenciadopor
foreign key (referenciadopor)
references clientes (codigo);

update clientes set referenciadopor=90 where referenciadopor=9;

alter table clientes


add constraint FK_clientes_referenciadopor
foreign key (referenciadopor)
references clientes (codigo);

select constraint_name, constraint_type,search_condition


from user_constraints
where table_name='CLIENTES';

insert into clientes values(150,'Karina Gomez','Caseros 444','Cruz del Eje',8);

update clientes set codigo=180 where codigo=90;

delete from clientes where nombre='Marta Juarez';

update clientes set codigo=180 where codigo=125;


delete from clientes where codigo=110;

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;
61 - Restricciones foreign key deshabilitar y validar

Problema:

Una librera almacena la informacin de sus libros para la venta en dos tablas, "libros" y
"editoriales".

Eliminamos ambas tablas:

drop table libros;


drop table editoriales;

Creamos las tablas:

create table libros(


codigo number(5),
titulo varchar2(40),
codigoeditorial number(3),
primary key (codigo)
);
create table editoriales(
codigo number(3),
nombre varchar2(20),
primary key (codigo)
);

Ingresamos algunos registros:

insert into editoriales values(1,'Planeta');


insert into editoriales values(2,'Emece');
insert into editoriales values(3,'Paidos');

insert into libros values(1,'Uno',1);


insert into libros values(2,'El aleph',2);
insert into libros values(3,'Aprenda PHP',5);

Agregamos una restriccin "foreign key" a la tabla "libros" para evitar que se ingresen cdigos
de editoriales inexistentes en "editoriales". Incluimos la opcin "novalidate" para evitar la
comprobacin de la restriccin en los datos existentes (note que hay un libro que tiene un
cdigo de editorial invlido):

alter table libros


add constraint FK_libros_codigoeditorial
foreign key (codigoeditorial)
references editoriales(codigo) novalidate;

La deshabilitacin de la comprobacin de la restriccin no afecta a los siguientes ingresos,


modificaciones y actualizaciones. Para poder ingresar, modificar o eliminar datos a una tabla
sin que Oracle compruebe la restriccin debemos deshabilitarla:

alter table libros


disable novalidate
constraint FK_LIBROS_CODIGOEDITORIAL;

Veamos si la restriccin est habilitada o no:

select constraint_name, constraint_type, status, validated


from user_constraints
where table_name='LIBROS';

En la columna "status" de la restriccin "foreign key" aparece "Disabled" y en "Validated"


muestra "not validated".

Ahora podemos ingresar un registro en "libros" con cdigo de editorial invlido:

insert into libros values(4,'Ilusiones',6);

Habilitamos la restriccin:

alter table libros


enable novalidate constraint FK_libros_codigoeditorial;

Veamos si la restriccin est habilitada o no y si valida los datos existentes:

select constraint_name, constraint_type, status, validated


from user_constraints where table_name='LIBROS';

En la columna "status" aparece "Enabled" y en "Validated" "not validate".

Intentamos alterar la restriccin para que se validen los datos existentes:


alter table libros
enable validate constraint FK_libros_codigoeditorial;

Oracle mostrar un mensaje indicando que no se pueden validar los datos existentes porque
existen valores invlidos.

Truncamos la tabla y alteramos la restriccin:

truncate table libros;

alter table libros


enable validate constraint FK_libros_codigoeditorial;

Solicitamos informacin sobre la restriccin:

select constraint_name, constraint_type, status, validated


from user_constraints where table_name='LIBROS';

En la columna "status" aparece "Enabled" y en "Validated" "Validate".

61 - Restricciones foreign key deshabilitar y validar

Primer problema:

Una empresa tiene registrados sus clientes en una tabla llamada "clientes", tambin tiene una
tabla "provincias" donde registra los nombres de las provincias.

1- Elimine las tablas "clientes" y "provincias":

drop table clientes;


drop table provincias;

2- Crelas con las siguientes estructuras:

create table clientes (


codigo number(5),
nombre varchar2(30),
domicilio varchar2(30),
ciudad varchar2(20),
codigoprovincia number(2),
primary key(codigo)
);

create table provincias(


codigo number(2),
nombre varchar2(20),
primary key (codigo)
);

3- Ingrese algunos registros para ambas tablas:

insert into provincias values(1,'Cordoba');


insert into provincias values(2,'Santa Fe');
insert into provincias values(3,'Misiones');
insert into provincias values(4,'Rio Negro');
insert into clientes values(100,'Perez Juan','San Martin 123','Carlos Paz',1);
insert into clientes values(101,'Moreno Marcos','Colon 234','Rosario',2);
insert into clientes values(102,'Garcia Juan','Sucre 345','Cordoba',1);
insert into clientes values(103,'Lopez Susana','Caseros 998','Posadas',3);
insert into clientes values(104,'Marcelo Moreno','Peru 876','Viedma',4);
insert into clientes values(105,'Lopez Sergio','Avellaneda 333','La Plata',5);

4- Intente agregar una restriccin "foreign key" para que los cdigos de provincia de "clientes"
existan en "provincias" sin especificar la opcin de comprobacin de datos
No se puede porque al no especificar opcin para la comprobacin de datos, por defecto es
"validate" y hay un registro que no cumple con la restriccin.

5- Agregue la restriccin anterior pero deshabilitando la comprobacin de datos existentes

6- Vea las restricciones de "clientes"

7- Deshabilite la restriccin "foreign key" de "clientes"

8- Vea las restricciones de "clientes"

9- Agregue un registro que no cumpla la restriccin "foreign key"


Se permite porque la restriccin est deshabilitada.

10- Modifique el cdigo de provincia del cliente cdigo 104 por 9


Oracle lo permite porque la restriccin est deshabilitada.

11-Habilite la restriccin "foreign key"

12- Intente modificar un cdigo de provincia existente por uno inexistente.

13- Intente alterar la restriccin "foreign key" para que valide los datos existentes

14- Elimine los registros que no cumplen la restriccin y modifique la restriccin a "enable" y
"validate"

15- Obtenga informacin sobre la restriccin "foreign key" de "clientes"

drop table clientes;


drop table provincias;

create table clientes (


codigo number(5),
nombre varchar2(30),
domicilio varchar2(30),
ciudad varchar2(20),
codigoprovincia number(2),
primary key(codigo)
);

create table provincias(


codigo number(2),
nombre varchar2(20),
primary key (codigo)
);

insert into provincias values(1,'Cordoba');


insert into provincias values(2,'Santa Fe');
insert into provincias values(3,'Misiones');
insert into provincias values(4,'Rio Negro');

insert into clientes values(100,'Perez Juan','San Martin 123','Carlos Paz',1);


insert into clientes values(101,'Moreno Marcos','Colon 234','Rosario',2);
insert into clientes values(102,'Garcia Juan','Sucre 345','Cordoba',1);
insert into clientes values(103,'Lopez Susana','Caseros 998','Posadas',3);
insert into clientes values(104,'Marcelo Moreno','Peru 876','Viedma',4);
insert into clientes values(105,'Lopez Sergio','Avellaneda 333','La Plata',5);

alter table clientes


add constraint FK_clientes_codigoprovincia
foreign key (codigoprovincia)
references provincias(codigo);

alter table clientes


add constraint FK_clientes_codigoprovincia
foreign key (codigoprovincia)
references provincias(codigo) novalidate;

select constraint_name,status,validated
from user_constraints
where table_name='CLIENTES';

alter table clientes


disable novalidate
constraint FK_clientes_codigoprovincia;

select constraint_name,status,validated
from user_constraints
where table_name='CLIENTES';

insert into clientes values(110,'Garcia Omar','San Martin 100','La Pampa',6);

update clientes set codigoprovincia=9 where codigo=104;

alter table clientes


enable novalidate
constraint FK_clientes_codigoprovincia;

update clientes set codigoprovincia=9 where codigoprovincia=1;

alter table clientes


enable validate
constraint FK_clientes_codigoprovincia;

delete from clientes where codigoprovincia not in (1,2,3,4);

alter table clientes


enable validate
constraint FK_clientes_codigoprovincia;
select status,validated
from user_constraints
where constraint_name='FK_CLIENTES_CODIGOPROVINCIA';

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".

62 - Restricciones foreign key (acciones)

Problema:

Una librera almacena la informacin de sus libros para la venta en dos tablas, "libros" y
"editoriales".

Eliminamos ambas tablas:

drop table libros;


drop table editoriales;

Creamos las tablas:

create table libros(


codigo number(5),
titulo varchar2(40),
autor varchar2(30),
codigoeditorial number(3),
primary key (codigo)
);
create table editoriales(
codigo number(3),
nombre varchar2(20),
primary key (codigo)
);

Ingresamos algunos registros en ambas tablas:

insert into editoriales values(1,'Emece');


insert into editoriales values(2,'Planeta');
insert into editoriales values(3,'Siglo XXI');

insert into libros values(1,'El aleph','Borges',1);


insert into libros values(2,'Martin Fierro','Jose Hernandez',2);
insert into libros values(3,'Aprenda PHP','Mario Molina',2);
insert into libros values(4,'El anillo del hechicero','Gaskin',3);

Establecemos una restriccin "foreign key" para evitar que se ingrese en "libros" un cdigo de
editorial inexistente en "editoriales" con la opcin "on cascade" para eliminaciones:

alter table libros


add constraint FK_libros_codigoeditorial
foreign key (codigoeditorial)
references editoriales(codigo)
on delete cascade;

Consultamos "user_constraints":

select constraint_name, constraint_type, delete_rule


from user_constraints
where table_name='LIBROS';

En la columna "delete_rule" de la restriccin "foreign key" mostrar "cascade".

Si eliminamos una editorial, se borra tal editorial de "editoriales" y todos los registros de
"libros" de dicha editorial:

delete from editoriales where codigo=1;

Veamos si la eliminacin se extendi a "libros":

select *from libros;

El libro "El aleph", de la editorial con cdigo 1 se ha eliminado.

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

alter table libros


drop constraint FK_LIBROS_CODIGOEDITORIAL;

Establecemos una restriccin "foreign key" sobre "codigoeditorial" de "libros" con la opcin "set
null" para eliminaciones:
alter table libros
add constraint FK_libros_codigoeditorial
foreign key (codigoeditorial)
references editoriales(codigo)
on delete set null;

Consultamos "user_constraints":

select constraint_name, constraint_type, delete_rule


from user_constraints
where table_name='LIBROS';

En la columna "delete_rule" de la restriccin "foreign key" mostrar "set null".

Si eliminamos una editorial cuyo cdigo est presente en "libros", se borra tal editorial de
"editoriales" y todos los registros de "libros" de dicha editorial se setean con el valor "null":

delete from editoriales where codigo=2;


select *from libros;

Ahora, los libros "Martin Fierro" y "Aprenda PHP" tiene valor nulo en "codigoeditorial".

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

alter table libros


drop constraint FK_LIBROS_CODIGOEDITORIAL;

Establecemos una restriccin "foreign key" sobre "codigoeditorial" de "libros" sin especificar
opcin para eliminaciones:

alter table libros


add constraint FK_libros_codigoeditorial
foreign key (codigoeditorial)
references editoriales(codigo);

Consultamos "user_constraints":

select constraint_name, constraint_type, delete_rule


from user_constraints
where table_name='LIBROS';

En la columna "delete_rule" de la restriccin "foreign key" mostrar "no action".

Intentamos eliminar una editorial cuyo cdigo est presente en "libros":

delete from editoriales where codigo=3;

Un mensaje de error indica que la accin no se ha realizado porque existen registros


coincidentes.

62 - Restricciones foreign key (acciones)

Primer problema:
Una empresa tiene registrados sus clientes en una tabla llamada "clientes", tambin tiene una
tabla "provincias" donde registra los nombres de las provincias.

1- Elimine las tablas "clientes" y "provincias":

drop table clientes;


drop table provincias;

2- Crelas con las siguientes estructuras:

create table clientes (


codigo number(5),
nombre varchar2(30),
domicilio varchar2(30),
ciudad varchar2(20),
codigoprovincia number(2),
primary key(codigo)
);

create table provincias(


codigo number(2),
nombre varchar2(20),
primary key (codigo)
);

3- Ingrese algunos registros para ambas tablas:

insert into provincias values(1,'Cordoba');


insert into provincias values(2,'Santa Fe');
insert into provincias values(3,'Misiones');
insert into provincias values(4,'Rio Negro');

insert into clientes values(100,'Perez Juan','San Martin 123','Carlos Paz',1);


insert into clientes values(101,'Moreno Marcos','Colon 234','Rosario',2);
insert into clientes values(102,'Acosta Ana','Avellaneda 333','Posadas',3);

4- Establezca una restriccin "foreign key" especificando la accin "set null" para
eliminaciones.

5- Elimine el registro con cdigo 3, de "provincias" y consulte "clientes" para ver qu cambios
ha realizado Oracle en los registros coincidentes
Todos los registros con "codigoprovincia" 3 han sido seteados a null.

6- Consulte el diccionario "user_constraints" para ver qu accin se ha establecido para las


eliminaciones

7- Intente modificar el registro con cdigo 2, de "provincias"

8- Elimine la restriccin "foreign key" establecida sobre "clientes"

9- Establezca una restriccin "foreign key" sobre "codigoprovincia" de "clientes" especificando


la accin "cascade" para eliminaciones

10- Consulte el diccionario "user_constraints" para ver qu accin se ha establecido para las
eliminaciones sobre las restricciones "foreign key" de la tabla "clientes"
11- Elimine el registro con cdigo 2, de "provincias"

12- Verifique que el cambio se realiz en cascada, es decir, que se elimin en la tabla
"provincias" y todos los clientes de la provincia eliminada

13- Elimine la restriccin "foreign key"

14- Establezca una restriccin "foreign key" sin especificar accin para eliminaciones

15- Intente eliminar un registro de la tabla "provincias" cuyo cdigo exista en "clientes"

16- Consulte el diccionario "user_constraints" para ver qu accin se ha establecido para las
eliminaciones sobre la restriccin "FK_CLIENTES_CODIGOPROVINCIA"

17- Intente elimimar la tabla "provincias"

18- Elimine la restriccin "foreign key"

19- Elimine la tabla "provincias"

drop table clientes;


drop table provincias;

create table clientes (


codigo number(5),
nombre varchar2(30),
domicilio varchar2(30),
ciudad varchar2(20),
codigoprovincia number(2),
primary key(codigo)
);

create table provincias(


codigo number(2),
nombre varchar2(20),
primary key (codigo)
);

insert into provincias values(1,'Cordoba');


insert into provincias values(2,'Santa Fe');
insert into provincias values(3,'Misiones');
insert into provincias values(4,'Rio Negro');

insert into clientes values(100,'Perez Juan','San Martin 123','Carlos Paz',1);


insert into clientes values(101,'Moreno Marcos','Colon 234','Rosario',2);
insert into clientes values(102,'Acosta Ana','Avellaneda 333','Posadas',3);

alter table clientes


add constraint FK_clientes_codigoprovincia
foreign key (codigoprovincia)
references provincias(codigo)
on delete set null;
delete from provincias where codigo=3;
select *from clientes;

select constraint_name, constraint_type, delete_rule


from user_constraints
where table_name='CLIENTES';

update provincias set codigo=9 where codigo=2;

alter table clientes


drop constraint FK_CLIENTES_CODIGOPROVINCIA;

alter table clientes


add constraint FK_clientes_codigoprovincia
foreign key (codigoprovincia)
references provincias(codigo)
on delete cascade;

select constraint_name, delete_rule


from user_constraints
where table_name='CLIENTES' and
constraint_type= 'R';

delete from provincias where codigo=2;

select *from provincias;


select *from clientes;

alter table clientes


drop constraint FK_CLIENTES_CODIGOPROVINCIA;

alter table clientes


add constraint FK_clientes_codigoprovincia
foreign key (codigoprovincia)
references provincias(codigo);

delete from provincias where codigo=1;

select constraint_type, delete_rule


from user_constraints
where table_name='CLIENTES' and
constraint_name='FK_CLIENTES_CODIGOPROVINCIA';

drop table provincias;

alter table clientes


drop constraint FK_CLIENTES_CODIGOPROVINCIA;

drop table provincias;

Segundo problema:
Un club dicta clases de distintos deportes. En una tabla llamada "deportes" guarda la
informacin de los distintos deportes que se ensean; en una tabla "socios", los datos de los
socios y en una tabla "inscripciones" almacena la informacin necesaria para las inscripciones
de los distintos socios a los distintos deportes.

1- Elimine las tablas:

drop table inscripciones;


drop table deportes;
drop table socios;

2- Cree las tablas:

create table deportes(


codigo number(2),
nombre varchar2(20),
primary key(codigo)
);

create table socios(


documento char(8),
nombre varchar2(30),
primary key(documento)
);

create table inscripciones(


documento char(8),
codigodeporte number(2),
matricula char(1),-- 's' si est paga, 'n' si no est paga
primary key(documento,codigodeporte)
);

3- Establezca una restriccin "foreign key" para "inscripciones" que haga referencia al campo
"codigo" de "deportes" indicando la accin "cascade" para eliminaciones

4- Establezca una restriccin "foreign key" para "inscripciones" que haga referencia al campo
"documento" de "socios" que permita la eliminacin "set null" (Recuerde que se pueden
establecer varias restricciones "foreign key" sobre una misma tabla)

5- Ingrese algunos registros en las tablas:

insert into deportes values(1,'basquet');


insert into deportes values(2,'futbol');
insert into deportes values(3,'natacion');
insert into deportes values(4,'tenis');

insert into socios values('30000111','Juan Lopez');


insert into socios values('31111222','Ana Garcia');
insert into socios values('32222333','Mario Molina');
insert into socios values('33333444','Julieta Herrero');

insert into inscripciones values ('30000111',1,'s');


insert into inscripciones values ('30000111',2,'s');
insert into inscripciones values ('31111222',1,'s');
insert into inscripciones values ('32222333',3,'n');
6- Intente ingresar una inscripcin con un cdigo de deporte inexistente:
Mensaje de error.

7- Intente ingresar una inscripcin con un documento inexistente en "socios"

8- Elimine un registro de "deportes" que no tenga inscriptos.


Se elimina porque no hay inscriptos en dicho deporte.

9- Consulte "inscripciones", "deportes" y "socios" (realizando un join)

10-Elimine un deporte para los cuales haya inscriptos


Se elimina el deporte "natacion" de "deportes" y de "inscripciones", todos los registros con el
valor correspondiente a "natacion" en "codigodeporte".

11- Verifique que se han eliminado los registros de "inscripciones" cuyo cdigo de deporte
corresponda a "natacion"

12- Intente eliminar el socio que est inscripto en algn deporte.


Mensaje de error, porque la restriccin "FK_inscripciones_documento" fue especificada "set
null", pero el campo clave fornea "documento" en "inscripciones" no admite valores nulos
(forma parte de la clave primaria).

13- Elimine la restriccin "FK_inscripciones_documento" y crela nuevamente especificando la


accin "cascade" para borrado

14- Elimine un socio que est inscripto en algn deporte

15- Verifique que el socio fue eliminado de "socios" y de "inscripciones"

16- Consulte el diccionario "user_constraints" especificando las tres tablas y analice la


informacin

Nos retorna la siguiente informacin:

TABLE_NAME CONSTRAINT_NAME CONSTRAINT_TYPE D


------------------------------------------------------------------------------------
DEPORTES SYS_C004914 P
INSCRIPCIONES SYS_C004916 P
INSCRIPCIONES FK_INSCRIPCIONES_CODIGODEPORTE R
CASCADE
INSCRIPCIONES FK_INSCRIPCIONES_DOCUMENTO R CASCADE
SOCIOS SYS_C004915 P

17- Intente eliminar la tabla "deportes"

16- Elimine la restriccin "foreign key" establecida sobre el campo "codigodeporte" de


"inscripciones" y luego la tabla "deportes"

drop table inscripciones;


drop table deportes;
drop table socios;

create table deportes(


codigo number(2),
nombre varchar2(20),
primary key(codigo)
);

create table socios(


documento char(8),
nombre varchar2(30),
primary key(documento)
);

create table inscripciones(


documento char(8),
codigodeporte number(2),
matricula char(1),-- 's' si est paga, 'n' si no est paga
primary key(documento,codigodeporte)
);

alter table inscripciones


add constraint FK_inscripciones_codigodeporte
foreign key (codigodeporte)
references deportes(codigo)
on delete cascade;

alter table inscripciones


add constraint FK_inscripciones_documento
foreign key (documento)
references socios(documento)
on delete set null;

insert into deportes values(1,'basquet');


insert into deportes values(2,'futbol');
insert into deportes values(3,'natacion');
insert into deportes values(4,'tenis');

insert into socios values('30000111','Juan Lopez');


insert into socios values('31111222','Ana Garcia');
insert into socios values('32222333','Mario Molina');
insert into socios values('33333444','Julieta Herrero');

insert into inscripciones values ('30000111',1,'s');


insert into inscripciones values ('30000111',2,'s');
insert into inscripciones values ('31111222',1,'s');
insert into inscripciones values ('32222333',3,'n');

insert into inscripciones values('30000111',6,'s');

insert into inscripciones values('40111222',1,'s');

delete from deportes where nombre='tenis';

select s.nombre, s.documento, d.nombre as deporte


from socios s
join inscripciones i
on s.documento=i.documento
join deportes d
on i.codigodeporte=d.codigo;
delete from deportes where nombre='natacion';

select *from inscripciones;


El registro de "inscripciones" con "documento" 32222333, ya no existe.

delete from socios where documento='30000111';

alter table inscripciones


drop constraint FK_INSCRIPCIONES_DOCUMENTO;

alter table inscripciones


add constraint FK_inscripciones_documento
foreign key (documento)
references socios(documento)
on delete cascade;

delete from socios where documento='30000111';

select *from socios where documento='30000111';


select *from inscripciones where documento='30000111';

select table_name,constraint_name, constraint_type, delete_rule


from user_constraints
where table_name='DEPORTES' OR
table_name='SOCIOS' OR
table_name='INSCRIPCIONES';

drop table deportes;

alter table inscripciones


drop constraint FK_INSCRIPCIONES_CODIGODEPORTE;

drop table deportes;

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".

64 - Restricciones al crear la tabla

Problema:

Trabajamos con las tablas "libros", "autores" y "editoriales" de una librera:

Eliminamos las tablas:

drop table libros;


drop table editoriales;
drop table autores;

Recuerde eliminar en primer lugar "libros", pues si las tablas existen y "libros" hace referencia
con una restriccin "foreign key" a "editoriales" y "autores", tales tablas no podrn eliminarse
hasta que ninguna restriccin las referencie.

Creamos la tabla "editoriales" con una restriccin "primary key":

create table editoriales(


codigo number(3) not null,
nombre varchar2(30),
constraint PK_editoriales
primary key (codigo)
);

Creamos la tabla "autores" con una restriccin "primary key", una "unique" y una "check":

create table autores(


codigo number(4) not null
constraint CK_autores_codigo
check (codigo>=0),
nombre varchar2(30) not null,
constraint PK_autores_codigo
primary key (codigo),
constraint UQ_autores_nombre
unique (nombre)
);

Aplicamos varias restricciones cuando creamos la tabla "libros":

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)
);

Recuerde que si definimos una restriccin "foreign key" al crear una tabla, la tabla
referenciada debe existir, por ello creamos las tablas "editoriales" y "autores" antes que
"libros".

Veamos las restricciones de "editoriales":

select constraint_name, constraint_type, search_condition, status,


validated
from user_constraints
where table_name='EDITORIALES';

Una tabla nos informa que hay una restriccin de control y una "primary key", ambas
habilitadas y validan los datos existentes.

Veamos las restricciones de "autores":

select constraint_name, constraint_type, search_condition, status,


validated
from user_constraints
where table_name='AUTORES';

Oracle nos informa que hay 3 restricciones de control, una "primary key" y una nica.

Veamos las restricciones de "libros":

select constraint_name, constraint_type, search_condition, status,


validated
from user_constraints
where table_name='LIBROS';

la tabla tiene 7 restricciones: 3 de control (2 "enabled" y "validated" y 1 "disabled" y "not


validated"), 1 "primary key" ("enabled" "validated"), 1 "unique" ("enabled" "validated") y 2
"foreign key" ("enabled" "validated").

Ingresamos algunos registros en las tres tablas.


Recuerde que debemos ingresar registros en las tablas "autores" y "editoriales" antes que en
"libros", a menos que deshabilitemos las restricciones "foreign key".

insert into editoriales values(1,'Emece');


insert into editoriales values(2,'Planeta');
insert into editoriales values(3,'Norma');

insert into autores values(100,'Borges');


insert into autores values(101,'Bach Richard');
insert into autores values(102,'Cervantes');
insert into autores values(103,'Gaskin');

insert into libros values(200,'El aleph',100,1,40);


insert into libros values(300,'Uno',101,2,20);
insert into libros values(400,'El quijote',102,3,20);
insert into libros values(500,'El experto en laberintos',103,3,null);

Note que un libro tiene precio nulo, la tabla "libros" tiene una restriccin de control que no
admite precios nulos, pero est deshabilitada.

Realizamos un "join" para mostrar todos los datos de los libros:

select l.codigo,a.nombre as autor,e.nombre as editorial,precio


from libros l
join autores a
on codigoautor=a.codigo
join editoriales e
on codigoeditorial=e.codigo;

Habilitamos la restriccin de control deshabilitada sin controlar los datos ya cargados:

alter table libros


enable novalidate
constraint CK_LIBROS_PRECIONONULO;

Intentamos ingresar un libro con precio nulo:

insert into libros values(600,'El anillo del hechicero',103,3,null);

Oracle no lo permite, la restriccin est habilitada.

Eliminamos un autor:

delete autores where codigo=100;

Veamos si se setearon a "null" los libros de tal autor (la restriccin "FK_LIBROS_AUTORES" as
lo especifica):

select *from libros;

El libro con cdigo 200 tiene el valor "null" en "autor".

Eliminamos una editorial:

delete editoriales where codigo=1;


Veamos si se eliminaron los libros de tal editorial (la restriccin "FK_LIBROS_EDITORIALES" fue
establecida "cascade"):

select *from libros;

Ya no est el libro "200".

64 - Restricciones al crear la tabla

Primer problema:

Un club de barrio tiene en su sistema 4 tablas:

- "socios": en la cual almacena documento, nmero, nombre y domicilio de cada socio;

- "deportes": que guarda un cdigo, nombre del deporte, da de la semana que se dicta y
documento del profesor instructor;

- "profesores": donde se guarda el documento, nombre y domicilio de los profesores e

- "inscriptos": que almacena el nmero de socio, el cdigo de deporte y si la matricula est


paga o no.

1- Elimine las tablas:

drop table inscriptos;


drop table socios;
drop table deportes;
drop table profesores;

2- Considere que:

- un socio puede inscribirse en varios deportes, pero no dos veces en el mismo.


- un socio tiene un documento nico y un nmero de socio nico.
- un deporte debe tener asignado un profesor que exista en "profesores" o "null" si an no
tiene un instructor definido.
- el campo "dia" de "deportes" puede ser: lunes, martes, miercoles, jueves, viernes o sabado.
- el campo "dia" de "deportes" por defecto debe almacenar 'sabado'.
- un profesor puede ser instructor de varios deportes o puede no dictar ningn deporte.
- un profesor no puede estar repetido en "profesores".
- un inscripto debe ser socio, un socio puede no estar inscripto en ningn deporte.
- una inscripcin debe tener un valor en socio existente en "socios" y un deporte que exista en
"deportes".
- el campo "matricula" de "inscriptos" debe aceptar solamente los caracteres 's' o'n'.
- si se elimina un profesor de "profesores", el "documentoprofesor" coincidente en "deportes"
debe quedar seteado a null.
- no se puede eliminar un deporte de "deportes" si existen inscriptos para tal deporte en
"inscriptos".
- si se elimina un socio de "socios", el registro con "numerosocio" coincidente en "inscriptos"
debe eliminarse.

3- Cree las tablas con las restricciones necesarias:

create table profesores(


documento char(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
constraint PK_profesores_documento
primary key (documento)
);

create table deportes(


codigo number(2),
nombre varchar2(20) not null,
dia varchar2(9) default 'sabado',
documentoprofesor char(8),
constraint CK_deportes_dia_lista
check (dia in ('lunes','martes','miercoles','jueves','viernes','sabado')),
constraint PK_deportes_codigo
primary key (codigo),
constraint FK_deportes_profesor
foreign key (documentoprofesor)
references profesores(documento)
on delete set null
);

create table socios(


numero number(4),
documento char(8),
nombre varchar2(30),
domicilio varchar2(30),
constraint PK_socios_numero
primary key (numero),
constraint UQ_socios_documento
unique (documento)
);

create table inscriptos(


numerosocio number(4),
codigodeporte number(2),
matricula char(1),
constraint PK_inscriptos_numerodeporte
primary key (numerosocio,codigodeporte),
constraint FK_inscriptos_deporte
foreign key (codigodeporte)
references deportes(codigo),
constraint FK_inscriptos_socios
foreign key (numerosocio)
references socios(numero)
on delete cascade,
constraint CK_matricula_valores
check (matricula in ('s','n'))
);

4- Ingrese registros en "profesores":

insert into profesores values('21111111','Andres Acosta','Avellaneda 111');


insert into profesores values('22222222','Betina Bustos','Bulnes 222');
insert into profesores values('23333333','Carlos Caseros','Colon 333');

5- Ingrese registros en "deportes". Ingrese el mismo da para distintos deportes, un deporte sin
da confirmado, un deporte sin profesor definido:
insert into deportes values(1,'basquet','lunes',null);
insert into deportes values(2,'futbol','lunes','23333333');
insert into deportes values(3,'natacion',null,'22222222');
insert into deportes values(4,'padle',default,'23333333');
insert into deportes values(5,'tenis','jueves',null);

6- Ingrese registros en "socios":

insert into socios values(100,'30111111','Martina Moreno','America 111');


insert into socios values(200,'30222222','Natalia Norte','Bolivia 222');
insert into socios values(300,'30333333','Oscar Oviedo','Caseros 333');
insert into socios values(400,'30444444','Pedro Perez','Dinamarca 444');

7- Ingrese registros en "inscriptos". Inscriba a un socio en distintos deportes, inscriba varios


socios en el mismo deporte.

insert into inscriptos values(100,3,'s');


insert into inscriptos values(100,5,'s');
insert into inscriptos values(200,1,'s');
insert into inscriptos values(400,1,'n');
insert into inscriptos values(400,4,'s');

8- Realice un "join" (del tipo que sea necesario) para mostrar todos los datos del socio junto
con el nombre de los deportes en los cuales est inscripto, el da que tiene que asistir y el
nombre del profesor que lo instruir (5 registros)

9- Realice la misma consulta anterior pero incluya los socios que no estn inscriptos en ningn
deporte (6 registros)

10- Muestre todos los datos de los profesores, incluido el deporte que dicta y el da,
incluyendo los profesores que no tienen asignado ningn deporte, ordenados por documento
(4 registros)

11- Muestre todos los deportes y la cantidad de inscriptos en cada uno de ellos, incluyendo
aquellos deportes para los cuales no hay inscriptos, ordenados por nombre de deporte (5
registros)

12- Muestre las restricciones de "socios"

13- Muestre las restricciones de "deportes"

14- Obtenga informacin sobre la restriccin "foreign key" de "deportes"

15- Muestre las restricciones de "profesores"

16- Muestre las restricciones de "inscriptos"

17- Consulte "user_cons_columns" y analice la informacin retornada sobre las restricciones


de "inscriptos"

18- Elimine un profesor al cual haga referencia algn registro de "deportes"

19- Vea qu sucedi con los registros de "deportes" cuyo "documentoprofesor" exista en
"profesores"
Fue seteado a null porque la restriccin "foreign key" sobre "documentoprofesor" de
"deportes" fue definida "on delete set null".
20- Elimine un socio que est inscripto

21- Vea qu sucedi con los registros de "inscriptos" cuyo "numerosocio" exista en "socios"
Fue eliminado porque la restriccin "foreign key" sobre "numerosocio" de "inscriptos" fue
definida "on delete cascade".

22- Intente eliminar un deporte para el cual haya inscriptos


Mensaje de error porque la restriccin "foreign key sobre "codigodeporte" de "inscriptos" fue
establecida "no action".

23- Intente eliminar la tabla "socios"


No puede eliminarse, mensaje de error, una "foreign key" sobre "inscriptos" hace referencia a
esta tabla.

24- Elimine la tabla "inscriptos"

25- Elimine la tabla "socios"

26- Intente eliminar la tabla "profesores"


No puede eliminarse, mensaje de error, una "foreign key" sobre "deportes" hace referencia a
esta tabla.

27- Elimine la tabla "deportes"

28- Elimine la tabla "profesores"

drop table inscriptos;


drop table socios;
drop table deportes;
drop table profesores;

create table profesores(


documento char(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
constraint PK_profesores_documento
primary key (documento)
);

create table deportes(


codigo number(2),
nombre varchar2(20) not null,
dia varchar2(9) default 'sabado',
documentoprofesor char(8),
constraint CK_deportes_dia_lista
check (dia in ('lunes','martes','miercoles','jueves','viernes','sabado')),
constraint PK_deportes_codigo
primary key (codigo),
constraint FK_deportes_profesor
foreign key (documentoprofesor)
references profesores(documento)
on delete set null
);
create table socios(
numero number(4),
documento char(8),
nombre varchar2(30),
domicilio varchar2(30),
constraint PK_socios_numero
primary key (numero),
constraint UQ_socios_documento
unique (documento)
);

create table inscriptos(


numerosocio number(4),
codigodeporte number(2),
matricula char(1),
constraint PK_inscriptos_numerodeporte
primary key (numerosocio,codigodeporte),
constraint FK_inscriptos_deporte
foreign key (codigodeporte)
references deportes(codigo),
constraint FK_inscriptos_socios
foreign key (numerosocio)
references socios(numero)
on delete cascade,
constraint CK_matricula_valores
check (matricula in ('s','n'))
);

insert into profesores values('21111111','Andres Acosta','Avellaneda 111');


insert into profesores values('22222222','Betina Bustos','Bulnes 222');
insert into profesores values('23333333','Carlos Caseros','Colon 333');

insert into deportes values(1,'basquet','lunes',null);


insert into deportes values(2,'futbol','lunes','23333333');
insert into deportes values(3,'natacion',null,'22222222');
insert into deportes values(4,'padle',default,'23333333');
insert into deportes values(5,'tenis','jueves',null);

insert into socios values(100,'30111111','Martina Moreno','America 111');


insert into socios values(200,'30222222','Natalia Norte','Bolivia 222');
insert into socios values(300,'30333333','Oscar Oviedo','Caseros 333');
insert into socios values(400,'30444444','Pedro Perez','Dinamarca 444');

insert into inscriptos values(100,3,'s');


insert into inscriptos values(100,5,'s');
insert into inscriptos values(200,1,'s');
insert into inscriptos values(400,1,'n');
insert into inscriptos values(400,4,'s');

select s.*,d.nombre as deporte,d.dia,p.nombre as profesor


from socios s
join inscriptos i
on numero=i.numerosocio
join deportes d
on d.codigo=i.codigodeporte
left join profesores p
on d.documentoprofesor=p.documento;

select s.*,d.nombre as deporte,d.dia,p.nombre as profesor


from socios s
full join inscriptos i
on numero=i.numerosocio
left join deportes d
on d.codigo=i.codigodeporte
left join profesores p
on d.documentoprofesor=p.documento;

select p.*,d.nombre as deporte,d.dia


from profesores p
left join deportes d
on d.documentoprofesor=p.documento
order by documento;

select d.nombre,count(i.codigodeporte) as cantidad


from deportes d
left join inscriptos i
on d.codigo=i.codigodeporte
group by d.nombre;

select constraint_name, constraint_type, status, validated


from user_constraints where table_name='SOCIOS';

select constraint_name, constraint_type, status, validated, search_condition


from user_constraints where table_name='DEPORTES';

select *from user_cons_columns


where constraint_name='FK_DEPORTES_PROFESOR';

select constraint_name, constraint_type, status, validated, search_condition


from user_constraints where table_name='PROFESORES';

select constraint_name, constraint_type, status, validated, search_condition


from user_constraints
where table_name='INSCRIPTOS';

select *from user_cons_columns


where table_name='INSCRIPTOS';

delete from profesores where documento='22222222';

select *from deportes;

delete from socios where numero=200;

select *from inscriptos;

delete from deportes where codigo=4;

drop table socios;

drop table inscriptos;

drop table socios;


drop table profesores;

drop table deportes;

drop table profesores;

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".

65 - Unin

Problema:

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".

Eliminamos las tablas:

drop table ingles;


drop table frances;

Creamos las tablas:

create table ingles(


documento varchar2(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
primary key(documento)
);

create table frances(


documento varchar2(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
primary key(documento)
);

Ingresamos algunos registros:

insert into ingles values('20111222','Ana Acosta','Avellaneda 111');


insert into ingles values('21222333','Betina Bustos','Bulnes 222');
insert into ingles values('22333444','Carlos Caseros','Colon 333');
insert into ingles values('23444555','Daniel Duarte','Duarte Quiros
444');
insert into ingles values('24555666','Estela Esper','Esmeralda 555');

insert into frances values('23444555','Daniel Duarte','Duarte Quiros


444');
insert into frances values('24555666','Estela Esper','Esmeralda
555');
insert into frances values('30111222','Fabiana Fuentes','Famatina
666');
insert into frances values('30222333','Gaston Gonzalez','Guemes
777');

La academia necesita el nombre y domicilio de todos los alumnos, de todos los cursos para
enviarles una tarjeta de invitacin para un festejo el da del alumno.
Empleamos el operador "union" para obtener dicha informacin de ambas tablas:

select nombre, domicilio from ingles


union
select nombre, domicilio from frances;

Note que existen dos alumnos (Daniel Duarte y Estela Esper) que cursan ambos idiomas, estn
presentes en la tabla "ingles" y "frances"; tales registros aparecen una sola vez en el resultado
de "union". Si queremos que los registros duplicados aparezcan, debemos emplear "all":

select nombre, domicilio from ingles


union all
select nombre, domicilio from frances;

Ordenamos por nombre:

select nombre, domicilio from ingles


union all
select nombre, domicilio from frances
order by nombre;

Podemos agregar una columna extra a la consulta con el encabezado "curso" en la que
aparezca el literal "ingls" o "francs" segn si la persona cursa uno u otro idioma:

select nombre, domicilio, 'ingles' as curso from ingles


union
select nombre, domicilio,'frances' from frances
order by curso;

Recuerde que los encabezados de los campos son los que se especifican en el primer "select".
Si queremos que el nombre tenga un encabezado "alumno" debemos especificar un alias en la
primer consulta. Si ordenamos por un campo que tiene un alias, debemos especificar el alias
no el nombre del campo. En la siguiente consulta realizamos una unin, colocamos un alias al
campo "nombre" y ordenamos el resultado por tal alias:

select nombre as alumno, domicilio from ingles


union
select nombre, domicilio from frances
order by alumno;
65 - Unin

Primer problema:

Una clnica almacena los datos de los mdicos en una tabla llamada "medicos" y los datos de
los pacientes en otra denominada "pacientes".

1- Eliminamos ambas tablas:

drop table medicos;


drop table pacientes;

2- Creamos las tablas:

create table medicos(


legajo number(3),
documento varchar2(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
especialidad varchar2(30),
primary key(legajo)
);

create table pacientes(


documento varchar2(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
obrasocial varchar2(20),
primary key(documento)
);

3- Ingresamos algunos registros:

insert into medicos values(1,'20111222','Ana Acosta','Avellaneda 111','clinica');


insert into medicos values(2,'21222333','Betina Bustos','Bulnes 222','clinica');
insert into medicos values(3,'22333444','Carlos Caseros','Colon 333','pediatria');
insert into medicos values(4,'23444555','Daniel Duarte','Duarte Quiros
444','oculista');
insert into medicos values(5,'24555666','Estela Esper','Esmeralda 555','alergia');

insert into pacientes values('24555666','Estela Esper','Esmeralda 555','IPAM');


insert into pacientes values('23444555','Daniel Duarte','Duarte Quiros
444','OSDOP');
insert into pacientes values('30111222','Fabiana Fuentes','Famatina 666','PAMI');
insert into pacientes values('31222333','Gaston Gonzalez','Guemes 777','PAMI');

4- La clnica necesita el nombre y domicilio de mdicos y pacientes para enviarles una tarjeta
de invitacin a la inauguracin de un nuevo establecimiento. Emplee el operador "union" para
obtener dicha informacin de ambas tablas (7 registros)
Note que existen dos mdicos que tambin estn presentes en la tabla "pacientes"; tales
registros aparecen una sola vez en el resultado de "union".

5- Realice la misma consulta anterior pero esta vez, incluya los registros duplicados. Emplee
"union all" (9 registros)

6- Realice la misma consulta anterior y esta vez ordene el resultado por nombre (9 registros)

7- Agregue una columna extra a la consulta con el encabezado "condicion" en la que aparezca
el literal "mdico" o "paciente" segn si la persona es uno u otro (9 registros)

drop table medicos;


drop table pacientes;

create table medicos(


legajo number(3),
documento varchar2(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
especialidad varchar2(30),
primary key(legajo)
);

create table pacientes(


documento varchar2(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
obrasocial varchar2(20),
primary key(documento)
);

insert into medicos values(1,'20111222','Ana Acosta','Avellaneda 111','clinica');


insert into medicos values(2,'21222333','Betina Bustos','Bulnes 222','clinica');
insert into medicos values(3,'22333444','Carlos Caseros','Colon 333','pediatria');
insert into medicos values(4,'23444555','Daniel Duarte','Duarte Quiros
444','oculista');
insert into medicos values(5,'24555666','Estela Esper','Esmeralda 555','alergia');

insert into pacientes values('24555666','Estela Esper','Esmeralda 555','IPAM');


insert into pacientes values('23444555','Daniel Duarte','Duarte Quiros
444','OSDOP');
insert into pacientes values('30111222','Fabiana Fuentes','Famatina 666','PAMI');
insert into pacientes values('31222333','Gaston Gonzalez','Guemes 777','PAMI');

select nombre, domicilio from medicos


union
select nombre, domicilio from pacientes;

select nombre, domicilio from medicos


union all
select nombre, domicilio from pacientes;

select nombre, domicilio from medicos


union all
select nombre, domicilio from pacientes
order by nombre;

select nombre, domicilio, 'mdico' as condicion from medicos


union
select nombre, domicilio,'paciente' from pacientes
order by condicion;

Segundo problema:

Un supermercado almacena en una tabla denominada "proveedores" los datos de las


compaas que le proveen de mercaderas; en una tabla llamada "clientes", los datos de los
comercios que le compran y en otra tabla "empleados" los datos de los empleados.

1- Elimine las tablas:

drop table clientes;


drop table proveedores;
drop table empleados;
2- Cree las tablas:

create table proveedores(


codigo number(3) not null,
nombre varchar2(30),
domicilio varchar2(30),
primary key(codigo)
);
create table clientes(
codigo number(4),
nombre varchar2(30),
domicilio varchar2(30),
primary key(codigo)
);
create table empleados(
documento char(8) not null,
nombre varchar2(20),
apellido varchar2(20),
domicilio varchar2(30),
primary key(documento)
);

3- Ingrese algunos registros:

insert into proveedores values(1,'Golosinas Dulce','Colon 123');


insert into proveedores values(2,'Carnes Unica','Caseros 222');
insert into proveedores values(3,'Lacteos Blanca','San Martin 987');
insert into proveedores values(4,'Luis Luque','San Martin 1234');
insert into clientes values(100,'Supermercado Lopez','Avellaneda 34');
insert into clientes values(101,'Almacen Anita','Colon 987');
insert into clientes values(102,'Juan Garcia','Sucre 345');
insert into clientes values(103,'Luis Luque','San Martin 1234');
insert into empleados values('23333333','Federico','Lopez','Colon 987');
insert into empleados values('28888888','Ana','Marquez','Sucre 333');
insert into empleados values('30111111','Pedro','Perez','Caseros 956');
insert into empleados values('31222333','Juan','Garcia','Sucre 345');

4- El supermercado quiere enviar una tarjeta de salutacin a todos los proveedores, clientes y
empleados y necesita el nombre y domicilio de todos ellos. Emplee el operador "union" para
obtener dicha informacin de las tres tablas. Ordene la informacin por nombre. La consulta
a la tabla "empleados" debe incluir el nombre y el apellido (10 registros)

5- Realice la misma operacin de unin anterior, pero ahora incluya los registros duplicados y
ordnelos por nombre (12 registros)
Note que "Luis Luque" es proveedor y cliente y que "Juan Garcia" es cliente y empleado; por lo
tanto ambos aparecen 2 veces.

6- Realice la misma consulta anterior y agregue una columna con un literal para indicar si es
un proveedor, un cliente o un empleado(12 registros)

drop table clientes;


drop table proveedores;
drop table empleados;
create table proveedores(
codigo number(3) not null,
nombre varchar2(30),
domicilio varchar2(30),
primary key(codigo)
);
create table clientes(
codigo number(4),
nombre varchar2(30),
domicilio varchar2(30),
primary key(codigo)
);
create table empleados(
documento char(8) not null,
nombre varchar2(20),
apellido varchar2(20),
domicilio varchar2(30),
primary key(documento)
);

insert into proveedores values(1,'Golosinas Dulce','Colon 123');


insert into proveedores values(2,'Carnes Unica','Caseros 222');
insert into proveedores values(3,'Lacteos Blanca','San Martin 987');
insert into proveedores values(4,'Luis Luque','San Martin 1234');
insert into clientes values(100,'Supermercado Lopez','Avellaneda 34');
insert into clientes values(101,'Almacen Anita','Colon 987');
insert into clientes values(102,'Juan Garcia','Sucre 345');
insert into clientes values(103,'Luis Luque','San Martin 1234');
insert into empleados values('23333333','Federico','Lopez','Colon 987');
insert into empleados values('28888888','Ana','Marquez','Sucre 333');
insert into empleados values('30111111','Pedro','Perez','Caseros 956');
insert into empleados values('31222333','Juan','Garcia','Sucre 345');

select nombre, domicilio from proveedores


union
select nombre, domicilio from clientes
union
select nombre||' '||apellido, domicilio from empleados
order by nombre;

select nombre, domicilio from proveedores


union all
select nombre, domicilio from clientes
union all
select nombre||' '||apellido, domicilio from empleados
order by nombre;

select nombre, domicilio, 'proveedor' as categoria from proveedores


union all
select nombre, domicilio, 'cliente' from clientes
union all
select nombre||' '||apellido, domicilio, 'empleado' from empleados;

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".

66 - Interseccin

Problema:

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 cursan portugues en
latabla "portugues".

Eliminamos las tablas:


drop table ingles;
drop table frances;
drop table portugues;

Creamos las tablas:

create table ingles(


documento varchar2(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
primary key(documento)
);

create table frances(


documento varchar2(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
primary key(documento)
);

create table portugues(


documento varchar2(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
primary key(documento)
);

Ingresamos algunos registros:

insert into ingles values('20111222','Ana Acosta','Avellaneda 111');


insert into ingles values('21222333','Betina Bustos','Bulnes 222');
insert into ingles values('22333444','Carlos Caseros','Colon 333');
insert into ingles values('23444555','Daniel Duarte','Duarte Quiros
444');
insert into ingles values('24555666','Estela Esper','Esmeralda 555');

insert into frances values('23444555','Daniel Duarte','Duarte Quiros


444');
insert into frances values('24555666','Estela Esper','Esmeralda
555');
insert into frances values('30111222','Fabiana Fuentes','Famatina
666');
insert into frances values('30222333','Gaston Gonzalez','Guemes
777');

insert into portugues values('23444555','Daniel Duarte','Duarte


Quiros 444');
insert into portugues values('22333444','Carlos Caseros','Colon
333');
insert into portugues values('30222333','Gaston Gonzalez','Guemes
777');
insert into portugues values('31222333','Hector Huerta','Homero
888');
insert into portugues values('32333444','Ines Ilara','Inglaterra
999');

La academia necesita el nombre y domicilio de todos los alumnos que cursan los tres idiomas
para enviarles una tarjeta de descuento.
Obtenemos los datos necesarios de las tres tablas en una sola consulta realizando una
interseccin entre ellas:

select nombre, domicilio from ingles


intersect
select nombre, domicilio from frances
intersect
select nombre, domicilio from portugues;

Aparece solamente un registro, correspondiente a "Daniel Duarte", que est en las tres tablas.
Note que los alumnos que solamente asisten a una clase o solamente a dos, no aparecen en el
resultado.

Si queremos los registros que estn presentes en ms de dos tablas podemos realizar una
consulta combinando los operadores de interseccin y de unin:

select nombre, domicilio from ingles


intersect
select nombre, domicilio from frances
union
(select nombre, domicilio from ingles
intersect
select nombre, domicilio from portugues)
union
(select nombre, domicilio from frances
intersect
select nombre, domicilio from portugues);

En la consulta anterior, la primera interseccin (ingls con francs) retorna 2 registros (Esper
y Duarte); la segunda interseccin (ingls y portugues) retorna 2 registros (Caseros y Duarte);
unimos estos dos resultados con "union" y obtenemos 3 registros (Caseros, Duarte y Esper); la
tercera interseccin (francs y portugus) retorna 2 registros (Duarte y Gozalez) que al
"unirlos" al resultado de la primera unin (Caseros, Duarte y Esper) nos devuelve 4 registros.
Note que algunas consultas se encierran entre parntesis para especificar que la operacin se
realiza entre las tablas incluidas en ellos.

66 - Interseccin

Primer problema:

Una clnica almacena los datos de los mdicos en una tabla llamada "medicos" y los datos de
los pacientes en otra denominada "pacientes".

1- Eliminamos ambas tablas:

drop table medicos;


drop table pacientes;

2- Creamos las tablas:

create table medicos(


legajo number(3),
documento varchar2(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
especialidad varchar2(30),
primary key(legajo)
);

create table pacientes(


documento varchar2(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
obrasocial varchar2(20),
primary key(documento)
);

3- Ingresamos algunos registros:

insert into medicos values(1,'20111222','Ana Acosta','Avellaneda 111','clinica');


insert into medicos values(2,'21222333','Betina Bustos','Bulnes 222','clinica');
insert into medicos values(3,'22333444','Carlos Caseros','Colon 333','pediatria');
insert into medicos values(4,'23444555','Daniel Duarte','Duarte Quiros
444','oculista');
insert into medicos values(5,'24555666','Estela Esper','Esmeralda 555','alergia');

insert into pacientes values('24555666','Estela Esper','Esmeralda 555','IPAM');


insert into pacientes values('23444555','Daniel Duarte','Duarte Quiros
444','OSDOP');
insert into pacientes values('30111222','Fabiana Fuentes','Famatina 666','PAMI');
insert into pacientes values('30111222','Gaston Gonzalez','Guemes 777','PAMI');

4- La clnica necesita el nombre y domicilio de mdicos y pacientes para enviarles una tarjeta
de invitacin a la inauguracin de un nuevo establecimiento. Emplee el operador "union" para
obtener dicha informacin de ambas tablas (7 registros)
Note que existen dos mdicos que tambin estn presentes en la tabla "pacientes"; tales
registros aparecen una sola vez en el resultado de "union".

5- La clnica necesita el nombre y domicilio de los pacientes que tambin son mdicos para
enviarles una tarjeta de descuento para ciertas prcticas. Emplee el operador "intersect" para
obtener dicha informacin de ambas tablas

drop table medicos;


drop table pacientes;

create table medicos(


legajo number(3),
documento varchar2(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
especialidad varchar2(30),
primary key(legajo)
);

create table pacientes(


documento varchar2(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
obrasocial varchar2(20),
primary key(documento)
);

insert into medicos values(1,'20111222','Ana Acosta','Avellaneda 111','clinica');


insert into medicos values(2,'21222333','Betina Bustos','Bulnes 222','clinica');
insert into medicos values(3,'22333444','Carlos Caseros','Colon 333','pediatria');
insert into medicos values(4,'23444555','Daniel Duarte','Duarte Quiros
444','oculista');
insert into medicos values(5,'24555666','Estela Esper','Esmeralda 555','alergia');

insert into pacientes values('24555666','Estela Esper','Esmeralda 555','IPAM');


insert into pacientes values('23444555','Daniel Duarte','Duarte Quiros
444','OSDOP');
insert into pacientes values('30111222','Fabiana Fuentes','Famatina 666','PAMI');
insert into pacientes values('30111222','Gaston Gonzalez','Guemes 777','PAMI');

select nombre, domicilio from medicos


union
select nombre, domicilio from pacientes;

select nombre, domicilio from medicos


intersect
select nombre, domicilio from pacientes;

Segundo problema:

Un supermercado almacena en una tabla denominada "proveedores" los datos de las


compaas que le proveen de mercaderas; en una tabla llamada "clientes", los datos de los
comercios que le compran y en otra tabla "empleados" los datos de los empleados.

1- Elimine las tablas:

drop table clientes;


drop table proveedores;
drop table empleados;

2- Cree las tablas:

create table proveedores(


codigo number(3) not null,
nombre varchar2(30),
domicilio varchar2(30),
primary key(codigo)
);
create table clientes(
codigo number(4),
nombre varchar2(30),
domicilio varchar2(30),
primary key(codigo)
);
create table empleados(
documento char(8) not null,
nombre varchar2(20),
apellido varchar2(20),
domicilio varchar2(30),
primary key(documento)
);

3- Ingrese algunos registros:

insert into proveedores values(1,'Valeria Vazquez','Colon 123');


insert into proveedores values(2,'Carnes Unica','Caseros 222');
insert into proveedores values(3,'Blanca Bustos','San Martin 987');
insert into proveedores values(4,'Luis Luque','San Martin 1234');
insert into clientes values(100,'Supermercado Lopez','Avellaneda 34');
insert into clientes values(101,'Almacen Anita','Colon 987');
insert into clientes values(102,'Juan Garcia','Sucre 345');
insert into clientes values(103,'Luis Luque','San Martin 1234');
insert into clientes values(104,'Valeria Vazquez','Colon 123');
insert into clientes values(105,'Federico Ferreyra','Colon 987');
insert into empleados values('23333333','Federico','Ferreyra','Colon 987');
insert into empleados values('28888888','Ana','Marquez','Sucre 333');
insert into empleados values('30111111','Pedro','Perez','Caseros 956');
insert into empleados values('31222333','Juan','Garcia','Sucre 345');
insert into empleados values('32333444','Luis','Luque','San Martin 1234');
insert into empleados values('33444555','Valeria','Vazquez','Colon 123');
insert into empleados values('34555666','Blanca','Bustos','San Martin 987');

4- El supermercado quiere enviar un bono de descuento a todos los empleados que son
clientes. Realice una combinacin de interseccin entre las tablas "clientes" y "empleados" (4
registros)

5- Se necesitan los nombres de aquellos proveedores que son clientes y tambin empleados
del supermercado (presentes en las tres tablas). Realice las operaciones necesarias (2
registros)

drop table clientes;


drop table proveedores;
drop table empleados;

create table proveedores(


codigo number(3) not null,
nombre varchar2(30),
domicilio varchar2(30),
primary key(codigo)
);
create table clientes(
codigo number(4),
nombre varchar2(30),
domicilio varchar2(30),
primary key(codigo)
);
create table empleados(
documento char(8) not null,
nombre varchar2(20),
apellido varchar2(20),
domicilio varchar2(30),
primary key(documento)
);

insert into proveedores values(1,'Valeria Vazquez','Colon 123');


insert into proveedores values(2,'Carnes Unica','Caseros 222');
insert into proveedores values(3,'Blanca Bustos','San Martin 987');
insert into proveedores values(4,'Luis Luque','San Martin 1234');
insert into clientes values(100,'Supermercado Lopez','Avellaneda 34');
insert into clientes values(101,'Almacen Anita','Colon 987');
insert into clientes values(102,'Juan Garcia','Sucre 345');
insert into clientes values(103,'Luis Luque','San Martin 1234');
insert into clientes values(104,'Valeria Vazquez','Colon 123');
insert into clientes values(105,'Federico Ferreyra','Colon 987');
insert into empleados values('23333333','Federico','Ferreyra','Colon 987');
insert into empleados values('28888888','Ana','Marquez','Sucre 333');
insert into empleados values('30111111','Pedro','Perez','Caseros 956');
insert into empleados values('31222333','Juan','Garcia','Sucre 345');
insert into empleados values('32333444','Luis','Luque','San Martin 1234');
insert into empleados values('33444555','Valeria','Vazquez','Colon 123');
insert into empleados values('34555666','Blanca','Bustos','San Martin 987');

select nombre, domicilio from clientes


intersect
select nombre||' '||apellido, domicilio from empleados;

select nombre from proveedores


intersect
select nombre from clientes
intersect
select nombre||' '||apellido from empleados;

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".

67 - Minus

Problema:

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".

Eliminamos las tablas:

drop table ingles;


drop table frances;

Creamos las tablas:

create table ingles(


documento varchar2(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
primary key(documento)
);

create table frances(


documento varchar2(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
primary key(documento)
);

Ingresamos algunos registros:

insert into ingles values('20111222','Ana Acosta','Avellaneda 111');


insert into ingles values('21222333','Betina Bustos','Bulnes 222');
insert into ingles values('22333444','Carlos Caseros','Colon 333');
insert into ingles values('23444555','Daniel Duarte','Duarte Quiros
444');
insert into ingles values('24555666','Estela Esper','Esmeralda 555');
insert into frances values('23444555','Daniel Duarte','Duarte Quiros
444');
insert into frances values('24555666','Estela Esper','Esmeralda
555');
insert into frances values('30111222','Fabiana Fuentes','Famatina
666');
insert into frances values('30222333','Gaston Gonzalez','Guemes
777');

La academia necesita el nombre y domicilio de todos los alumnos que cursan solamente ingls
(no presentes en la tabla "frances") para enviarles publicidad referida al curso de francs.
Empleamos el operador "minus" para obtener dicha informacin:

select nombre, domicilio from ingles


minus
select nombre,domicilio from frances;

El resultado muestra los registros de la primer consulta que NO coinciden con ningn registro
de la segunda consulta.

Los registros presentes en ambas tablas (Daniel Duarte y Estela Esper), no aparecen en el
resultado final.

La academia necesita el nombre y domicilio de todos los alumnos que cursan solamente
francs (no presentes en la tabla "ingles") para enviarles publicidad referida al curso de
ingls. Empleamos el operador "minus" para obtener dicha informacin:

select nombre, domicilio from frances


minus
select nombre,domicilio from ingles;

El resultado muestra los registros de la primer consulta que NO coinciden con ningn registro
de la segunda consulta. Los registros presentes en ambas tablas (Daniel Duarte y Estela
Esper), no aparecen en el resultado final.

Si queremos los alumnos que cursan un solo idioma (registros de "ingles" y de "frances" que no
coinciden), podemos unir ambas tablas y luego restarle la interseccin:

select nombre from ingles


union
select nombre from frances
minus
(select nombre from ingles
intersect
select nombre from frances);

Podemos obtener el mismo resultado anterior con la siguiente consulta en la cual se buscan
los registros de "ingles" que no coinciden con "frances" y los registros de "frances" que no
coinciden con "ingles" y luego se unen ambos resultados:

select nombre from ingles


minus
select nombre from frances
union
(select nombre from frances
minus
select nombre from ingles);
67 - Minus

Primer problema:

Una clnica almacena los datos de los mdicos en una tabla llamada "medicos" y los datos de
los pacientes en otra denominada "pacientes".

1- Eliminamos ambas tablas:

drop table medicos;


drop table pacientes;

2- Creamos las tablas:

create table medicos(


legajo number(3),
documento varchar2(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
especialidad varchar2(30),
primary key(legajo)
);

create table pacientes(


documento varchar2(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
obrasocial varchar2(20),
primary key(documento)
);

3- Ingresamos algunos registros:

insert into medicos values(1,'20111222','Ana Acosta','Avellaneda 111','clinica');


insert into medicos values(2,'21222333','Betina Bustos','Bulnes 222','clinica');
insert into medicos values(3,'22333444','Carlos Caseros','Colon 333','pediatria');
insert into medicos values(4,'23444555','Daniel Duarte','Duarte Quiros
444','oculista');
insert into medicos values(5,'24555666','Estela Esper','Esmeralda 555','alergia');

insert into pacientes values('24555666','Estela Esper','Esmeralda 555','IPAM');


insert into pacientes values('23444555','Daniel Duarte','Duarte Quiros
444','OSDOP');
insert into pacientes values('30111222','Fabiana Fuentes','Famatina 666','PAMI');
insert into pacientes values('30111222','Gaston Gonzalez','Guemes 777','PAMI');

4- La clnica necesita el nombre y domicilio de mdicos y pacientes para enviarles una tarjeta
de invitacin a la inauguracin de un nuevo establecimiento. Emplee el operador "union" para
obtener dicha informacin de ambas tablas (7 registros)

5- Se necesitan los nombres de los mdicos que tambin son pacientes de la clnica. Realice
una interseccin entre las tablas.

6- La clnica necesita los nombres de los pacientes que no son mdicos. Realice una operacin
de resta.
7- Se necesitan los registros que no coinciden en ambas tablas. Realice la operacin
necesaria.

drop table medicos;


drop table pacientes;

create table medicos(


legajo number(3),
documento varchar2(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
especialidad varchar2(30),
primary key(legajo)
);

create table pacientes(


documento varchar2(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
obrasocial varchar2(20),
primary key(documento)
);

insert into medicos values(1,'20111222','Ana Acosta','Avellaneda 111','clinica');


insert into medicos values(2,'21222333','Betina Bustos','Bulnes 222','clinica');
insert into medicos values(3,'22333444','Carlos Caseros','Colon 333','pediatria');
insert into medicos values(4,'23444555','Daniel Duarte','Duarte Quiros
444','oculista');
insert into medicos values(5,'24555666','Estela Esper','Esmeralda 555','alergia');

insert into pacientes values('24555666','Estela Esper','Esmeralda 555','IPAM');


insert into pacientes values('23444555','Daniel Duarte','Duarte Quiros
444','OSDOP');
insert into pacientes values('30111222','Fabiana Fuentes','Famatina 666','PAMI');
insert into pacientes values('30111222','Gaston Gonzalez','Guemes 777','PAMI');

select nombre, domicilio from medicos


union
select nombre, domicilio from pacientes;

select nombre from medicos


intersect
select nombre from pacientes;

select nombre, domicilio from pacientes


minus
select nombre, domicilio from medicos;

select nombre from pacientes


minus
select nombre from medicos
union
(select nombre from medicos
minus
select nombre from pacientes);

Segundo problema:

Un colegio guarda los datos de los alumnos que estn cursando primer ao en una tabla
denominada "primero", los datos de los alumnos que estn cursando segundo ao en una tabla
llamada "segundo" y en la tabla "inscriptos2" los datos de los alumnos inscriptos para segundo
ao para el siguiente ao.

1- Elimine las tablas:

drop table primero;


drop table segundo;
drop table inscriptos2;

2- Cree las tablas:

create table primero(


documento char(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
primary key(documento)
);

create table segundo(


documento char(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
primary key(documento)
);

create table inscriptos2(


documento char(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
primary key(documento)
);

3- Ingrese algunos registros:

insert into primero values('40111222','Alicia Acosta','Avellaneda 111');


insert into primero values('41222333','Bernardo Bustos','Bulnes 222');
insert into primero values('41555666','Carlos Caseres','Colon 333');
insert into primero values('41888999','Diana Duarte','Dinamarca 444');
insert into primero values('42333444','Eduardo Esper','San Martin 555');

insert into segundo values('43444555','Federico Fuentes','Francia 666');


insert into segundo values('43666777','Gabriela Gomez','Garzon 777');
insert into segundo values('44555666','Hector Huerta','Colon 888');
insert into segundo values('44999000','Ines Irala','Inglaterra 999');
insert into segundo values('45111444','Juan Juarez','Jamaica 111');
insert into inscriptos2 values('41555666','Carlos Caseres','Colon 333');
insert into inscriptos2 values('41888999','Diana Duarte','Dinamarca 444');
insert into inscriptos2 values('42333444','Eduardo Esper','San Martin 555');
insert into inscriptos2 values('43444555','Federico Fuentes','Francia 666');
insert into inscriptos2 values('46777888','Luis Lopez','Lules 222');
insert into inscriptos2 values('47888999','Marina Moreno','Martin Garcia 333');
insert into inscriptos2 values('48999000','Nora Nores','Natividad 333');

Tenga en cuenta algunas consideraciones:


- algunos alumnos de primero, se han inscripto en el mismo colegio para cursar segundo ao;
- algunos alumnos de primero no estn inscriptos en segundo porque repetirn el prximo ao
o se cambiarn de colegio;
- algunos alumnos que estn cursando segundo estn inscriptos nuevamente en segundo
porque repetirn el curso;
- algunos inscriptos para el ao prximo en segundo, no estn cursando primero en este
colegio.

4- El colegio quiere saber los nombres de los inscriptos a segundo del ao prximo que repiten
segundo (presentes en "segundo" y en "inscriptos2") (1 registro):

5- El colegio quiere saber los nombres de los alumnos que estn cursando primero y estn
inscriptos para segundo el prximo ao (presentes en "inscriptos2" y en "primero") (3 registros)

6- El colegio quiere saber los nombres y domicilios de los alumnos inscriptos para segundo que
no estn cursando este ao en este colegio (presentes en "inscriptos2" y ausentes en "primero"
y "segundo") para enviarles una nota con la fecha para una reunin informativa (3 registros)

7- El colegios quiere saber los nombres de los alumnos inscriptos para segundo el prximo
ao, que estn cursando primero o segundo este ao (presentes en "inscriptos2" y en "primero"
o "segundo). Realice las operaciones necesarias. (4 registros)

8- El colegio necesita los nombres de los alumnos que estn cursando primero y no estn
inscriptos el prximo ao en segundo para enviarles un mail preguntando la razn por la cual
no se han anotado an (2 registros)

drop table primero;


drop table segundo;
drop table inscriptos2;

create table primero(


documento char(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
primary key(documento)
);

create table segundo(


documento char(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
primary key(documento)
);

create table inscriptos2(


documento char(8) not null,
nombre varchar2(30),
domicilio varchar2(30),
primary key(documento)
);

insert into primero values('40111222','Alicia Acosta','Avellaneda 111');


insert into primero values('41222333','Bernardo Bustos','Bulnes 222');
insert into primero values('41555666','Carlos Caseres','Colon 333');
insert into primero values('41888999','Diana Duarte','Dinamarca 444');
insert into primero values('42333444','Eduardo Esper','San Martin 555');

insert into segundo values('43444555','Federico Fuentes','Francia 666');


insert into segundo values('43666777','Gabriela Gomez','Garzon 777');
insert into segundo values('44555666','Hector Huerta','Colon 888');
insert into segundo values('44999000','Ines Irala','Inglaterra 999');
insert into segundo values('45111444','Juan Juarez','Jamaica 111');

insert into inscriptos2 values('41555666','Carlos Caseres','Colon 333');


insert into inscriptos2 values('41888999','Diana Duarte','Dinamarca 444');
insert into inscriptos2 values('42333444','Eduardo Esper','San Martin 555');
insert into inscriptos2 values('43444555','Federico Fuentes','Francia 666');
insert into inscriptos2 values('46777888','Luis Lopez','Lules 222');
insert into inscriptos2 values('47888999','Marina Moreno','Martin Garcia 333');
insert into inscriptos2 values('48999000','Nora Nores','Natividad 333');

select nombre from segundo


intersect
select nombre from inscriptos2;

select nombre from inscriptos2


intersect
select nombre from primero;

select nombre from inscriptos2


minus
select nombre from primero
minus
select nombre from segundo;

select nombre,domicilio from inscriptos2


intersect
select nombre,domicilio from primero
union
(select nombre,domicilio from inscriptos2
intersect
select nombre,domicilio from segundo);

select nombre from primero


minus
select nombre from inscriptos2;

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.

68 - Agregar campos (alter table- add)

Problema:

Trabajamos con la tabla "libros" de una librera.


Eliminamos la tabla:

drop table libros;

Creamos la tabla:

create table libros(


titulo varchar2(30),
editorial varchar2(20)
);

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;

Verificamos la estructura de la tabla:

describe libros;

aparece el nuevo campo.

Agregamos un nuevo campo "precio" a la tabla "libros", de tipo number(4) que acepta valores
nulos:

alter table libros


add precio number(4);
Verificamos la estructura de la tabla:

describe libros;

aparece el nuevo campo.

Ingresamos algunos registros:

insert into libros values('El aleph','Emece',100,25.5);


insert into libros values('Uno','Planeta',150,null);

Intentamos agregar un nuevo campo "autor" de tipo varchar2(30) que no admita valores nulos:

alter table libros


add autor varchar2(30) not null;

Mensaje de error. Si el campo no aceptar valores nulos y no tiene definido un valor por
defecto, no se pueden llenar los registros existentes con ningn valor. Por ello, debemos
definirlo con un valor por defecto:

alter table libros


add autor varchar2(30) default 'Desconocido' not null;

Veamos qu sucedi con los registros existentes:

select *from libros;

contienen el valor por defecto en "autor".

68 - Agregar campos (alter table- add)

Primer problema:

Trabaje con una tabla llamada "empleados".

1- Elimine la tabla y crela:

drop table empleados;

create table empleados(


apellido varchar2(20),
nombre varchar2(20) not null,
domicilio varchar2(30)
);

2- Agregue un campo "fechaingreso" de tipo date que acepte valores nulos

3- Verifique que la estructura de la tabla ha cambiado

4- Agregue un campo "seccion" de tipo caracter que no permita valores nulos y verifique que
el nuevo campo existe

5- Ingrese algunos registros:


insert into empleados values('Lopez','Juan','Colon 123','10/10/1980','Contaduria');
insert into empleados values('Gonzalez','Juana','Avellaneda
222','01/05/1990','Sistemas');
insert into empleados values('Perez','Luis','Caseros 987','12/09/2000','Secretaria');

6- Intente agregar un campo "sueldo" que no admita valores nulos.

7- Agregue el campo "sueldo" no nulo y con el valor 0 por defecto.

8- Verifique que la estructura de la tabla ha cambiado.

drop table empleados;

create table empleados(


apellido varchar2(20),
nombre varchar2(20) not null,
domicilio varchar2(30)
);
alter table empleados
add fechaingreso date;

describe empleados;

alter table empleados


add seccion varchar2(30) not null;

describe empleados;

insert into empleados values('Lopez','Juan','Colon 123','10/10/1980','Contaduria');


insert into empleados values('Gonzalez','Juana','Avellaneda
222','01/05/1990','Sistemas');
insert into empleados values('Perez','Luis','Caseros 987','12/09/2000','Secretaria');

alter table empleados


add sueldo number(6,2) not null;

alter table empleados


add sueldo number(6,2) default 0 not null;

describe empleados;

69 - Modificar campos (alter table- modify)

"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.

69 - Modificar campos (alter table- modify)

Problema:

Trabajamos con la tablas "libros" y "editoriales" de una librera.


Eliminamos las tablas:

drop table libros;


drop table editoriales;
Creamos las tablas:

create table editoriales(


codigo number(3),
nombre varchar2(30),
primary key(codigo)
);

create table libros(


titulo varchar2(40),
editorial number(3),
autor varchar2(30),
precio number(4),
constraint FK_libros_editorial
foreign key(editorial)
references editoriales(codigo)
);

Modificamos el campo precio para que tome valores de 6 dgitos incluyendo 2 decimales y
acepte valores nulos:

alter table libros


modify precio number(6,2);

Verificamos el cambio viendo la estructura de la tabla:

describe libros;

Ingresamos algunos registros:

insert into editoriales values(1, 'Emece');

insert into libros values('Uno',1,'Richard Bach',24.6);

Intentamos modificar el campo "precio" a "varchar(8)":

alter table libros modify precio varchar(8);

No lo permite, porque existe un registro con un valor numrico en tal campo.

Actualizamos el registro de "libros" con precio no nulo a nulo:

update libros set precio= null;

Ahora si podemos cambiar el tipo de dato de "precio", los registros existentes contienen "null"
en tal campo:

alter table libros modify precio varchar(8);

Verificamos el cambio:

describe libros;

Intentamos modificar el campo "codigo" de "editoriales" a "char(3)":

alter table editoriales modify codigo char(3);


No lo permite porque tal campo es referenciado por una clave externa.

Modificamos un atributo del campo "codigo" de "editoriales":

alter table editoriales modify codigo number(4);

Oracle permite el cambio pues no afecta a la restriccin.

Intentamos redefinir "precio" para que no acepte valores nulos:

alter table libros


modify precio not null;

No lo permite porque existe un registro con valor nulo en "precio".

Eliminamos el registro y modificamos el campo "precio" a "no nulo":

delete from libros;

alter table libros


modify precio not null;

Intentamos redefinir como no nulo el campo "codigo" de "editoriales":

alter table editoriales


modify codigo not null;

No aparece mensaje de error, pero si verificamos la estructura de la tabla veremos que


continua siendo "not null", ya que es clave primaria:

describe editoriales;

Redefinimos el campo "precio" como number(6,2), con un valor por defecto 0:

alter table libros


modify precio number(6,2) default 0;

Oracle permite modificar el campo "precio" a "char(8)". Si luego ingresamos un registro sin
valor para "precio", guardar el valor por defecto (0) convertido a cadena ('0'):

alter table libros


modify precio char(8) default 0;

insert into libros values('El aleph',1,'Borges',default);

select *from libros;

Redefinimos el valor por defecto del campo "precio" (que ahora es de tipo char) a "cero":

alter table libros


modify precio default 'cero';

Oracle no permite modificar el campo "precio" a "number(8,2)" porque si luego ingresamos un


registro sin valor para tal campo, el valor por defecto ('cero') no podr convertirse a nmero:

alter table libros


modify precio number(8,2);

Mensaje de error.

Modificamos el valor por defecto para que luego pueda ser convertido:

alter table libros


modify precio default '0';

Vaciamos la tabla:

truncate table libros;

Oracle permite modificar el campo "precio" a "number(8,2)" porque si luego ingresamos un


registro sin valor para tal campo, el valor por defecto ('0') podr convertirse a nmero (0):

alter table libros


modify precio number(8,2);

Oracle permite modificar el campo "precio" a "char(8)". Si luego ingresamos un registro sin
valor para "precio", guardar el valor por defecto (0) convertido a cadena ('0'):

alter table libros


modify precio char(8) default 0;

insert into libros values('El aleph',1,'Borges',default);

select *from libros;


69 - Modificar campos (alter table- modify)

Primer problema:

Trabaje con una tabla llamada "empleados" y "secciones".

1- Elimine las tablas y crelas:

drop table empleados;


drop table secciones;

create table secciones(


codigo number(2),
nombre varchar(20),
primary key (codigo)
);

create table empleados(


apellido varchar2(20) not null,
nombre varchar2(20),
domicilio varchar2(30),
seccion number(2),
fechaingreso date,
telefono number(7),
constraint FK_empleados_seccion
foreign key (seccion)
references secciones(codigo)
on delete set null
);

2- Modifique el tipo de dato del campo "telefono" a varchar(11)


Oracle lo permite porque la tabla est vaca; si no lo estuviese, no lo permitira.

3- Ingrese algunos registros en ambas tablas

insert into secciones values(8,'Secretaria');


insert into secciones values(9,'Contaduria');
insert into secciones values(10,'Sistemas');

insert into empleados values('Lopez','Luciano','Colon


123',8,'10/10/1980','4819977');
insert into empleados values('Gonzalez',null,'Avellaneda
222',9,'01/05/1990','4515566');

4- Modifique el campo "nombre" de "empleados" para que permita cadenas variables de 10


caracteres (menor longitud) y luego verifique el cambio.
Oracle lo permite, porque los valores en tal campo son menores a 10.

5- Intente modificar el campo "nombre" de "empleados" para que permita cadenas variables
de 6 caracteres (menor longitud)
Oracle no lo permite, porque un valor en tal campo consta de 7 caracteres.

6- Elimine el registro correspondiente a "Lopez Luciano"

7- Modifique el campo "nombre" de "empleados" para que permita cadenas variables de 6


caracteres
Oracle lo permite, la tabla no est vaca pero los registros contienen valor nulo en el campo
"nombre".

8- Intente cambiar el tipo de dato del campo "codigo" de "secciones" a char(2)


Oracle no lo permite porque tal campo es referenciado por una clave externa.

9- Cambie la longitud del campo "codigo" de "secciones" a 3.


Oracle lo permite porque el cambio no afecta la restriccin "foreign key" que referencia el
campo "codigo".

10- Intente modificar el campo "nombre" de "empleados" para que no admita valores nulos.
Mensaje de error, la tabla contiene valores nulos en tal campo.

11- Modifique el valor nulo por uno vlido del campo "nombre" de "empleados" y luego realice
la modificacin del punto anterior.

12- Verifique que "nombre" ya no admite valores nulos.

drop table empleados;


drop table secciones;

create table secciones(


codigo number(2),
nombre varchar(20),
primary key (codigo)
);

create table empleados(


apellido varchar2(20) not null,
nombre varchar2(20),
domicilio varchar2(30),
seccion number(2),
fechaingreso date,
telefono number(7),
constraint FK_empleados_seccion
foreign key (seccion)
references secciones(codigo)
on delete set null
);

alter table empleados


modify telefono varchar(11);

insert into secciones values(8,'Secretaria');


insert into secciones values(9,'Contaduria');
insert into secciones values(10,'Sistemas');

insert into empleados values('Lopez','Luciano','Colon


123',8,'10/10/1980','4819977');
insert into empleados values('Gonzalez',null,'Avellaneda
222',9,'01/05/1990','4515566');

alter table empleados


modify nombre varchar2(10);

describe empleados;

alter table empleados


modify nombre varchar2(6);

delete empleados where apellido='Lopez';

alter table empleados


modify nombre varchar2(6);

alter table secciones


modify codigo char(2);

alter table secciones


modify codigo number(3);

alter table empleados


modify nombre not null;

update empleados set nombre='Marina' where nombre is null;

alter table empleados


modify nombre not null;

describe empleados;
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;
70 - Eliminar campos (alter table- drop)

Problema:

Trabajamos con la tablas "libros" y "editoriales" de una librera.


Eliminamos las tablas:

drop table libros;


drop table editoriales;

Creamos las tablas:

create table editoriales(


codigo number(3),
nombre varchar2(30),
primary key(codigo)
);

create table libros(


titulo varchar2(30),
editorial number(3),
autor varchar2(30),
precio number(6,2),
constraint FK_libros_editorial
foreign key(editorial)
references editoriales(codigo)
);
Eliminamos un campo de la tabla "libros":

alter table libros


drop column precio;

Vemos la estructura de la tabla "libros":

describe libros;

El campo "precio" ya no existe.

Recuerde que no pueden eliminarse los campos referenciados por una "foreign key".
Intentamos eliminar el campo "codigo" de "editoriales":

alter table editoriales


drop column codigo;

Un mensaje indica que la sentencia no fue ejecutada.

Eliminamos el campo "editorial" de "libros":

alter table libros


drop column editorial;

Verificamos que el campo no existe:

describe libros;

El campo se ha eliminado y junto con l la restriccin "foreign key":

select *from user_constraints


where table_name='LIBROS';

Ahora si podemos eliminar el campo "codigo" de "editoriales", pues la restriccin "foreign key"
que haca referencia a ella ya no existe:

alter table editoriales


drop column codigo;

El campo "codigo" de "editoriales" se ha eliminado y junto con l la restriccin "primary key":

select *from user_constraints


where table_name='EDITORIALES';

Agregamos un ndice compuesto sobre "titulo" y "autor" de "libros":

create unique index I_libros_titulo


on libros(titulo,autor);

Veamos si existe tal ndice:

select index_name,column_name,column_position
from user_ind_columns
where table_name='LIBROS';
Recuerde que si elimina un campo indizado, su ndice tambin se elimina. Eliminamos el
campo "autor" de "libros":

alter table libros


drop column autor;

Veamos si existe el ndice compuesto creado anteriormente sobre los campos "titulo" y "autor"
de "libros":

select index_name,column_name,column_position
from user_ind_columns
where table_name='LIBROS';

Ya no existe.

La tabla ahora solamente consta de un campo, por lo tanto, no puede eliminarse, pues la
tabla no puede quedar vaca de campos:

alter table libros


drop column titulo;

Mensaje de error.

70 - Eliminar campos (alter table- drop)

Primer problema:

Trabaje con una tabla llamada "empleados" y "secciones".


1- Elimine las tablas y crelas:

drop table empleados;


drop table secciones;

create table secciones(


codigo number(2),
nombre varchar(20),
primary key (codigo)
);

create table empleados(


apellido varchar2(20),
nombre varchar2(20) not null,
domicilio varchar2(30),
seccion number(2),
sueldo number(8,2),
constraint CK_empleados_sueldo
check (sueldo>=0) disable,
fechaingreso date,
constraint FK_empleados_seccion
foreign key (seccion)
references secciones(codigo)
on delete set null
);

2- Ingrese algunos registros en ambas tablas:


insert into secciones values(8,'Secretaria');
insert into secciones values(9,'Contaduria');
insert into secciones values(10,'Sistemas');

insert into empleados values('Lopez','Juan','Colon 123',8,505.50,'10/10/1980');


insert into empleados values('Gonzalez','Juana','Avellaneda
222',9,600,'01/05/1990');
insert into empleados values('Perez','Luis','Caseros 987',10,800,'12/09/2000');

3- Elimine el campo "domicilio" y luego verifique la eliminacin

4- Vea las restricciones de "empleados" (1 restriccin "foreign key" y 2 "check")

5- Intente eliminar el campo "codigo" de "secciones"

6- Elimine la restriccin "foreign key" de "empleados", luego elimine el campo "codigo" de


"secciones" y verifique la eliminacin

7- Verifique que al eliminar el campo "codigo" de "secciones" se ha eliminado la "primary key"


de "secciones"

8- Elimine el campo "sueldo" y verifique que la restriccin sobre tal campo se ha eliminado

9- Cree un ndice no nico por el campo "apellido" y verifique su existencia consultando


"user_indexes"

10- Elimine el campo "apellido" y verifique que el ndice se ha eliminado

11- Elimine 2 campos de "empleados" y vea la estructura de la tabla

12- Intente eliminar el nico campo de "empleados"

drop table empleados;


drop table secciones;

create table secciones(


codigo number(2),
nombre varchar(20),
primary key (codigo)
);

create table empleados(


apellido varchar2(20),
nombre varchar2(20) not null,
domicilio varchar2(30),
seccion number(2),
sueldo number(8,2),
constraint CK_empleados_sueldo
check (sueldo>=0) disable,
fechaingreso date,
constraint FK_empleados_seccion
foreign key (seccion)
references secciones(codigo)
on delete set null
);

insert into secciones values(8,'Secretaria');


insert into secciones values(9,'Contaduria');
insert into secciones values(10,'Sistemas');

insert into empleados values('Lopez','Juan','Colon 123',8,505.50,'10/10/1980');


insert into empleados values('Gonzalez','Juana','Avellaneda
222',9,600,'01/05/1990');
insert into empleados values('Perez','Luis','Caseros 987',10,800,'12/09/2000');

alter table empleados


drop column domicilio;

describe empleados;

select *from user_constraints


where table_name='EMPLEADOS';

alter table secciones


drop column codigo;

alter table empleados


drop constraint FK_empleados_seccion;

alter table secciones


drop column codigo;

describe secciones;

select *from user_constraints


where table_name='SECCIONES';

alter table empleados


drop column sueldo;

select *from user_constraints


where table_name='EMPLEADOS';

create index I_empleados_apellido


on empleados(apellido);

select *from user_indexes


where table_name='EMPLEADOS';

alter table empleados


drop column apellido;

select *from user_indexes


where table_name='EMPLEADOS';

alter table empleados


drop column fechaingreso;

alter table empleados


drop column seccion;
describe empleados;

alter table empleados


drop column nombre;

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);
71 - Agregar campos y restricciones (alter table)

Problema:

Trabajamos con la tabla "libros" de una librera.


Eliminamos la tabla:

drop table libros;

Creamos la tabla con la siguiente estructura:

create table libros(


autor varchar2(30),
editorial varchar2(15)
);

Agregamos el campo "titulo" de tipo varchar2(30) y una restriccin "unique":

alter table libros


add titulo varchar2(30)
constraint UQ_libros_autor unique;

Veamos si la estructura cambi:

describe libros;

Agregamos el campo "codigo" de tipo number(4) not null y en la misma sentencia una
restriccin "primary key":

alter table libros


add codigo number(4) not null
constraint PK_libros_codigo primary key;

Agregamos el campo "precio" de tipo number(6,2) y una restriccin "check" que no permita
valores negativos para dicho campo:

alter table libros


add precio number(6,2)
constraint CK_libros_precio check (precio>=0);

Veamos la estructura de la tabla y las restricciones:

describe libros;
select *from user_constraints where table_name='LIBROS';

La tabla contiene 5 campos y 4 restricciones.

71 - Agregar campos y restricciones (alter table)

Primer problema:

Trabaje con una tabla llamada "empleados".


1- Elimine la tabla y crela:

drop table empleados;

create table empleados(


documento char(8) not null,
nombre varchar2(10),
domicilio varchar2(30),
ciudad varchar2(20) default 'Buenos Aires'
);

2- Agregue el campo "legajo" de tipo number(3) y una restriccin "primary key"

3- Vea si la estructura cambi y si se agreg la restriccin

4- Agregue el campo "hijos" de tipo number(2) y en la misma sentencia una restriccin "check"
que no permita valores superiores a 30

5- Ingrese algunos registros:

insert into empleados values('22222222','Juan Lopez','Colon


123','Cordoba',100,2);
insert into empleados values('23333333','Ana Garcia','Sucre 435','Cordoba',200,3);
6- Intente agregar el campo "sueldo" de tipo number(6,2) no nulo y una restriccin "check"
que no permita valores negativos para dicho campo.
No lo permite porque no damos un valor por defecto para dicho campo no nulo y los registros
existentes necesitan cargar un valor.

7- Agregue el campo "sueldo" de tipo number(6,2) no nulo, con el valor por defecto 0 y una
restriccin "check" que no permita valores negativos para dicho campo

8- Recupere los registros

select *from empleados;

9- Vea la nueva estructura de la tabla

10- Vea las restricciones

drop table empleados;

create table empleados(


documento char(8) not null,
nombre varchar2(10),
domicilio varchar2(30),
ciudad varchar2(20) default 'Buenos Aires'
);

alter table empleados


add legajo number(3)
constraint PK_empleados_legajo primary key;

describe empleados;
select *from user_constraints where table_name='EMPLEADOS';

alter table empleados


add hijos number(2)
constraint CK_empleados_hijos check (hijos<=30);

insert into empleados values('22222222','Juan Lopez','Colon


123','Cordoba',100,2);
insert into empleados values('23333333','Ana Garcia','Sucre 435','Cordoba',200,3);

alter table empleados


add sueldo number(6,2) not null
constraint CK_empleados_sueldo check (sueldo>=0);

alter table empleados


add sueldo number(6,2) default 0 not null
constraint CK_empleados_sueldo check (sueldo>=0);

select *from empleados;

describe empleados;

select *from user_constraints where table_name='EMPLEADOS';


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);
73 - Subconsultas como expresion

Problema:

Trabajamos con la tabla "libros" de una librera.


Eliminamos la tabla y la creamos:

drop table libros;

create table libros(


codigo number(5),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(5,2)
);

Ingresamos los siguientes registros:

insert into libros values(1,'Alicia en el pais de las


maravillas','Lewis Carroll','Emece',20.00);
insert into libros values(2,'Alicia en el pais de las
maravillas','Lewis Carroll','Plaza',35.00);
insert into libros values(3,'Aprenda PHP','Mario Molina','Siglo
XXI',40.00);
insert into libros values(4,'El aleph','Borges','Emece',10.00);
insert into libros values(5,'Ilusiones','Richard
Bach','Planeta',15.00);
insert into libros values(6,'Java en 10 minutos','Mario
Molina','Siglo XXI',50.00);
insert into libros values(7,'Martin Fierro','Jose
Hernandez','Planeta',20.00);
insert into libros values(8,'Martin Fierro','Jose
Hernandez','Emece',30.00);
insert into libros values(9,'Uno','Richard Bach','Planeta',10.00);

Obtenemos el ttulo, precio de un libro especfico y la diferencia entre su precio y el mximo


valor:

select titulo,precio,
precio-(select max(precio) from libros) as diferencia
from libros
where titulo='Uno';

Mostramos el ttulo y precio del libro ms costoso:

select titulo,autor, precio


from libros
where precio=
(select max(precio) from libros);

Actualizamos el precio del libro con mximo valor:

update libros set precio=45


where precio=
(select max(precio) from libros);

Eliminamos los libros con precio menor:

delete from libros


where precio=
(select min(precio) from libros);
73 - Subconsultas como expresion

Primer problema:

Un profesor almacena el documento, nombre y la nota final de cada alumno de su clase en


una tabla llamada "alumnos".
1- Elimine la tabla:

drop table alumnos;

2- Crela con los campos necesarios. Agregue una restriccin "primary key" para el campo
"documento" y una "check" para validar que el campo "nota" se encuentre entre los valores 0 y
10:

create table alumnos(


documento char(8),
nombre varchar2(30),
nota number(4,2),
primary key(documento),
constraint CK_alumnos_nota_valores check (nota>=0 and nota <=10)
);

3-Ingrese algunos registros:

insert into alumnos values('30111111','Ana Algarbe',5.1);


insert into alumnos values('30222222','Bernardo Bustamante',3.2);
insert into alumnos values('30333333','Carolina Conte',4.5);
insert into alumnos values('30444444','Diana Dominguez',9.7);
insert into alumnos values('30555555','Fabian Fuentes',8.5);
insert into alumnos values('30666666','Gaston Gonzalez',9.70);

4- Obtenga todos los datos de los alumnos con la nota ms alta, empleando subconsulta

5- Realice la misma consulta anterior pero intente que la consulta interna retorne, adems
del mximo valor de nota, el nombre del alumno.
Mensaje de error, porque la lista de seleccin de una subconsulta que va luego de un
operador de comparacin puede incluir slo un campo o expresin (excepto si se emplea
"exists" o "in").

6- Muestre los alumnos que tienen una nota menor al promedio, su nota, y la diferencia con el
promedio.

7- Cambie la nota del alumno que tiene la menor nota por 4.

8- Elimine los alumnos cuya nota es menor al promedio.

drop table alumnos;

create table alumnos(


documento char(8),
nombre varchar2(30),
nota number(4,2),
primary key(documento),
constraint CK_alumnos_nota_valores check (nota>=0 and nota <=10)
);

insert into alumnos values('30111111','Ana Algarbe',5.1);


insert into alumnos values('30222222','Bernardo Bustamante',3.2);
insert into alumnos values('30333333','Carolina Conte',4.5);
insert into alumnos values('30444444','Diana Dominguez',9.7);
insert into alumnos values('30555555','Fabian Fuentes',8.5);
insert into alumnos values('30666666','Gaston Gonzalez',9.70);

select alumnos.*
from alumnos
where nota=
(select max(nota) from alumnos);

select alumnos.*
from alumnos
where nota=
(select nombre, max(nota) from alumnos);

select alumnos.*,
(select avg(nota) from alumnos)-nota as diferencia
from alumnos
where nota<
(select avg(nota) from alumnos);

update alumnos set nota=4


where nota=
(select min(nota) from alumnos);

delete from alumnos


where nota<
(select avg(nota) from alumnos);

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');
74 - Subconsultas con in

Problema:

Trabajamos con las tablas "libros" y "editoriales" de una librera.


Eliminamos las tablas y las creamos:

drop table libros;


drop table editoriales;

create table editoriales(


codigo number(3),
nombre varchar2(30),
primary key (codigo)
);

create table libros (


codigo number(5),
titulo varchar2(40),
autor varchar2(30),
codigoeditorial number(3),
primary key(codigo),
constraint FK_libros_editorial
foreign key (codigoeditorial)
references editoriales(codigo)
);
Ingresamos algunos registros:

insert into editoriales values(1,'Planeta');


insert into editoriales values(2,'Emece');
insert into editoriales values(3,'Paidos');
insert into editoriales values(4,'Siglo XXI');

insert into libros values(100,'Uno','Richard Bach',1);


insert into libros values(101,'Ilusiones','Richard Bach',1);
insert into libros values(102,'Aprenda PHP','Mario Molina',4);
insert into libros values(103,'El aleph','Borges',2);
insert into libros values(104,'Puente al infinito','Richard Bach',2);

Queremos conocer el nombre de las editoriales que han publicado libros del autor "Richard
Bach":

select nombre
from editoriales
where codigo in
(select codigoeditorial
from libros
where autor='Richard Bach');

Probamos la subconsulta separada de la consulta exterior para verificar que retorna una lista
de valores de un solo campo:

select codigoeditorial
from libros
where autor='Richard Bach';

Podemos reemplazar por un "join" la primera consulta:

select distinct nombre


from editoriales e
join libros
on codigoeditorial=e.codigo
where autor='Richard Bach';

Tambin podemos buscar las editoriales que no han publicado libros de "Richard Bach":

select nombre
from editoriales
where codigo not in
(select codigoeditorial
from libros
where autor='Richard Bach');
74 - Subconsultas con in

Primer problema:

Una empresa tiene registrados sus clientes en una tabla llamada "clientes", tambin tiene una
tabla "ciudades" donde registra los nombres de las ciudades.

1- Elimine las tablas "clientes" y "ciudades":

drop table clientes;


drop table ciudades;
2- Cree la tabla "clientes" (codigo, nombre, domicilio, ciudad, codigociudad) y "ciudades"
(codigo, nombre). Agregue una restriccin "primary key" para el campo "codigo" de ambas
tablas y una "foreing key" para validar que el campo "codigociudad" exista en "ciudades" con
eliminacin en cascada:

create table ciudades(


codigo number(2),
nombre varchar2(20),
primary key (codigo)
);

create table clientes (


codigo number(4),
nombre varchar2(30),
domicilio varchar2(30),
codigociudad number(2) not null,
primary key(codigo),
constraint FK_clientes_ciudad
foreign key (codigociudad)
references ciudades(codigo)
on delete cascade
);

3- Ingrese algunos registros para ambas tablas:

insert into ciudades values(1,'Cordoba');


insert into ciudades values(2,'Cruz del Eje');
insert into ciudades values(3,'Carlos Paz');
insert into ciudades values(4,'La Falda');
insert into ciudades values(5,'Villa Maria');

insert into clientes values (100,'Lopez Marcos','Colon 111',1);


insert into clientes values (101,'Lopez Hector','San Martin 222',1);
insert into clientes values (105,'Perez Ana','San Martin 333',2);
insert into clientes values (106,'Garcia Juan','Rivadavia 444',3);
insert into clientes values (107,'Perez Luis','Sarmiento 555',3);
insert into clientes values (110,'Gomez Ines','San Martin 666',4);
insert into clientes values (111,'Torres Fabiola','Alem 777',5);
insert into clientes values (112,'Garcia Luis','Sucre 888',5);

4- Necesitamos conocer los nombres de las ciudades de aquellos clientes cuyo domicilio es en
calle "San Martin", empleando subconsulta.

5- Obtenga la misma salida anterior pero empleando join.

6- Obtenga los nombre de las ciudades de los clientes cuyo apellido no comienza con una
letra especfica (letra "G"), empleando subconsulta.

7- Pruebe la subconsulta del punto 6 separada de la consulta exterior para verificar que
retorna una lista de valores de un solo campo.

drop table clientes;


drop table ciudades;
create table ciudades(
codigo number(2),
nombre varchar2(20),
primary key (codigo)
);

create table clientes (


codigo number(4),
nombre varchar2(30),
domicilio varchar2(30),
codigociudad number(2) not null,
primary key(codigo),
constraint FK_clientes_ciudad
foreign key (codigociudad)
references ciudades(codigo)
on delete cascade
);

insert into ciudades values(1,'Cordoba');


insert into ciudades values(2,'Cruz del Eje');
insert into ciudades values(3,'Carlos Paz');
insert into ciudades values(4,'La Falda');
insert into ciudades values(5,'Villa Maria');

insert into clientes values (100,'Lopez Marcos','Colon 111',1);


insert into clientes values (101,'Lopez Hector','San Martin 222',1);
insert into clientes values (105,'Perez Ana','San Martin 333',2);
insert into clientes values (106,'Garcia Juan','Rivadavia 444',3);
insert into clientes values (107,'Perez Luis','Sarmiento 555',3);
insert into clientes values (110,'Gomez Ines','San Martin 666',4);
insert into clientes values (111,'Torres Fabiola','Alem 777',5);
insert into clientes values (112,'Garcia Luis','Sucre 888',5);

select nombre
from ciudades
where codigo in
(select codigociudad
from clientes
where domicilio like 'San Martin %');

select distinct ci.nombre


from ciudades ci
join clientes cl
on codigociudad=ci.codigo
where domicilio like 'San Martin%';

select nombre
from ciudades
where codigo not in
(select codigociudad
from clientes
where nombre like 'G%');

select codigociudad
from clientes
where nombre like 'G%';

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".

75 - Subconsultas any- some- all

Problema:

Trabajamos con las tablas "libros" y "editoriales" de una librera.


Eliminamos las tablas y las creamos:

drop table libros;


drop table editoriales;

create table editoriales(


codigo number(3),
nombre varchar2(30),
primary key (codigo)
);

create table libros (


codigo number(5),
titulo varchar2(40),
autor varchar2(30),
codigoeditorial number(3),
precio number(5,2),
primary key(codigo),
constraint FK_libros_editorial
foreign key (codigoeditorial)
references editoriales(codigo)
on delete cascade
);

Ingresamos algunos registros:

insert into editoriales values(1,'Planeta');


insert into editoriales values(2,'Emece');
insert into editoriales values(3,'Paidos');
insert into editoriales values(4,'Siglo XXI');

insert into libros values(100,'Uno','Richard Bach',1,15);


insert into libros values(101,'Ilusiones','Richard Bach',4,18);
insert into libros values(102,'Puente al infinito','Richard
Bach',2,20);
insert into libros values(103,'Aprenda PHP','Mario Molina',4,40);
insert into libros values(104,'El aleph','Borges',2,10);
insert into libros values(105,'Antologa','Borges',1,20);
insert into libros values(106,'Cervantes y el
quijote','Borges',3,25);

Mostramos los ttulos de los libros de "Borges" de editoriales que han publicado tambin libros
de "Richard Bach":

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

Realizamos la misma consulta pero empleando "all" en lugar de "any":

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

Mostramos los ttulos y precios de los libros "Borges" cuyo precio supera a ALGUN precio de los
libros de "Richard Bach":

select titulo,precio
from libros
where autor like '%Borges%' and
precio > any
(select precio
from libros
where autor like '%Bach%');

Veamos la diferencia si empleamos "all" en lugar de "any":

select titulo,precio
from libros
where autor like '%Borges%' and
precio > all
(select precio
from libros
where autor like '%Bach%');

Empleamos la misma subconsulta para eliminacin:

delete from libros


where autor like '%Borges%' and
precio > all
(select precio
from libros
where autor like '%Bach%');
75 - Subconsultas any- some- all

Primer problema:

Un club dicta clases de distintos deportes a sus socios. El club tiene una tabla llamada
"inscriptos" en la cual almacena el nmero de "socio", el cdigo del deporte en el cual se
inscribe y la cantidad de cuotas pagas (desde 0 hasta 10 que es el total por todo el ao), y
una tabla denominada "socios" en la que guarda los datos personales de cada socio.

1- Elimine las tablas:

drop table inscriptos;


drop table socios;

2- Cree las tablas:

create table socios(


numero number(5),
documento char(8),
nombre varchar2(30),
domicilio varchar2(30),
primary key (numero)
);

create table inscriptos (


numerosocio number(5),
deporte varchar2(20) not null,
cuotas number(2) default 0,
constraint CK_inscriptos_cuotas
check (cuotas>=0 and cuotas<=10),
primary key(numerosocio,deporte),
constraint FK_inscriptos_socio
foreign key (numerosocio)
references socios(numero)
on delete cascade
);

3- Ingrese algunos registros:

insert into socios values(1,'23333333','Alberto Paredes','Colon 111');


insert into socios values(2,'24444444','Carlos Conte','Sarmiento 755');
insert into socios values(3,'25555555','Fabian Fuentes','Caseros 987');
insert into socios values(4,'26666666','Hector Lopez','Sucre 344');

insert into inscriptos values(1,'tenis',1);


insert into inscriptos values(1,'basquet',2);
insert into inscriptos values(1,'natacion',1);
insert into inscriptos values(2,'tenis',9);
insert into inscriptos values(2,'natacion',1);
insert into inscriptos values(2,'basquet',default);
insert into inscriptos values(2,'futbol',2);
insert into inscriptos values(3,'tenis',8);
insert into inscriptos values(3,'basquet',9);
insert into inscriptos values(3,'natacion',0);
insert into inscriptos values(4,'basquet',10);

4- Muestre el nmero de socio, el nombre del socio y el deporte en que est inscripto con un
join de ambas tablas

5- Muestre los socios que se sern compaeros en tenis y tambin en natacin (empleando
subconsulta)

6- Vea si el socio 1 se ha inscripto en algn deporte en el cual se haya inscripto el socio 2

7- Realice la misma consulta anterior pero empleando "in" en lugar de "=any"

8- Obtenga el mismo resultado anterior pero empleando join

9- Muestre los deportes en los cuales el socio 2 pag ms cuotas que ALGUN deporte en los
que se inscribi el socio 1

select deporte from inscriptos i where numerosocio=2 and cuotas>any (select cuotas from
inscriptos where numerosocio=1);

10- Realice la misma consulta anterior pero empleando "some" en lugar de "any"

11- Muestre los deportes en los cuales el socio 2 pag ms cuotas que TODOS los deportes en
que se inscribi el socio 1

12- Cuando un socio no ha pagado la matrcula de alguno de los deportes en que se ha


inscripto, se lo borra de la inscripcin de todos los deportes. Elimine todos los socios que no
pagaron ninguna cuota en algn deporte (cuota=0)

drop table inscriptos;


drop table socios;
create table socios(
numero number(5),
documento char(8),
nombre varchar2(30),
domicilio varchar2(30),
primary key (numero)
);

create table inscriptos (


numerosocio number(5),
deporte varchar2(20) not null,
cuotas number(2) default 0,
constraint CK_inscriptos_cuotas
check (cuotas>=0 and cuotas<=10),
primary key(numerosocio,deporte),
constraint FK_inscriptos_socio
foreign key (numerosocio)
references socios(numero)
on delete cascade
);

insert into socios values(1,'23333333','Alberto Paredes','Colon 111');


insert into socios values(2,'24444444','Carlos Conte','Sarmiento 755');
insert into socios values(3,'25555555','Fabian Fuentes','Caseros 987');
insert into socios values(4,'26666666','Hector Lopez','Sucre 344');

insert into inscriptos values(1,'tenis',1);


insert into inscriptos values(1,'basquet',2);
insert into inscriptos values(1,'natacion',1);
insert into inscriptos values(2,'tenis',9);
insert into inscriptos values(2,'natacion',1);
insert into inscriptos values(2,'basquet',default);
insert into inscriptos values(2,'futbol',2);
insert into inscriptos values(3,'tenis',8);
insert into inscriptos values(3,'basquet',9);
insert into inscriptos values(3,'natacion',0);
insert into inscriptos values(4,'basquet',10);

select numero,nombre,deporte
from socios s
join inscriptos i
on numerosocio=numero;

select nombre
from socios
join inscriptos i
on numero=numerosocio
where deporte='natacion' and
numero= any
(select numerosocio
from inscriptos i
where deporte='tenis');

select deporte
from inscriptos i
where numerosocio=1 and
deporte= any
(select deporte
from inscriptos i
where numerosocio=2);

select deporte
from inscriptos i
where numerosocio=1 and
deporte in
(select deporte
from inscriptos i
where numerosocio=2);

select i1.deporte
from inscriptos i1
join inscriptos i2
on i1.deporte=i2.deporte
where i1.numerosocio=1 and
i2.numerosocio=2;

select deporte
from inscriptos i
where numerosocio=2 and
cuotas>any
(select cuotas
from inscriptos
where numerosocio=1);

select deporte
from inscriptos i
where numerosocio=2 and
cuotas>some
(select cuotas
from inscriptos
where numerosocio=1);

select deporte
from inscriptos i
where numerosocio=2 and
cuotas>all
(select cuotas
from inscriptos
where numerosocio=1);

delete from inscriptos


where numerosocio=any
(select numerosocio
from inscriptos
where cuotas=0);

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.

76 - Subconsultas correlacionadas

Problema:

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.

Eliminamos las tablas:

drop table detalles;


drop table facturas;

Las creamos con las siguientes estructuras:

create table facturas(


numero number(5) not null,
fecha date,
cliente varchar2(30),
primary key(numero)
);

create table detalles(


numerofactura number(5) not null,
numeroitem number(3) not null,
articulo varchar2(30),
precio number(5,2),
cantidad number(4),
primary key(numerofactura,numeroitem),
constraint FK_detalles_numerofactura
foreign key (numerofactura)
references facturas(numero)
on delete cascade
);

Ingresamos algunos registros:

insert into facturas values(1200,'15/01/2007','Juan Lopez');


insert into facturas values(1201,'15/01/2007','Luis Torres');
insert into facturas values(1202,'15/01/2007','Ana Garcia');
insert into facturas values(1300,'20/01/2007','Juan Lopez');+

insert into detalles values(1200,1,'lapiz',1,100);


insert into detalles values(1200,2,'goma',0.5,150);
insert into detalles values(1201,1,'regla',1.5,80);
insert into detalles values(1201,2,'goma',0.5,200);
insert into detalles values(1201,3,'cuaderno',4,90);
insert into detalles values(1202,1,'lapiz',1,200);
insert into detalles values(1202,2,'escuadra',2,100);
insert into detalles values(1300,1,'lapiz',1,300);

Se necesita una lista de todas las facturas que incluya el nmero, la fecha, el cliente, la
cantidad de artculos comprados y el total en dinero:

select f.*,
(select count(d.numeroitem)
from detalles d
where f.numero=d.numerofactura) as cantidad,
(select sum(d.precio*cantidad)
from detalles d
where f.numero=d.numerofactura) as total
from facturas f;
76 - Subconsultas correlacionadas

Primer problema:

Un club dicta clases de distintos deportes a sus socios. El club tiene una tabla llamada
"inscriptos" en la cual almacena el nmero de "socio", el cdigo del deporte en el cual se
inscribe y la cantidad de cuotas pagas (desde 0 hasta 10 que es el total por todo el ao), y
una tabla denominada "socios" en la que guarda los datos personales de cada socio.

1- Elimine las tablas:

drop table inscriptos;


drop table socios;

2- Cree las tablas:

create table socios(


numero number(4),
documento char(8),
nombre varchar2(30),
domicilio varchar2(30),
primary key (numero)
);
create table inscriptos (
numerosocio number(4) not null,
deporte varchar(20) not null,
cuotas number(2) default 0,
constraint CK_inscriptos_cuotas
check (cuotas>=0 and cuotas<=10),
primary key(numerosocio,deporte),
constraint FK_inscriptos_socio
foreign key (numerosocio)
references socios(numero)
on delete cascade
);

3- Ingrese algunos registros:

insert into socios values(1,'23333333','Alberto Paredes','Colon 111');


insert into socios values(2,'24444444','Carlos Conte','Sarmiento 755');
insert into socios values(3,'25555555','Fabian Fuentes','Caseros 987');
insert into socios values(4,'26666666','Hector Lopez','Sucre 344');

insert into inscriptos values(1,'tenis',1);


insert into inscriptos values(1,'basquet',2);
insert into inscriptos values(1,'natacion',1);
insert into inscriptos values(2,'tenis',9);
insert into inscriptos values(2,'natacion',1);
insert into inscriptos values(2,'basquet',default);
insert into inscriptos values(2,'futbol',2);
insert into inscriptos values(3,'tenis',8);
insert into inscriptos values(3,'basquet',9);
insert into inscriptos values(3,'natacion',0);
insert into inscriptos values(4,'basquet',10);

4- Se necesita un listado de todos los socios que incluya nombre y domicilio, la cantidad de
deportes a los cuales se ha inscripto, empleando subconsulta.

5- Se necesita el nombre de todos los socios, el total de cuotas que debe pagar (10 por cada
deporte) y el total de cuotas pagas, empleando subconsulta.

6- Obtenga la misma salida anterior empleando join.

drop table inscriptos;


drop table socios;

create table socios(


numero number(4),
documento char(8),
nombre varchar2(30),
domicilio varchar2(30),
primary key (numero)
);

create table inscriptos (


numerosocio number(4) not null,
deporte varchar(20) not null,
cuotas number(2) default 0,
constraint CK_inscriptos_cuotas
check (cuotas>=0 and cuotas<=10),
primary key(numerosocio,deporte),
constraint FK_inscriptos_socio
foreign key (numerosocio)
references socios(numero)
on delete cascade
);

insert into socios values(1,'23333333','Alberto Paredes','Colon 111');


insert into socios values(2,'24444444','Carlos Conte','Sarmiento 755');
insert into socios values(3,'25555555','Fabian Fuentes','Caseros 987');
insert into socios values(4,'26666666','Hector Lopez','Sucre 344');

insert into inscriptos values(1,'tenis',1);


insert into inscriptos values(1,'basquet',2);
insert into inscriptos values(1,'natacion',1);
insert into inscriptos values(2,'tenis',9);
insert into inscriptos values(2,'natacion',1);
insert into inscriptos values(2,'basquet',default);
insert into inscriptos values(2,'futbol',2);
insert into inscriptos values(3,'tenis',8);
insert into inscriptos values(3,'basquet',9);
insert into inscriptos values(3,'natacion',0);
insert into inscriptos values(4,'basquet',10);

select nombre,domicilio,
(select count(*)
from inscriptos i
where s.numero=i.numerosocio) as deportes
from socios s;

select nombre,
(select (count(*)*10)
from inscriptos i
where s.numero=i.numerosocio) as total,
(select sum(i.cuotas)
from inscriptos i
where s.numero=i.numerosocio) as pagas
from socios s;

select nombre,
count(i.deporte)*10 as total,
sum(i.cuotas) as pagas
from socios s
join inscriptos i
on numero=numerosocio
group by nombre;

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');
77 - Exists y No Exists

Primer problema:

Un club dicta clases de distintos deportes a sus socios. El club tiene una tabla llamada
"inscriptos" en la cual almacena el nmero de "socio", el cdigo del deporte en el cual se
inscribe y la cantidad de cuotas pagas (desde 0 hasta 10 que es el total por todo el ao), y
una tabla denominada "socios" en la que guarda los datos personales de cada socio.

1- Elimine las tablas:

drop table inscriptos;


drop table socios;

2- Cree las tablas:

create table socios(


numero number(4),
documento char(8),
nombre varchar2(30),
domicilio varchar2(30),
primary key (numero)
);

create table inscriptos (


numerosocio number(4) not null,
deporte varchar2(20) not null,
cuotas number(2) default 0,
constraint CK_inscriptos_cuotas
check (cuotas>=0 and cuotas<=10),
primary key(numerosocio,deporte),
constraint FK_inscriptos_socio
foreign key (numerosocio)
references socios(numero)
on delete cascade
);

3- Ingrese algunos registros:

insert into socios values(1,'23333333','Alberto Paredes','Colon 111');


insert into socios values(2,'24444444','Carlos Conte','Sarmiento 755');
insert into socios values(3,'25555555','Fabian Fuentes','Caseros 987');
insert into socios values(4,'26666666','Hector Lopez','Sucre 344');

insert into inscriptos values(1,'tenis',1);


insert into inscriptos values(1,'basquet',2);
insert into inscriptos values(1,'natacion',1);
insert into inscriptos values(2,'tenis',9);
insert into inscriptos values(2,'natacion',1);
insert into inscriptos values(2,'basquet',default);
insert into inscriptos values(2,'futbol',2);
insert into inscriptos values(3,'tenis',8);
insert into inscriptos values(3,'basquet',9);
insert into inscriptos values(3,'natacion',0);
insert into inscriptos values(4,'basquet',10);

4- Emplee una subconsulta con el operador "exists" para devolver la lista de socios que se
inscribieron en un determinado deporte.

5- Busque los socios que NO se han inscripto en un deporte determinado empleando "not
exists".

6- Muestre todos los datos de los socios que han pagado todas las cuotas.

7- Obtenga el mismo resultado de la consulta anterior pero esta vez emplee una combinacin.

drop table inscriptos;


drop table socios;

create table socios(


numero number(4),
documento char(8),
nombre varchar2(30),
domicilio varchar2(30),
primary key (numero)
);

create table inscriptos (


numerosocio number(4) not null,
deporte varchar2(20) not null,
cuotas number(2) default 0,
constraint CK_inscriptos_cuotas
check (cuotas>=0 and cuotas<=10),
primary key(numerosocio,deporte),
constraint FK_inscriptos_socio
foreign key (numerosocio)
references socios(numero)
on delete cascade
);

insert into socios values(1,'23333333','Alberto Paredes','Colon 111');


insert into socios values(2,'24444444','Carlos Conte','Sarmiento 755');
insert into socios values(3,'25555555','Fabian Fuentes','Caseros 987');
insert into socios values(4,'26666666','Hector Lopez','Sucre 344');

insert into inscriptos values(1,'tenis',1);


insert into inscriptos values(1,'basquet',2);
insert into inscriptos values(1,'natacion',1);
insert into inscriptos values(2,'tenis',9);
insert into inscriptos values(2,'natacion',1);
insert into inscriptos values(2,'basquet',default);
insert into inscriptos values(2,'futbol',2);
insert into inscriptos values(3,'tenis',8);
insert into inscriptos values(3,'basquet',9);
insert into inscriptos values(3,'natacion',0);
insert into inscriptos values(4,'basquet',10);

select nombre
from socios s
where exists
(select *from inscriptos i
where s.numero=i.numerosocio
and i.deporte='natacion');

select nombre
from socios s
where not exists
(select *from inscriptos i
where s.numero=i.numerosocio
and i.deporte='natacion');

select s.*
from socios s
where exists
(select *from inscriptos i
where s.numero=i.numerosocio
and i.cuotas=10);

select s.* from socios s


join inscriptos i
on s.numero=i.numerosocio
where i.cuotas=10;

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".

78 - Subconsulta simil autocombinacion

Problema:

Trabajamos con la tabla "libros" de una librera.


Eliminamos la tabla y la creamos:

drop table libros;

create table libros(


codigo number(5),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(5,2)
);

Ingresamos los siguientes registros:

insert into libros values(1,'Alicia en el pais de las


maravillas','Lewis Carroll','Emece',20.00);
insert into libros values(2,'Alicia en el pais de las
maravillas','Lewis Carroll','Plaza',35.00);
insert into libros values(3,'Aprenda PHP','Mario Molina','Siglo
XXI',40.00);
insert into libros values(4,'El aleph','Borges','Emece',10.00);
insert into libros values(5,'Ilusiones','Richard
Bach','Planeta',15.00);
insert into libros values(6,'Java en 10 minutos','Mario
Molina','Siglo XXI',50.00);
insert into libros values(7,'Martin Fierro','Jose
Hernandez','Planeta',20.00);
insert into libros values(8,'Martin Fierro','Jose
Hernandez','Emece',30.00);
insert into libros values(9,'Uno','Richard Bach','Planeta',10.00);

Obtenemos la lista de los libros que han sido publicados por distintas editoriales empleando
una consulta correlacionada:

select distinct l1.titulo


from libros l1
where l1.titulo in
(select l2.titulo
from libros l2
where l1.editorial <> l2.editorial);

El siguiente "join" retorna el mismo resultado:

select distinct l1.titulo


from libros l1
join libros l2
on l1.titulo=l2.titulo
where l1.editorial<>l2.editorial;

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');

Obtenemos la misma salida empleando "join":

select l1.titulo
from libros l1
join libros l2
on l1.precio=l2.precio
where l2.titulo='El aleph' and
l1.titulo<>l2.titulo;

Buscamos los libros cuyo precio supera 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);

Obtenemos la misma salida pero empleando un "join" con "having":

select l1.titulo,l1.editorial,l1.precio
from libros l1
join libros l2
on l1.editorial=l2.editorial
group by l1.editorial, l1.titulo, l1.precio
having l1.precio > avg(l2.precio);
78 - Subconsulta simil autocombinacion

Primer problema:

Un club dicta clases de distintos deportes a sus socios. El club tiene una tabla llamada
"deportes" en la cual almacena el nombre del deporte, el nombre del profesor que lo dicta, el
da de la semana que se dicta y el costo de la cuota mensual.

1- Elimine la tabla:

drop table deportes;

2- Cree la tabla:

create table deportes(


nombre varchar2(15),
profesor varchar2(30),
dia varchar2(10),
cuota number(5,2)
);
3- Ingrese algunos registros. Incluya profesores que dicten ms de un curso:

insert into deportes values('tenis','Ana Lopez','lunes',20);


insert into deportes values('natacion','Ana Lopez','martes',15);
insert into deportes values('futbol','Carlos Fuentes','miercoles',10);
insert into deportes values('basquet','Gaston Garcia','jueves',15);
insert into deportes values('padle','Juan Huerta','lunes',15);
insert into deportes values('handball','Juan Huerta','martes',10);

4- Muestre los nombres de los profesores que dictan ms de un deporte empleando


subconsulta (2 registros)

5- Obtenga el mismo resultado empleando join

6- Buscamos todos los deportes que se dictan el mismo da que un determinado deporte
(natacion) empleando subconsulta (1 registro)

7- Obtenga la misma salida empleando "join"

drop table deportes;

create table deportes(


nombre varchar2(15),
profesor varchar2(30),
dia varchar2(10),
cuota number(5,2)
);

insert into deportes values('tenis','Ana Lopez','lunes',20);


insert into deportes values('natacion','Ana Lopez','martes',15);
insert into deportes values('futbol','Carlos Fuentes','miercoles',10);
insert into deportes values('basquet','Gaston Garcia','jueves',15);
insert into deportes values('padle','Juan Huerta','lunes',15);
insert into deportes values('handball','Juan Huerta','martes',10);

select distinct d1.profesor


from deportes d1
where d1.profesor in
(select d2.profesor
from deportes d2
where d1.nombre <> d2.nombre);

select distinct d1.profesor


from deportes d1
join deportes d2
on d1.profesor=d2.profesor
where d1.nombre<>d2.nombre;

select nombre
from deportes
where nombre<>'natacion' and
dia =
(select dia
from deportes
where nombre='natacion');

select d1.nombre
from deportes d1
join deportes d2
on d1.dia=d2.dia
where d2.nombre='natacion' and
d1.nombre<>d2.nombre;

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.

79 - Subconsulta con update y delete

Problema:

Trabajamos con las tablas "libros" y "editoriales" de una librera.


Eliminamos las tablas y las creamos:
drop table libros;
drop table editoriales;

create table editoriales(


codigo number(2),
nombre varchar2(30),
primary key (codigo)
);

create table libros (


codigo number(5),
titulo varchar2(40),
autor varchar2(30),
codigoeditorial number(2),
precio number(5,2),
primary key(codigo),
constraint FK_libros_editorial
foreign key (codigoeditorial)
references editoriales(codigo)
);

Ingresamos algunos registros:

insert into editoriales values(1,'Planeta');


insert into editoriales values(2,'Emece');
insert into editoriales values(3,'Paidos');
insert into editoriales values(4,'Siglo XXI');

insert into libros values(100,'Uno','Richard Bach',1,15);


insert into libros values(101,'Ilusiones','Richard Bach',2,20);
insert into libros values(102,'El aleph','Borges',3,10);
insert into libros values(103,'Aprenda PHP','Mario Molina',4,40);
insert into libros values(104,'Poemas','Juan Perez',1,20);
insert into libros values(105,'Cuentos','Juan Perez',3,25);
insert into libros values(106,'Java en 10 minutos','Marcelo
Perez',2,30);

Actualizamos el precio de todos los libros de editorial "Emece" incrementndolos en un 10%:

update libros set precio=precio+(precio*0.1)


where codigoeditorial=
(select codigo
from editoriales
where nombre='Emece');

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');
79 - Subconsulta con update y delete

Primer problema:
Un supermercado almacena los datos de sus empleados en una tabla denominada "empleados"
y en una tabla llamada "sucursales" los cdigos y ciudades de las diferentes sucursales.

1- Elimine las tablas "empleados" y "sucursales":

drop table empleados;


drop table sucursales;

2- Cree la tabla "sucursales":

create table sucursales(


codigo number(2),
ciudad varchar2(30) not null,
provincia varchar2(30),
primary key(codigo)
);

3- Cree la tabla "empleados":

create table empleados(


documento char(8) not null,
nombre varchar2(30) not null,
codigosucursal number(2),
sueldo number(6,2),
primary key(documento),
constraint FK_empleados_sucursal
foreign key (codigosucursal)
references sucursales(codigo)
);

4- Ingrese algunos registros para ambas tablas:

insert into sucursales values(1,'Cordoba','Cordoba');


insert into sucursales values(2,'Tucuman','Tucuman');
insert into sucursales values(3,'Carlos Paz','Cordoba');
insert into sucursales values(4,'Cruz del Eje','Cordoba');
insert into sucursales values(5,'La Plata','Buenos Aires');

insert into empleados values('22222222','Ana Acosta',1,500);


insert into empleados values('23333333','Carlos Caseros',1,610);
insert into empleados values('24444444','Diana Dominguez',2,600);
insert into empleados values('25555555','Fabiola Fuentes',5,700);
insert into empleados values('26666666','Gabriela Gonzalez',3,800);
insert into empleados values('27777777','Juan Juarez',4,850);
insert into empleados values('28888888','Luis Lopez',4,500);
insert into empleados values('29999999','Maria Morales',5,800);

5- Realice un join para mostrar el documento, nombre, sueldo, ciudad y provincia de todos
los empleados

6- El supermercado necesita incrementar en un 10% el sueldo de los empleados de la sucursal


de "Cruz del Eje". Actualice el campo "sueldo" de la tabla "empleados" de todos los empleados
de dicha sucursal empleando subconsulta.
7- El supermercado quiere incrementar en un 20% el sueldo de los empleados de las sucursales
de la provincia de Crdoba. Actualice el campo "sueldo" de la tabla "empleados" de todos los
empleados de tales sucursales empleando subconsulta.

8- La empleada "Ana Acosta" es trasladada a la sucursal de Carlos Paz. Se necesita actualizar


el sueldo y la sucursal de tal empleada empleando subconsultas, debe tener el mismo sueldo
que la empleada "Maria Morales".

9- El empleado "Carlos Caseros" se traslada a la sucursal de "La Plata". Se necesita actualizar


el sueldo y sucursal de tal empleado con los mismos valores que la empleada "Maria Morales"
(emplee subconsulta).

10- El supermercado cerrar todas las sucursales de la provincia de "Cordoba". Elimine los
empleados que pertenezcan a sucursales de tal provincia empleando subconsulta.

drop table empleados;


drop table sucursales;

create table sucursales(


codigo number(2),
ciudad varchar2(30) not null,
provincia varchar2(30),
primary key(codigo)
);

create table empleados(


documento char(8) not null,
nombre varchar2(30) not null,
codigosucursal number(2),
sueldo number(6,2),
primary key(documento),
constraint FK_empleados_sucursal
foreign key (codigosucursal)
references sucursales(codigo)
);

insert into sucursales values(1,'Cordoba','Cordoba');


insert into sucursales values(2,'Tucuman','Tucuman');
insert into sucursales values(3,'Carlos Paz','Cordoba');
insert into sucursales values(4,'Cruz del Eje','Cordoba');
insert into sucursales values(5,'La Plata','Buenos Aires');

insert into empleados values('22222222','Ana Acosta',1,500);


insert into empleados values('23333333','Carlos Caseros',1,610);
insert into empleados values('24444444','Diana Dominguez',2,600);
insert into empleados values('25555555','Fabiola Fuentes',5,700);
insert into empleados values('26666666','Gabriela Gonzalez',3,800);
insert into empleados values('27777777','Juan Juarez',4,850);
insert into empleados values('28888888','Luis Lopez',4,500);
insert into empleados values('29999999','Maria Morales',5,800);

select documento,nombre,sueldo,ciudad,provincia from empleados e


join sucursales s
on e.codigosucursal=s.codigo;
update empleados set sueldo=sueldo+sueldo*0.1
where codigosucursal=
(select codigo from sucursales
where ciudad='Cruz del Eje');

update empleados set sueldo=sueldo+sueldo*0.2


where codigosucursal in
(select codigo from sucursales
where provincia='Cordoba');

update empleados set sueldo=


(select sueldo from empleados
where nombre='Maria Morales'),
codigosucursal=
(select codigo from sucursales
where ciudad='Carlos Paz')
where nombre='Ana Acosta';

update empleados set (sueldo,codigosucursal)=


(select sueldo,codigosucursal from empleados
where nombre='Maria Morales')
where nombre='Carlos Caseros';

delete from empleados


where codigosucursal in
(select codigo
from sucursales
where provincia='Cordoba');

Segundo problema:

Un club dicta clases de distintos deportes a sus socios. El club tiene una tabla llamada
"inscriptos" en la cual almacena el nmero de "socio", el cdigo del deporte en el cual se
inscribe y si la matricula est o no paga, y una tabla denominada "socios" en la que guarda los
datos personales de cada socio.

1- Elimine las tablas:

drop table inscriptos;


drop table socios;

2- Cree las tablas:

create table socios(


numero number(5),
documento char(8),
nombre varchar2(30),
domicilio varchar2(30),
primary key (numero)
);
create table inscriptos (
numerosocio number(5) not null,
deporte varchar2(20) not null,
matricula char(1),-- 'n' o 's'
primary key(numerosocio,deporte),
constraint FK_inscriptos_socio
foreign key (numerosocio)
references socios(numero)
);

3- Ingrese algunos registros:

insert into socios values(1,'23333333','Alberto Paredes','Colon 111');


insert into socios values(2,'24444444','Carlos Conte','Sarmiento 755');
insert into socios values(3,'25555555','Fabian Fuentes','Caseros 987');
insert into socios values(4,'26666666','Hector Lopez','Sucre 344');
insert into socios values(5,'27777777','Ines Irala','Colon 888');

insert into inscriptos values(1,'tenis','s');


insert into inscriptos values(1,'basquet','s');
insert into inscriptos values(1,'natacion','s');
insert into inscriptos values(2,'tenis','s');
insert into inscriptos values(2,'natacion','s');
insert into inscriptos values(2,'basquet','n');
insert into inscriptos values(2,'futbol','n');
insert into inscriptos values(3,'tenis','s');
insert into inscriptos values(3,'basquet','s');
insert into inscriptos values(3,'natacion','n');
insert into inscriptos values(4,'basquet','n');

4- Realice una combinacin mostrando todos los datos de "socios", el deporte y la matrcula
de todos los socios (se encuentren o no en "inscriptos")

5- Actualizamos la cuota ('s') de todas las inscripciones de un socio determinado (por


documento) empleando subconsulta (3 registros)

6- Elimine todas las inscripciones de los socios que deben alguna matrcula empleando
subconsulta

drop table inscriptos;


drop table socios;

create table socios(


numero number(5),
documento char(8),
nombre varchar2(30),
domicilio varchar2(30),
primary key (numero)
);

create table inscriptos (


numerosocio number(5) not null,
deporte varchar2(20) not null,
matricula char(1),-- 'n' o 's'
primary key(numerosocio,deporte),
constraint FK_inscriptos_socio
foreign key (numerosocio)
references socios(numero)
);

insert into socios values(1,'23333333','Alberto Paredes','Colon 111');


insert into socios values(2,'24444444','Carlos Conte','Sarmiento 755');
insert into socios values(3,'25555555','Fabian Fuentes','Caseros 987');
insert into socios values(4,'26666666','Hector Lopez','Sucre 344');
insert into socios values(5,'27777777','Ines Irala','Colon 888');

insert into inscriptos values(1,'tenis','s');


insert into inscriptos values(1,'basquet','s');
insert into inscriptos values(1,'natacion','s');
insert into inscriptos values(2,'tenis','s');
insert into inscriptos values(2,'natacion','s');
insert into inscriptos values(2,'basquet','n');
insert into inscriptos values(2,'futbol','n');
insert into inscriptos values(3,'tenis','s');
insert into inscriptos values(3,'basquet','s');
insert into inscriptos values(3,'natacion','n');
insert into inscriptos values(4,'basquet','n');

select numero,documento,nombre,domicilio,deporte,matricula
from socios s
full join inscriptos i
on numerosocio=numero;

update inscriptos set matricula='s'


where numerosocio=
(select numero
from socios
where documento='25555555');

delete from inscriptos


where numerosocio in
(select numero
from socios s
join inscriptos
on numerosocio=numero
where matricula='n');

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".

80 - Subconsulta e insert

Problema:

Un profesor almacena las notas de sus alumnos en una tabla llamada "alumnos" (documento,
nombre, nota). Tiene otra tabla llamada "aprobados" (documento,nota) en la que guarda los
alumnos que han aprobado el ciclo.

Eliminamos las tablas:

drop table alumnos;


drop table aprobados;

Creamos las tablas:

create table alumnos(


documento char(8) not null,
nombre varchar2(30),
nota number(4,2)
constraint CK_alumnos_nota_valores check (nota>=0 and nota <=10),
primary key(documento)
);

create table aprobados(


documento char(8) not null,
nota number(4,2)
constraint CK_aprobados_nota_valores check (nota>=0 and nota <=10),
primary key(documento)
);

Ingresamos registros en "alumnos":

insert into alumnos values('30000000','Ana Acosta',8);


insert into alumnos values('30111111','Betina Bustos',9);
insert into alumnos values('30222222','Carlos Caseros',2.5);
insert into alumnos values('30333333','Daniel Duarte',7.7);
insert into alumnos values('30444444','Estela Esper',3.4);

Ingresamos registros en la tabla "aprobados" seleccionando registros de la tabla "alumnos":

insert into aprobados


select documento,nota
from alumnos
where nota>=4;

Note que no se listan los campos en los cuales se cargan los datos porque tienen el mismo
nombre que los de la tabla de la cual extraemos la informacin.

Veamos si los registros se han cargado:

select *from aprobados;


80 - Subconsulta e insert

Primer problema:

Un comercio que vende artculos de librera y papelera almacena la informacin de sus


ventas en una tabla llamada "facturas" y otra "clientes".

1- Elimine las tablas:

drop table facturas;


drop table clientes;

2-Crelas:

create table clientes(


codigo number(5),
nombre varchar2(30),
domicilio varchar2(30),
primary key(codigo)
);

create table facturas(


numero number(6) not null,
fecha date,
codigocliente number(5) not null,
total number(6,2),
primary key(numero),
constraint FK_facturas_cliente
foreign key (codigocliente)
references clientes(codigo)
);

3-Ingrese algunos registros:

insert into clientes values(1,'Juan Lopez','Colon 123');


insert into clientes values(2,'Luis Torres','Sucre 987');
insert into clientes values(3,'Ana Garcia','Sarmiento 576');
insert into clientes values(4,'Susana Molina','San Martin 555');
insert into facturas values(1200,'15/04/2007',1,300);
insert into facturas values(1201,'15/04/2007',2,550);
insert into facturas values(1202,'15/04/2007',3,150);
insert into facturas values(1300,'20/04/2007',1,350);
insert into facturas values(1310,'22/04/2007',3,100);

4- El comercio necesita una tabla llamada "clientespref" en la cual quiere almacenar el


nombre y domicilio de aquellos clientes que han comprado hasta el momento ms de 500
pesos en mercaderas. Elimine la tabla y crela con esos 2 campos:

drop table clientespref;


create table clientespref(
nombre varchar2(30),
domicilio varchar2(30)
);

5- Ingrese los registros en la tabla "clientespref" seleccionando registros de la tabla "clientes"


y "facturas"

6- Vea los registros de "clientespref" (2 registros)

drop table facturas;


drop table clientes;

create table clientes(


codigo number(5),
nombre varchar2(30),
domicilio varchar2(30),
primary key(codigo)
);

create table facturas(


numero number(6) not null,
fecha date,
codigocliente number(5) not null,
total number(6,2),
primary key(numero),
constraint FK_facturas_cliente
foreign key (codigocliente)
references clientes(codigo)
);

insert into clientes values(1,'Juan Lopez','Colon 123');


insert into clientes values(2,'Luis Torres','Sucre 987');
insert into clientes values(3,'Ana Garcia','Sarmiento 576');
insert into clientes values(4,'Susana Molina','San Martin 555');

insert into facturas values(1200,'15/04/2007',1,300);


insert into facturas values(1201,'15/04/2007',2,550);
insert into facturas values(1202,'15/04/2007',3,150);
insert into facturas values(1300,'20/04/2007',1,350);
insert into facturas values(1310,'22/04/2007',3,100);
drop table clientespref;
create table clientespref(
nombre varchar2(30),
domicilio varchar2(30)
);

insert into clientespref


select nombre,domicilio
from clientes
where codigo in
(select codigocliente
from clientes c
join facturas f
on codigocliente=codigo
group by codigocliente
having sum(total)>500);

select *from clientespref;

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.

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


Problema:

Tenemos la tabla "libros" de una librera y queremos crear una tabla llamada "editoriales" que
contenga los nombres de las editoriales.

Eliminamos las tablas "libros" y "editoriales":

drop table libros;


drop table editoriales;

Creamos la tabla "libros":

create table libros(


codigo number(5),
titulo varchar2(40) not null,
autor varchar2(30),
editorial varchar2(20),
precio number(5,2),
primary key(codigo)
);

Ingresamos algunos registros;

insert into libros values(1,'Uno','Richard Bach','Planeta',15);


insert into libros values(2,'El aleph','Borges','Emece',25);
insert into libros values(3,'Matematica estas ahi','Paenza','Nuevo
siglo',18);
insert into libros values(4,'Aprenda PHP','Mario Molina','Nuevo
siglo',45);
insert into libros values(5,'Ilusiones','Richard Bach','Planeta',14);
insert into libros values(6,'Java en 10 minutos','Mario
Molina','Nuevo siglo',50);

Creamos una tabla llamada "editoriales" que contenga los nombres de las editoriales
obteniendo tales nombres de la tabla "libros":

create table editoriales as


(select distinct editorial as nombre
from libros);

Veamos la nueva tabla:

select *from editoriales;

Necesitamos una nueva tabla llamada "librosporeditorial" que contenga la cantidad de libros
de cada editorial. Primero eliminamos la tabla:

drop table cantidadporeditorial;

Creamos la nueva tabla empleando una subconsulta:

create table cantidadporeditorial as


(select editorial as nombre,count(*) as cantidad
from libros
group by editorial);
Veamos los registros de la nueva tabla:

select *from cantidadporeditorial;

La tabla "cantidadporeditorial" se ha creado con el campo llamado "nombre" seleccionado del


campo "editorial" de "libros" y con el campo "cantidad" con el valor calculado con count(*) de
la tabla "libros".

Queremos una tabla llamada "ofertas20" que contenga los mismos campos que "libros" y
guarde los libros con un precio menor o igual a 20. Primero eliminamos la tabla "ofertas20":

drop table ofertas20;

Creamos "ofertas20" e insertamos la consulta de "libros":

create table ofertas20 as


(select *from libros
where precio<=20)
order by precio desc;

La consulta anterior retorna los libros de la tabla "libros" cuyo precio es menor o igual a 20 y
los almacena en la nueva tabla ("ofertas20") ordenados en forma descendente por precio.
Note que no se listan los campos a extraer, se coloca un asterisco para indicar que se incluyen
todos los campos.

Veamos los registros de la nueva tabla:

select *from ofertas20;

Agregamos una columna a la tabla "editoriales" que contiene la ciudad en la cual est la casa
central de cada editorial:

alter table editoriales add ciudad varchar2(30);

Actualizamos dicho campo:

update editoriales set ciudad='Cordoba' where nombre='Planeta';


update editoriales set ciudad='Cordoba' where nombre='Emece';
update editoriales set ciudad='Buenos Aires' where nombre='Nuevo
siglo';

Queremos una nueva tabla llamada "librosdecordoba" que contenga los ttulos y autores de los
libros de editoriales de Cordoba. En primer lugar, la eliminamos:

drop table librosdecordoba;

Consultamos las 2 tablas y guardamos el resultado en la nueva tabla que estamos creando:

create table librosdecordoba as


(select titulo,autor from libros
join editoriales
on editorial=nombre
where ciudad='Cordoba');

Consultamos la nueva tabla:


select *from librosdecordoba;
81 - Crear tabla a partir de otra (create table- select)

Primer problema:

Un supermercado almacena los datos de sus empleados en una tabla denominada "empleados"
y en una tabla llamada "sucursales" los cdigos y ciudades de las diferentes sucursales.

1- Elimine las tablas "empleados" y "sucursales":

drop table empleados;


drop table sucursales;

2- Cree la tabla "sucursales":

create table sucursales(


codigo number(4),
ciudad varchar2(30) not null,
primary key(codigo)
);

3- Cree la tabla "empleados":

create table empleados(


documento char(8) not null,
nombre varchar2(30) not null,
domicilio varchar2(30),
seccion varchar2(20),
sueldo number(6,2),
codigosucursal number(4),
primary key(documento),
constraint FK_empleados_sucursal
foreign key (codigosucursal)
references sucursales(codigo)
);

4- Ingrese algunos registros para ambas tablas:

insert into sucursales values(1,'Cordoba');


insert into sucursales values(2,'Villa Maria');
insert into sucursales values(3,'Carlos Paz');
insert into sucursales values(4,'Cruz del Eje');

insert into empleados values('22222222','Ana Acosta','Avellaneda


111','Secretaria',500,1);
insert into empleados values('23333333','Carlos Caseros','Colon
222','Sistemas',800,1);
insert into empleados values('24444444','Diana Dominguez','Dinamarca
333','Secretaria',550,2);
insert into empleados values('25555555','Fabiola Fuentes','Francia
444','Sistemas',750,2);
insert into empleados values('26666666','Gabriela Gonzalez','Guemes
555','Secretaria',580,3);
insert into empleados values('27777777','Juan Juarez','Jujuy
777','Secretaria',500,4);
insert into empleados values('28888888','Luis Lopez','Lules 888','Sistemas',780,4);
insert into empleados values('29999999','Maria Morales','Marina
999','Contaduria',670,4);

5- Realice un join para mostrar todos los datos de "empleados" incluyendo la ciudad de la
sucursal

6-Cree una tabla llamada "secciones" que contenga las secciones de la empresa (primero
elimnela)

drop table secciones;

create table secciones as


(select distinct seccion as nombre
from empleados);

7- Recupere la informacin de "secciones"

8- Se necesita una nueva tabla llamada "sueldosxseccion" que contenga la suma de los sueldos
de los empleados por seccin (de todas las sucursales). Primero elimine la tabla

drop table sueldosxseccion;

create table sueldosxseccion as


(select seccion, sum(sueldo) as total
from empleados
group by seccion);

9- Recupere los registros de la nueva tabla

10- Se necesita una nueva tabla llamada "sucursalCordoba" que contenga los nombres y
seccin de los empleados de la ciudad de Crdoba. En primer lugar, eliminamos la tabla.
Luego, consulte las tablas "empleados" y "sucursales" y guarde el resultado en la nueva tabla

11- Consulte la nueva tabla

drop table empleados;


drop table sucursales;

create table sucursales(


codigo number(4),
ciudad varchar2(30) not null,
primary key(codigo)
);

create table empleados(


documento char(8) not null,
nombre varchar2(30) not null,
domicilio varchar2(30),
seccion varchar2(20),
sueldo number(6,2),
codigosucursal number(4),
primary key(documento),
constraint FK_empleados_sucursal
foreign key (codigosucursal)
references sucursales(codigo)
);

insert into sucursales values(1,'Cordoba');


insert into sucursales values(2,'Villa Maria');
insert into sucursales values(3,'Carlos Paz');
insert into sucursales values(4,'Cruz del Eje');

insert into empleados values('22222222','Ana Acosta','Avellaneda


111','Secretaria',500,1);
insert into empleados values('23333333','Carlos Caseros','Colon
222','Sistemas',800,1);
insert into empleados values('24444444','Diana Dominguez','Dinamarca
333','Secretaria',550,2);
insert into empleados values('25555555','Fabiola Fuentes','Francia
444','Sistemas',750,2);
insert into empleados values('26666666','Gabriela Gonzalez','Guemes
555','Secretaria',580,3);
insert into empleados values('27777777','Juan Juarez','Jujuy
777','Secretaria',500,4);
insert into empleados values('28888888','Luis Lopez','Lules 888','Sistemas',780,4);
insert into empleados values('29999999','Maria Morales','Marina
999','Contaduria',670,4);

select documento,nombre,domicilio,seccion,sueldo,ciudad
from empleados
join sucursales
on codigosucursal=codigo;

drop table secciones;

create table secciones as


(select distinct seccion as nombre
from empleados);

select *from secciones;

drop table sueldosxseccion;

create table sueldosxseccion as


(select seccion, sum(sueldo) as total
from empleados
group by seccion);

select *from sueldosxseccion;

drop table sucursalCordoba;

create table sucursalCordoba as


(select nombre,ciudad
from empleados
join sucursales
on codigosucursal=codigo
where ciudad='Cordoba');
select *from sucursalCordoba;

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.


82 - Vistas (create view)

Problema:

Una empresa almacena la informacin de sus empleados en dos tablas llamadas "empleados" y
"secciones".

Eliminamos las tablas:

drop table empleados;


drop table secciones;

Creamos las tablas:

create table secciones(


codigo number(2),
nombre varchar2(20),
sueldo number(5,2)
constraint CK_secciones_sueldo check (sueldo>=0),
constraint PK_secciones primary key (codigo)
);

create table empleados(


legajo number(5),
documento char(8),
sexo char(1)
constraint CK_empleados_sexo check (sexo in ('f','m')),
apellido varchar2(20),
nombre varchar2(20),
domicilio varchar2(30),
seccion number(2) not null,
cantidadhijos number(2)
constraint CK_empleados_hijos check (cantidadhijos>=0),
estadocivil char(10)
constraint CK_empleados_estadocivil check (estadocivil in
('casado','divorciado','soltero','viudo')),
fechaingreso date,
constraint PK_empleados primary key (legajo),
constraint FK_empleados_seccion
foreign key (seccion)
references secciones(codigo),
constraint UQ_empleados_documento
unique(documento)
);

Ingresamos algunos registros:

insert into secciones values(1,'Administracion',300);


insert into secciones values(2,'Contadura',400);
insert into secciones values(3,'Sistemas',500);

insert into empleados values(100,'22222222','f','Lopez','Ana','Colon


123',1,2,'casado','10/10/1990');
insert into empleados values(102,'23333333','m','Lopez','Luis','Sucre
235',1,0,'soltero','02/10/1990');
insert into empleados
values(103,'24444444','m','Garcia','Marcos','Sarmiento
1234',2,3,'divorciado','12/07/1998');
insert into empleados
values(104,'25555555','m','Gomez','Pablo','Bulnes
321',3,2,'casado','10/09/1998');
insert into empleados values(105,'26666666','f','Perez','Laura','Peru
1254',3,3,'casado','05/09/2000');

Eliminamos la vista "vista_empleados". An no hemos aprendido a eliminar vistas, lo veremos


prximamente:

drop view vista_empleados;

Creamos la vista "vista_empleados", que es resultado de una combinacin en la cual se


muestran 5 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;

Vemos la informacin de la vista:

select *from vista_empleados;

Realizamos una consulta a la vista como si se tratara de una tabla:

select seccion,count(*) as cantidad


from vista_empleados
group by seccion;

Eliminamos la vista "vista_empleados_ingreso":

drop view vista_empleados_ingreso;

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);

Vemos la informacin:

select *from vista_empleados_ingreso;

Hemos aprendido que los registros resultantes de una vista no se almacena en la base de
datos, sino la definicin de la vista, por lo tanto, al modificar las tablas referenciadas por la
vista, el resultado de la vista cambia.

Modificamos una fecha en la tabla "empleados" y luego consultamos la vista para verificar que
est actualizada:
update empleados set fechaingreso='10/09/2000' where
fechaingreso='10/09/1998';

select *from vista_empleados_ingreso;


82 - Vistas (create view)

Primer problema:

Un club dicta cursos de distintos deportes. Almacena la informacin en varias tablas. El


director no quiere que los empleados de administracin conozcan la estructura de las tablas
ni algunos datos de los profesores y socios, por ello se crean vistas a las cuales tendrn
acceso.

1- Elimine las tablas y crelas nuevamente:

drop table inscriptos;


drop table cursos;
drop table socios;
drop table profesores;

create table socios(


documento char(8) not null,
nombre varchar2(40),
domicilio varchar2(30),
primary key (documento)
);

create table profesores(


documento char(8) not null,
nombre varchar2(40),
domicilio varchar2(30),
primary key (documento)
);

create table cursos(


numero number(2),
deporte varchar2(20),
dia varchar2(15),
documentoprofesor char(8),
constraint CK_inscriptos_dia
check (dia in('lunes','martes','miercoles','jueves','viernes','sabado')),
constraint FK_documentoprofesor
foreign key (documentoprofesor)
references profesores(documento),
primary key (numero)
);

create table inscriptos(


documentosocio char(8) not null,
numero number(2) not null,
matricula char(1),
constraint CK_inscriptos_matricula check (matricula in('s','n')),
constraint FK_documentosocio
foreign key (documentosocio)
references socios(documento),
constraint FK_numerocurso
foreign key (numero)
references cursos(numero),
primary key (documentosocio,numero)
);

2- Ingrese algunos registros para todas las tablas:

insert into socios values('30000000','Fabian Fuentes','Caseros 987');


insert into socios values('31111111','Gaston Garcia','Guemes 65');
insert into socios values('32222222','Hector Huerta','Sucre 534');
insert into socios values('33333333','Ines Irala','Bulnes 345');

insert into profesores values('22222222','Ana Acosta','Avellaneda 231');


insert into profesores values('23333333','Carlos Caseres','Colon 245');
insert into profesores values('24444444','Daniel Duarte','Sarmiento 987');
insert into profesores values('25555555','Esteban Lopez','Sucre 1204');

insert into cursos values(1,'tenis','lunes','22222222');


insert into cursos values(2,'tenis','martes','22222222');
insert into cursos values(3,'natacion','miercoles','22222222');
insert into cursos values(4,'natacion','jueves','23333333');
insert into cursos values(5,'natacion','viernes','23333333');
insert into cursos values(6,'futbol','sabado','24444444');
insert into cursos values(7,'futbol','lunes','24444444');
insert into cursos values(8,'basquet','martes','24444444');

insert into inscriptos values('30000000',1,'s');


insert into inscriptos values('30000000',3,'n');
insert into inscriptos values('30000000',6,null);
insert into inscriptos values('31111111',1,'s');
insert into inscriptos values('31111111',4,'s');
insert into inscriptos values('32222222',8,'s');

3- Elimine la vista "vista_club":

drop view vista_club;

4- Cree una vista en la que aparezca el nombre del socio, el deporte, el da, el nombre del
profesor y el estado de la matrcula (deben incluirse los socios que no estn inscriptos en
ningn deporte, los cursos para los cuales no hay inscriptos y los profesores que no tienen
designado deporte tambin)

5- Muestre la informacin contenida en la vista (11 registros)

6- Realice una consulta a la vista donde muestre la cantidad de socios inscriptos en cada
deporte (agrupe por deporte y da) ordenados por cantidad

7- Muestre (consultando la vista) los cursos (deporte y da) para los cuales no hay inscriptos (3
registros)

8- Muestre los nombres de los socios que no se han inscripto en ningn curso (consultando la
vista) (1 registro)

9- Muestre (consultando la vista) los profesores que no tienen asignado ningn deporte an (1
registro)
10- Muestre (consultando la vista) el nombre de los socios que deben matrculas (1 registro)

11- Consulte la vista y muestre los nombres de los profesores y los das en que asisten al club
para dictar sus clases (9 registros)

12- Muestre la misma informacin anterior pero ordenada por da

13- Muestre todos los socios que son compaeros en tenis los lunes (2 registros)

14- Intente crear una vista denominada "vista_inscriptos" que muestre la cantidad de
inscriptos por curso, incluyendo el nmero del curso, el nombre del deporte y el da

15- Elimine la vista "vista_inscriptos" y crela para que muestre la cantidad de inscriptos por
curso, incluyendo el nmero del curso, el nombre del deporte y el da

16- Consulte la vista (9 registros)

drop table inscriptos;


drop table cursos;
drop table socios;
drop table profesores;

create table socios(


documento char(8) not null,
nombre varchar2(40),
domicilio varchar2(30),
primary key (documento)
);

create table profesores(


documento char(8) not null,
nombre varchar2(40),
domicilio varchar2(30),
primary key (documento)
);

create table cursos(


numero number(2),
deporte varchar2(20),
dia varchar2(15),
documentoprofesor char(8),
constraint CK_inscriptos_dia
check (dia in('lunes','martes','miercoles','jueves','viernes','sabado')),
constraint FK_documentoprofesor
foreign key (documentoprofesor)
references profesores(documento),
primary key (numero)
);

create table inscriptos(


documentosocio char(8) not null,
numero number(2) not null,
matricula char(1),
constraint CK_inscriptos_matricula check (matricula in('s','n')),
constraint FK_documentosocio
foreign key (documentosocio)
references socios(documento),
constraint FK_numerocurso
foreign key (numero)
references cursos(numero),
primary key (documentosocio,numero)
);

insert into socios values('30000000','Fabian Fuentes','Caseros 987');


insert into socios values('31111111','Gaston Garcia','Guemes 65');
insert into socios values('32222222','Hector Huerta','Sucre 534');
insert into socios values('33333333','Ines Irala','Bulnes 345');

insert into profesores values('22222222','Ana Acosta','Avellaneda 231');


insert into profesores values('23333333','Carlos Caseres','Colon 245');
insert into profesores values('24444444','Daniel Duarte','Sarmiento 987');
insert into profesores values('25555555','Esteban Lopez','Sucre 1204');

insert into cursos values(1,'tenis','lunes','22222222');


insert into cursos values(2,'tenis','martes','22222222');
insert into cursos values(3,'natacion','miercoles','22222222');
insert into cursos values(4,'natacion','jueves','23333333');
insert into cursos values(5,'natacion','viernes','23333333');
insert into cursos values(6,'futbol','sabado','24444444');
insert into cursos values(7,'futbol','lunes','24444444');
insert into cursos values(8,'basquet','martes','24444444');

insert into inscriptos values('30000000',1,'s');


insert into inscriptos values('30000000',3,'n');
insert into inscriptos values('30000000',6,null);
insert into inscriptos values('31111111',1,'s');
insert into inscriptos values('31111111',4,'s');
insert into inscriptos values('32222222',8,'s');

drop view vista_club;

create view vista_club as


select s.nombre as socio,c.deporte,dia,
p.nombre as profesor, matricula
from socios s
full join inscriptos i
on s.documento=i.documentosocio
full join cursos c
on i.numero=c.numero
full join profesores p
on c.documentoprofesor=p.documento;

select *from vista_club;

select deporte,dia,count(socio) as cantidad


from vista_club
where deporte is not null
group by deporte,dia
order by cantidad;
select deporte,dia from vista_club
where socio is null and deporte is not null;

select socio from vista_club


where deporte is null and socio is not null;

select profesor from vista_club where deporte is null and profesor is not null;

select socio from vista_club where deporte is not null and matricula <> 's';

select distinct profesor,dia


from vista_club where profesor is not null;

select distinct profesor,dia


from vista_club where profesor is not null
order by dia;

select socio from vista_club


where deporte='tenis' and dia='lunes';

create view vista_inscriptos as


select deporte,dia,
(select count(*)
from inscriptos i
where i.numero=c.numero) as cantidad
from cursos c;

drop view vista_inscriptos;

create view vista_inscriptos as


select deporte,dia,
(select count(*)
from inscriptos i
where i.numero=c.numero) as cantidad
from cursos c;

select *from vista_inscriptos;

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.

84 - Vistas eliminar (drop view)

Problema:

Una empresa almacena la informacin de sus empleados en dos tablas llamadas "empleados" y
"secciones".

Eliminamos las tablas:

drop table empleados;


drop table secciones;

Creamos las tablas:

create table secciones(


codigo number(2),
nombre varchar2(20),
sueldo number(5,2),
constraint CK_secciones_sueldo check (sueldo>=0),
constraint PK_secciones primary key (codigo)
);

create table empleados(


legajo number(3),
documento char(8),
sexo char(1),
constraint CK_empleados_sexo check (sexo in ('f','m')),
apellido varchar2(20),
nombre varchar2(20),
domicilio varchar2(30),
seccion number(2) not null,
cantidadhijos number(2),
constraint CK_empleados_hijos check (cantidadhijos>=0),
estadocivil char(10),
constraint CK_empleados_estadocivil check (estadocivil in
('casado','divorciado','soltero','viudo')),
fechaingreso date,
constraint PK_empleados primary key (legajo),
constraint FK_empleados_seccion
foreign key (seccion)
references secciones(codigo),
constraint UQ_empleados_documento
unique(documento)
);

Ingresamos algunos registros:

insert into secciones values(1,'Administracion',300);


insert into secciones values(2,'Contadura',400);
insert into secciones values(3,'Sistemas',500);

insert into empleados values(100,'22222222','f','Lopez','Ana','Colon


123',1,2,'casado','10/10/1990');
insert into empleados values(101,'23333333','m','Lopez','Luis','Sucre
235',1,0,'soltero','02/10/1990');
insert into empleados
values(102,'24444444','m','Garcia','Marcos','Sarmiento
1234',2,3,'divorciado','07/12/1998');
insert into empleados
values(103,'25555555','m','Gomez','Pablo','Bulnes
321',3,2,'casado','10/09/1998');
insert into empleados values(104,'26666666','f','Perez','Laura','Peru
1254',3,3,'casado','05/09/2000');

Eliminamos la vista "vista_empleados":

drop view vista_empleados;

Creamos la vista "vista_empleados", que es resultado de una combinacin en la cual se


muestran 5 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;

Veamos la informacin de la vista:

select *from vista_empleados;

Eliminamos la tabla "empleados":

drop table empleados;


Verificamos que la vista an existe consultando "user_objects":

select *from user_objects where object_name='VISTA_EMPLEADOS';

Verificamos que la vista "vista_empleados" an existe consultando "user_catalog":

select *from user_catalog where table_type='VIEW';

Si consultamos la vista, aparecer un mensaje de error, pues la tabla "empleados" a la cual


hace referencia la vista, no existe:

select *from vista_empleados;

Eliminamos la vista:

drop view vista_empleados;

Verificamos que la vista ya no existe:

select *from user_catalog where table_name='VISTA_EMPLEADOS';


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.

85 - Vistas (modificar datos a travs de ella)

Problema:

Una empresa almacena la informacin de sus empleados en dos tablas llamadas "empleados" y
"secciones".

Eliminamos las tablas:

drop table empleados;


drop table secciones;

Creamos las tablas:


create table secciones(
codigo number(2),
nombre varchar2(20),
constraint PK_secciones primary key (codigo)
);

create table empleados(


legajo number(4) not null,
documento char(8),
sexo char(1),
constraint CK_empleados_sexo check (sexo in ('f','m')),
apellido varchar2(20),
nombre varchar2(20),
domicilio varchar2(30),
seccion number(2) not null,
cantidadhijos number(2),
constraint CK_empleados_hijos check (cantidadhijos>=0),
estadocivil char(10),
constraint CK_empleados_estadocivil check (estadocivil in
('casado','divorciado','soltero','viudo')),
fechaingreso date,
constraint PK_empleados primary key (legajo),
sueldo number(6,2),
constraint CK_empleados_sueldo check (sueldo>=0),
constraint FK_empleados_seccion
foreign key (seccion)
references secciones(codigo),
constraint UQ_empleados_documento
unique(documento)
);

Ingresamos algunos registros:

insert into secciones values(1,'Administracion');


insert into secciones values(2,'Contadura');
insert into secciones values(3,'Sistemas');

insert into empleados values(100,'22222222','f','Lopez','Ana','Colon


123',1,2,'casado','10/10/1990',600);
insert into empleados values(101,'23333333','m','Lopez','Luis','Sucre
235',1,0,'soltero','02/10/1990',650);
insert into empleados values(103,'24444444', 'm', 'Garcia', 'Marcos',
'Sarmiento 1234', 2, 3, 'divorciado', '07/12/1998',800);
insert into empleados
values(104,'25555555','m','Gomez','Pablo','Bulnes
321',3,2,'casado','10/09/1998',900);
insert into empleados values(105,'26666666','f','Perez','Laura','Peru
1254',3,3,'casado','05/09/2000',700);

Eliminamos la vista "vista_empleados":

drop view vista_empleados;

Creamos la vista "vista_empleados", que es resultado de una combinacin en la cual se


muestran 5 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;

Vemos la informacin contenida en la vista:

select *from vista_empleados;

Eliminamos la vista "vista_empleados2":

drop view vista_empleados2;

Creamos otra vista de "empleados" denominada "vista_empleados2" que consulta solamente la


tabla "empleados":

create view vista_empleados2


as
select legajo,nombre,apellido,fechaingreso,seccion,sueldo
from empleados
where sueldo>=600;

Consultamos la vista:

select *from vista_empleados2;

No podemos ingresar un registro en la vista "vista_empleados" porque tal vista tiene campos
calculados ("nombre", que es una concatenacin de "apellido" y "nombre"), adems afecta a 2
tablas ("empleados" y "secciones") y hay campos no accesibles desde la vista que no admiten
valores nulos. Si ejecutamos el siguiente "insert", Oracle mostrar un mensaje de error:

insert into vista_empleados values('Pedro Perez','m','Sistemas',2);

Podemos ingresar un registro en la vista "vista_empleados2" porque tal vista afecta a una sola
tabla y los campos de ""empleados" no accesibles desde la vista admiten valores nulos:

insert into vista_empleados2


values(200,'Pedro','Perez','10/10/2000',2,800);

Vemos la tabla "empleados" para comprobar que el nuevo registro insertado desde la vista
est presente en "empleados", los campos para los cuales no se ingresaron datos, almacenan
el valor "null":

select *from empleados;

Actualizamos el campo "nombre" de un registro de la vista "vista_empleados2":

update vista_empleados2 set nombre='Beatriz' where nombre='Ana';

Verificamos que se actualiz la tabla:

select *from empleados;

Si intentamos actualizar el campo "nombre" de un empleado a travs de la vista


"vista_empleados", Oracle no lo permite porque es una columna calculada (concatenacin de
dos campos):
update vista_empleados set nombre='Lopez Carmen' where nombre='Lopez
Beatriz';

Si podemos actualizar otros campos, por ejemplo, el campo "cantidadhijos" de un empleado a


travs de la vista "vista_empleados":

update vista_empleados set cantidadhijos=3 where nombre='Lopez


Beatriz';

Verificamos que se actualiz la tabla:

select *from empleados;

Eliminamos un registro de "empleados" a travs de la vista "vista_empleados2":

delete from vista_empleados2 where apellido='Lopez' and


nombre='Beatriz';

Verificamos que se elimin tal registro de la tabla "empleados":

select *from empleados;

Podemos eliminar registros de empleados a travs de la vista "vista_empleados":

delete from vista_empleados where seccion='Administracion';

Verificamos que no hay registros en "empleados" de la seccin "1" ("Administracion"):

select *from empleados;


85 - Vistas (modificar datos a travs de ella)

Primer problema:

Un club dicta cursos de distintos deportes. Almacena la informacin en varias tablas.

1- Elimine las tabla "inscriptos", "socios" y "cursos":

drop table inscriptos;


drop table socios;
drop table cursos;

2- Cree las tablas:

create table socios(


documento char(8) not null,
nombre varchar2(40),
domicilio varchar2(30),
constraint PK_socios_documento
primary key (documento)
);

create table cursos(


numero number(2),
deporte varchar2(20),
dia varchar2(15),
constraint CK_inscriptos_dia check (dia
in('lunes','martes','miercoles','jueves','viernes','sabado')),
profesor varchar2(20),
constraint PK_cursos_numero
primary key (numero)
);

create table inscriptos(


documentosocio char(8) not null,
numero number(2) not null,
matricula char(1),
constraint PK_inscriptos_documento_numero
primary key (documentosocio,numero),
constraint FK_inscriptos_documento
foreign key (documentosocio)
references socios(documento),
constraint FK_inscriptos_numero
foreign key (numero)
references cursos(numero)
);

3- Ingrese algunos registros para todas las tablas:

insert into socios values('30000000','Fabian Fuentes','Caseros 987');


insert into socios values('31111111','Gaston Garcia','Guemes 65');
insert into socios values('32222222','Hector Huerta','Sucre 534');
insert into socios values('33333333','Ines Irala','Bulnes 345');

insert into cursos values(1,'tenis','lunes','Ana Acosta');


insert into cursos values(2,'tenis','martes','Ana Acosta');
insert into cursos values(3,'natacion','miercoles','Ana Acosta');
insert into cursos values(4,'natacion','jueves','Carlos Caseres');
insert into cursos values(5,'futbol','sabado','Pedro Perez');
insert into cursos values(6,'futbol','lunes','Pedro Perez');
insert into cursos values(7,'basquet','viernes','Pedro Perez');

insert into inscriptos values('30000000',1,'s');


insert into inscriptos values('30000000',3,'n');
insert into inscriptos values('30000000',6,null);
insert into inscriptos values('31111111',1,'s');
insert into inscriptos values('31111111',4,'s');
insert into inscriptos values('32222222',1,'s');
insert into inscriptos values('32222222',7,'s');

4- Realice un join para mostrar todos los datos de todas las tablas, sin repetirlos (7 registros)

5- Elimine la vista "vista_cursos"

6- Cree la vista "vista_cursos" que muestre el nmero, deporte y da de todos los cursos.

7- Consulte la vista ordenada por deporte (7 registros)

8- Ingrese un registro mediante la vista "vista_cursos" y vea si afect a "cursos"

9- Actualice un registro sobre la vista y vea si afect a la tabla "cursos"


10- Elimine un registro de la vista para el cual no haya inscriptos y vea si afect a "cursos"

11- Intente eliminar un registro de la vista para el cual haya inscriptos

12- Elimine la vista "vista_inscriptos" y crela para que muestre el documento y nombre del
socio, el numero de curso, el deporte y da de los cursos en los cuales est inscripto

13- Intente ingresar un registro en la vista:

insert into vista_inscriptos values('32222222','Hector Huerta',6,'futbol','lunes');

No lo permite porque la modificacin afecta a ms de una tabla base.

14- Intente actualizar el documento de un socio (no lo permite)

15- Elimine un registro mediante la vista

16- Verifique que el registro se ha eliminado de "inscriptos"

drop table inscriptos;


drop table socios;
drop table cursos;

create table socios(


documento char(8) not null,
nombre varchar2(40),
domicilio varchar2(30),
constraint PK_socios_documento
primary key (documento)
);

create table cursos(


numero number(2),
deporte varchar2(20),
dia varchar2(15),
constraint CK_inscriptos_dia check (dia
in('lunes','martes','miercoles','jueves','viernes','sabado')),
profesor varchar2(20),
constraint PK_cursos_numero
primary key (numero)
);

create table inscriptos(


documentosocio char(8) not null,
numero number(2) not null,
matricula char(1),
constraint PK_inscriptos_documento_numero
primary key (documentosocio,numero),
constraint FK_inscriptos_documento
foreign key (documentosocio)
references socios(documento),
constraint FK_inscriptos_numero
foreign key (numero)
references cursos(numero)
);

insert into socios values('30000000','Fabian Fuentes','Caseros 987');


insert into socios values('31111111','Gaston Garcia','Guemes 65');
insert into socios values('32222222','Hector Huerta','Sucre 534');
insert into socios values('33333333','Ines Irala','Bulnes 345');

insert into cursos values(1,'tenis','lunes','Ana Acosta');


insert into cursos values(2,'tenis','martes','Ana Acosta');
insert into cursos values(3,'natacion','miercoles','Ana Acosta');
insert into cursos values(4,'natacion','jueves','Carlos Caseres');
insert into cursos values(5,'futbol','sabado','Pedro Perez');
insert into cursos values(6,'futbol','lunes','Pedro Perez');
insert into cursos values(7,'basquet','viernes','Pedro Perez');

insert into inscriptos values('30000000',1,'s');


insert into inscriptos values('30000000',3,'n');
insert into inscriptos values('30000000',6,null);
insert into inscriptos values('31111111',1,'s');
insert into inscriptos values('31111111',4,'s');
insert into inscriptos values('32222222',1,'s');
insert into inscriptos values('32222222',7,'s');

select documento,nombre,domicilio,c.numero,deporte,dia, profesor,matricula


from socios s
join inscriptos i
on s.documento=documentosocio
join cursos c
on c.numero=i.numero;

drop view vista_cursos;

create view vista_cursos


as
select numero,deporte,dia
from cursos;

select *from vista_cursos order by deporte;

insert into vista_cursos values(8,'futbol','martes');


select *from cursos;

update vista_cursos set dia='miercoles' where numero=8;


select *from cursos;

delete from vista_cursos where numero=8;


select *from cursos;

delete from vista_cursos where numero=1;

drop view vista_inscriptos;


create view vista_inscriptos
as
select i.documentosocio,s.nombre,i.numero,c.deporte,dia
from inscriptos i
join socios s
on s.documento=documentosocio
join cursos c
on c.numero=i.numero;

insert into vista_inscriptos values('32222222','Hector Huerta',6,'futbol','lunes');

update vista_inscriptos set documentosocio='30000111' where


documentosocio='30000000';

delete from vista_inscriptos where documentosocio='30000000' and


deporte='tenis';

select *from inscriptos;

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.

86 - Vistas (with read only)

Problema:

Una empresa almacena la informacin de sus empleados en una tabla llamada "empleados".

Eliminamos la tabla:

drop table empleados;

Creamos las tablas:


create table empleados(
documento char(8),
sexo char(1)
constraint CK_empleados_sexo check (sexo in ('f','m')),
apellido varchar2(20),
nombre varchar2(20),
domicilio varchar2(30),
seccion varchar2(30),
cantidadhijos number(2),
constraint CK_empleados_hijos check (cantidadhijos>=0),
estadocivil char(10)
constraint CK_empleados_estadocivil check (estadocivil in
('casado','divorciado','soltero','viudo')),
fechaingreso date
);

Ingresamos algunos registros:

insert into empleados values('22222222','f','Lopez','Ana','Colon


123','Administracion',2,'casado','10/10/1990');
insert into empleados values('23333333','m','Lopez','Luis','Sucre
235','Administracion',0,'soltero','02/10/1990');
insert into empleados
values('24444444','m','Garcia','Marcos','Sarmiento
1234','Contaduria',3,'divorciado','07/12/1998');
insert into empleados values('25555555','m','Gomez','Pablo','Bulnes
321','Contaduria',2,'casado','10/09/1998');
insert into empleados values('26666666','f','Perez','Laura','Peru
1254','Sistemas',3,'casado','05/09/2000');

Eliminamos las vistas "vista_empleados" y "vista_empleados2":

drop view vista_empleados;


drop view vista_empleados2;

Creamos la vista "vista_empleados", que muestra solamente algunos campos de "empleados":

create view vista_empleados


as
select apellido, nombre, sexo, seccion
from empleados;

Creamos la vista "vista_empleados2", igual que "vista_empleados", pero ahora colocamos "with
read only" para impedir que puedan ejecutarse "insert", "update" y "delete" sobre esta vista:

create view vista_empleados2


as
select apellido, nombre, sexo, seccion
from empleados
with read only;

Actualizamos el nombre de un empleado a travs de la vista "vista_empleados":

update vista_empleados set nombre='Beatriz' where nombre='Ana';

Veamos si la modificacin se realiz en la tabla:

select *from empleados;


Intentamos actualizar el nombre de un empleado a travs de la vista "vista_empleados2":

update vista_empleados2 set nombre='Pedro' where nombre='Marcos';

No lo permite.

Ingresamos un registro en la tabla "empleados" a travs de la vista "vista_empleados":

insert into vista_empleados values('Juarez','Juan','m','Sistemas');

Oracle acepta la insercin. Verificamos que la insercin se realiz en la tabla:

select *from empleados;

Intentamos ingresar un registro a travs de la vista "vista_empleados2":

insert into vista_empleados2


values('Gimenez','Julieta','f','Sistemas');

Oracle no lo permite porque la vista fue definida con "with read only".

Eliminamos un registro en la tabla "empleados" a travs de la vista "vista_empleados":

delete from vista_empleados where apellido='Juarez';

Oracle acepta la eliminacin. Verificamos que la eliminacin se realiz en la tabla:

select *from empleados;

Intentamos eliminar registros a travs de la vista "vista_empleados2":

delete from vista_empleados2 where apellido='Lopez';

Oracle no lo permite porque la vista fue definida con "with read only".

86 - Vistas (with read only)

Primer problema:

Una empresa almacena la informacin de sus clientes en una tabla llamada "clientes".

1- Elimine la tabla:

drop table clientes;

2- Cree la tabla:

create table clientes(


nombre varchar2(40),
documento char(8),
domicilio varchar2(30),
ciudad varchar2(30)
);
3- Ingrese algunos registros:

insert into clientes values('Juan Perez','22222222','Colon 1123','Cordoba');


insert into clientes values('Karina Lopez','23333333','San Martin 254','Cordoba');
insert into clientes values('Luis Garcia','24444444','Caseros 345','Cordoba');
insert into clientes values('Marcos Gonzalez','25555555','Sucre 458','Santa Fe');
insert into clientes values('Nora Torres','26666666','Bulnes 567','Santa Fe');
insert into clientes values('Oscar Luque','27777777','San Martin 786','Santa Fe');
insert into clientes values('Pedro Perez','28888888','Colon 234','Buenos Aires');
insert into clientes values('Rosa Rodriguez','29999999','Avellaneda 23','Buenos
Aires');

4- Cree o reemplace la vista "vista_clientes" para que recupere el nombre y ciudad de todos
los clientes

5- Cree o reemplace la vista "vista_clientes2" para que recupere el nombre y ciudad de todos
los clientes no permita modificaciones.

6- Consulte ambas vistas

7- Intente ingresar el siguiente registro mediante la vista que permite slo lectura
Oracle no lo permite.

8- Ingrese el registro anterior en la vista "vista_clientes"

9- Intente modificar un registro mediante la vista que permite slo lectura

10- Actualice el registro anterior en la vista "vista_clientes"

11- Intente eliminar un registro mediante la vista "vista_clientes2"

12- Elimine todos los clientes de "Buenos Aires" a travs de la vista "vista_clientes"

drop table clientes;

create table clientes(


nombre varchar2(40),
documento char(8),
domicilio varchar2(30),
ciudad varchar2(30)
);

insert into clientes values('Juan Perez','22222222','Colon 1123','Cordoba');


insert into clientes values('Karina Lopez','23333333','San Martin 254','Cordoba');
insert into clientes values('Luis Garcia','24444444','Caseros 345','Cordoba');
insert into clientes values('Marcos Gonzalez','25555555','Sucre 458','Santa Fe');
insert into clientes values('Nora Torres','26666666','Bulnes 567','Santa Fe');
insert into clientes values('Oscar Luque','27777777','San Martin 786','Santa Fe');
insert into clientes values('Pedro Perez','28888888','Colon 234','Buenos Aires');
insert into clientes values('Rosa Rodriguez','29999999','Avellaneda 23','Buenos
Aires');

create or replace view vista_clientes


as
select nombre, ciudad
from clientes;

create or replace view vista_clientes2


as
select nombre, ciudad
from clientes
with read only;

select *from vista_clientes;


select *from vista_clientes2;

insert into vista_clientes2 values ('Ana Acosta','Salta');

insert into vista_clientes values ('Ana Acosta','Salta');

update vista_clientes2 set ciudad='Salta' where nombre='Juan Perez';

update vista_clientes set ciudad='Salta' where nombre='Juan Perez';

delete from vista_clientes2 where ciudad='Buenos Aires';

delete from vista_clientes where ciudad='Buenos Aires';

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.

87 - Vistas modificar (create or replace view)

Problema:

Una empresa almacena la informacin de sus empleados en dos tablas llamadas "empleados" y
"secciones".

Eliminamos las tablas:

drop table empleados;


drop table secciones;

Creamos las tablas:

create table secciones(


codigo number(2),
nombre varchar2(20),
constraint PK_secciones primary key (codigo)
);

create table empleados(


documento char(8),
nombre varchar2(30),
domicilio varchar2(30),
seccion number(2) not null,
constraint FK_empleados_seccion
foreign key (seccion)
references secciones(codigo),
constraint PK_empleados
primary key (documento)
);

Ingresamos algunos registros:

insert into secciones values(1,'Administracion');


insert into secciones values(2,'Contadura');
insert into secciones values(3,'Sistemas');

insert into empleados values('22222222','Lopez Ana','Colon 123',1);


insert into empleados values('23333333','Lopez Luis','Sucre 235',1);
insert into empleados values('24444444','Garcia Marcos','Sarmiento
1234',2);
insert into empleados values('25555555','Gomez Pablo','Bulnes
321',3);
insert into empleados values('26666666','Perez Laura','Peru 1254',3);

Eliminamos la vista "vista_empleados":

drop view vista_empleados;

Creamos la vista "vista_empleados" que muestre algunos campos de los empleados de la


seccin 1:

create view vista_empleados


as
select documento,nombre,seccion
from empleados
where seccion=1;

Consultamos la vista:

select *from vista_empleados;

Veamos el texto de la vista consultando "user_views":

select view_name,text from user_views where


view_name='VISTA_EMPLEADOS';

Modificamos la vista para que muestre el domicilio:

create or replace view vista_empleados


as
select documento,nombre,seccion, domicilio
from empleados
where seccion=1;

Consultamos la vista para ver si se modific:

select *from vista_empleados;

Aparece el nuevo campo.

Veamos el texto de la vista consultando "user_views":

select view_name,text from user_views where


view_name='VISTA_EMPLEADOS';
87 - Vistas modificar (create or replace view)

Primer problema:

Un club dicta cursos de distintos deportes. Almacena la informacin en varias tablas.

1- Elimine las tablas "inscriptos", "socios" y "cursos":

drop table inscriptos;


drop table socios;
drop table cursos;

2- Cree las tablas:

create table socios(


documento char(8) not null,
nombre varchar2(40),
domicilio varchar2(30),
constraint PK_socios_documento
primary key (documento)
);

create table cursos(


numero number(2),
deporte varchar2(20),
dia varchar2(15),
constraint CK_inscriptos_dia check (dia
in('lunes','martes','miercoles','jueves','viernes','sabado')),
profesor varchar2(20),
constraint PK_cursos_numero
primary key (numero)
);

create table inscriptos(


documentosocio char(8) not null,
numero number(2) not null,
matricula char(1),
constraint PK_inscriptos_documento_numero
primary key (documentosocio,numero),
constraint FK_inscriptos_documento
foreign key (documentosocio)
references socios(documento),
constraint FK_inscriptos_numero
foreign key (numero)
references cursos(numero)
);

3- Ingrese algunos registros para todas las tablas:

insert into socios values('30000000','Fabian Fuentes','Caseros 987');


insert into socios values('31111111','Gaston Garcia','Guemes 65');
insert into socios values('32222222','Hector Huerta','Sucre 534');
insert into socios values('33333333','Ines Irala','Bulnes 345');

insert into cursos values(1,'tenis','lunes','Ana Acosta');


insert into cursos values(2,'tenis','martes','Ana Acosta');
insert into cursos values(3,'natacion','miercoles','Ana Acosta');
insert into cursos values(4,'natacion','jueves','Carlos Caseres');
insert into cursos values(5,'futbol','sabado','Pedro Perez');
insert into cursos values(6,'futbol','lunes','Pedro Perez');
insert into cursos values(7,'basquet','viernes','Pedro Perez');

insert into inscriptos values('30000000',1,'s');


insert into inscriptos values('30000000',3,'s');
insert into inscriptos values('30000000',6,null);
insert into inscriptos values('31111111',1,'n');
insert into inscriptos values('31111111',4,'s');
insert into inscriptos values('32222222',1,'n');
insert into inscriptos values('32222222',7,'n');

4- Cree o reemplace la vista "vista_inscriptos" que muestre el documento y nombre del socio,
el deporte, el da y la matrcula, de todas las inscripciones no pagas

5- Consulte la vista

6- Veamos el texto de la vista

7- Modifique la vista para que muestre el domicilio

8- Consulte la vista para ver si se modific

9- Vea el texto de la vista

drop table inscriptos;


drop table socios;
drop table cursos;
create table socios(
documento char(8) not null,
nombre varchar2(40),
domicilio varchar2(30),
constraint PK_socios_documento
primary key (documento)
);

create table cursos(


numero number(2),
deporte varchar2(20),
dia varchar2(15),
constraint CK_inscriptos_dia check (dia
in('lunes','martes','miercoles','jueves','viernes','sabado')),
profesor varchar2(20),
constraint PK_cursos_numero
primary key (numero)
);

create table inscriptos(


documentosocio char(8) not null,
numero number(2) not null,
matricula char(1),
constraint PK_inscriptos_documento_numero
primary key (documentosocio,numero),
constraint FK_inscriptos_documento
foreign key (documentosocio)
references socios(documento),
constraint FK_inscriptos_numero
foreign key (numero)
references cursos(numero)
);

insert into socios values('30000000','Fabian Fuentes','Caseros 987');


insert into socios values('31111111','Gaston Garcia','Guemes 65');
insert into socios values('32222222','Hector Huerta','Sucre 534');
insert into socios values('33333333','Ines Irala','Bulnes 345');

insert into cursos values(1,'tenis','lunes','Ana Acosta');


insert into cursos values(2,'tenis','martes','Ana Acosta');
insert into cursos values(3,'natacion','miercoles','Ana Acosta');
insert into cursos values(4,'natacion','jueves','Carlos Caseres');
insert into cursos values(5,'futbol','sabado','Pedro Perez');
insert into cursos values(6,'futbol','lunes','Pedro Perez');
insert into cursos values(7,'basquet','viernes','Pedro Perez');

insert into inscriptos values('30000000',1,'s');


insert into inscriptos values('30000000',3,'s');
insert into inscriptos values('30000000',6,null);
insert into inscriptos values('31111111',1,'n');
insert into inscriptos values('31111111',4,'s');
insert into inscriptos values('32222222',1,'n');
insert into inscriptos values('32222222',7,'n');

create or replace view vista_deudores


as
select documento,nombre,c.deporte,c.dia,matricula
from socios s
join inscriptos i
on documento=documentosocio
join cursos c
on c.numero=i.numero
where matricula='n';

select *from vista_deudores;


select view_name,text from user_views where view_name='VISTA_DEUDORES';

create or replace view vista_deudores


as
select documento,nombre,domicilio,c.deporte,c.dia,matricula
from socios s
join inscriptos i
on documento=documentosocio
join cursos c
on c.numero=i.numero
where matricula='n';

select *from vista_deudores;

select view_name,text from user_views where view_name='VISTA_DEUDORES';

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;
88 - Vistas (with check option)

Problema:

Una empresa almacena la informacin de sus empleados en una tabla llamada "empleados".
Eliminamos la tabla:

drop table empleados;

Creamos la tabla:

create table empleados(


documento char(8),
sexo char(1)
constraint CK_empleados_sexo check (sexo in ('f','m')),
apellido varchar2(20),
nombre varchar2(20),
seccion varchar2(30),
cantidadhijos number(2),
constraint CK_empleados_hijos check (cantidadhijos>=0),
estadocivil char(10)
constraint CK_empleados_estadocivil check (estadocivil in
('casado','divorciado','soltero','viudo'))
);

Ingresamos algunos registros:

insert into empleados


values('22222222','f','Lopez','Ana','Administracion',2,'casado');
insert into empleados
values('23333333','m','Lopez','Luis','Administracion',0,'soltero');
insert into empleados
values('24444444','m','Garcia','Marcos','Sistemas',3,'divorciado');
insert into empleados
values('25555555','m','Gomez','Pablo','Sistemas',2,'casado');
insert into empleados
values('26666666','f','Perez','Laura','Contaduria',3,'casado');

Creamos o reemplazamos (si existe) la vista "vista_empleados", para que muestre el nombre,
apellido, sexo y seccin de todos los empleados de "Administracion" agregando la clusula
"with check option" para evitar que se modifique la seccin de tales empleados a travs de la
vista y que se ingresen empleados de otra seccin:

create or replace view vista_empleados


as
select apellido, nombre, sexo, seccion
from empleados
where seccion='Administracion'
with check option;

Consultamos la vista:

select *from vista_empleados;

Actualizarmos el nombre de un empleado a travs de la vista:

update vista_empleados set nombre='Beatriz' where nombre='Ana';

Oracle acept la actualizacin porque el campo "nombre" no est restringido.

Veamos si la modificacin se realiz en la tabla:

select *from empleados;


Intentamos actualizar la seccin de un empleado a travs de la vista:

update vista_empleados set seccion='Sistemas' where nombre='Beatriz';

Oracle no acept la actualizacin porque el campo "nombre" est restringido.

Ingresamos un registro mediante la vista:

insert into vista_empleados


values('Gomez','Gabriela','f','Administracion');

Oracle acepta la insercin porque ingresamos un valor para "seccion" que incluir el registro
en la vista.

Intentamos ingresar un empleado de otra seccin:

insert into vista_empleados


values('Torres','Tatiana','f','Sistemas');

Oracle no acepta la insercin porque ingresamos un valor para "seccion" que excluir el nuevo
registro de la vista.

88 - Vistas (with check option)

Primer problema:

Una empresa almacena la informacin de sus clientes en una tabla llamada "clientes".

1- Elimine la tabla:

drop table clientes;

2- Cree la tabla:

create table clientes(


nombre varchar2(40),
documento char(8),
domicilio varchar2(30),
ciudad varchar2(30)
);

3- Ingrese algunos registros:

insert into clientes values('Juan Perez','22222222','Colon 1123','Cordoba');


insert into clientes values('Karina Lopez','23333333','San Martin 254','Cordoba');
insert into clientes values('Luis Garcia','24444444','Caseros 345','Cordoba');
insert into clientes values('Marcos Gonzalez','25555555','Sucre 458','Santa Fe');
insert into clientes values('Nora Torres','26666666','Bulnes 567','Santa Fe');
insert into clientes values('Oscar Luque','27777777','San Martin 786','Santa Fe');
insert into clientes values('Pedro Perez','28888888','Colon 234','Buenos Aires');
insert into clientes values('Rosa Rodriguez','29999999','Avellaneda 23','Buenos
Aires');
4- Cree o reemplace la vista "vista_clientes" para que recupere el nombre y ciudad de todos
los clientes que no sean de "Cordoba" sin emplear "with check option"

5- Cree o reemplace la vista "vista_clientes2" para que recupere el nombre y ciudad de todos
los clientes que no sean de "Cordoba" empleando "with check option"

6- Consulte ambas vistas

7- Intente modificar la ciudad del cliente "Pedro Perez" a "Cordoba" travs de la vista que est
restringida.

8- Realice la misma modificacin que intent en el punto anterior a travs de la vista que no
est restringida

9- Actualice la ciudad del cliente "Oscar Luque" a "Buenos Aires" mediante la vista restringida

10- Verifique que "Oscar Luque" an se incluye en la vista

11- Intente ingresar un empleado de "Cordoba" en la vista restringida

12- Ingrese el empleado anterior a travs de la vista no restringida

13- Ingrese un empleado de "Salta" en la vista restringida

14- Verifique que el nuevo registro est incluido en la vista

drop table clientes;

create table clientes(


nombre varchar2(40),
documento char(8),
domicilio varchar2(30),
ciudad varchar2(30)
);

insert into clientes values('Juan Perez','22222222','Colon 1123','Cordoba');


insert into clientes values('Karina Lopez','23333333','San Martin 254','Cordoba');
insert into clientes values('Luis Garcia','24444444','Caseros 345','Cordoba');
insert into clientes values('Marcos Gonzalez','25555555','Sucre 458','Santa Fe');
insert into clientes values('Nora Torres','26666666','Bulnes 567','Santa Fe');
insert into clientes values('Oscar Luque','27777777','San Martin 786','Santa Fe');
insert into clientes values('Pedro Perez','28888888','Colon 234','Buenos Aires');
insert into clientes values('Rosa Rodriguez','29999999','Avellaneda 23','Buenos
Aires');

create or replace view vista_clientes


as
select nombre, ciudad
from clientes
where ciudad <>'Cordoba';

create or replace view vista_clientes2


as
select nombre, ciudad
from clientes
where ciudad <>'Cordoba'
with check option;

select *from vista_clientes;


select *from vista_clientes2;

update vista_clientes2 set ciudad='Cordoba' where nombre='Pedro Perez';

update vista_clientes set ciudad='Cordoba' where nombre='Pedro Perez';

update vista_clientes2 set ciudad='Buenos Aires' where nombre='Oscar Luque';

select *from vista_clientes2;

insert into vista_clientes2 values('Viviana Valdez','Cordoba');

insert into vista_clientes values('Viviana Valdez','Cordoba');

insert into vista_clientes2 values('Viviana Valdez','Salta');

select *from vista_clientes2;

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").

89 - Vistas (otras consideraciones)

Problema:
Una empresa almacena la informacin de sus empleados en una tabla llamada "empleados".

Eliminamos la tabla:

drop table empleados;

Eliminamos la vista "vista_empleados":

drop view vista_empleados;

Creamos la vista "vista_empleados" que muestre algunos campos de "empleados", pero la tabla
"empleados" no existe, por ello, debemos agregar, al crear la vista "force":

create force view vista_empleados


as
select documento,nombre,seccion
from empleados;

Creamos la tabla:

create table empleados(


documento char(8),
nombre varchar2(30),
domicilio varchar2(30),
seccion varchar2(30)
);

Ingresamos algunos registros:

insert into empleados values('22222222','Lopez Ana','Colon


123','Sistemas');
insert into empleados values('23333333','Lopez Luis','Sucre
235','Sistemas');
insert into empleados values('24444444','Garcia Marcos','Sarmiento
1234','Contaduria');
insert into empleados values('25555555','Gomez Pablo','Bulnes
321','Contaduria');
insert into empleados values('26666666','Perez Laura','Peru
1254','Secretaria');

Consultamos la vista:

select *from vista_empleados;

Veamos el texto de la vista consultando "user_views":

select view_name,text from user_views where


view_name='VISTA_EMPLEADOS';

Creamos o reemplazamos (si existe) la vista "vista_empleados" que muestre todos los campos
de la tabla "empleados":

create or replace view vista_empleados


as
select *from empleados;

Consultamos la vista:
select *from vista_empleados;

Agregamos un campo a la tabla "empleados":

alter table empleados


add sueldo number(6,2);

Consultamos la vista "vista_empleados":

select *from vista_empleados;

Note que el nuevo campo agregado a "empleados" no aparece, a pesar que la vista indica que
muestre todos los campos de dicha tabla; esto sucede porque los campos se seleccionan al
ejecutar "create view", para que aparezcan debemos volver a crear la vista:

create or replace view vista_empleados


as
select *from empleados;

Consultemos la vista:

select *from vista_empleados;

Ahora si aparece el nuevo campo "sueldo" de "empleados";

89 - Vistas (otras consideraciones)

Primer problema:

Una empresa almacena la informacin de sus clientes en una tabla llamada "clientes".

1- Elimine la tabla:

drop table clientes;

2- Elimine la vista "vista_clientes":

drop view vista_clientes;

3- Intente crear o reemplazar la vista "vista_clientes" para que muestre el nombre, domicilio
y ciudad de todos los clientes de "Cordoba" (sin emplear "force")
Mensaje de error porque la tabla referenciada no existe.

4- Cree o reemplace la vista "vista_clientes" para que recupere el nombre, apellido y ciudad
de todos los clientes de "Cordoba" empleando "force"

5- Cree la tabla:

create table clientes(


nombre varchar2(40),
documento char(8),
domicilio varchar2(30),
ciudad varchar2(30)
);
6- Ingrese algunos registros:

insert into clientes values('Juan Perez','22222222','Colon 1123','Cordoba');


insert into clientes values('Karina Lopez','23333333','San Martin 254','Cordoba');
insert into clientes values('Luis Garcia','24444444','Caseros 345','Cordoba');
insert into clientes values('Marcos Gonzalez','25555555','Sucre 458','Santa Fe');
insert into clientes values('Nora Torres','26666666','Bulnes 567','Santa Fe');
insert into clientes values('Oscar Luque','27777777','San Martin 786','Santa Fe');
insert into clientes values('Pedro Perez','28888888','Colon 234','Buenos Aires');
insert into clientes values('Rosa Rodriguez','29999999','Avellaneda 23','Buenos
Aires');

7- Cree o reemplace la vista "vista_clientes" para que muestre todos los campos de la tabla
"clientes"

8- Consulte la vista

9- Agregue un campo a la tabla "clientes"

10- Consulte la vista "vista_clientes"


El nuevo campo agregado a "clientes" no aparece, pese a que la vista indica que muestre
todos los campos de dicha tabla.

11- Modifique la vista para que aparezcan todos los campos

12- Consulte la vista:


Ahora si aparece el campo.

drop table clientes;

drop view vista_clientes;

create or replace view vista_clientes


as
select nombre, ciudad
from clientes
where ciudad ='Cordoba';

create or replace force view vista_clientes


as
select nombre, ciudad
from clientes
where ciudad ='Cordoba';

create table clientes(


nombre varchar2(40),
documento char(8),
domicilio varchar2(30),
ciudad varchar2(30)
);

insert into clientes values('Juan Perez','22222222','Colon 1123','Cordoba');


insert into clientes values('Karina Lopez','23333333','San Martin 254','Cordoba');
insert into clientes values('Luis Garcia','24444444','Caseros 345','Cordoba');
insert into clientes values('Marcos Gonzalez','25555555','Sucre 458','Santa Fe');
insert into clientes values('Nora Torres','26666666','Bulnes 567','Santa Fe');
insert into clientes values('Oscar Luque','27777777','San Martin 786','Santa Fe');
insert into clientes values('Pedro Perez','28888888','Colon 234','Buenos Aires');
insert into clientes values('Rosa Rodriguez','29999999','Avellaneda 23','Buenos
Aires');

create or replace view vista_clientes


as
select *from clientes;

select *from vista_clientes;

alter table clientes


add telefono char(11);

select *from vista_clientes;

create or replace view vista_clientes


as
select *from clientes;

select *from vista_clientes;

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.

90 - Vistas materializadas (materialized view)

Problema:

Un profesor almacena los datos y notas de sus alumnos en dos tablas "alumnos" y notas".

Eliminamos las tablas:

drop table notas;


drop table alumnos;

Creamos las tablas:

create table alumnos(


documento char(8),
apellido varchar(30),
nombre varchar(30),
domicilio varchar2(40),
primary key(documento)
);

create table notas(


documento char(8),
fecha date,
nota number(4,2),
constraints FK_notas_documento
foreign key (documento)
references alumnos(documento)
);

Ingresamos algunos registros:

insert into alumnos values('23333333','Acosta','Ana','Avellaneda


111');
insert into alumnos values('24444444','Bustos','Betina','Bulnes
222');
insert into alumnos values('25555555','Caseros','Carlos','Colon
333');
insert into alumnos values('26666666','Duarte','Daniel','Dinamarca
444');

insert into notas values('23333333','10/05/2007',5.3);


insert into notas values('23333333','15/07/2007',8.3);
insert into notas values('23333333','20/09/2007',7.4);
insert into notas values('24444444','10/05/2007',8.6);
insert into notas values('24444444','15/07/2007',9.4);
insert into notas values('25555555','10/05/2007',9);
insert into notas values('25555555','15/07/2007',6);
insert into notas values('26666666','10/05/2007',3.2);
insert into notas values('26666666','15/07/2007',5.3);
insert into notas values('26666666','20/09/2007',3.5);

Creamos o reemplazamos una vista normal que muestre el documento del alumnos y el
promedio de sus notas:

create or replace view vista_promedios


as select a.documento,avg(nota) as promedio
from alumnos a
join notas n
on a.documento=n.documento
group by a.documento;

Eliminamos la vista materializada "vm_promedios:

drop materialized view vm_promedios;

Creamos una vista materializada que muestre el documento del alumnos y el promedio de sus
notas:

create materialized view vm_promedios


as
select a.documento,avg(nota) as promedio
from alumnos a
join notas n
on a.documento=n.documento
group by a.documento;

Consultamos ambas vistas:

select *from vista_promedios;


select *from vm_promedios;

El resultado es el mismo.

Ahora agregamos algunas notas:

insert into notas values('23333333','12/10/2007',9);


insert into notas values('24444444','12/10/2007',7.5);
insert into notas values('25555555','12/10/2007',3);
insert into notas values('26666666','12/10/2007',4);

Consultamos ambas vistas y comparamos los promedios:

select *from vista_promedios;


select *from vm_promedios;

Los promedios de la vista actualizable han cambiado porque al ejecutar el primer "select" se
consultaron las tablas "notas" y "alumnos"; los promedios de la vista materializada no han
cambiado, porque almacenaron el resultado de la consulta, al ejecutar el segundo "select" no
se consultaron las tablas "alumnos" y "notas".
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 (crear- ejecutar)

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.

92 - Procedimientos Almacenados (crear- ejecutar)

Problema:

Una librera almacena los datos de sus libros en una tabla denominada "libros".

Eliminamos "libros", creamos la tabla y luego ingresamos algunos registros:

drop table libros;


create table libros(
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(5,2)
);

insert into libros values('Uno','Richard Bach','Planeta',15);


insert into libros values('Ilusiones','Richard Bach','Planeta',18);
insert into libros values('El aleph','Borges','Emece',25);
insert into libros values('Aprenda PHP','Mario Molina','Nuevo
siglo',45);
insert into libros values('Matematica estas ahi','Paenza','Nuevo
siglo',12);
insert into libros values('Java en 10 minutos','Mario
Molina','Paidos',35);

La librera, frecuentemente, aumenta los precios de los libros en un 10%. Necesitamos un


procedimiento almacenado que actualice los precios de los libros aumentndolos en un 10%:

create or replace procedure pa_libros_aumentar10


as
begin
update libros set precio=precio+(precio*0.1);
end;
Lo ejecutamos:

execute pa_libros_aumentar10;

Verificamos que los precios han aumentado:

select *from libros;

Volvemos a ejecutar el procedimiento:

execute pa_libros_aumentar10;

Verificamos que los precios han aumentado nuevamente:

select *from libros;


92 - Procedimientos Almacenados (crear- ejecutar)

Primer problema:

Una empresa almacena los datos de sus empleados en una tabla llamada "empleados".

1- Eliminamos la tabla y la creamos:

drop table empleados;

create table empleados(


documento char(8),
nombre varchar2(20),
apellido varchar2(20),
sueldo number(6,2),
cantidadhijos number(2,0),
fechaingreso date,
primary key(documento)
);

2- Ingrese algunos registros:

insert into empleados values('22222222','Juan','Perez',200,2,'10/10/1980');


insert into empleados values('22333333','Luis','Lopez',250,0,'01/02/1990');
insert into empleados values('22444444','Marta','Perez',350,1,'02/05/1995');
insert into empleados values('22555555','Susana','Garcia',400,2,'15/12/2000');
insert into empleados values('22666666','Jose
Maria','Morales',500,3,'25/08/2005');

3- Cree (o reemplace) el procedimiento almacenado llamado "pa_aumentarsueldo" que


aumente los sueldos inferiores al promedio en un 20%

4- Ejecute el procedimiento creado anteriormente

5- Verifique que los sueldos han aumentado

6- Ejecute el procedimiento nuevamente

7- Verifique que los sueldos han aumentado


8- Elimine la tabla "empleados_antiguos"

9- Cree la tabla "empleados_antiguos"

create table empleados_antiguos(


documento char(8),
nombre varchar2(40)
);

10- Cree (o reemplace) un procedimiento almacenado que ingrese en la tabla


"empleados_antiguos" el documento, nombre y apellido (concatenados) de todos los
empleados de la tabla "empleados" que ingresaron a la empresa hace ms de 10 aos

11- Ejecute el procedimiento creado anteriormente

12- Verifique que la tabla "empleados_antiguos" ahora tiene registros (3 registros)

drop table empleados;

create table empleados(


documento char(8),
nombre varchar2(20),
apellido varchar2(20),
sueldo number(6,2),
cantidadhijos number(2,0),
fechaingreso date,
primary key(documento)
);

insert into empleados values('22222222','Juan','Perez',200,2,'10/10/1980');


insert into empleados values('22333333','Luis','Lopez',250,0,'01/02/1990');
insert into empleados values('22444444','Marta','Perez',350,1,'02/05/1995');
insert into empleados values('22555555','Susana','Garcia',400,2,'15/12/2000');
insert into empleados values('22666666','Jose
Maria','Morales',500,3,'25/08/2005');

create or replace procedure pa_aumentarsueldo


as
begin
update empleados set sueldo=sueldo+(sueldo*0.2)
where sueldo<(select max(sueldo) from empleados);
end;

exec pa_aumentarsueldo;

select *from empleados;

exec pa_aumentarsueldo;

select *from empleados;

drop table empleados_antiguos;


create table empleados_antiguos(
documento char(8),
nombre varchar2(40)
);

create or replace procedure pa_empleados_antiguos


as
begin
insert into empleados_antiguos
select documento,nombre||' '||apellido
from empleados
where (extract(year from current_date)-extract(year from fechaingreso))>10;
end;

execute pa_empleados_antiguos;

select *from empleados_antiguos;

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;

94 - Procedimientos almacenados (parmetros de entrada)

Problema:

Trabajamos con la tabla "libros" de una librera.

Eliminamos la tabla y la creamos nuevamente:

drop table libros;

create table libros(


titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(5,2)
);

Ingresamos algunos registros:

insert into libros values ('Uno','Richard Bach','Planeta',15);


insert into libros values ('Ilusiones','Richard Bach','Planeta',12);
insert into libros values ('El aleph','Borges','Emece',25);
insert into libros values ('Aprenda PHP','Mario Molina','Nuevo
siglo',50);
insert into libros values ('Matematica estas ahi','Paenza','Nuevo
siglo',18);
insert into libros values ('Puente al infinito','Bach
Richard','Sudamericana',14);
insert into libros values ('Antologa','J. L. Borges','Paidos',24);
insert into libros values ('Java en 10 minutos','Mario Molina','Siglo
XXI',45);
insert into libros values ('Cervantes y el quijote','Borges-
Casares','Planeta',34);

Creamos un procedimiento que recibe el nombre de una editorial y luego aumenta en un 10%
los precios de los libros 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;

Ejecutamos el procedimiento:

execute pa_libros_aumentar10('Planeta');

Verificamos que los precios de los libros de la editorial "Planeta" han aumentado un 10%:

select *from libros;

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;

Ejecutamos el procedimiento enviando valores para ambos argumentos:

execute pa_libros_aumentar('Planeta',30);

Consultamos la tabla "libros" para verificar que los precios de los libros de la editorial
"Planeta" han sido aumentados en un 30%:

select *from libros;

Ejecutamos el procedimiento "pa_libros_aumentar" omitiendo el segundo parmetro porque


tiene establecido un valor por defecto:

execute pa_libros_aumentar('Paidos');

Consultamos la tabla "libros" para verificar que los precios de los libros de la editorial "Paidos"
han sido aumentados en un 10% (valor por defecto):

select *from libros;

Definimos un procedimiento almacenado que ingrese un nuevo libro en la tabla "libros":

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;
Llamamos al procedimiento sin enviarle valores para los parmetros:

execute pa_libros_insertar;

Veamos cmo se almacen el registro:

select *from libros;

Llamamos al procedimiento envindole valores solamente para el primer y cuarto parmetros


correspondientes al ttulo y precio:

execute pa_libros_insertar('Uno',100);

Oracle asume que los argumentos son el primero y segundo, vea cmo se almacen el nuevo
registro:

select *from libros;

94 - Procedimientos almacenados (parmetros de entrada)

Primer problema:

Una empresa almacena los datos de sus empleados en una tabla llamada "empleados".

1- Eliminamos la tabla y la creamos:

drop table empleados;

create table empleados(


documento char(8),
nombre varchar2(20),
apellido varchar2(20),
sueldo number(6,2),
fechaingreso date
);

2- Ingrese algunos registros:

insert into empleados values('22222222','Juan','Perez',300,'10/10/1980');


insert into empleados values('22333333','Luis','Lopez',300,'12/05/1998');
insert into empleados values('22444444','Marta','Perez',500,'25/08/1990');
insert into empleados values('22555555','Susana','Garcia',400,'05/05/2000');
insert into empleados values('22666666','Jose Maria','Morales',400,'24/10/2005');

3- Cree un procedimiento almacenado llamado "pa_empleados_aumentarsueldo". Debe


incrementar el sueldo de los empleados con cierta cantidad de aos en la empresa
(parmetro "ayear" de tipo numrico) en un porcentaje (parmetro "aporcentaje" de tipo
numerico); es decir, recibe 2 parmetros.

4- Ejecute el procedimiento creado anteriormente.

5- Verifique que los sueldos de los empleados con ms de 10 aos en la empresa han
aumentado un 20%
6- Ejecute el procedimiento creado anteriormente enviando otros valores como parmetros
(por ejemplo, 8 y 10)

7- Verifique que los sueldos de los empleados con ms de 8 aos en la empresa han
aumentado un 10%

8- Ejecute el procedimiento almacenado "pa_empleados_aumentarsueldo" sin parmetros

9- Cree un procedimiento almacenado llamado "pa_empleados_ingresar" que ingrese un


empleado en la tabla "empleados", debe recibir valor para el documento, el nombre, apellido
y almacenar valores nulos en los campos "sueldo" y "fechaingreso"

10- Ejecute el procedimiento creado anteriormente y verifique si se ha ingresado en


"empleados" un nuevo registro

11- Reemplace el procedimiento almacenado llamado "pa_empleados_ingresar" para que


ingrese un empleado en la tabla "empleados", debe recibir valor para el documento (con valor
por defecto nulo) y fechaingreso (con la fecha actual como valor por defecto), los dems
campos se llenan con valor nulo

12- Ejecute el procedimiento creado anteriormente envindole valores para los 2 parmetros
y verifique si se ha ingresado en "empleados" un nuevo registro

13- Ejecute el procedimiento creado anteriormente enviando solamente la fecha de ingreso y


vea el resultado
Oracle toma el valor enviado como primer argumento e intenta ingresarlo en el campo
"documento", muestra un mensaje de error indicando que el valor es muy grande, ya que tal
campo admite 8 caracteres.

14- Cree (o reemplace) un procedimiento almacenado que reciba un documento y elimine de


la tabla "empleados" el empleado que coincida con dicho documento

15- Elimine un empleado empleando el procedimiento del punto anterior

16- Verifique la eliminacin

drop table empleados;

create table empleados(


documento char(8),
nombre varchar2(20),
apellido varchar2(20),
sueldo number(6,2),
fechaingreso date
);

insert into empleados values('22222222','Juan','Perez',300,'10/10/1980');


insert into empleados values('22333333','Luis','Lopez',300,'12/05/1998');
insert into empleados values('22444444','Marta','Perez',500,'25/08/1990');
insert into empleados values('22555555','Susana','Garcia',400,'05/05/2000');
insert into empleados values('22666666','Jose Maria','Morales',400,'24/10/2005');
create or replace procedure pa_empleados_aumentarsueldo(ayear in number,
aporcentaje in number)
as
begin
update empleados set sueldo=sueldo+(sueldo*aporcentaje/100)
where (extract(year from current_date)-extract(year from fechaingreso))>ayear;
end;

execute pa_empleados_aumentarsueldo(10,20);

select *from empleados;

execute pa_empleados_aumentarsueldo(8,10);

select *from empleados;

execute pa_empleados_aumentarsueldo;

create or replace procedure pa_empleados_ingresar


(adocumento in char, anombre in varchar2, aapellido in varchar2)
as
begin
insert into empleados values(adocumento, anombre, aapellido, null,null);
end;

execute pa_empleados_ingresar('30000000','Ana', 'Acosta');


select *from empleados;

create or replace procedure pa_empleados_ingresar


(adocumento in char default null, afecha in date default current_date)
as
begin
insert into empleados values(adocumento, null, null, null,afecha);
end;

execute pa_empleados_ingresar('32222222','10/10/2007');
select *from empleados;

execute pa_empleados_ingresar ('15/12/2000');

create or replace procedure pa_empleado_eliminar(adocumento in varchar2)


as
begin
delete from empleados where documento=adocumento;
end;

execute pa_empleado_eliminar('30000000');

select *from empleados;

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);


97 - Funciones

Problema:

Una librera almacena la informacin de sus libros en una tabla llamada "libros".

Eliminamos la tabla:

drop table libros;

Creamos la tabla "libros" con la siguiente estructura:

create table libros(


codigo number(3),
titulo varchar2(40),
autor varchar2(30),
precio number(5,2)
);

Ingresamos algunos registros:

insert into libros values(100,'Uno','Richard Bach',15);


insert into libros values(300,'Aprenda PHP','Mario Molina',55);
insert into libros values(102,'Matematica estas ahi','Paenza',18);
insert into libros values(105,'El aleph','Borges',25);
insert into libros values(109,'El experto en
laberintos','Gaskin',20);
insert into libros values(204,'Alicia en el pais de las
maravillas','Carroll',31);

Creamos o reemplazamos una funcin que reciba 1 parmetro (un valor numrico a
incrementar) y retorne 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;

Realizamos un "select" sobre "libros" que muestre el ttulo, precio y llamamos a la funcin
creada anteriormente para que nos devuelva el precio incrementado en un 10%:

select titulo,precio,f_incremento10(precio) from libros;

Creamos otra funcin que reciba 2 parmetros, un valor a incrementar y el incremento, y que
nos retorne 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" sobre "libros" que muestre el ttulo, precio y el precio incrementado en
un 20% (llamando a la funcin creada anteriormente, enviando como primer argumento el
campo "precio" y como segundo argumento el valor "20"):

select titulo,precio,f_incremento(precio,20) from libros;

Realizamos otro "select" similar al anterior, pero en esta ocasin le enviamos a la funcin otro
valor como segundo argumento:

select titulo,precio,f_incremento(precio,50) from libros;

Creamos o reemplazamos una funcin que 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 varchar2
is
valorretornado varchar2(20);
begin
valorretornado:='';
if avalor<=20 then
valorretornado:='economico';
else valorretornado:='costoso';
end if;
return valorretornado;
end;

Realizamos un "select" para mostrar el ttulo, precio y una cadena que indique si el libro es
econmico o costoso (llamando a la funcin creada anteriormente):

select titulo,precio,f_costoso(precio) from libros;.

Podemos emplear la funcin "f_costoso" sin incluir campos de una tabla. Por ejemplo:

select f_costoso (10) from dual;


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;
98 - Control de flujo (if)

Problema:

Un profesor almacena las notas de sus alumnos en una tabla denominada "notas".

Eliminamos la tabla:

drop table notas;

Creamos la tabla con la siguiente estructura:

create table notas(


nombre varchar2(30),
nota number(4,2)
);

Ingresamos algunos registros:


insert into notas values('Acosta Ana', 6.7);
insert into notas values('Bustos Brenda', 9.5);
insert into notas values('Caseros Carlos', 3.7);
insert into notas values('Dominguez Daniel', 2);
insert into notas values('Fuentes Federico', 8);
insert into notas values('Gonzalez Gaston', 7);
insert into notas values('Juarez Juana', 4);
insert into notas values('Lopez Luisa',5.3);

Creamos o reemplazamos la funcin "f_condicion" que recibe una nota y retorna una cadena
de caracteres indicando si aprueba o no:

create or replace function f_condicion (anota number)


return varchar2
is
condicion varchar2(20);
begin
condicion:='';
if anota<4 then
condicion:='desaprobado';
else condicion:='aprobado';
end if;
return condicion;
end;

Realizamos un "select" sobre "notas" mostrando el nombre y nota del alumno y en una
columna su condicin (empleando la funcin creada anteriormente):

select nombre, nota, f_condicion(nota) from notas;

En el siguiente ejemplo omitimos la clusula "else" porque slo indicaremos acciones en caso
que el "if" sea verdadero:

create or replace function f_condicion (anota number)


return varchar2
is
condicion varchar2(20);
begin
condicion:='aprobado';
if anota<4 then
condicion:='desaprobado';
end if;
return condicion;
end;

Realizamos el "select" sobre "notas" mostrando la misma informacin que antes:

select nombre, nota, f_condicion(nota) from notas;

En el siguiente ejemplo colocamos un "if" dentro de otro "if". En el cuerpo de la funcin


controlamos si la nota es menor a 4 (retorna "desaprobado"), luego, dentro del "else",
controlamos si la nota es menor a 8 (retorna "regular") y si no lo es ("else"), retorna
"promocionado":

create or replace function f_condicion (anota number)


return varchar2
is
condicion varchar2(20);
begin
condicion:='';
if anota<4 then
condicion:='desaprobado';
else
if anota<8 then
condicion:='regular';
else
condicion:='promocionado';
end if;
end if;
return condicion;
end;

Realizamos el "select" sobre "notas" mostrando la misma informacin que antes:

select nombre, nota, f_condicion(nota) from notas;

Simplificamos la funcin anteriormente creada empleando la sintaxis "if...elsif":

create or replace function f_condicion (anota number)


return varchar2
is
condicion varchar2(20);
begin
condicion:='';
if anota<4 then
condicion:='desaprobado';
elsif anota<8 then
condicion:='regular';
else
condicion:='promocionado';
end if;
return condicion;
end;

Realizamos el "select" sobre "notas" mostrando la misma informacin que antes:

select nombre, nota, f_condicion(nota) from notas;


98 - Control de flujo (if)

Primer problema:

Un negocio almacena los datos de sus productos en una tabla denominada "productos". Dicha
tabla contiene el cdigo de producto, el precio, el stock mnimo que se necesita (cantidad
mnima requerida antes de comprar ms) y el stock actual (cantidad disponible en depsito).
Si el stock actual es cero, es urgente reponer tal producto; menor al stock mnimo requerido,
es necesario reponer tal producto; si el stock actual es igual o supera el stock minimo, est
en estado normal.

1- Elimine la tabla "productos":

drop table productos;

2- Cree la tabla con la siguiente estructura:

create table productos(


codigo number(5),
precio number(6,2),
stockminimo number(4),
stockactual number(4)
);

3- Ingrese algunos registros:

insert into productos values(100,10,100,200);


insert into productos values(102,15,200,500);
insert into productos values(130,8,100,0);
insert into productos values(240,23,100,20);
insert into productos values(356,12,100,250);
insert into productos values(360,7,100,100);
insert into productos values(400,18,150,100);

4- Cree una funcin que reciba dos valores numricos correspondientes a ambos stosks. Debe
comparar ambos stocks y retornar una cadena de caracteres indicando el estado de cada
producto, si stock actual es:

- cero: "faltante",
- menor al stock mnimo: "reponer",
- igual o superior al stock mnimo: "normal".

5- Realice un "select" mostrando el cdigo del producto, ambos stocks y, empleando la


funcin creada anteriormente, una columna que muestre el estado del producto

6- Realice la misma funcin que en el punto 4, pero esta vez empleando en la estructura
condicional la sintaxis "if... elsif...end if"

7- Realice un "select" mostrando el cdigo del producto, ambos stocks y, empleando la


funcin creada anteriormente, una columna que muestre el estado del producto

8- Realice una funcin similar a las anteriores, pero esta vez, si el estado es "reponer" o
"faltante", debe especificar la cantidad necesaria (valor necesario para llegar al stock
mnimo)

7- Realice un "select" mostrando el cdigo del producto, ambos stocks y, empleando la


funcin creada anteriormente, una columna que muestre el estado del producto

drop table productos;

create table productos(


codigo number(5),
precio number(6,2),
stockminimo number(4),
stockactual number(4)
);

insert into productos values(100,10,100,200);


insert into productos values(102,15,200,500);
insert into productos values(130,8,100,0);
insert into productos values(240,23,100,20);
insert into productos values(356,12,100,250);
insert into productos values(360,7,100,100);
insert into productos values(400,18,150,100);

create or replace function f_estado(aactual number,aminimo number)


return varchar2
is
estado varchar2(20);
begin
estado:='normal';
if aactual>=aminimo then
estado:='normal';
else
if aactual=0 then estado:='faltante';
else
estado:='reponer';
end if;
end if;
return estado;
end;

select codigo, stockactual, stockminimo, f_estado(stockactual,stockminimo) as


estado from productos;

create or replace function f_estado(aactual number,aminimo number)


return varchar2
is
estado varchar2(20);
begin
estado:='normal';
if aactual>=aminimo then
estado:='normal';
elsif
aactual=0 then estado:='faltante';
else
estado:='reponer';
end if;
return estado;
end;

select codigo, stockactual, stockminimo, f_estado(stockactual,stockminimo) as


estado from productos;

create or replace function f_estado(aactual number,aminimo number)


return varchar2
is
estado varchar2(20);
begin
estado:='normal';
if aactual>=aminimo then
estado:='normal';
elsif
aactual=0 then estado:='faltante '||to_char(aminimo);
else
estado:='reponer '||to_char(aminimo-aactual);
end if;
return estado;
end;
select codigo, stockactual, stockminimo, f_estado(stockactual,stockminimo) as
estado from productos;

Segundo problema:

Una clnica almacena la informacin de sus pacientes en una tabla denominada "pacientes".

1- Elimine la tabla y crela con la siguiente estructura:

drop table pacientes;

create table pacientes(


documento char(8),
nombre varchar2(30),
edad number(2),
sexo char(1)
);

2- Ingrese los siguientes registros:

insert into pacientes values('11111111','Acosta Ana',40,'f');


insert into pacientes values('22222222','Bustos Betina',35,'f');
insert into pacientes values('33333333','Caseres Carlos',18,'m');
insert into pacientes values('44444444','Dominguez Diego',6,'m');
insert into pacientes values('15555555','Fuentes Fabiana',55,'f');
insert into pacientes values('26666666','Gomez Gaston',38,'m');
insert into pacientes values('37777777','Irala Ines',16,'f');
insert into pacientes values('38888888','Juarez Julieta',17,'f');
insert into pacientes values('40000000','Lopez Lucas',3,'m');

3- Realice una funcin que reciba la edad del paciente y retorne la cadena "menor" o "mayor"
segn sea menor a 18 aos o no

4- Realice una funcin que reciba el caracter correspondiente al sexo del paciente y retorne
la cadena "femenino" o "masculino"

5- Realice un "select" mostrando el nombre del paciente y empleando las funciones de los
puntos 3 y 4, dos columnas que indiquen si es mayor o menor de edad y el sexo.

drop table pacientes;

create table pacientes(


documento char(8),
nombre varchar2(30),
edad number(2),
sexo char(1)
);
insert into pacientes values('11111111','Acosta Ana',40,'f');
insert into pacientes values('22222222','Bustos Betina',35,'f');
insert into pacientes values('33333333','Caseres Carlos',18,'m');
insert into pacientes values('44444444','Dominguez Diego',6,'m');
insert into pacientes values('15555555','Fuentes Fabiana',55,'f');
insert into pacientes values('26666666','Gomez Gaston',38,'m');
insert into pacientes values('37777777','Irala Ines',16,'f');
insert into pacientes values('38888888','Juarez Julieta',17,'f');
insert into pacientes values('40000000','Lopez Lucas',3,'m');

create or replace function f_menormayor(aedad number)


return varchar2
is
resultado varchar2(10);
begin
resultado:='menor';
if aedad<18 then
resultado:='menor';
else resultado:='mayor';
end if;
return resultado;
end;

create or replace function f_sexo(asexo char)


return varchar2
is
resultado varchar2(12);
begin
resultado:='femenino';
if asexo='m' then
resultado:='masculino';
else resultado:='femenino';
end if;
return resultado;
end;

select nombre, edad,f_mayormenor(edad) as categoria, f_sexo(sexo) as sexo from


pacientes;

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;
99 - Control de flujo (case)

Problema:

Trabajamos con la tabla "empleados". Eliminamos la tabla y luego la creamos con la siguiente
estructura:

drop table empleados;

create table empleados (


documento char(8),
nombre varchar(30),
fechanacimiento date
);

Ingresamos algunos registros:

insert into empleados values('20111111','Acosta Ana','10/05/1968');


insert into empleados values('22222222','Bustos
Bernardo','09/07/1970');
insert into empleados values('22333333','Caseros
Carlos','15/10/1971');
insert into empleados values('23444444','Fuentes
Fabiana','25/01/1972');
insert into empleados values('23555555','Gomez Gaston','28/03/1979');
insert into empleados values('24666666','Juarez
Julieta','18/02/1981');
insert into empleados values('25777777','Lopez Luis','17/09/1978');
insert into empleados values('26888888','Morales
Marta','22/12/1975');

Nos interesa el nombre del mes en el cual cada empleado cumple aos. 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;

Recuperamos el nombre del empleado y el mes de su cumpleaos realizando un "select":

select nombre, f_mes(fechanacimiento) as cumpleaos from empleados;

Podemos probar la funcin creada anteriormente envindole la siguiente fecha:

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

obtenemos como resultado "octubre".

Realizamos una funcin que reciba una fecha y retorne 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;

Recuperamos el nombre del empleado y el trimestre de su cumpleaos empleando la funcin


creada anteriormente:

select nombre, f_trimestre(fechanacimiento) from empleados;

Vamos a 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;
99 - Control de flujo (case)

Primer problema:

Trabajamos con la tabla "empleados".

1- Elimine la tabla y luego crela con la siguiente estructura:

drop table empleados;

create table empleados (


documento char(8),
nombre varchar(30),
fechanacimiento date,
hijos number(2),
sueldo number(6,2),
sexo char(1)
);

2- Ingrese algunos registros:

insert into empleados values('20000000','Acosta Ana','10/05/1968',0,800,'f');


insert into empleados values('21111111','Bustos
Bernardo','09/07/1970',2,550,'m');
insert into empleados values('22222222','Caseros Carlos','15/10/1971',3,500,'m');
insert into empleados values('23333333','Fuentes Fabiana','25/08/1972',0,500,'f');
insert into empleados values('24444444','Gomez Gaston','28/03/1979',1,850,'m');
insert into empleados values('25555555','Juarez Javier','18/08/1981',2,600,'m');
insert into empleados values('26666666','Lopez Luis','17/09/1978',4,690,'m');
insert into empleados values('27777777','Morales Marta','22/08/1975',2,480,'f');
insert into empleados values('28888888','Norberto Nores','11/08/1973',3,460,'m');
insert into empleados values('29999999','Oscar Oviedo','19/07/1976',0,700,'m');

3- La empresa tiene por poltica festejar los cumpleaos de sus empleados cada mes, si es de
sexo femenino se le regala un ramo de flores, sino, una lapicera. Realice un "select"
mostrando el nombre del empleado, el da del cumpleaos y una columna extra que muestre
"FLORES" o "LAPICERA" segn el sexo del empleado (case), de todos los empleados que
cumplen aos en el mes de agosto (where) y ordene por da.

drop table empleados;

create table empleados (


documento char(8),
nombre varchar(30),
fechanacimiento date,
hijos number(2),
sueldo number(6,2),
sexo char(1)
);

insert into empleados values('20000000','Acosta Ana','10/05/1968',0,800,'f');


insert into empleados values('21111111','Bustos
Bernardo','09/07/1970',2,550,'m');
insert into empleados values('22222222','Caseros Carlos','15/10/1971',3,500,'m');
insert into empleados values('23333333','Fuentes Fabiana','25/08/1972',0,500,'f');
insert into empleados values('24444444','Gomez Gaston','28/03/1979',1,850,'m');
insert into empleados values('25555555','Juarez Javier','18/08/1981',2,600,'m');
insert into empleados values('26666666','Lopez Luis','17/09/1978',4,690,'m');
insert into empleados values('27777777','Morales Marta','22/08/1975',2,480,'f');
insert into empleados values('28888888','Norberto Nores','11/08/1973',3,460,'m');
insert into empleados values('29999999','Oscar Oviedo','19/07/1976',0,700,'m');

select nombre,extract (day from fechanacimiento) as dia,


case sexo
when 'f' then 'FLORES'
else 'LAPICERA'
end as regalo
from empleados
where extract(month from fechanacimiento)='08'
order by 2;

Segundo problema:

Un profesor guarda los promedios de sus alumnos de un curso en una tabla llamada "alumnos".

1- Elimine la tabla.

drop table alumnos;

2- Cree la tabla:

create table alumnos(


legajo char(5) not null,
nombre varchar2(30),
promedio number(4,2)
);

3- Ingrese los siguientes registros:

insert into alumnos values(3456,'Perez Luis',8.5);


insert into alumnos values(3556,'Garcia Ana',7.0);
insert into alumnos values(3656,'Luduea Juan',9.6);
insert into alumnos values(2756,'Moreno Gabriela',4.8);
insert into alumnos values(4856,'Morales Hugo',3.2);
insert into alumnos values(7856,'Gomez Susana',6.4);

4- Si el alumno tiene un promedio menor a 4, muestre un mensaje "reprobado", si el promedio


es mayor o igual a 4 y menor a 7, muestre "regular", si el promedio es mayor o igual a 7,
muestre "promocionado", usando "case" (recuerde que "case" toma valores puntuales, emplee
"trunc")

5- Elimine la tabla "alumnos"

6- La nueva tabla contendr varias notas por alumno. Cree la tabla:

create table alumnos(


legajo char(5) not null,
nombre varchar2(30),
nota number(4,2)
);

7- Ingrese los siguientes registros:

insert into alumnos values(3456,'Perez Luis',8.5);


insert into alumnos values(3456,'Perez Luis',9.9);
insert into alumnos values(3456,'Perez Luis',7.8);
insert into alumnos values(3556,'Garcia Ana',7.0);
insert into alumnos values(3556,'Garcia Ana',6.0);
insert into alumnos values(3656,'Luduea Juan',9.6);
insert into alumnos values(3656,'Luduea Juan',10);
insert into alumnos values(2756,'Moreno Gabriela',4.2);
insert into alumnos values(2756,'Moreno Gabriela',2.6);
insert into alumnos values(2756,'Moreno Gabriela',2);
insert into alumnos values(4856,'Morales Hugo',3.2);
insert into alumnos values(4856,'Morales Hugo',4.7);
insert into alumnos values(7856,'Gomez Susana',6.4);
insert into alumnos values(7856,'Gomez Susana',8.6);

8- Si el alumno tiene un promedio menor a 4, muestre un mensaje "reprobado", si el promedio


es mayor o igual a 4 y menor a 7, muestre "regular", si el promedio es mayor o igual a 7,
muestre "promocionado", usando "case" (recuerde que "case" toma valores puntuales, emplee
"trunc"). Para obtener el promedio agrupe por legajo y emplee la funcin "avg"

9- Cree una tabla denominada "alumnosCondicion" con los campos "legajo", "notafinal" y
"condicion":

drop table alumnosCondicion;


create table alumnosCondicion(
legajo char(5),
notafinal number(4,2),
condicion varchar2(15)
);

10- Cree o reemplace un procedimiento almacenado llamado "pa_CargarCondicion" que


guarde en la tabla "alumnosCondicion" el legajo de cada alumno, el promedio de sus notas y
la condicin (libre, regular o promocionado)

11- Ejecute el procedimiento "pa_cargarCondicion" y recupere todos los datos de la tabla


"alumnoscondicion"

drop table alumnos;

create table alumnos(


legajo char(5) not null,
nombre varchar2(30),
promedio number(4,2)
);

insert into alumnos values(3456,'Perez Luis',8.5);


insert into alumnos values(3556,'Garcia Ana',7.0);
insert into alumnos values(3656,'Luduea Juan',9.6);
insert into alumnos values(2756,'Moreno Gabriela',4.8);
insert into alumnos values(4856,'Morales Hugo',3.2);
insert into alumnos values(7856,'Gomez Susana',6.4);

select legajo,promedio,
case trunc(promedio)
when 0 then 'reprobado'
when 1 then 'reprobado'
when 2 then 'reprobado'
when 3 then 'reprobado'
when 4 then 'regular'
when 5 then 'regular'
when 6 then 'regular'
when 7 then 'promocionado'
when 8 then 'promocionado'
when 9 then 'promocionado'
else 'promocionado'
end as Condicion
from alumnos;

drop table alumnos;

create table alumnos(


legajo char(5) not null,
nombre varchar2(30),
nota number(4,2)
);

insert into alumnos values(3456,'Perez Luis',8.5);


insert into alumnos values(3456,'Perez Luis',9.9);
insert into alumnos values(3456,'Perez Luis',7.8);
insert into alumnos values(3556,'Garcia Ana',7.0);
insert into alumnos values(3556,'Garcia Ana',6.0);
insert into alumnos values(3656,'Luduea Juan',9.6);
insert into alumnos values(3656,'Luduea Juan',10);
insert into alumnos values(2756,'Moreno Gabriela',4.2);
insert into alumnos values(2756,'Moreno Gabriela',2.6);
insert into alumnos values(2756,'Moreno Gabriela',2);
insert into alumnos values(4856,'Morales Hugo',3.2);
insert into alumnos values(4856,'Morales Hugo',4.7);
insert into alumnos values(7856,'Gomez Susana',6.4);
insert into alumnos values(7856,'Gomez Susana',8.6);

select legajo,trunc(avg(nota),2),
case trunc(avg(nota))
when 0 then 'reprobado'
when 1 then 'reprobado'
when 2 then 'reprobado'
when 3 then 'reprobado'
when 4 then 'regular'
when 5 then 'regular'
when 6 then 'regular'
when 7 then 'promocionado'
when 8 then 'promocionado'
when 9 then 'promocionado'
else 'promocionado'
end as Condicion
from alumnos
group by legajo;

create table alumnosCondicion(


legajo char(5),
notafinal number(4,2),
condicion varchar2(15)
);

create or replace procedure pa_cargarCondicion


as
begin
insert into alumnoscondicion
select legajo,avg(nota),
case trunc(avg(nota))
when 0 then 'libre'
when 1 then 'libre'
when 2 then 'libre'
when 3 then 'libre'
when 4 then 'regular'
when 5 then 'regular'
when 6 then 'regular'
when 7 then 'promocionado'
when 8 then 'promocionado'
when 9 then 'promocionado'
else 'promocionado'
end
from alumnos
group by legajo;
end;

execute pa_CargarCondicion;
select *from alumnoscondicion;

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(result
ado));
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(result
ado));
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.

100 - Control de flujo (loop)

Problema:

Mostramos la tabla del 3.

En primer lugar activamos el paquete que contiene los procedimientos necesarios para la
salida de datos por pantalla (set serveroutput on) y habilitamos las llamadas a tales
procedimientos.

Declaramos dos variables, "resultado" almacenar el resultado de las multiplicaciones (le


asignamos el valor cero) y "multiplicador" ser la que contenga los diferentes valores por los
cuales multiplicaremos 3 (asignndole el valor cero).

En el ciclo repetitivo se almacena en "resultado" el primer valor ("multiplicador" contiene 0


as que el resultado es cero), luego se imprime, se incrementa la variable "multiplicador"
(ahora contiene 1) y se evala la condicin, dado que "multiplicador" no es mayor a 5, el ciclo
se repite.

Cuando la condicin resulta cierta, es decir, cuando "multiplicador" sea igual a 6, el ciclo
acabar:

set serveroutput on;


execute dbms_output.enable (1000000);
declare
resultado number;
multiplicador number:=0;
begin
loop
resultado:=3*multiplicador;

dbms_output.put_line('3x'||to_char(multiplicador)||'='||to_char(result
ado));
multiplicador:=multiplicador+1;
exit when multiplicador>5;
end loop;
end;

En el siguiente ejemplo se muestra la tabla del 4. Se almacena en una variable "resultado" el


resultado de la multiplicacin, se chequea la condicin, se imprime el resultado y se va
incrementando la variable "multiplicador"; 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(result
ado));
multiplicador:=multiplicador+1;
end loop;
end;

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

100 - Control de flujo (loop)

Primer problema:

Una empresa almacena los datos de sus empleados en una tabla denominada "empleados".

1- Elimine la tabla y crela con la siguiente estructura:

drop table empleados;


create table empleados(
nombre varchar2(40),
sueldo number(6,2)
);

2- Ingrese algunos registros:

insert into empleados values('Acosta Ana',550);


insert into empleados values('Bustos Bernardo',850);
insert into empleados values('Caseros Carolina',900);
insert into empleados values('Dominguez Daniel',490);
insert into empleados values('Fuentes Fabiola',820);
insert into empleados values('Gomez Gaston',740);
insert into empleados values('Huerta Hernan',1050);

3- Muestre la suma total de todos los sueldos realizando un "select" (5400)

4- Se necesita incrementar los sueldos en forma proporcional, en un 10% cada vez y controlar
que la suma total de sueldos no sea menor a $7000, si lo es, el bucle debe continuar y volver
a incrementar los sueldos, en caso de superarlo, se saldr del ciclo repetitivo; es decir, este
bucle continuar el incremento de sueldos hasta que la suma de los mismos llegue o supere
los 7000.

5- Verifique que los sueldos han sido incrementados y la suma de todos los sueldos es superior
a 7000

6- Muestre el sueldo mximo realizando un "select"

7- Se necesita incrementar los sueldos en forma proporcional, en un 5% cada vez y controlar


que el sueldo mximo alcance o supere los $1600, al llegar o superarlo, el bucle debe
finalizar. Incluya una variable contador que cuente cuntas veces se repite el bucle

8- Verifique que los sueldos han sido incrementados y el sueldo mximo es igual o superior a
1600

9- Muestre el sueldo mnimo realizando un "select"

10- Se necesita incrementar los sueldos en forma proporcional, en un 10% cada vez y
controlar que el sueldo mnimo no supere los $900. Emplee la sintaxis "if CONDICION then
exit"

11- Muestre el sueldo mnimo realizando un "select"

drop table empleados;


create table empleados(
nombre varchar2(40),
sueldo number(6,2)
);

insert into empleados values('Acosta Ana',550);


insert into empleados values('Bustos Bernardo',850);
insert into empleados values('Caseros Carolina',900);
insert into empleados values('Dominguez Daniel',490);
insert into empleados values('Fuentes Fabiola',820);
insert into empleados values('Gomez Gaston',740);
insert into empleados values('Huerta Hernan',1050);
select sum(sueldo) from empleados;

declare
total number;
begin
loop
update empleados set sueldo=sueldo+(sueldo*0.1);
select sum(sueldo) into total from empleados;
exit when total>7000;
end loop;
end;

select sueldo from empleados;


select sum(sueldo) from empleados;

select max(sueldo) from empleados;

set serveroutput on;


execute dbms_output.enable (20000);
declare
maximo number;
contador number:=0;
begin
loop
update empleados set sueldo=sueldo+(sueldo*0.05);
contador:=contador+1;
select max(sueldo) into maximo from empleados;
exit when maximo>1600;
end loop;
dbms_output.put_line(contador);
end;

select sueldo from empleados;


select max(sueldo) from empleados;

select min(sueldo) from empleados;

declare
minimo number;
begin
loop
select min(sueldo) into minimo from empleados;
if (minimo+minimo*0.1>900) then exit;
else
update empleados set sueldo=sueldo+(sueldo*0.1);
end if;
end loop;
end;

select min(sueldo) from empleados;

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;
101 - Control de flujo (for)

Problema:
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;


execute dbms_output.enable(20000);
begin
for f in 0..5 loop
dbms_output.put_line('3x'||to_char(f)||'='||to_char(f*3));
end loop;
end;

Para que el contador "f" se decremente en cada repeticin, colocamos "reverse"; el contador
comenzar por el valor del lmite superior (5) y finalizar al llegar al lmite inferior (0)
decrementando de a uno. En este ejemplo mostramos la tabla del 3 desde el 5 hasta el 0:

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;
101 - Control de flujo (for)

Primer problema:

Con la estructura repetitiva "for... loop" que vaya del 1 al 20, muestre los nmeros pares.
Dentro del ciclo debe haber una estructura condicional que controle que el nmero sea par y
si lo es, lo imprima por pantalla.

Con la estructura repetitiva "for... loop" muestre la sumatoria del nmero 5; la suma de todos
los nmeros del 1 al 5. Al finalizar el ciclo debe mostrarse por pantalla la sumatoria de 5 (15)

Cree una funcin que reciba un valor entero y retorne el factorial de tal nmero; el factorial
se obtiene multiplicando el valor que recibe por el anterior hasta llegar a multiplicarlo por
uno)

Llame a la funcin creada anteriormente y obtenga el factorial de 5 y de 4 (120 y 24)

1- Cree un procedimiento que reciba dos parmetros numricos; la funcin debe mostrar la
tabla de multiplicar del nmero enviado como primer argumento, desde el 1 hasta el nmeo
enviado como segundo argumento. Emplee "for"

Execute el procedimiento creado anteriormente envindole los valores necesarios para que
muestre la tabla del 6 hasta el 20
Execute el procedimiento creado anteriormente envindole los valores necesarios para que
muestre la tabla del 9 hasta el 10

set serveroutput on;


execute dbms_output.enable(20000);
begin
for numero in 1..20 loop
if mod(numero,2)=0 then
dbms_output.put_line(numero);
end if;
end loop;
end;

declare
sumatoria number:=0;
begin
for numero in 1..5 loop
sumatoria:=sumatoria+numero;
end loop;
dbms_output.put_line(sumatoria);
end;

create or replace function f_factorial(avalor number)


return number
is
valorretornado number:=1;
begin
for f in reverse 1..avalor loop
valorretornado:=valorretornado*f;
end loop;
return valorretornado;
end;

select f_factorial(5) from dual;


select f_factorial(4) from dual;

create or replace procedure pa_tabla(anumero number, alimite number)


as
begin
dbms_output.put_line('Tabla del '||to_char(anumero));
for f in 1..alimite loop

dbms_output.put_line(to_char(anumero)||'x'||to_char(f)||'='||to_char(f*anumero)
);
end loop;
end;

execute pa_tabla(6,20);

execute pa_tabla(9,10);

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.

102 - Control de flujo (while loop)


Problema:

Mostramos la tabla del 3 hasta el 5. En primer lugar activamos el paquete "dbms_output" para
poder emplear los procedimientos de dicho paquete, luego ejecutamos el procedimiento
"dbms_output.enable" para habilitar las llamadas a los procedimientos y funciones de tal
paquete, as podremos emplear la funcin de salida "dbms_output.put_line".

set server output on;


execute dbms_output.enable (1000000);

Luego, declaramos la variable numrica "numero" y le asignamos el valor cero; tal variable
contendr el multiplicando. Tambin declaramos la variable "resultado" de tipo numrico que
almacenar el resultado de cada multiplicacin. Comenzamos el bloque "begin... end" con la
estructura repetitiva "while... loop". La condicin chequea si el valor de la variable "numero"
es menmor o igual a 5; las sentencias que se repetirn sern:

- multiplicar "numero" por 3 y asignrselo a "resultado",

- imprimir "resultado" y

- incrementar la variable "numero" para que la siguiente vez que se entre al bucle repetitivo
se multiplique 3 por otro nmero.

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;
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").

105 - Disparador de insercin a nivel de sentencia

Problema:

Una librera almacena los datos de sus libros en una tabla denominada "libros" y controla las
acciones que los empleados realizan sobre dicha tabla almacenando en la tabla "control" el
nombre del usuario y la fecha, cada vez que se ingresa un registro en la tabla "libros".

Eliminamos la tabla:

drop table libros;

Creamos la tabla con la siguiente estructura:

create table libros(


codigo number(6),
titulo varchar2(40),
autor varchar2(30),
precio number(6,2)
);

Creamos la tabla "control", antes la eliminamos:

drop table control;


create table control(
usuario varchar2(30),
fecha date
);

Creamos un disparador que se dispare cada vez que se ingrese un registro en "libros"; el
trigger debe ingresar en la tabla "control", el nombre del usuario, la fecha y la hora en la cual
se realiz un "insert" sobre "libros":

create or replace trigger tr_ingresar_libros


before insert
on libros
begin
insert into Control values(user,sysdate);
end tr_ingresar_libros;

Establecemos el formato de fecha para que muestre "DD/MM/YYYY HH24:MI":

alter session set NLS_DATE_FORMAT = 'DD/MM/YYYY HH24:MI';

Veamos qu nos informa el diccionario "user_triggers" respecto del trigger anteriormente


creado:

select *from user_triggers where trigger_name ='TR_INGRESAR_LIBROS';


obtenemos la siguiente informacin:

- trigger_name: nombre del disparador;

- trigger_type: momento y nivel, en este caso es un desencadenador "before" y a nivel de


sentencia (statement);

- triggering_event: evento que lo dispara, en este caso, "insert";

- base_object_type: a qu objeto est asociado, puede ser una tabla o una vista, en este
caso, una tabla (table);

- table_name: nombre de la tabla al que est asociado (libros);

- y otras columnas que no analizaremos por el momento.

Ingresamos un registro en "libros":

insert into libros values(100,'Uno','Richard Bach',25);

Verificamos que el trigger se dispar consultando la tabla "control" para ver si tiene un nuevo
registro:

select *from control;

Ingresamos dos registros ms en "libros":

insert into libros values(150,'Matematica estas ahi','Paenza',12);


insert into libros values(185,'El aleph','Borges',42);

Verificamos que el trigger se dispar consultando la tabla "control" para ver si tiene dos
nuevos registros:

select *from control;


105 - Disparador de insercin a nivel de sentencia

Primer problema:

Una librera almacena los datos de sus libros en una tabla denominada "libros" y en una tabla
"ofertas", algunos datos de los libros cuyo precio no supera los $30. Adems, controla las
inserciones que los empleados realizan sobre "ofertas", almacenando en la tabla "control" el
nombre del usuario, la fecha y hora, cada vez que se ingresa un nuevo registro en la tabla
"ofertas".

1- Elimine las tres tablas:

drop table libros;


drop table ofertas;
drop table control;

2- Cree las tablas con las siguientes estructuras:

create table libros(


codigo number(6),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(6,2)
);

create table ofertas(


titulo varchar2(40),
autor varchar2(30),
precio number(6,2)
);

create table control(


usuario varchar2(30),
fecha date
);

3- Establezca el formato de fecha para que muestre "DD/MM/YYYY HH24:MI":

4- Cree un disparador que se dispare cuando se ingrese un nuevo registro en "ofertas"; el


trigger debe ingresar en la tabla "control", el nombre del usuario, la fecha y la hora en la cual
se realiz un "insert" sobre "ofertas"

5- Vea qu informa el diccionario "user_triggers" respecto del trigger anteriormente creado

6- Ingrese algunos registros en "libros"

insert into libros values(100,'Uno','Richard Bach','Planeta',25); insert into libros


values(102,'Matematica estas ahi','Paenza','Nuevo siglo',12); insert into libros values(105,'El
aleph','Borges','Emece',32); insert into libros values(120,'Aprenda PHP','Molina Mario','Nuevo
siglo',55);

7- Ingrese en "ofertas" los libros de "libros" cuyo precio no superen los $30, utilizando la
siguiente sentencia:

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

8- Verifique que el trigger se dispar consultando la tabla "control"

drop table libros;


drop table ofertas;
drop table control;

create table libros(


codigo number(6),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(6,2)
);

create table ofertas(


titulo varchar2(40),
autor varchar2(30),
precio number(6,2)
);

create table control(


usuario varchar2(30),
fecha date
);

alter session set NLS_DATE_FORMAT = 'DD/MM/YYYY HH24:MI';

create or replace trigger tr_ingresar_ofertas


before insert
on ofertas
begin
insert into Control values(user,sysdate);
end tr_ingresar_ofertas;

select *from user_triggers where trigger_name ='TR_INGRESAR_OFERTAS';

insert into libros values(100,'Uno','Richard Bach','Planeta',25);


insert into libros values(102,'Matematica estas ahi','Paenza','Nuevo siglo',12);
insert into libros values(105,'El aleph','Borges','Emece',32);
insert into libros values(120,'Aprenda PHP','Molina Mario','Nuevo siglo',55);

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

select *from control;

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".

106 - Disparador de insercion a nivel de fila (insert trigger for each


row)

Problema:

Una librera almacena los datos de sus libros en una tabla denominada "libros" y en una tabla
"ofertas", algunos datos de los libros cuyo precio no supera los $30. Adems, controla las
inserciones que los empleados realizan sobre "ofertas", almacenando en la tabla "control" el
nombre del usuario, la fecha y hora, cada vez que se ingresa un nuevo registro en la tabla
"ofertas".

Creamos un desencadenador que se dispara una vez por cada registro ingresado en la tabla
"ofertas":

Eliminamos las tres tablas:

drop table libros;


drop table ofertas;
drop table control;

Creamos las tablas con las siguientes estructuras:

create table libros(


codigo number(6),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(6,2)
);

create table ofertas(


titulo varchar2(40),
autor varchar2(30),
precio number(6,2)
);

create table control(


usuario varchar2(30),
fecha date
);
Establecemos el formato de fecha para que muestre "DD/MM/YYYY HH24:MI":

alter session set NLS_DATE_FORMAT = 'DD/MM/YYYY HH24:MI';

Creamos un disparador que se dispare una vez por cada registro ingresado en "ofertas"; el
trigger debe ingresar en la tabla "control", el nombre del usuario, la fecha y la hora en la cual
se realiz un "insert" sobre "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;

Veamos qu nos informa el diccionario "user_triggers" respecto del trigger anteriormente


creado:

select *from user_triggers where trigger_name ='TR_INGRESAR_OFERTAS';

Ingresamos algunos registros en "libros":

insert into libros values(100,'Uno','Richard Bach','Planeta',25);


insert into libros values(102,'Matematica estas ahi','Paenza','Nuevo
siglo',12);
insert into libros values(105,'El aleph','Borges','Emece',32);
insert into libros values(120,'Aprenda PHP','Molina Mario','Nuevo
siglo',55);

Ingresamos en "ofertas" los libros de "libros" cuyo precio no superen los $30, utilizando la
siguiente sentencia:

insert into ofertas select titulo,autor,precio from libros where


precio<30;

Verificamos que el trigger se dispar 2 veces, una por cada fila afectada en la sentencia
"insert" anteriormente ejecutada; consultamos la tabla "control":

select *from control;

Si el trigger hubiese sido creado a nivel de sentencia, no de fila, el "insert" anterior se


hubiese activado una sola vez aun cuando se ingresaron 2 registros.

106 - Disparador de insercion a nivel de fila (insert trigger for each


row)

Primer problema:

Una empresa almacena los datos de sus empleados en una tabla denominada "empleados" y en
una tabla "control", el nombre del usuario y la fecha, cada vez que se ingresa un nuevo
registro en la tabla "empleados".

1 Elimine las tablas:


drop table empleados;
drop table control;

2- Cree las tablas con las siguientes estructuras:

create table empleados(


documento char(8),
apellido varchar2(30),
nombre varchar2(30),
seccion varchar2(20)
);

create table control(


usuario varchar2(30),
fecha date
);

3- Cree un disparador que se dispare una vez por cada registro ingresado en "empleados"; el
trigger debe ingresar en la tabla "control", el nombre del usuario y la fecha en la cual se
realiz un "insert" sobre "empleados"

4- Vea qu nos informa el diccionario "user_triggers" respecto del trigger anteriormente


creado

5- Ingrese algunos registros en "empleados":

insert into empleados values('22333444','ACOSTA','Ana','Secretaria');


insert into empleados values('22777888','DOMINGUEZ','Daniel','Secretaria');
insert into empleados values('22999000','FUENTES','Federico','Sistemas');
insert into empleados values('22555666','CASEROS','Carlos','Contaduria');
insert into empleados values('23444555','GOMEZ','Gabriela','Sistemas');
insert into empleados values('23666777','JUAREZ','Juan','Contaduria');

6- Verifique que el trigger se dispar 6 veces, una por cada fila afectada en la sentencia
"insert" anteriormente ejecutada; consultamos la tabla "control":

select *from control;

Si el trigger hubiese sido creado a nivel de sentencia, no de fila, el "insert" anterior se


hubiese activado una sola vez an cuando se ingresaron 6 registros.

drop table empleados;


drop table control;

create table empleados(


documento char(8),
apellido varchar2(30),
nombre varchar2(30),
seccion varchar2(20)
);

create table control(


usuario varchar2(30),
fecha date
);

create or replace trigger tr_ingresar_empleados


before insert
on empleados
for each row
begin
insert into Control values(user,sysdate);
end tr_ingresar_empleados;

select *from user_triggers where trigger_name ='TR_INGRESAR_EMPLEADOS';

insert into empleados values('22333444','ACOSTA','Ana','Secretaria');


insert into empleados values('22777888','DOMINGUEZ','Daniel','Secretaria');
insert into empleados values('22999000','FUENTES','Federico','Sistemas');
insert into empleados values('22555666','CASEROS','Carlos','Contaduria');
insert into empleados values('23444555','GOMEZ','Gabriela','Sistemas');
insert into empleados values('23666777','JUAREZ','Juan','Contaduria');

select *from 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;
107 - Disparador de borrado (nivel de sentencia y de fila)

Problema:

Una librera almacena los datos de sus libros en una tabla denominada "libros" y controla las
acciones que los empleados realizan sobre dicha tabla almacenando en la tabla "control" el
nombre del usuario y la fecha, cada vez que se elimina un registro de la tabla "libros".

Eliminamos la tabla "libros" y la tabla "control":

drop table libros;


drop table control;

Creamos las tablas con las siguientes estructuras:

create table libros(


codigo number(6),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(6,2)
);

create table control(


usuario varchar2(30),
fecha date
);

Ingresamos algunos registros en "libros":

insert into libros values(97,'Uno','Richard Bach','Planeta',25);


insert into libros values(98,'El aleph','Borges','Emece',28);
insert into libros values(99,'Matematica estas ahi','Paenza','Nuevo
siglo',12);
insert into libros values(100,'Aprenda PHP','Molina Mario','Nuevo
siglo',55);
insert into libros values(101,'Alicia en el pais de las
maravillas','Carroll','Planeta',35);
insert into libros values(102,'El experto en
laberintos','Gaskin','Planeta',20);

Establecemos el formato de fecha para que muestre "DD/MM/YYYY HH24:MI":

alter session set NLS_DATE_FORMAT = 'DD/MM/YYYY HH24:MI';

Creamos un disparador a nivel de fila, que se dispare cada vez que se borre un registro de
"libros"; el trigger debe ingresar en la tabla "control", el nombre del usuario, la fecha y la
hora en la cual se realiz un "delete" sobre "libros":

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;

Veamos qu nos informa el diccionario "user_triggers" respecto del trigger anteriormente


creado:

select *from user_triggers where trigger_name ='TR_BORRAR_LIBROS';

obtenemos la siguiente informacin:

- trigger_name: nombre del disparador;

- trigger_type: momento y nivel, en este caso es un desencadenador "before" y a nivel de fila


(each row);

- triggering_event: evento que lo dispara, en este caso, "delete";

- base_object_type: a qu objeto est asociado, puede ser una tabla o una vista, en este
caso, una tabla (table);

- table_name: nombre de la tabla al que est asociado (libros);

- y otras columnas que no analizaremos por el momento.

Eliminamos todos los libros cuyo cdigo sea inferior a 100:

delete from libros where codigo<100;

Veamos si el trigger se dispar consultando la tabla "control":

select *from control;

Se eliminaron 3 registros, como el trigger fue definido a nivel de fila, se dispar 3 veces, una
vez por cada registro eliminado. Si el trigger hubiese sido definido a nivel de sentencia, se
hubiese disparado una sola vez.

Reemplazamos el disparador creado anteriormente por otro con igual cdigo pero a nivel de
sentencia:

create or replace trigger tr_borrar_libros


before delete
on libros
begin
insert into control values(user,sysdate);
end tr_borrar_libros;

Veamos qu nos informa el diccionario "user_triggers" respecto del trigger anteriormente


creado:

select *from user_triggers where trigger_name ='TR_BORRAR_LIBROS';

en este caso es un desencadenador a nivel de sentencia.

Eliminamos todos los libros cuya editorial sea "Planeta":

delete from libros where editorial='Planeta';

Se han eliminado 2 registros, pero el trigger se ha disparado una sola vez, consultamos la
tabla "control":

select *from control;

Si el trigger hubiese sido definido a nivel de fila, se hubiese disparado dos veces.

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

Primer problema:

Una empresa almacena los datos de sus empleados en una tabla denominada "empleados" y en
otra llamada "control" guarda un registro por cada empleado que se elimina de la tabla
"empleados".

1- Elimine las tablas:

drop table empleados;


drop table control;

2- Cree las tablas con las siguientes estructuras:

create table empleados(


documento char(8),
apellido varchar2(20),
nombre varchar2(20),
seccion varchar2(30),
sueldo number(8,2)
);

create table control(


usuario varchar2(30),
fecha date
);

3- Ingrese algunos registros en "empleados":

insert into empleados values('22333444','ACOSTA','Ana','Secretaria',500);


insert into empleados values('22777888','DOMINGUEZ','Daniel','Secretaria',560);
insert into empleados values('22999000','FUENTES','Federico','Sistemas',680);
insert into empleados values('22555666','CASEROS','Carlos','Contaduria',900);
insert into empleados values('23444555','GOMEZ','Gabriela','Sistemas',1200);
insert into empleados values('23666777','JUAREZ','Juan','Contaduria',1000);

4- Cree un disparador a nivel de fila, que se dispare cada vez que se borre un registro de
"empleados"; el trigger debe ingresar en la tabla "control", el nombre del usuario y la fecha en
la cual se realiz un "delete" sobre "empleados"

5- Vea qu informa el diccionario "user_triggers" respecto del trigger anteriormente creado

6- Elimine todos los empleados cuyo sueldo supera los $800

7- Vea si el trigger se dispar consultando la tabla "control"


Se eliminaron 3 registros, como el trigger fue definido a nivel de fila, se dispar 3 veces, una
vez por cada registro eliminado. Si el trigger hubiese sido definido a nivel de sentencia, se
hubiese disparado una sola vez.

8- Reemplace el disparador creado anteriormente por otro con igual cdigo pero a nivel de
sentencia

9- Vea qu nos informa el diccionario "user_triggers" respecto del trigger anteriormente


creado
en este caso es un desencadenador a nivel de sentencia; en la columna "TRIGGER_TYPE"
muestra "BEFORE STATEMENT".

10- Elimine todos los empleados de la seccin "Secretaria"


Se han eliminado 2 registros, pero el trigger se ha disparado una sola vez.

11- Consultamos la tabla "control"


Si el trigger hubiese sido definido a nivel de fila, se hubiese disparado dos veces.

drop table empleados;


drop table control;

create table empleados(


documento char(8),
apellido varchar2(20),
nombre varchar2(20),
seccion varchar2(30),
sueldo number(8,2)
);

create table control(


usuario varchar2(30),
fecha date
);

insert into empleados values('22333444','ACOSTA','Ana','Secretaria',500);


insert into empleados values('22777888','DOMINGUEZ','Daniel','Secretaria',560);
insert into empleados values('22999000','FUENTES','Federico','Sistemas',680);
insert into empleados values('22555666','CASEROS','Carlos','Contaduria',900);
insert into empleados values('23444555','GOMEZ','Gabriela','Sistemas',1200);
insert into empleados values('23666777','JUAREZ','Juan','Contaduria',1000);

create or replace trigger tr_borrar_empleados


before delete
on empleados
for each row
begin
insert into control values(user,sysdate);
end tr_borrar_empleados;

select *from user_triggers where trigger_name ='TR_BORRAR_EMPLEADOS';

delete from empleados where sueldo>800;

select *from control;

create or replace trigger tr_borrar_empleados


before delete
on empleados
begin
insert into control values(user,sysdate);
end tr_borrar_empleados;

select *from user_triggers where trigger_name ='TR_BORRAR_EMPLEADOS';

delete from empleados where seccion='Secretaria';

select *from control;

08 - 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").

108 - Disparador de actualizacion a nivel de sentencia (update


trigger)

Problema:

Una librera almacena los datos de sus libros en una tabla denominada "libros" y controla las
acciones que los empleados realizan sobre dicha tabla almacenando en la tabla "control" el
nombre del usuario y la fecha, cada vez que se modifica un registro en la tabla "libros".

Eliminamos la tabla "libros" y la tabla "control":

drop table libros;


drop table control;

Creamos la tabla con la siguiente estructura:

create table libros(


codigo number(6),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(6,2)
);

Creamos la tabla "control":


create table control(
usuario varchar2(30),
fecha date
);

Ingresamos algunos registros en "libros":

insert into libros values(100,'Uno','Richard Bach','Planeta',25);


insert into libros values(103,'El aleph','Borges','Emece',28);
insert into libros values(105,'Matematica estas ahi','Paenza','Nuevo
siglo',12);
insert into libros values(120,'Aprenda PHP','Molina Mario','Nuevo
siglo',55);
insert into libros values(145,'Alicia en el pais de las
maravillas','Carroll','Planeta',35);

Establecemos el formato de fecha para que muestre "DD/MM/YYYY HH24:MI":

alter session set NLS_DATE_FORMAT = 'DD/MM/YYYY HH24:MI';

Creamos un disparador a nivel de sentencia, que se dispare cada vez que se actualice un
registro en "libros"; el trigger debe ingresar en la tabla "control", el nombre del usuario, la
fecha y la hora en la cual se realiz un "update" sobre "libros":

create or replace trigger tr_actualizar_libros


before update
on libros
begin
insert into control values(user,sysdate);
end tr_actualizar_libros;

Veamos qu nos informa el diccionario "user_triggers" respecto del trigger anteriormente


creado:

select *from user_triggers where trigger_name


='TR_ACTUALIZAR_LIBROS';

obtenemos la siguiente informacin:

- trigger_name: nombre del disparador;

- trigger_type: momento y nivel, en este caso es un desencadenador "before" y a nivel de


sentencia (statement);

- triggering_event: evento que lo dispara, en este caso, "update";

- base_object_type: a qu objeto est asociado, puede ser una tabla o una vista, en este
caso, una tabla (table);

- table_name: nombre de la tabla al que est asociado (libros);

- y otras columnas que no analizaremos por el momento.

Actualizamos un registro en "libros":

update libros set codigo=99 where codigo=100;


Veamos si el trigger se dispar consultando la tabla "control":

select *from control;

Actualizamos varios registros de "libros":

update libros set precio=precio+precio*0.1 where editorial='Nuevo


siglo';

Veamos si el trigger se dispar consultando la tabla "control":

select *from control;

Note que se modificaron 2 registros de "libros", pero como la modificacin se realiz con una
sola sentencia "update" y el trigger es a nivel de sentencia, se agreg solamente una fila a la
tabla "control"; si el trigger hubiese sido creado a nivel de fila, la sentencia anterior, hubiese
disparado el trigger 2 veces y habra ingresado en "control" 2 filas.

108 - Disparador de actualizacion a nivel de sentencia (update


trigger)

Primer problema:

Una empresa almacena los datos de sus empleados en una tabla denominada "empleados" y en
otra llamada "control" guarda un registro por cada vez que un empleado actualiza datos sobre
la tabla "empleados".

1- Elimine las tablas:

drop table empleados;


drop table control;

2- Cree las tablas con las siguientes estructuras:

create table empleados(


documento char(8),
apellido varchar2(20),
nombre varchar2(20),
seccion varchar2(30),
sueldo number(8,2)
);

create table control(


usuario varchar2(30),
fecha date
);

3- Ingrese algunos registros en "empleados":

insert into empleados values('22333444','ACOSTA','Ana','Secretaria',500);


insert into empleados values('22777888','DOMINGUEZ','Daniel','Secretaria',560);
insert into empleados values('22999000','FUENTES','Federico','Sistemas',680);
insert into empleados values('22555666','CASEROS','Carlos','Contaduria',900);
insert into empleados values('23444555','GOMEZ','Gabriela','Sistemas',1200);
insert into empleados values('23666777','JUAREZ','Juan','Contaduria',1000);

4- Cree un disparador a nivel de sentencia, que se dispare cada vez que se actualicen
registros en "empleados"; el trigger debe ingresar en la tabla "control", el nombre del usuario
y la fecha en la cual se realiz un "update" sobre "empleados"

5- Vea qu informa el diccionario "user_triggers" respecto del trigger anteriormente creado

6- Actualice un registro en "empleados":

update empleados set nombre='Graciela' where documento='23444555';

7- Vea si el trigger se dispar consultando la tabla "control"

8- Actualice varios registros de "empleados" en una sola sentencia

9- Vea si el trigger se dispar consultando la tabla "control"


Note que se modificaron 2 registros de "empleados", pero como la modificacin se realiz con
una sola sentencia "update" y el trigger es a nivel de sentencia, se agreg solamente una fila a
la tabla "control"; si el trigger hubiese sido creado a nivel de fila, la sentencia anterior,
hubiese disparado el trigger 2 veces y habra ingresado en "control" 2 filas.

drop table empleados;


drop table control;

create table empleados(


documento char(8),
apellido varchar2(20),
nombre varchar2(20),
seccion varchar2(30),
sueldo number(8,2)
);

create table control(


usuario varchar2(30),
fecha date
);

insert into empleados values('22333444','ACOSTA','Ana','Secretaria',500);


insert into empleados values('22777888','DOMINGUEZ','Daniel','Secretaria',560);
insert into empleados values('22999000','FUENTES','Federico','Sistemas',680);
insert into empleados values('22555666','CASEROS','Carlos','Contaduria',900);
insert into empleados values('23444555','GOMEZ','Gabriela','Sistemas',1200);
insert into empleados values('23666777','JUAREZ','Juan','Contaduria',1000);

create or replace trigger tr_actualizar_empleados


before update
on empleados
begin
insert into control values(user,sysdate);
end tr_actualizar_empleados;

select *from user_triggers where trigger_name ='TR_ACTUALIZAR_EMPLEADOS';


update empleados set nombre='Graciela' where documento='23444555';

select *from control;

update empleados set sueldo=sueldo+sueldo*0.1 where seccion='Secretaria';

select *from control;

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".

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

Problema:

Una librera almacena los datos de sus libros en una tabla denominada "libros" y controla las
acciones que los empleados realizan sobre dicha tabla almacenando en la tabla "control" el
nombre del usuario y la fecha, cada vez que se modifica un registro en la tabla "libros".

Eliminamos las tablas:


drop table control;
drop table libros;

Creamos las tablas con las siguientes estructuras:

create table libros(


codigo number(6),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(6,2)
);

create table control(


usuario varchar2(30),
fecha date
);

Ingresamos algunos registros en "libros":

insert into libros values(100,'Uno','Richard Bach','Planeta',25);


insert into libros values(103,'El aleph','Borges','Emece',28);
insert into libros values(105,'Matematica estas ahi','Paenza','Nuevo
siglo',12);
insert into libros values(120,'Aprenda PHP','Molina Mario','Nuevo
siglo',55);
insert into libros values(145,'Alicia en el pais de las
maravillas','Carroll','Planeta',35);

Establecemos el formato de fecha para que muestre "DD/MM/YYYY HH24:MI":

alter session set NLS_DATE_FORMAT = 'DD/MM/YYYY HH24:MI';

Creamos un disparador que se dispare cada vez que se actualice un registro en "libros"; el
trigger debe ingresar en la tabla "control", el nombre del usuario, la fecha y la hora en la cual
se realiz un "update" sobre "libros":

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;

Actualizamos varios registros de "libros". Aumentamos en un 10% el precio de todos los libros
de editorial "Nuevo siglo':

update libros set precio=precio+precio*0.1 where editorial='Nuevo


siglo';

Veamos cuntas veces se dispar el trigger consultando la tabla "control":

select *from control;


El trigger se dispar 2 veces, una vez por cada registro modificado en "libros". Si el trigger
hubiese sido creado a nivel de sentencia, el "update" anterior hubiese disparado el trigger 1
sola vez an cuando se modifican 2 filas.

Veamos qu nos informa el diccionario "user_triggers" respecto del trigger anteriormente


creado:

select *from user_triggers where trigger_name


='TR_ACTUALIZAR_LIBROS';

obtenemos el nombre del disparador, el momento y nivel (before each row), evento que lo
dispara (update), a qu objeto est asociado (table), nombre de la tabla al que est asociado
(libros) y otras columnas que no analizaremos por el momento.

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

Primer problema:

Una empresa almacena los datos de sus empleados en una tabla denominada "empleados" y en
otra llamada "control" guarda un registro por cada vez que un empleado actualiza datos sobre
la tabla "empleados".

1- Elimine las tablas:

drop table empleados;


drop table control;

2- Cree las tablas con las siguientes estructuras:

create table empleados(


documento char(8),
apellido varchar2(20),
nombre varchar2(20),
seccion varchar2(30),
sueldo number(8,2)
);

create table control(


usuario varchar2(30),
fecha date
);

3- Ingrese algunos registros en "empleados":

insert into empleados values('22333444','ACOSTA','Ana','Secretaria',500);


insert into empleados values('22777888','DOMINGUEZ','Daniel','Secretaria',560);
insert into empleados values('22999000','FUENTES','Federico','Sistemas',680);
insert into empleados values('22555666','CASEROS','Carlos','Contaduria',900);
insert into empleados values('23444555','GOMEZ','Gabriela','Sistemas',1200);
insert into empleados values('23666777','JUAREZ','Juan','Contaduria',1000);

4- Cree un disparador que se dispare cada vez que se actualice un registro en "empleados"; el
trigger debe ingresar en la tabla "control", el nombre del usuario y la fecha en la cual se
realiz un "update" sobre "empleados"
5- Actualice varios registros de "empleados". Aumentamos en un 10% el sueldo de todos los
empleados de la seccion "Secretaria'

6- Vea cuntas veces se dispar el trigger consultando la tabla "control"

7- El trigger se dispar 2 veces, una vez por cada registro modificado en "empleados". Si el
trigger hubiese sido creado a nivel de sentencia, el "update" anterior hubiese disparado el
trigger 1 sola vez an cuando se modifican 2 filas.

8- Vea qu informa el diccionario "user_triggers" respecto del trigger anteriormente creado


obtenemos el nombre del disparador, el momento y nivel (before each row), evento que lo
dispara (update), a qu objeto est asociado (table), nombre de la tabla al que est asociado
(empleados) y otras columnas que no analizaremos por el momento.

drop table empleados;


drop table control;

create table empleados(


documento char(8),
apellido varchar2(20),
nombre varchar2(20),
seccion varchar2(30),
sueldo number(8,2)
);

create table control(


usuario varchar2(30),
fecha date
);

insert into empleados values('22333444','ACOSTA','Ana','Secretaria',500);


insert into empleados values('22777888','DOMINGUEZ','Daniel','Secretaria',560);
insert into empleados values('22999000','FUENTES','Federico','Sistemas',680);
insert into empleados values('22555666','CASEROS','Carlos','Contaduria',900);
insert into empleados values('23444555','GOMEZ','Gabriela','Sistemas',1200);
insert into empleados values('23666777','JUAREZ','Juan','Contaduria',1000);

create or replace trigger tr_actualizar_empleados


before update
on empleados
for each row
begin
insert into control values(user,sysdate);
end tr_actualizar_empleados;

update empleados set sueldo=sueldo+sueldo*0.1 where seccion='Secretaria';

select *from control;

select *from user_triggers where trigger_name ='TR_ACTUALIZAR_EMPLEADOS';

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".

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

Problema:

Una librera almacena los datos de sus libros en una tabla denominada "libros" y controla las
acciones que los empleados realizan sobre dicha tabla almacenando en la tabla "control" el
nombre del usuario y la fecha, cada vez que se modifica el "precio" de un libro.

Eliminamos las tablas:

drop table control;


drop table libros;

Creamos las tablas con las siguientes estructuras:

create table libros(


codigo number(6),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(6,2)
);

create table control(


usuario varchar2(30),
fecha date
);

Ingresamos algunos registros en "libros":

insert into libros values(100,'Uno','Richard Bach','Planeta',25);


insert into libros values(103,'El aleph','Borges','Emece',28);
insert into libros values(105,'Matematica estas ahi','Paenza','Nuevo
siglo',12);
insert into libros values(120,'Aprenda PHP','Molina Mario','Nuevo
siglo',55);
insert into libros values(145,'Alicia en el pais de las
maravillas','Carroll','Planeta',35);

Establecemos el formato de fecha para que muestre "DD/MM/YYYY HH24:MI":

alter session set NLS_DATE_FORMAT = 'DD/MM/YYYY HH24:MI';

Creamos un desencadenador a nivel de fila que se dispare cada vez que se actualiza el campo
"precio"; el trigger debe ingresar en la tabla "control", el nombre del usuario, la fecha y la
hora en la cual se realiz un "update" sobre "precio" de "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;

Veamos qu nos informa el diccionario "user_triggers" respecto del trigger anteriormente


creado:

select *from user_triggers where trigger_name


='TR_ACTUALIZAR_PRECIO_LIBROS';

Aumentamos en un 10% el precio de todos los libros de editorial "Nuevo siglo':

update libros set precio=precio+precio*0.1 where editorial='Nuevo


siglo';

Veamos cuntas veces se dispar el trigger consultando la tabla "control":

select *from control;

El trigger se dispar 2 veces, una vez por cada registro modificado en "libros". Si el trigger
hubiese sido creado a nivel de sentencia, el "update" anterior hubiese disparado el trigger 1
sola vez an cuando se modifican 2 filas.

Modificamos otro campo, diferente de "precio":


update libros set autor='Lewis Carroll' where autor='Carroll';

Veamos si el trigger se dispar consultando la tabla "control":

select *from control;

El trigger no se dispar (no hay nuevas filas en "control"), pues est definido solamente sobre
el campo "precio".

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

Primer problema:

Una librera almacena los datos de sus libros en una tabla denominada "libros" y controla las
acciones que los empleados realizan sobre dicha tabla almacenando en la tabla "control" el
nombre del usuario y la fecha, cada vez que se modifica el precio o la editorial de un libro.

1- Elimine las tablas:

drop table control;


drop table libros;

2- Cree las tablas con las siguientes estructuras:

create table libros(


codigo number(6),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(6,2)
);

create table control(


usuario varchar2(30),
fecha date
);

3- Ingrese algunos registros en "libros":

insert into libros values(100,'Uno','Richard Bach','Planeta',25);


insert into libros values(103,'El aleph','Borges','Emece',28);
insert into libros values(105,'Matematica estas ahi','Paenza','Nuevo siglo',12);
insert into libros values(120,'Aprenda PHP','Molina Mario','Nuevo siglo',55);
insert into libros values(145,'Alicia en el pais de las
maravillas','Carroll','Planeta',35);

4- Establezca el formato de fecha para que muestre "DD/MM/YYYY HH24:MI":

alter session set NLS_DATE_FORMAT = 'DD/MM/YYYY HH24:MI';

5- Cree un desencadenador a nivel de sentencia que se dispare cada vez que se actualicen los
campos "precio" y "editorial" ; el trigger debe ingresar en la tabla "control", el nombre del
usuario, la fecha y la hora en la cual se realiz un "update" sobre "precio" o "editorial" de
"libros"
6- Vea qu informa el diccionario "user_triggers" respecto del trigger anteriormente creado

7- Aumente en un 10% el precio de todos los libros de editorial "Nuevo siglo'

8- Vea cuntas veces se dispar el trigger consultando la tabla "control"


El trigger se dispar 1 vez.

9- Cambie la editorial, de "Planeta" a "Sudamericana"

10- Veamos si el trigger se dispar consultando la tabla "control"


El trigger se dispar.

11- Modifique un campo diferente de los que activan el trigger

12- Verifique que el cambio se realiz

13- Verifique que el trigger no se dispar


El trigger no se dispar (no hay nuevas filas en "control"), pues est definido nicamente
sobre los campos "precio" y "editorial".

drop table control;


drop table libros;

create table libros(


codigo number(6),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(6,2)
);

create table control(


usuario varchar2(30),
fecha date
);

insert into libros values(100,'Uno','Richard Bach','Planeta',25);


insert into libros values(103,'El aleph','Borges','Emece',28);
insert into libros values(105,'Matematica estas ahi','Paenza','Nuevo siglo',12);
insert into libros values(120,'Aprenda PHP','Molina Mario','Nuevo siglo',55);
insert into libros values(145,'Alicia en el pais de las
maravillas','Carroll','Planeta',35);

alter session set NLS_DATE_FORMAT = 'DD/MM/YYYY HH24:MI';

create or replace trigger tr_actualizar_precio_libros


before update of precio,editorial
on libros
begin
insert into control values(user,sysdate);
end tr_actualizar_precio_libros;
select *from user_triggers where trigger_name
='TR_ACTUALIZAR_PRECIO_LIBROS';

update libros set precio=precio+precio*0.1 where editorial='Nuevo siglo';

select *from control;

update libros set editorial='Sudamericana' where editorial='Planeta';

select *from control;

update libros set autor='Lewis Carroll' where autor='Carroll';

select *from libros;

select *from control;

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 into TABLA values ...;


insert into TABLA select ... from...;
update TABLA set...;
delete from TABLA...;
111 - Disparador de mltiples eventos

Problema:

Una librera almacena los datos de sus libros en una tabla denominada "libros" y controla las
acciones que los empleados realizan sobre dicha tabla almacenando en la tabla "control" el
nombre del usuario, la fecha, y el tipo de modificacin que se realiz sobre la tabla "libros".

Eliminamos la tabla "libros" y la tabla "control":

drop table libros;


drop table control;

Creamos la tabla con la siguiente estructura:

create table libros(


codigo number(6),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(6,2)
);

Creamos la tabla "control":

create table control(


usuario varchar2(30),
fecha date,
operacion varchar2(20)
);

Ingresamos algunos registros en "libros":


insert into libros values(100,'Uno','Richard Bach','Planeta',25);
insert into libros values(103,'El aleph','Borges','Emece',28);
insert into libros values(105,'Matematica estas ahi','Paenza','Nuevo
siglo',12);
insert into libros values(120,'Aprenda PHP','Molina Mario','Nuevo
siglo',55);
insert into libros values(145,'Alicia en el pais de las
maravillas','Carroll','Planeta',35);

Establecemos el formato de fecha para que muestre "DD/MM/YYYY HH24:MI":

alter session set NLS_DATE_FORMAT = 'DD/MM/YYYY HH24:MI';

Creamos un disparador a nivel de sentencia, que se dispare cada vez que se ingrese, actualice
o elimine un registro de la tabla "libros". El trigger ingresa en la tabla "control", el nombre del
usuario, la fecha y la hora en la cual se realiz la modificacin y el tipo de operacin que se
realiz:

- si se realiz una insercin (insert), 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;

Veamos qu nos informa el diccionario "user_triggers" respecto del trigger anteriormente


creado:

select *from user_triggers where trigger_name ='TR_CAMBIOS_LIBROS';

obtenemos la siguiente informacin:

- trigger_name: nombre del disparador;

- trigger_type: momento y nivel, en este caso es un desencadenador "before" y a nivel de fila


(each row);

- triggering_event: evento que lo dispara, en este caso, "insert or update or delete";

- base_object_type: a qu objeto est asociado, puede ser una tabla o una vista, en este
caso, una tabla (table);
- table_name: nombre de la tabla al que est asociado (libros);

Ingresamos un registro en "libros":

insert into libros values(150,'El experto en


laberintos','Gaskin','Planeta',23);

Veamos si el trigger se dispar consultando la tabla "control":

select *from control;

Vemos que se ingres un registro que muestra que el usuario "system", el da y hora actual
realiz una insercin sobre "libros".

Actualizamos algunos registros de "libros":

update libros set precio=precio+precio*0.1 where editorial='Planeta';

Veamos cuntas veces el trigger se dispar consultando la tabla "control":

select *from control;

Vemos que se ingresaron 3 nuevos registros que muestran que el usuario "system", el da y
hora actual actualiz tres registros de "libros". Si el trigger se hubiese definido a nivel de
sentencia, el "update" anterior se hubiese disparado una sola vez.

Eliminamos un registro de "libros":

delete from libros where codigo=145;

Veamos si el trigger se dispar consultando la tabla "control":

select *from control;

Vemos que se elimin 1 registro.

111 - Disparador de mltiples eventos

Primer problema:

Una librera almacena los datos de sus libros en una tabla denominada "libros" y controla las
acciones que los empleados realizan sobre dicha tabla almacenando en la tabla "control" el
nombre del usuario y la fecha, cada vez que se modifica el precio o la editorial de un libro.

1- Elimine las tablas:

drop table control;


drop table libros;

2- Cree las tablas con las siguientes estructuras:

create table libros(


codigo number(6),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(6,2)
);

create table control(


usuario varchar2(30),
fecha date,
operacion varchar2(20)
);

3- Ingrese algunos registros en "libros":

insert into libros values(100,'Uno','Richard Bach','Planeta',25);


insert into libros values(103,'El aleph','Borges','Emece',28);
insert into libros values(105,'Matematica estas ahi','Paenza','Nuevo siglo',12);
insert into libros values(120,'Aprenda PHP','Molina Mario','Nuevo siglo',55);
insert into libros values(145,'Alicia en el pais de las
maravillas','Carroll','Planeta',35);

4- El gerente permite:

- ingresar o borrar libros de la tabla "libros" unicamente los sbados de 8 a 12 hs.

- actualizar los precios de los libros de lunes a viernes de 8 a 18 hs. y sbados entre la 8 y 12
hs.

Cree un disparador para los tres eventos que controle la hora en que se realizan las
operaciones sobre "libros". Si se intenta eliminar, ingresar o actualizar registros de "libros"
fuera de los das y horarios permitidos, debe aparecer un mensaje de error. Si la operacin de
ingreso, borrado o actualizacin de registros se realiza, se debe almacenar en "control", el
nombre del usuario, la fecha y el tipo de operacin ejecutada

5- Cambie la fecha y hora del sistema a "domingo 19 hs.". Intente ingresar un libro
Mensaje de error.

6- Cambie la fecha y hora del sistema a "lunes 10 hs.". Intente ingresar un libro.
Mensaje de error.

7- Cambie la fecha y hora del sistema a "sabado 8 hs.". Ingrese un libro

8- Realice un "select" sobre "libros" y sobre "control" para verificar que se han cargado los
datos correspondientes/
Aparece el nuevo libro en "libros" y una fila de "ingreso" en "control".

9- Cambie la fecha y hora del sistema a "domingo 18 hs.". Intente modificar el precio de un
libro.
Mensaje de error.

10- Cambie la fecha y hora del sistema a "sabado 15 hs.". Intente modificar el precio de un
libro.
Mensaje de error.

11- Cambie la fecha y hora del sistema a "sabado 9 hs.". Actualice el precio de un libro
12- Realice un "select" sobre "libros" y sobre "control" para verificar que se han cargado los
datos correspondientes.
Aparece el nuevo precio en "libros" y una nueva fila de "actualizacin" en "control".

13- Cambie la fecha y hora del sistema a "martes 11:30 hs.". Actualice el precio de un libro

14- Realice un "select" sobre "libros" y sobre "control" para verificar que se han cargado los
datos correspondientes.
Aparece el nuevo precio en "libros" y una nueva fila de "actualizacin" en "control".

15- Cambie la fecha y hora del sistema a "domingo 18:30 hs.". Intente borrar un libro.
Mensaje de error.

16- Cambie la fecha y hora del sistema a "miercoles 15 hs.". Intente borrar un libro.
Mensaje de error.

17- Cambie la fecha y hora del sistema a "sbado 11:55 hs.". Borre un libro

18- Realice un "select" sobre "libros" y sobre "control" para verificar que se han cargado los
datos correspondientes.
Se ha eliminado el registro en "libros" y se ha cargado una nueva fila de "borrado" en "control".

drop table control;


drop table libros;

create table libros(


codigo number(6),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(6,2)
);

create table control(


usuario varchar2(30),
fecha date,
operacion varchar2(20)
);

insert into libros values(100,'Uno','Richard Bach','Planeta',25);


insert into libros values(103,'El aleph','Borges','Emece',28);
insert into libros values(105,'Matematica estas ahi','Paenza','Nuevo siglo',12);
insert into libros values(120,'Aprenda PHP','Molina Mario','Nuevo siglo',55);
insert into libros values(145,'Alicia en el pais de las
maravillas','Carroll','Planeta',35);

create or replace trigger tr_cambios_libros


before insert or update or delete
on libros
for each row
begin
if inserting then
if ((to_char(sysdate,'dy','nls_date_language=SPANISH') in ('sb')) and
(to_number(to_char(sysdate,'HH24')) between 8 and 11)) then
insert into control values (user, sysdate,'ingreso');
else
raise_application_error(-20000,'Los ingresos slo los Sab. de 8 a 12 hs.');
end if;
end if;
if deleting then
if (to_char(sysdate,'dy','nls_date_language=SPANISH') in ('sb')) and
(to_number(to_char(sysdate,'HH24')) between 8 and 11) then
insert into control values (user, sysdate,'borrado');
else
raise_application_error(-20001,'Las eliminaciones solo los Sab. de 8 a 12 hs.');
end if;
end if;
if updating then
if ((to_char(sysdate,'dy','nls_date_language=SPANISH') in
('lun','mar','mi','jue','vie')) and
(to_number(to_char(sysdate,'HH24')) between 8 and 19)) or
((to_char(sysdate,'dy','nls_date_language=SPANISH') in('sb')) and
(to_number(to_char(sysdate,'HH24')) between 8 and 11))then
insert into control values (user, sysdate,'actualizacin');
else
raise_application_error(-20002,'Las actualizaciones solo de L a V de 8 a 20 o S
de 8 a 12 hs.');
end if;
end if;
end tr_cambios_libros;

insert into libros values(150,'El experto en laberintos','Gaskin','Planeta',25);

insert into libros values(150,'El experto en laberintos','Gaskin','Planeta',25);

insert into libros values(150,'El experto en laberintos','Gaskin','Planeta',25);

select *from libros;


select *from control;

update libros set precio=45 where codigo=150;

update libros set precio=45 where codigo=150;

update libros set precio=45 where codigo=150;

select *from libros;


select *from control;

update libros set precio=50 where codigo=150;

select *from libros;


select *from control;

delete from libros where codigo=150;

delete from libros where codigo=150;

delete from libros where codigo=150;


select *from libros;
select *from control;

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).

112 - Disparador (old y new)

Problema:
Una librera almacena los datos de sus libros en una tabla denominada "libros" y controla las
actualizaciones del precio de los libros almacenando en la tabla "control" el nombre del
usuario, la fecha, el precio anterior y el nuevo.

Eliminamos las tablas:

drop table control;


drop table libros;

Creamos las tablas con las siguientes estructuras:

create table libros(


codigo number(6),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(6,2)
);

create table control(


usuario varchar2(30),
fecha date,
codigo number(6),
precioanterior number(6,2),
precionuevo number(6,2)
);

Ingresamos algunos registros en "libros":

insert into libros values(100,'Uno','Richard Bach','Planeta',25);


insert into libros values(103,'El aleph','Borges','Emece',28);
insert into libros values(105,'Matematica estas ahi','Paenza','Nuevo
siglo',12);
insert into libros values(120,'Aprenda PHP','Molina Mario','Nuevo
siglo',55);
insert into libros values(145,'Alicia en el pais de las
maravillas','Carroll','Planeta',35);

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.

Actualizamos el precio del libro con cdigo 100:

update libros set precio=30 where codigo=100;


Veamos lo que se almacen en "control" al dispararse el trigger:

select *from control;

Los campos "precioanterior" y "precionuevo" de la tabla "control" almacenaron los valores de


":old.precio" y ":new.precio" respectivamente.

Actualizamos varios registros:

update libros set precio=precio+precio*0.1 where editorial='Planeta';

Veamos lo que se almacen en "control" al dispararse el trigger:

select *from control;

Los campos "precioanterior" y "precionuevo" de la tabla "control" almacenaron los valores de


":old.precio" y ":new.precio" respectivamente de cada registro afectado por la actualizacin.

Modificamos la editorial de un libro:

update libros set editorial='Sudamericana' where editorial='Planeta';

El trigger no se dispar, pues fue definido para actualizaciones del campo "precio"
unicamente.

Verifiqumoslo:

select *from control;

Vamos a reemplazar el trigger anteriormente creado. Ahora el disparador


"tr_actualizar_precio_libros" 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;

Vaciamos la tabla "control":

truncate table control;

Actualizamos el precio del libro con cdigo 100:

update libros set precio=54.99 where codigo=100;

Veamos cmo se actualiz tal libro en "libros":


select *from libros where codigo=100;

El nuevo precio actualizado se redonde a 54.

Veamos lo que se almacen en "control" al dispararse el trigger:

select *from control;

Los campos "precioanterior" y "precionuevo" de la tabla "control" almacenaron los valores de


":old.precio" y ":new.precio" respectivamente.

Truncamos la tabla "control" nuevamente:

truncate table control;

Creamos 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 de "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;

Ingresamos un registro:

insert into libros values (150,'El gato con


botas','Anonimo','Emece',21);

Veamos lo que se almacen en "control":

select *from control;

Resultado:

USUARIO FECHA CODIGO PRECIOANTERIOR


PRECIONUEVO
----------------------------------------------------------------------
-------------
SYSTEM 20/03/08 21

La sentencia disparadora fue una insercin, por lo tanto, los campos ":old.codigo" y
":old.precio" contienen "null", as que en "codigo" y en "precioanterior" se almacena "null"; el
nico campo con valor diferente de "null" es "precionuevo" correspondiente al valor de
":new.precio".

Actualizamos el campo "precio" de un libro:

update libros set precio=12 where codigo=103;

Veamos lo que se almacen en "control":


select *from control;

Resultado:

USUARIO FECHA CODIGO PRECIOANTERIOR


PRECIONUEVO
----------------------------------------------------------------------
-------------
SYSTEM 20/03/08 103 28 12

Analicemos: actualizamos el precio, por lo tanto, ninguno de los campos consultados contiene
"null".

Actualizamos un campo diferente de "precio" de un libro:

update libros set autor='J.L.Borges' where autor='Borges';

Veamos lo que se almacen en "control":

select *from control;

Resultado:

USUARIO FECHA CODIGO PRECIOANTERIOR


PRECIONUEVO
----------------------------------------------------------------------
-------------
SYSTEM 20/03/08 103 12 12

Actualizamos el autor, por lo tanto, los campos ":old.precio" y ":new.precio" son iguales.

Eliminamos un registro de "libros":

delete from libros where codigo=100;

Veamos lo que se almacen en "control":

select *from control;

Resultado:

USUARIO FECHA CODIGO PRECIOANTERIOR


PRECIONUEVO
----------------------------------------------------------------------
-------------
SYSTEM 20/03/08 100 54

Analicemos: la sentencia que dispar el trigger fue un "delete", por lo tanto, el campo
":new.precio" contiene "null".

Veamos qu informa el diccionario "user_triggers" respecto del trigger anteriormente creado:

select *from user_triggers where trigger_name ='TR_LIBROS';


112 - Disparador (old y new)
Primer problema:

Un comercio almacena los datos de sus artculos para la venta en una tabla denominada
"articulos" y controla las operaciones que se realizan en ella guardando ciertos datos en otra
tabla denominada "control".

1- Elimine las tablas:

drop table control;


drop table articulos;

2- Cree las tablas con las siguientes estructuras:

create table articulos(


codigo number(6),
descripcion varchar2(40),
precio number (6,2),
stock number(4)
);

create table control(


usuario varchar2(30),
fecha date,
codigo number(6)
);

3- Ingrese algunos registros en "articulos":

insert into articulos values(100,'regla 20 cm.',5.4,100);


insert into articulos values(102,'regla 40 cm.',15,80);
insert into articulos values(109,'lapices color x12',6,150);
insert into articulos values(130,'lapices color x6',4.5,100);
insert into articulos values(200,'compas metal',21.8,50);

4- Cree un trigger a nivel de fila que se dispara "antes" que se ejecute un "insert" sobre la
tabla "articulos". En el cuerpo del disparador se debe ingresar en la tabla "control", el nombre
del usuario que realiz la insercin, la fecha y el cdigo del articulo que se ha ingresado

5- Ingrese un nuevo registro en "articulos"

6- Vea qu se almacen en "control"

7- Cree un disparador que calcule el cdigo cada vez que se inserte un nuevo registro

8- Ingrese un nuevo registro en "articulos"

9- Vea qu se almacen en "articulos".


Note que ignora el valor de cdigo ingresado y calcula el siguiente valor a partir del mximo
existente.

10- Vea qu se almacen en "control"

11- Ingrese un nuevo artculo sin especificar cdigo

12- Vea qu se almacen en "articulos"


13- Vea qu se almacen en "control"

drop table control;


drop table articulos;

create table articulos(


codigo number(6),
descripcion varchar2(40),
precio number (6,2),
stock number(4)
);

create table control(


usuario varchar2(30),
fecha date,
codigo number(6)
);

insert into articulos values(100,'regla 20 cm.',5.4,100);


insert into articulos values(102,'regla 40 cm.',15,80);
insert into articulos values(109,'lapices color x12',6,150);
insert into articulos values(130,'lapices color x6',4.5,100);
insert into articulos values(200,'compas metal',21.8,50);

create or replace trigger tr_ingresar_art


before insert
on articulos
for each row
begin
insert into control values(user,sysdate,:new.codigo);
end tr_ingresar_art;

insert into articulos values(200,'compas plastico',18.3,50);

select *from control;

create or replace trigger tr_codigo


before insert
on articulos
for each row
begin
select max(codigo)+1 into :new.codigo from articulos;
if :new.codigo is null then
:new.codigo:=1;
end if;
end tr_codigo;

insert into articulos values(200,'cuaderno rayado x12',6,200);

select *from articulos;

select *from control;

insert into articulos (descripcion,precio,stock) values('cuaderno liso x12',5.5,200);


select *from articulos;

select *from control;

Segundo problema:

Una librera almacena los datos de sus libros en una tabla denominada "libros" y en otra
denominada "ofertas", almacena los cdigos y precios de los libros cuyo precio es inferior a
$50.

1- Elimine las tablas:

drop table libros;


drop table ofertas;

2- Cree las tablas con las siguientes estructuras:

create table libros(


codigo number(6),
titulo varchar2(40),
autor varchar2(30),
editorial varchar(20),
precio number(6,2)
);

create table ofertas(


codigo number(6),
precio number(6,2)
);

3- Ingrese algunos registros en "libros":

insert into libros values(100,'Uno','Richard Bach','Planeta',25);


insert into libros values(103,'El aleph','Borges','Emece',28);
insert into libros values(105,'Matematica estas ahi','Paenza','Nuevo siglo',12);
insert into libros values(120,'Aprenda PHP','Molina Mario','Nuevo siglo',55);
insert into libros values(145,'Alicia en el pais de las
maravillas','Carroll','Planeta',35);

4- Cree un trigger a nivel de fila que se dispare al ingresar un registro en "libros"; si alguno de
los libros ingresados tiene un precio menor o igual a $30 debe ingresarlo en "ofertas"

5- Ingrese un libro en "libros" cuyo precio sea inferior a $30

6- Verifique que el trigger se dispar consultando "ofertas"

7- Ingrese un libro en "libros" cuyo precio supere los $30

8- Verifique que no se ingres ningn registro en "ofertas"


9- Cree un trigger a nivel de fila que se dispare al modificar el precio de un libro. Si tal libro
existe en "ofertas" y su nuevo precio ahora es superior a $30, debe eliminarse de "ofertas"; si
tal libro no existe en "ofertas" y su nuevo precio ahora es inferior a $30, debe agregarse a
"ofertas"

10- Aumente a ms de $30 el precio de un libro que se encuentra en "ofertas"

11- Verifique que el trigger se dispar consultando "libros" y "ofertas"

12- Disminuya a menos de $31 el precio de un libro que no se encuentra en "ofertas"

13- Verifique que el trigger se dispar consultando "libros" y "ofertas"

14- Aumente el precio de un libro que no se encuentra en "ofertas"

15- Verifique que el trigger se dispar pero no se modific "ofertas"

16- Cree un trigger a nivel de fila que se dispare al borrar un registro en "libros"; si alguno de
los libros eliminados est en "ofertas", tambin debe eliminarse de dicha tabla.

17- Elimine un libro en "libros" que est en "ofertas"

18- Verifique que el trigger se dispar consultando "libros" y "ofertas"

19- Elimine un libro en "libros" que No est en "ofertas"

20- Verifique que el trigger se dispar consultando "libros" y "ofertas"

21- Cree una tabla llamada "control" que almacene el cdigo, la fecha y el precio de un libro,
antes elimnela por si existe

22- Cree un disparador que se dispare cada vez que se actualice el precio de un libro; el
trigger debe ingresar en la tabla "control", el cdigo del libro cuyo precio se actualiz, la
fecha y el precio anterior.

23- Actualice el precio de un libro

24- Controle que el precio se ha modificado en "libros" y que se agreg un registro en "control"

25- Modifique nuevamente el precio del libro cambiado en el punto 11

26- Controle que el precio se ha modificado en "libros" y que se agreg un nuevo registro en
"control"

27- Modifique el precio de varios libros en una sola sentencia que incluya al modificado
anteriormente

28- Controle que el precio se ha modificado en "libros" y que se agreg un nuevo registro en
"control"

29- Vea qu informa el diccionario "user_triggers" respecto del trigger anteriormente creado

drop table libros;


drop table ofertas;

create table libros(


codigo number(6),
titulo varchar2(40),
autor varchar2(30),
editorial varchar(20),
precio number(6,2)
);

create table ofertas(


codigo number(6),
precio number(6,2)
);

insert into libros values(100,'Uno','Richard Bach','Planeta',25);


insert into libros values(103,'El aleph','Borges','Emece',28);
insert into libros values(105,'Matematica estas ahi','Paenza','Nuevo siglo',12);
insert into libros values(120,'Aprenda PHP','Molina Mario','Nuevo siglo',55);
insert into libros values(145,'Alicia en el pais de las
maravillas','Carroll','Planeta',35);

create or replace trigger tr_ingresar_libros_ofertas


before insert
on libros
for each row
begin
if (:new.precio<=30) then
insert into ofertas values(:new.codigo,:new.precio);
end if;
end tr_ingresar_libros_ofertas;

insert into libros values(150,'El experto en laberintos','Gaskin','Planeta',28);

select *from ofertas;

insert into libros values(155,'El gato con botas',null,'Planeta',38);

select *from ofertas;

create or replace trigger tr_modificar_libros_precio


before update of precio
on libros
for each row
begin
if (:old.precio<=30) and (:new.precio>30) then
delete from ofertas where codigo=:old.codigo;
end if;
if (:old.precio>30) and (:new.precio<=30) then
insert into ofertas values(:new.codigo,:new.precio);
end if;
end tr_modificar_libros_precio;

update libros set precio=50 where codigo=150;

select *from libros;


select *from ofertas;
update libros set precio=30 where codigo=155;

select *from libros;


select *from ofertas;

update libros set precio=precio+2 where codigo=150;

select *from libros;


select *from ofertas;

create or replace trigger tr_eliminar_libros_ofertas


before delete
on libros
for each row
begin
delete from ofertas where codigo=:old.codigo;
end tr_eliminar_libros_ofertas;

delete from libros where codigo=155;

select *from libros;


select *from ofertas;

delete from libros where codigo=150;

select *from libros;


select *from ofertas;

create table control(


codigo number(6),
fecha date,
precio number(6,2)
);

create or replace trigger tr_actualizar_precio


before update of precio
on libros
for each row
begin
insert into control values(:old.codigo,sysdate,:old.precio);
end tr_actualizar_precio;

update libros set precio=40 where codigo=120;

select *from libros where codigo=120;


select *from control;

update libros set precio=45 where codigo=120;

select *from libros where codigo=120;


select *from control;

update libros set precio=precio+(precio*0.5) where codigo>=120;

select *from libros where codigo>120;


select *from control;
select *from user_triggers where trigger_name ='TR_ACTUALIZAR_PRECIO';

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.

113 - Disparador condiciones (when)

Problema:

Una librera almacena los datos de sus libros en una tabla denominada "libros".

Eliminamos la tabla:

drop table libros;

Creamos la tabla con la siguiente estructura:

create table libros(


codigo number(6),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(6,2)
);

Ingresamos algunos registros en "libros":

insert into libros values(100,'Uno','Richard Bach','Planeta',25);


insert into libros values(103,'El aleph','Borges','Planeta',40);
insert into libros values(105,'Matematica estas ahi','Paenza','Nuevo
siglo',12);
insert into libros values(120,'Aprenda PHP','Molina Mario','Nuevo
siglo',55);

Creamos un trigger a nivel de fila que se dispara "antes" que se ejecute un "insert" o un
"update" sobre el campo "precio" de la tabla "libros". Se activa solamente si el nuevo precio
que se ingresa o se modifica es superior a 50, en caso de serlo, se modifica el valor ingresado
redondendolo a entero:
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;

Ingresamos un registro con el valor 30.80 para "precio":

insert into libros values(250,'El experto en


laberintos','Gaskin','Emece',30.80);

El trigger no se dispara.

Veamos si el precio ingresado se redonde:

select *from libros where titulo like '%experto%';

El precio no se redonde porque no es superior a 50, el trigger no se dispar.

Ingresamos un registro con el valor "55.6" para "precio":

insert into libros values(300,'Alicia en el pais de las


maravillas','Carroll','Emece',55.6);

Consultamos "libros":

select *from libros where titulo like '%maravillas%';

El trigger se dispar y se redonde el nuevo precio a 56.

Actualizamos el precio de un libro a "40.30":

update libros set precio=40.30 where codigo=105;

Consultamos "libros":

select *from libros where codigo =105;

Se almacen el valor tal como se solicit, el trigger no se dispar ya que ":new.precio" no


cumpli con la condicin del "when".

Actualizamos el precio de un libro a "50.30":

update libros set precio=50.30 where codigo=105;

Consultamos la tabla:

select *from libros where codigo=105;

El trigger se activa porque ":new.precio" cumple con la condicin "when" y modifica el valor a
"50".

Actualizamos el precio de 2 registros a "50.30":


update libros set precio=50.30 where editorial='Nuevo siglo';

Consultamos:

select *from libros where editorial='Nuevo siglo';

El trigger se activa 2 veces redondeado el valor a 50.

Ejecutamos el siguiente "update":

update libros set precio=precio+15.8 where editorial='Planeta';

Consultamos:

select *from libros where editorial='Planeta';

De los dos libros de editorial "Planeta" solamente uno supera el valor 50, por lo tanto, el
trigger se dispara una sola vez.

Activamos el paquete "dbms_output":

set serveroutput on;


execute dbms_output.enable(20000);

Reemplazamos el trigger anterior por uno sin condicin "when". La condicin se controla en
un "if" en el interior del trigger. En este caso, el trigger se dispara SIEMPRE que se actualice
un precio en "libros", dentro del trigger se controla el precio, si cumple la condicin, se
modifica, sino no:

create or replace trigger tr_precio_libros


before insert or update of precio
on libros
for each row
begin
dbms_output.put_line('Trigger disparado');
if :new.precio>50 then
dbms_output.put_line('Precio redondeado');
:new.precio:= round(:new.precio);
end if;
end tr_precio_libros;

Note que agregamos una salida de texto para controlar si el trigger se ha disparado y otra,
para controlar si entra por la condicin "if".

Ingresamos un registro con un valor inferior a 50 para "precio":

insert into libros values(350,'Ilusiones','Bach','Planeta',20.35);

El trigger se dispara (aparece el primer mensaje), pero no realiza ninguna accin ya que al
evaluarse la condicin del "if", resulta falsa.

Ingresamos un registro con un valor superior a 50 para "precio":

insert into libros values(380,'El anillo del


hechicero','Gaskin','Planeta',60.35);
El trigger se dispara (aparece el primer mensaje) y al evaluarse como cierta la condicin,
realiza la accin (aparece el segundo mensaje).

Consultamos el diccionario para ver qu nos informa sobre el disparador recientemente


creado:

select *from user_triggers where trigger_name ='TR_LIBROS';


113 - Disparador condiciones (when)

Primer problema:

Una librera almacena los datos de sus libros en una tabla denominada "libros" y en otra
denominada "ofertas", almacena los cdigos y precios de los libros cuyo precio es inferior a
$50.

1- Elimine las tablas:

drop table libros;


drop table ofertas;

2- Cree las tablas con las siguientes estructuras:

create table libros(


codigo number(6),
titulo varchar2(40),
autor varchar2(30),
editorial varchar(20),
precio number(6,2)
);

create table ofertas(


codigo number(6),
titulo varchar2(40)
);

3- Ingrese algunos registros en "libros":

insert into libros values(100,'Uno','Richard Bach','Planeta',25);


insert into libros values(103,'El aleph','Borges','Emece',28);
insert into libros values(105,'Matematica estas ahi','Paenza','Nuevo siglo',12);
insert into libros values(120,'Aprenda PHP','Molina Mario','Nuevo siglo',55);
insert into libros values(145,'Alicia en el pais de las
maravillas','Carroll','Planeta',35);

4- Cree un trigger a nivel de fila que se dispara "antes" que se ejecute un "insert" sobre
"libros". Se activa solamente si el precio que se ingresa es inferior a $30, en caso de serlo, se
ingresa en "ofertas" el cdigo y precio del libro

5- Ingrese un libro en "libros" cuyo precio sea inferior a $30

6- Verifique que el trigger se dispar consultando "ofertas"

7- Ingrese un libro en "libros" cuyo precio supere los $30

8- Verifique que el trigger no se dispar consultando "ofertas"


9- Cree un trigger a nivel de fila que se dispare al borrar un libro de "libros", nicamente si el
precio del libro que se elimina es inferior a $30, es decir, si existe en "ofertas"

10- Elimine un registro de "libros" cuyo precio sea inferior a $30

11- Verifique que el trigger se dispar consultando "ofertas" y "libros"

12- Elimine un registro de "libros" cuyo precio supere los $30

13- Verifique que el trigger no se dispar consultando "ofertas" y que si se ha eliminado el


registro en "libros"

drop table libros;


drop table ofertas;

create table libros(


codigo number(6),
titulo varchar2(40),
autor varchar2(30),
editorial varchar(20),
precio number(6,2)
);

create table ofertas(


codigo number(6),
titulo varchar2(40)
);

insert into libros values(100,'Uno','Richard Bach','Planeta',25);


insert into libros values(103,'El aleph','Borges','Emece',28);
insert into libros values(105,'Matematica estas ahi','Paenza','Nuevo siglo',12);
insert into libros values(120,'Aprenda PHP','Molina Mario','Nuevo siglo',55);
insert into libros values(145,'Alicia en el pais de las
maravillas','Carroll','Planeta',35);

create or replace trigger tr_ingresar_libros_ofertas


before insert
on libros
for each row when(new.precio<30)
begin
insert into ofertas values(:new.codigo,:new.titulo);
end tr_ingresar_libros_ofertas;

insert into libros values(150,'El experto en laberintos','Gaskin','Planeta',28);

select *from ofertas;

insert into libros values(155,'El gato con botas',null,'Planeta',38);

select *from ofertas;

create or replace trigger tr_borrar_libros_ofertas


before delete
on libros
for each row when(old.precio<30)
begin
delete from ofertas where codigo=:old.codigo;
end tr_borrar_libros_ofertas;

delete from libros where codigo=150;

select *from ofertas;


select *from libros;

delete from libros where codigo=155;

select *from ofertas;


select *from libros;

Segundo problema:

Una empresa almacena los datos de sus empleados en una tabla denominada "empleados".

1- Elimine la tabla:

drop table empleados;

2- Cree la tabla con la siguiente estructura:

create table empleados(


documento char(8),
apellido varchar2(20),
nombre varchar2(20),
seccion varchar2(30),
sueldo number(8,2)
);

3- Ingrese algunos registros:

insert into empleados values('22333444','ACOSTA','Ana','Secretaria',500);


insert into empleados values('22555666','CASEROS','Carlos','Contaduria',900);
insert into empleados values('22777888','DOMINGUEZ','Daniel','Secretaria',560);
insert into empleados values('22999000','FUENTES','Federico','Sistemas',680);
insert into empleados values('23444555','GOMEZ','Gabriela','Sistemas',1200);
insert into empleados values('23666777','JUAREZ','Juan','Contaduria',1000);

4- La empresa necesita controlar cuando se le aumenta el sueldo a los empleados, guardando


en una tabla denominada "control", el nombre del usuario, la fecha, el documento de quien se
ha modificado el sueldo, el antiguo sueldo y el nuevo sueldo. Para ello cree la tabla control
(antes elimnela por si existe):

drop table control;


create table control(
usuario varchar2(30),
fecha date,
documento char(8),
antiguosueldo number(8,2),
nuevosueldo number(8,2)
);

5- Cree un disparador que almacene el nombre del usuario, la fecha, documento, el antiguo y
el nuevo sueldo en "control" cada vez que se actualice un sueldo de la tabla "empleados" a un
valor mayor. Si el sueldo se disminuye, el trigger no debe activarse. Si se modifica otro campo
diferente de "sueldo", no debe activarse.

6- Actualice el sueldo de todos los empleados de la seccin "Sistemas" a "1000"

7- Consulte la tabla "control" para ver cuntas veces se ha disparado el trigger


Se ha disparado una sola vez; se actualizaron 2 registros, pero en solo uno de ellos se
aument el sueldo.

8- Al empleado con documento "22333444" se lo ha cambiado a la seccin "contaduria".


Realice el cambio en la tabla "empleados"

9- Verifique que el trigger no se ha activado porque no se ha modificado el campo "sueldo".


Consulte "control"

10- Cree un disparador a nivel de fila que se dispare cada vez que se ingrese un nuevo
empleado y coloque en maysculas el apellido ingresado. Adems, si no se ingresa sueldo,
debe ingresar '0'

11- Ingrese un nuevo empleado empleando minsculas en el apellido

12- Verifique que el trigger "tr_ingresar_empleados" se dispar

13- Ingrese dos nuevos empleados, uno sin sueldo y otro con sueldo "null"

14- Verifique que el trigger "tr_ingresar_empleados" se ha disparado


Los dos registros deben tener el apellido en maysculas y deben tener el valor '0' en sueldo.

15- Cree un disparador a nivel de fila que se dispare cada vez que se ingresa un nuevo
empleado y coloque "null" en "sueldo" si el sueldo ingresado supera los $1000 o es inferior a
$500

16- Ingrese un nuevo empleado con un sueldo que dispare el trigger creado anteriormente

17- Verifique que el trigger "tr_ingresar_empleados" se dispar

drop table empleados;

create table empleados(


documento char(8),
apellido varchar2(20),
nombre varchar2(20),
seccion varchar2(30),
sueldo number(8,2)
);

insert into empleados values('22333444','ACOSTA','Ana','Secretaria',500);


insert into empleados values('22555666','CASEROS','Carlos','Contaduria',900);
insert into empleados values('22777888','DOMINGUEZ','Daniel','Secretaria',560);
insert into empleados values('22999000','FUENTES','Federico','Sistemas',680);
insert into empleados values('23444555','GOMEZ','Gabriela','Sistemas',1200);
insert into empleados values('23666777','JUAREZ','Juan','Contaduria',1000);

drop table control;


create table control(
usuario varchar2(30),
fecha date,
documento char(8),
antiguosueldo number(8,2),
nuevosueldo number(8,2)
);

create or replace trigger tr_aumentar_sueldo_empleados


before update of sueldo
on empleados
for each row when(new.sueldo>old.sueldo)
begin
insert into control values(user,sysdate,:old.documento,:old.sueldo,:new.sueldo);
end;

update empleados set sueldo=1000 where seccion='Sistemas';

select *from control;

update empleados set seccion='Contaduria' where documento='22333444';

select *from control;

create or replace trigger tr_ingresar_empleados


before insert
on empleados
for each row
begin
:new.apellido := upper(:new.apellido);
if (:new.sueldo is null) then
:new.sueldo := 0;
end if;
end;

insert into empleados values('25666777','Lopez','Luisa','Secretaria',650);

select *from empleados where documento='25666777';

insert into empleados (documento,apellido,nombre, seccion)


values('26777888','Morales','Marta','Secretaria');
insert into empleados values('26999000','Perez','Patricia','Contaduria',null);

select *from empleados;

create or replace trigger tr_ingresar_empleados


before insert
on empleados
for each row when (new.sueldo>1000 or new.sueldo<500)
begin
:new.sueldo := null;
end tr_ingresar_empleados;

select *from empleados where documento='31313131';

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;
114 - Disparador de actualizacion - campos (updating)

Problema:

Una librera almacena los datos de sus libros en una tabla denominada "libros" y controla las
actualizaciones de los precios de los libros almacenando en la tabla "controlprecios", la fecha,
el cdigo del libro, el antiguo y nuevo precio. Tambin controla cualquier otra actualizacin
almacenando en "control" el nombre del usuario, la fecha y el cdigo del libro.

Elimine las tablas:

drop table controlprecios;


drop table libros;
drop table control;

Cree las tablas con las siguientes estructuras:


create table libros(
codigo number(6),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(6,2),
stock number(4)
);

create table control(


usuario varchar2(30),
fecha date,
codigo number(6)
);

create table controlprecios(


fecha date,
codigo number(6),
precioanterior number(6,2),
precionuevo number(6,2)
);

Ingrese algunos registros en "libros":

insert into libros values(100,'Uno','Richard Bach','Planeta',25,100);


insert into libros values(103,'El aleph','Borges','Emece',28,0);
insert into libros values(105,'Matematica estas ahi','Paenza','Nuevo
siglo',12,50);
insert into libros values(120,'Aprenda PHP','Molina Mario','Nuevo
siglo',55,200);
insert into libros values(145,'Alicia en el pais de las
maravillas','Carroll','Planeta',35,10);

Cree un trigger a nivel de fila que se dispare "antes" que se ejecute un "update" sobre la tabla
"libros".

En el cuerpo del trigger se debe averiguar 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;

Actualice el precio de un libro:

update libros set precio=35 where codigo=100;


Verifique que el trigger se ha disparado consultando la tabla "controlprecios":

select *from controlprecios;

Se ha insertado una fila.

Verifique que la tabla "control" no tiene registros.

select *from control;

Actualice un campo diferente de precio:

update libros set stock=0 where codigo=145;

Verifique que el trigger se ha disparado consultando la tabla "control":

select *from control;

Se ha insertado una fila.

Verifique que la tabla "controlprecios" no tiene nuevos registros:

select *from controlprecios;


114 - Disparador de actualizacion - campos (updating)

Primer problema:

Una librera almacena los datos de sus libros en una tabla denominada "libros".

1- Elimine la tabla:

drop table libros;

2- Cree la tabla con la siguiente estructura:

create table libros(


codigo number(6),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(6,2),
stock number(4)
);

3-Ingrese algunos registros en "libros":

insert into libros values(100,'Uno','Richard Bach','Planeta',25,100);


insert into libros values(103,'El aleph','Borges','Emece',28,0);
insert into libros values(105,'Matematica estas ahi','Paenza','Nuevo siglo',12,50);
insert into libros values(120,'Aprenda PHP','Molina Mario','Nuevo siglo',55,200);
insert into libros values(145,'Alicia en el pais de las
maravillas','Carroll','Planeta',35,10);
4- Cree un trigger a nivel de fila que se dispare "antes" que se ejecute un "update" sobre la
tabla "libros". En el cuerpo del trigger se debe averiguar el campo que ha sido modificado. En
caso de modificarse:

- el cdigo, debe rechazarse la modificacin con un mensaje de error.

- el "precio", se controla si es mayor o igual a cero, si lo es, debe dejarse el precio anterior y
mostrar un mensaje de error.

- el stock, debe controlarse que no se ingrese un nmero negativo ni superior a 1000, en tal
caso, debe rechazarse con un mensaje de error.

5- Intente modificar el precio de un libro con un valor negativo


Mensaje de error 20001;

6- Verifique que el trigger se ha disparado consultando la tabla "libros"


El cambio de precio no se realiz.

7- Actualice un precio a un valor aceptado

8- Verifique que el trigger se ha disparado consultando la tabla "libros"


El cambio de precio se realiz.

9- Intente cambiar el cdigo de un libro


Mensaje de error 20000.

10- Verifique que el cambio no se ha realizado

11- Intente cambiar el stock de un libro a un valor negativo


Mensaje de error 20002.

12- Verifique que el cambio no se ha realizado

13- Intente cambiar el stock de un libro a un valor que supere los 1000
Mensaje de error 20002.

14- Cambie el stock de un libro a un valor permitido

15- Verifique que el cambio se ha realizado

drop table libros;

create table libros(


codigo number(6),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(6,2),
stock number(4)
);

insert into libros values(100,'Uno','Richard Bach','Planeta',25,100);


insert into libros values(103,'El aleph','Borges','Emece',28,0);
insert into libros values(105,'Matematica estas ahi','Paenza','Nuevo siglo',12,50);
insert into libros values(120,'Aprenda PHP','Molina Mario','Nuevo siglo',55,200);
insert into libros values(145,'Alicia en el pais de las
maravillas','Carroll','Planeta',35,10);

create or replace trigger tr_actualizar_libros


before update
on libros
for each row
begin
if updating ('codigo') then
raise_application_error(-20000,'No puede modificar el codigo');
end if;
if updating ('precio') then
if (:new.precio<0) then
raise_application_error(-20001,'No puede colocar precios negativos');
end if;
end if;
if updating ('stock') then
if (:new.stock<0) or (:new.stock>1000)then
raise_application_error(-20002,'El valor de stock debe estar entre 0 y 1000');
end if;
end if;
end tr_actualizar_libros;

update libros set precio=-50 where codigo=100;

select *from libros;

update libros set precio=1 where codigo=100;

select *from libros;

update libros set codigo=1 where codigo=100;

select *from libros;

update libros set stock=-1 where codigo=100;

select *from libros;

update libros set stock=2000 where codigo=100;

update libros set stock=200 where codigo=100;

select *from libros;

Segundo problema:

Un comercio almacena los datos de los artculos que tiene para la venta en una tabla
denominada "articulos". En otra tabla denominada "pedidos" almacena el cdigo de cada
artculo y la cantidad que necesita solicitar a los mayoristas. En una tabla llamada
"controlPrecios" almacena la fecha, el cdigo del artculo y ambos precios (antiguo y nuevo).
1- Elimine las tablas:

drop table articulos;


drop table pedidos;
drop table controlPrecios;

2- Cree las tablas con las siguientes estructuras:

create table articulos(


codigo number(4),
descripcion varchar2(40),
precio number (6,2),
stock number(4)
);

create table pedidos(


codigo number(4),
cantidad number(4)
);

create table controlPrecios(


fecha date,
codigo number(4),
anterior number(6,2),
nuevo number(6,2)
);

3- Ingrese algunos registros en "articulos":

insert into articulos values(100,'cuaderno rayado 24h',4.5,100);


insert into articulos values(102,'cuaderno liso 12h',3.5,150);
insert into articulos values(104,'lapices color x6',8.4,60);
insert into articulos values(160,'regla 20cm.',6.5,40);
insert into articulos values(173,'compas xxx',14,35);
insert into articulos values(234,'goma lapiz',0.95,200);

4- Ingrese en "pedidos" todos los cdigos de "articulos", con "cantidad" cero

5- Active el paquete "dbms_output":

set serveroutput on;


execute dbms_output.enable(20000);

6- Cada vez que se disminuye el stock de un artculo de la tabla "articulos", se debe


incrementar la misma cantidad de ese artculo en "pedidos" y cuando se incrementa en
"articulos", se debe disminuir la misma cantidad en "pedidos". Si se ingresa un nuevo artculo
en "articulos", debe agregarse un registro en "pedidos" con "cantidad" cero. Si se elimina un
registro en "articulos", debe eliminarse tal artculo de "pedidos". Cree un trigger para los tres
eventos (insercin, borrado y actualizacin), a nivel de fila, sobre "articulos", para los campos
"stock" y "precio", que realice las tareas descriptas anteriormente, si el campo modificado es
"stock". Si el campo modificado es "precio", almacene en la tabla "controlPrecios", la fecha, el
cdigo del artculo, el precio anterior y el nuevo.
El trigger muestra el mensaje "Trigger activado" cada vez que se dispara; en cada "if" muestra
un segundo mensaje que indica cul condicin se ha cumplido.
7- Disminuya el stock del artculo "100" a 30
Un mensaje muestra que el trigger se ha disparado actualizando el "stock".

8- Verifique que el trigger se dispar consultando la tabla "pedidos" (debe aparecer "70" en
"cantidad" en el registro correspondiente al artculo "100")

9- Ingrese un nuevo artculo en "articulos"


Un mensaje muestra que el trigger se ha disparado por una insercin.

10- Verifique que se ha agregado un registro en "pedidos" con cdigo "280" y cantidad igual a 0

11- Elimine un artculo de "articulos"


Un mensaje muestra que el trigger se ha disparado por un borrado.

12- Verifique que se ha borrado el registro correspondiente al artculo con cdigo "234" en
"pedidos"

13- Modifique el precio de un artculo


Un mensaje muestra que el trigger se ha disparado por una actualizacin de precio.

14- Verifique que se ha agregado un registro en "controlPrecios"

15- Modifique la descripcin de un artculo


El trigger no se ha disparado, no aparece mensaje.

16- Modifique el precio, stock y descripcion de un artculo


Un mensaje muestra que el trigger se ha disparado por una actualizacin de stock y otra de
precio. La actualizacin de "descripcion" no dispar el trigger.

17- Verifique que se ha agregado un registro en "controlPrecios" y se ha modificado el campo


"cantidad" con el valor "5"

18- Modifique el stock de varios artculos en una sola sentencia


Cuatro mensajes muestran que el trigger se ha disparado 4 veces, por actualizaciones de
stock.

19- Verifique que se han modificado 4 registros en "pedidos"

20- Modifique el precio de varios artculos en una sola sentencia


Cuatro mensajes muestran que el trigger se ha disparado 4 veces, por actualizaciones de
precio.

21- Verifique que se han agregado 4 nuevos registros en "controlPrecios"

22- Elimine varios artculos en una sola sentencia


Cuatro mensajes muestran que el trigger se ha disparado 4 veces, por borrado de registros.

23- Verifique que se han eliminado 4 registros en "pedidos"

drop table articulos;


drop table pedidos;
drop table controlPrecios;

create table articulos(


codigo number(4),
descripcion varchar2(40),
precio number (6,2),
stock number(4)
);

create table pedidos(


codigo number(4),
cantidad number(4)
);

create table controlPrecios(


fecha date,
codigo number(4),
anterior number(6,2),
nuevo number(6,2)
);

insert into articulos values(100,'cuaderno rayado 24h',4.5,100);


insert into articulos values(102,'cuaderno liso 12h',3.5,150);
insert into articulos values(104,'lapices color x6',8.4,60);
insert into articulos values(160,'regla 20cm.',6.5,40);
insert into articulos values(173,'compas xxx',14,35);
insert into articulos values(234,'goma lapiz',0.95,200);

insert into pedidos (codigo)


select (codigo) from articulos;
update pedidos set cantidad=0;

set serveroutput on;


execute dbms_output.enable(20000);

create or replace trigger tr_articulos


before insert or delete or update of stock, precio
on articulos
for each row
begin
dbms_output.put_line('Trigger disparado');
if (inserting) then
insert into pedidos values(:new.codigo,0);
dbms_output.put_line(' insercion');
end if;
if (deleting) then
delete from pedidos where codigo = :old.codigo;
dbms_output.put_line(' borrado');
end if;
if updating ('STOCK') then
update pedidos set cantidad=cantidad+(:old.stock - :new.stock) where codigo =
:old.codigo;
dbms_output.put_line(' actualizacion de stock');
end if;
if updating('PRECIO') then
insert into controlPrecios values(sysdate,:old.codigo,:old.precio,:new.precio);
dbms_output.put_line(' actualizacion de precio');
end if;
end tr_articulos;
update articulos set stock=30 where codigo=100;

select *from pedidos;

insert into articulos values(280,'carpeta oficio',15,50);

select *from pedidos;

delete articulos where codigo=234;

select *from pedidos;

update articulos set precio=4.8 where codigo=102;

select *from controlPrecios;

update articulos set descripcion='compas metal xxx' where codigo=173;

update articulos set precio=10, stock=55, descripcion='lapices colorx6 Faber'


where codigo=104;

select *from controlPrecios;


select *from pedidos;

update articulos set stock=10 where codigo>=104;

select *from pedidos;

update articulos set precio=precio+precio*0.1 where codigo>=104;

select *from controlPrecios;

delete from articulos where codigo>=104;

select *from pedidos;

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.

115 - Disparadores (habilitar y deshabilitar)

Problema:

Una empresa almacena los datos de sus empleados en una tabla denominada "empleados". En
una tabla denominada "controlCambios" guarda los cambios que se realizan en la tabla
"empleados", en ella almacena el nombre del usuario que realiza la modificacin, la fecha, el
valor anterior del campo modificado y el nuevo valor.

Eliminamos las tablas:

drop table empleados;


drop table controlCambios;

Creamos las tablas, con las siguientes estructuras:

create table empleados(


documento char(8) not null,
nombre varchar2(30) not null,
domicilio varchar2(30),
seccion varchar2(20)
);

create table controlCambios(


usuario varchar2(30),
fecha date,
datoanterior varchar2(30),
datonuevo varchar2(30)
);

Ingresamos algunos registros:

insert into empleados values('22222222','Ana Acosta','Bulnes


56','Secretaria');
insert into empleados values('23333333','Bernardo Bustos','Bulnes
188','Contaduria');
insert into empleados values('24444444','Carlos Caseres','Caseros
364','Sistemas');
insert into empleados values('25555555','Diana Duarte','Colon
1234','Sistemas');
insert into empleados values('26666666','Diana Duarte','Colon
897','Sistemas');
insert into empleados values('27777777','Matilda Morales','Colon
542','Gerencia');

Creamos un disparador que se active cuando modificamos algn campo de "empleados" y


almacene en "controlCambios" el nombre del usuario que realiza la actualizacin, la fecha, el
dato que se cambia y el nuevo valor:

create or replace trigger tr_actualizar_empleados


before update
on empleados
for each row
begin
if updating('documento') then
insert into controlCambios values(user,sysdate, :old.documento,
:new.documento);
end if;
if updating('nombre') then
insert into controlCambios values(user,sysdate, :old.nombre,
:new.nombre);
end if;
if updating('domicilio') then
insert into controlCambios values(user,sysdate, :old.domicilio,
:new.domicilio);
end if;
if updating('seccion') then
insert into controlCambios values(user,sysdate, :old.seccion,
:new.seccion);
end if;
end tr_actualizar_empleados;

Creamos otro desencadenador que se active cuando ingresamos un nuevo registro en


"empleados", debe almacenar en "controlCambios" el nombre del usuario que realiza el
ingreso, la fecha, "null" en "datoanterior" (porque se dispara con una insercin) y en
"datonuevo" el documento:

create or replace trigger tr_ingresar_empleados


before insert
on empleados
for each row
begin
insert into controlCambios values(user,sysdate, null,
:new.documento);
end tr_ingresar_empleados;

Creamos un tercer trigger sobre "empleados" que se active cuando eliminamos un registro en
"empleados", debe almacenar en "controlCambios" el nombre del usuario que realiza la
eliminacin, la fecha, el documento en "datoanterior" y "null" en "datonuevo":

create or replace trigger tr_eliminar_empleados


before delete
on empleados
for each row
begin
insert into controlCambios values(user,sysdate, :old.documento,
null);
end tr_eliminar_empleados;

Los tres triggers estn habilitados. Consultamos el diccionario "user_triggers" para


corroborarlo:

select trigger_name, triggering_event, status


from user_triggers
where trigger_name like 'TR%EMPLEADOS';

Vamos a ingresar un empleado y comprobar que el trigger "tr_ingresar_empleados" se dispara


recuperando los registros de "controlCambios":

insert into empleados values('28888888','Pedro Perez','Peru


374','Secretaria');
select *from controlCambios;

Deshabilitamos el trigger "tr_ingresar_empleados":

alter trigger tr_ingresar_empleados disable;

Consultamos el diccionario "user_triggers" para corroborarlo:

select trigger_name, status


from user_triggers
where trigger_name like 'TR%EMPLEADOS';

El trigger "tr_ingresar_empleados" est deshabilitado, "tr_actualizar_empleados" y


"tr_elimnar_empleados" estn habilitados.

Vamos a ingresar un empleado y comprobar que el trigger de insercin no se dispara


recuperando los registros de "controlCambios":

insert into empleados values('29999999','Rosa Rodriguez','Rivadavia


627','Secretaria');
select *from controlCambios;

Vamos a actualizar el domicilio de un empleado y comprobar que el trigger de actualizacin


se dispara recuperando los registros de "controlCambios":

update empleados set domicilio='Bulnes 567' where


documento='22222222';
select *from controlCambios;

Deshabilitamos el trigger "tr_actualizar_empleados":

alter trigger tr_actualizar_empleados disable;

Consultamos el diccionario "user_triggers" para corroborarlo:

select trigger_name, status


from user_triggers
where trigger_name like 'TR%EMPLEADOS';

Los triggers "tr_ingresar_empleados" y "tr_actualizar_empleados" estn deshabilitados,


"tr_eliminar_empleados" est habilitado.
Vamos a borrar un empleado de "empleados" y comprobar que el trigger de borrado se dispar
recuperando los registros de "controlCambios":

delete from empleados where documento= '29999999';


select *from controlCambios;

Deshabilitamos el trigger "tr_eliminar_empleados":

alter trigger tr_eliminar_empleados disable;

Consultamos el diccionario "user_triggers" para comprobarlo:

select trigger_name, status


from user_triggers
where table_name = 'EMPLEADOS';

Los tres trigger establecidos sobre "empleados" estn deshabilitados.

Eliminamos un empleado de "empleados" y comprobamos que el trigger de borrado no se


dispara recuperando los registros de "controlCambios":

delete from empleados where documento= '28888888';


select *from controlCambios;

Habilitamos el trigger "tr_actualizar_empleados":

alter trigger tr_actualizar_empleados enable;

Actualizamos la seccin de un empleado y comprobamos que el trigger de actualizacin se


dispara recuperando los registros de "controlCambios":

update empleados set seccion='Sistemas' where documento='23333333';


select *from controlCambios;

Habilitamos todos los triggers establecidos sobre "empleados":

alter table empleados enable all triggers;

Consultamos el diccionario "user_triggers" para comprobar que el estado (status) de todos los
triggers establecidos sobre "empleados" es habilitado:

select trigger_name, triggering_event, status


from user_triggers
where table_name = 'EMPLEADOS';

Los tres trigger establecidos sobre "empleados" han sido habilitados. Se activarn ante
cualquier sentencia "insert", "update" y "delete".

115 - Disparadores (habilitar y deshabilitar)

Primer problema:

Una librera almacena los datos de sus libros en una tabla denominada "libros" y controla las
acciones que los empleados realizan sobre dicha tabla almacenando en la tabla "control" el
nombre del usuario, la fecha, y el tipo de modificacin que se realiz sobre la tabla "libros".
1- Elimine la tabla "libros" y la tabla "control":

drop table libros;


drop table control;

2- Cree las tablas con las siguientes estructuras:

create table libros(


codigo number(6),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(6,2)
);

create table control(


usuario varchar2(30),
fecha date,
operacion varchar2(20)
);

3- Ingrese algunos registros en "libros":

insert into libros values(100,'Uno','Richard Bach','Planeta',25);


insert into libros values(103,'El aleph','Borges','Emece',28);
insert into libros values(105,'Matematica estas ahi','Paenza','Nuevo siglo',12);
insert into libros values(120,'Aprenda PHP','Molina Mario','Nuevo siglo',55);
insert into libros values(145,'Alicia en el pais de las
maravillas','Carroll','Planeta',35);

4- Cree un disparador que se active cuando modificamos algn campo de "libros" y almacene
en "control" el nombre del usuario que realiza la actualizacin, la fecha y en "operacion"
coloque el nombre del campo actualizado

5- Cree otro desencadenador que se active cuando ingresamos un nuevo registro en "libros",
debe almacenar en "control" el nombre del usuario que realiza el ingreso, la fecha e
"insercion" en "operacion"

6- Cree un tercer trigger sobre "libros" que se active cuando eliminamos un registro de
"libros", debe almacenar en "control" el nombre del usuario que realiza la eliminacin, la
fecha y "borrado" en "operacion"

7- Los tres triggers estn habilitados. Consultamos el diccionario "user_triggers" para


corroborarlo

8- Ingrese un libro y compruebe que el trigger "tr_ingresar_libros" se dispara recuperando los


registros de "control"

9- Deshabilite el trigger "tr_ingresar_libros"

10- Consulte el diccionario "user_triggers" para corroborarlo


El trigger "tr_ingresar_libros" est deshabilitado, "tr_actualizar_libros" y "tr_eliminar_libros"
estn habilitados.

11- Ingrese un libro y compruebe que el trigger de insercin no se dispara recuperando los
registros de "control":
insert into libros values(152,'El anillo del hechicero','Gaskin','Planeta',22);
select *from control;

12- Actualice la editorial de varios libros y compruebe que el trigger de actualizacin se


dispara recuperando los registros de "control"

13- Deshabilite el trigger "tr_actualizar_libros"

14- Consulte el diccionario "user_triggers" para corroborarlo


Los triggers "tr_ingresar_libros" y "tr_actualizar_libros" estn deshabilitados,
"tr_eliminar_libros" est habilitado.

15- Borre un libro de "libros" y compruebe que el trigger de borrado se dispar recuperando
los registros de "control"

16- Deshabilite el trigger "tr_eliminar_libros"

17- Consulte el diccionario "user_triggers" para comprobarlo


Los tres trigger establecidos sobre "empleados" estn deshabilitados.

18- Elimine un libro de "libros" y compruebe que tal registro se elimin de "libros" pero que el
trigger de borrado no se dispara recuperando los registros de "control"

19- Habilite el trigger "tr_actualizar_libros"

20- Actualice el autor de un libro y compruebe que el trigger de actualizacin se dispara


recuperando los registros de "control"

21- Habilite todos los triggers establecidos sobre "libros"

22- Consulte el diccionario "user_triggers" para comprobar que el estado (status) de todos los
triggers establecidos sobre "libros" es habilitado
Los tres trigger establecidos sobre "libros" han sido habilitados. Se activarn ante cualquier
sentencia "insert", "update" y "delete".

drop table libros;


drop table control;

create table libros(


codigo number(6),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(6,2)
);

create table control(


usuario varchar2(30),
fecha date,
operacion varchar2(20)
);

insert into libros values(100,'Uno','Richard Bach','Planeta',25);


insert into libros values(103,'El aleph','Borges','Emece',28);
insert into libros values(105,'Matematica estas ahi','Paenza','Nuevo siglo',12);
insert into libros values(120,'Aprenda PHP','Molina Mario','Nuevo siglo',55);
insert into libros values(145,'Alicia en el pais de las
maravillas','Carroll','Planeta',35);

create or replace trigger tr_actualizar_libros


before update
on libros
for each row
begin
if updating('codigo') then
insert into control values(user,sysdate,'codigo');
end if;
if updating('titulo') then
insert into control values(user,sysdate,'titulo');
end if;
if updating('autor') then
insert into control values(user,sysdate,'autor');
end if;
if updating('editorial') then
insert into control values(user,sysdate,'editorial');
end if;
if updating('precio') then
insert into control values(user,sysdate,'precio');
end if;
end tr_actualizar_libros;

create or replace trigger tr_ingresar_libros


before insert
on libros
for each row
begin
insert into control values(user,sysdate,'insercion');
end tr_ingresar_libros;

create or replace trigger tr_eliminar_libros


before delete
on libros
for each row
begin
insert into control values(user,sysdate,'borrado');
end tr_eliminar_libros;

select trigger_name, triggering_event, status


from user_triggers
where table_name = 'LIBROS';

insert into libros values(150,'El experto en laberintos','Gaskin','Planeta',38);


select *from control;

alter trigger tr_ingresar_libros disable;

select trigger_name, status


from user_triggers
where table_name = 'LIBROS';
insert into libros values(152,'El anillo del hechicero','Gaskin','Planeta',22);
select *from control;

update libros set editorial='Sudamericana' where editorial='Planeta';


select *from control;

alter trigger tr_actualizar_libros disable;

select trigger_name, status


from user_triggers
where table_name ='LIBROS';

delete from libros where codigo=152;


select *from control;

alter trigger tr_eliminar_libros disable;

select trigger_name, status


from user_triggers
where table_name = 'EMPLEADOS';

delete from libros where codigo=150;


select *from libros where codigo=150;
select *from control;

alter trigger tr_actualizar_libros enable;

update libros set autor='Adrian Paenza' where autor='Paenza';


select *from control;

alter table libros enable all triggers;

select trigger_name, triggering_event, status


from user_triggers
where table_name = 'LIBROS';

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.

116 - Disparador (eliminar)

Problema:
Una librera almacena los datos de sus libros en una tabla denominada "libros" y controla las
acciones que los empleados realizan sobre dicha tabla almacenando en la tabla "control" el
nombre del usuario, la fecha, y el tipo de modificacin que se realiz sobre la tabla "libros".

Eliminamos la tabla "libros" y la tabla "control":

drop table libros;


drop table control;

Creamos las tablas con las siguientes estructuras:

create table libros(


codigo number(6),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(6,2)
);

create table control(


usuario varchar2(30),
fecha date,
operacion varchar2(20)
);

Creamos un desencadenador que se active cuando ingresamos un nuevo registro en "libros",


debe almacenar en "control" el nombre del usuario que realiza el ingreso, la fecha e
"insercion" en "operacion":

create or replace trigger tr_ingresar_libros


before insert
on libros
for each row
begin
insert into control values(user,sysdate,'insercion');
end tr_ingresar_libros;

Creamos un segundo disparador que se active cuando modificamos algn campo de "libros" y
almacene en "control" el nombre del usuario que realiza la actualizacin, la fecha y en
"operacion" coloque el nombre del campo actualizado:

create or replace trigger tr_actualizar_libros


before update
on libros
for each row
begin
if updating('codigo') then
insert into control values(user,sysdate,'codigo');
end if;
if updating('titulo') then
insert into control values(user,sysdate,'titulo');
end if;
if updating('autor') then
insert into control values(user,sysdate,'autor');
end if;
if updating('editorial') then
insert into control values(user,sysdate,'editorial');
end if;
if updating('precio') then
insert into control values(user,sysdate,'precio');
end if;
end tr_actualizar_libros;

Creamos un tercer trigger sobre "libros" que se active cuando eliminamos un registro de
"libros", debe almacenar en "control" el nombre del usuario que realiza la eliminacin, la
fecha y "borrado" en "operacion":

create or replace trigger tr_eliminar_libros


before delete
on libros
for each row
begin
insert into control values(user,sysdate,'borrado');
end tr_eliminar_libros;

Vemos cuntos triggers estn asociados a "libros"; consultamos el diccionario "user_triggers":

select trigger_name, triggering_event, status


from user_triggers
where table_name = 'LIBROS';

Hay tres.

Ingresamos algunos registros en "libros":

insert into libros values(100,'Uno','Richard Bach','Planeta',25);


insert into libros values(101,'El aleph','Borges','Emece',28);
insert into libros values(102,'Matematica estas ahi','Paenza','Nuevo
siglo',12);
insert into libros values(103,'Aprenda PHP','Molina Mario','Nuevo
siglo',55);
insert into libros values(144,'Alicia en el pais de las
maravillas','Carroll','Planeta',35);

Comprobamos que el trigge "tr_ingresar_libros" se dispar recuperando los registros de


"control":

select *from control;

Hay 5 registros.

Actualizamos la editorial de varios libros y comprobamos que el trigger de actualizacin se


dispar recuperando los registros de "control":

update libros set editorial='Sudamericana' where editorial='Planeta';


select *from control;

2 nuevos registros.

Borramos un libro de "libros" y comprobamos que el trigger de borrado se dispar recuperando


los registros de "control":

delete from libros where codigo=101;


select *from control;
Actualizamos el autor de un libro y comprobamos que el trigger de actualizacin se dispara
recuperando los registros de "control":

update libros set autor='Adrian Paenza' where autor='Paenza';


select *from control;

Eliminamos la tabla "libros":

drop table libros;

Consultamos el diccionario "user_triggers" para comprobar que al eliminar "libros" se


eliminaron tambin los triggers asociados a ella:

select trigger_name, triggering_event, status


from user_triggers
where table_name = 'LIBROS';

Los tres trigger asociados a "libros" han sido eliminados.

116 - Disparador (eliminar)

Primer problema:

Un comercio almacena los datos de los artculos que tiene para la venta en una tabla
denominada "articulos". En otra tabla denominada "ventas" almacena el cdigo de cada
artculo, la cantidad que se vende y la fecha.

1- Elimine las tablas:

drop table ventas;


drop table articulos;

2- Cree las tablas con las siguientes estructuras:

create table articulos(


codigo number(4) not null,
descripcion varchar2(40),
precio number (6,2),
stock number(4),
constraint PK_articulos_codigo
primary key (codigo)
);

create table ventas(


codigo number(4),
cantidad number(4),
fecha date,
constraint FK_ventas_articulos
foreign key (codigo)
references articulos(codigo)
);

3- Cree una secuencia llamada "sec_codigoart", estableciendo que comience en 1, sus valores
estn entre 1 y 9999 y se incrementen en 1. Antes elimnela por si existe
4- Active el paquete para permitir mostrar salida en pantalla

5- Cree un trigger que coloque el siguiente valor de una secuencia para el cdigo de
"articulos" cada vez que se ingrese un nuevo artculo
Podemos ingresar un nuevo registro en "articulos" sin incluir el cdigo porque lo ingresar el
disparador luego de calcularlo. Si al ingresar un registro en "articulos" incluimos un valor para
cdigo, ser ignorado y reemplazado por el valor calculado por el disparador.

6- Ingrese algunos registros en "articulos" sin incluir el cdigo:

insert into articulos (descripcion, precio, stock) values ('cuaderno rayado


24h',4.5,100);
insert into articulos (descripcion, precio, stock) values ('cuaderno liso
12h',3.5,150);
insert into articulos (descripcion, precio, stock) values ('lapices color x6',8.4,60);

7- Recupere todos los artculos para ver cmo se almacen el cdigo

8- Ingrese algunos registros en "articulos" incluyendo el cdigo:

insert into articulos values(160,'regla 20cm.',6.5,40);


insert into articulos values(173,'compas metal',14,35);
insert into articulos values(234,'goma lapiz',0.95,200);

9- Recupere todos los artculos para ver cmo se almacen los cdigos
Ignora los cdigos especificados ingresando el siguiente de la secuencia.

10- Cuando se ingresa un registro en "ventas", se debe:

- controlar que el cdigo del artculo exista en "articulos" (lo hacemos con la restriccin
"foreign key" establecida en "ventas");

- controlar que exista stock, lo cual no puede controlarse con una restriccin "foreign key"
porque el campo "stock" no es clave primaria en la tabla "articulos"; cree un trigger. Si existe
stock, debe disminuirse en "articulos".

Cree un trigger a nivel de fila sobre la tabla "ventas" para el evento se insercin. Cada vez
que se realiza un "insert" sobre "ventas", el disparador se ejecuta. El disparador controla que
la cantidad que se intenta vender sea menor o igual al stock del articulo y actualiza el campo
"stock" de "articulos", restando al valor anterior la cantidad vendida. Si la cantidad supera el
stock, debe producirse un error, revertirse la accin y mostrar un mensaje

11- Ingrese un registro en "ventas" cuyo cdigo no exista en "articulos"


Aparece un mensaje de error, porque el cdigo no existe. El trigger se ejecut.

12- Verifique que no se ha agregado ningn registro en "ventas"

13- Ingrese un registro en "ventas" cuyo cdigo exista en "articulos" y del cual haya suficiente
stock
Note que el trigger se dispar, aparece el texto "tr_insertar_ventas activado".

14- Verifique que el trigger se dispar consultando la tabla "articulos" (debe haberse
disminuido el stock) y se agreg un registro en "ventas"
15- Ingrese un registro en "ventas" cuyo cdigo exista en "articulos" y del cual NO haya
suficiente stock
Aparece el mensaje mensaje de error 20001 y el texto que muestra que se dispar el trigger.

16- Verifique que NO se ha disminuido el stock en "articulos" ni se ha agregado un registro en


"ventas"

17- El comercio quiere que se realicen las ventas de lunes a viernes de 8 a 18 hs. Reemplace
el trigger creado anteriormente "tr_insertar_ventas" para que No permita que se realicen
ventas fuera de los das y horarios especificados y muestre un mensaje de error

18- Ingrese un registro en "ventas", un da y horario permitido, si es necesario, modifique la


fecha y la hora del sistema

19- Verifique que se ha agregado un registro en "ventas" y se ha disminuido el stock en


"articulos"

20- Ingrese un registro en "ventas", un da permitido fuera del horario permitido (si es
necesario, modifique la fecha y hora del sistema)
Se muestra un mensaje de error.

21- Ingrese un registro en "ventas", un da sbado a las 15 hs.

22- El comercio quiere que los registros de la tabla "articulos" puedan ser ingresados,
modificados y/o eliminados nicamente los sbados de 8 a 12 hs. Cree un trigger "tr_articulos"
que No permita que se realicen inserciones, actualizaciones ni eliminaciones en "articulos"
fuera del horario especificado los das sbados, mostrando un mensaje de error. Recuerde
que al ingresar un registro en "ventas", se actualiza el "stock" en "articulos"; el trigger debe
permitir las actualizaciones del campo "stock" en "articulos" de lunes a viernes de 8 a 18 hs.
(horario de ventas)

23- Ingrese un nuevo artculo un sbado a las 9 AM


Note que se activan 2 triggers.

24- Elimine un artculo, un sbado a las 16 hs.


Mensaje de error.

25- Actualice el precio de un artculo, un domingo

26- Actualice el precio de un artculo, un lunes en horario de ventas


Mensaje de error.

27- Ingrese un registro en "ventas" que modifique el "stock" en "articulos", un martes entre las
8 y 18 hs.
Note que se activan 2 triggers.

28- Consulte el diccionario "user_triggers" para ver cuntos trigger estn asociados a
"articulos" y a "ventas" (3 triggers)

29- Elimine el trigger asociado a "ventas"

30- Elimine las tablas "ventas" y "articulos"

31- Consulte el diccionario "user_triggers" para verificar que al eliminar la tabla "articulos" se
han eliminado todos los triggers asociados a ella
drop table ventas;
drop table articulos;

create table articulos(


codigo number(4) not null,
descripcion varchar2(40),
precio number (6,2),
stock number(4),
constraint PK_articulos_codigo
primary key (codigo)
);

create table ventas(


codigo number(4),
cantidad number(4),
fecha date,
constraint FK_ventas_articulos
foreign key (codigo)
references articulos(codigo)
);

drop sequence sec_codigoart;


create sequence sec_codigoart
start with 1
increment by 1;

set serveroutputon;
execute dbms_output.enable (20000);

create or replace trigger tr_insertar_codigo_articulos


before insert
on articulos
for each row
begin
select sec_codigoart.nextval into :new.codigo from dual;
dbms_output.put_line('"tr_insertar_codigo_articulos" activado');
end tr_insertar_codigo_articulos;

insert into articulos (descripcion, precio, stock) values ('cuaderno rayado


24h',4.5,100);
insert into articulos (descripcion, precio, stock) values ('cuaderno liso
12h',3.5,150);
insert into articulos (descripcion, precio, stock) values ('lapices color x6',8.4,60);

select *from articulos;

insert into articulos values(160,'regla 20cm.',6.5,40);


insert into articulos values(173,'compas metal',14,35);
insert into articulos values(234,'goma lapiz',0.95,200);

select *from articulos;

create or replace trigger tr_insertar_ventas


before insert
on ventas
for each row
declare
canti number:=null;
begin
dbms_output.put_line('"tr_insertar_ventas" activado');
select stock into canti from articulos where codigo=:new.codigo;
if :new.cantidad>canti then
raise_application_error(-20001,'Slo hay '|| to_char(canti)||' en stock');
else
update articulos set stock=stock-:new.cantidad where codigo=:new.codigo;
end if;
end tr_insertar_ventas;

insert into ventas values(200,10,sysdate);

select *from ventas;

insert into ventas values(2,10,sysdate);

select *from articulos;


select *from ventas;

insert into ventas values(2,300,sysdate);

select *from articulos;


select *from ventas;

create or replace trigger tr_insertar_ventas


before insert
on ventas
for each row
declare
canti number:=null;
begin
dbms_output.put_line('"tr_insertar_ventas" activado');
if (to_char(sysdate, 'DY','nls_date_language=SPANISH') in
('LUN','MAR','MIE','JUE','VIE')) then
if(to_number(to_char(sysdate, 'HH24')) between 8 and 17) then
select stock into canti from articulos where codigo=:new.codigo;
if :new.cantidad>canti then
raise_application_error(-20001,'Slo hay '|| to_char(canti)||' en stock');
else
update articulos set stock=stock-:new.cantidad where codigo=:new.codigo;
end if;
else--hora
raise_application_error(-20002,'Solo se pueden realizar ventas entre las 8 y 18
hs.');
end if;--hora
else
raise_application_error(-20003,'Solo se pueden realizar ventas de lunes a
viernes.');
end if; --dia
end tr_insertar_ventas;

insert into ventas values(3,20,sysdate);


select *from articulos;
select *from ventas;

insert into ventas values(3,20,sysdate);

insert into ventas values(3,20,sysdate);

create or replace trigger tr_articulos


before insert or update or delete
on articulos
for each row
begin
dbms_output.put_line('"tr_update_articulos" activado');
if (to_char(sysdate, 'DY','nls_date_language=SPANISH')='SB')then
if(to_number(to_char(sysdate, 'HH24')) not between 8 and 11) then
raise_application_error(-20004,'Esta tarea en sbado slo de 8 a 12 hs.');
end if;
else
if(to_char(sysdate, 'DY','nls_date_language=SPANISH')='DOM')then
raise_application_error(-20005,'Esta tarea no en domingo.');
else
if updating ('stock') then
if (to_number(to_char(sysdate, 'HH24')) not between 8 and 17) then
raise_application_error(-20006,'Esta tarea de LUN a VIE de 8 a 18 hs. o
SAB de 8 a 12 hs.');
end if;
else
raise_application_error(-20007,'Esta tarea solo SAB de 8 a 12 hs.');
end if;--stock
end if;--domingo
end if;--sab
end tr_articulos;

insert into articulos values(234,'cartulina',0.95,100);

delete from articulos where codigo=1;

update articulos set precio=precio+precio*0.1 where codigo=5;

update articulos set precio=precio+precio*0.1 where codigo=5;

insert into ventas values(3,5,sysdate);

select table_name, trigger_name, triggering_event from user_triggers


where table_name ='ARTICULOS' or table_name='VENTAS';

drop trigger tr_insertar_ventas;

drop table ventas;


drop table articulos;

select * from user_triggers where trigger_name='TR_ARTICULOS' or


trigger_name='TR_INSERTAR_CODIGO_ARTICULOS';
Segundo problema:

Una empresa almacena los datos de sus empleados en una tabla denominada "empleados" y en
otra tabla llamada "secciones", el cdigo de la seccin y el sueldo mximo de cada una de
ellas.

1- Elimine las tablas:

drop table empleados;


drop table secciones;

2- Cree las tablas, con las siguientes estructuras:

create table secciones(


codigo number(2),
nombre varchar2(30),
sueldomaximo number(8,2),
constraint PK_secciones primary key(codigo)
);

create table empleados(


documento char(8) not null,
nombre varchar2(30) not null,
domicilio varchar2(30),
codigoseccion number(2) not null,
sueldo number(8,2),
constraint PK_empleados primary key(documento),
constraint FK_empleados_seccion
foreign key (codigoseccion)
references secciones(codigo)
);

3- Ingrese algunos registros en ambas tablas:

insert into secciones values(1,'Administracion',1500);


insert into secciones values(2,'Sistemas',2000);
insert into secciones values(3,'Secretaria',1000);

insert into empleados values('22222222','Ana Acosta','Avellaneda 88',1,1100);


insert into empleados values('23333333','Bernardo Bustos','Bulnes 345',1,1200);
insert into empleados values('24444444','Carlos Caseres','Colon 674',2,1800);
insert into empleados values('25555555','Diana Duarte','Colon 873',3,1000);

4- Active el paquete necesario para mostrar mensaje por pantalla:

set serveroutput on;


execute dbms_output.enable (20000);

5- En cada disparador que cree prximamente muestre un mensaje por pantalla que indique
su nombre.

6- Cree un disparador para que se ejecute cada vez que una instruccin "insert" ingrese datos
en "empleados"; el mismo debe verificar que el sueldo del empleado no sea mayor al sueldo
mximo establecido para la seccin, si lo es, debe mostrar un mensaje indicando tal situacin
y deshacer la transaccin
7- Ingrese un nuevo registro en "empleados" cuyo sueldo sea menor o igual al establecido para
la seccin:

insert into empleados values('26666666','Federico Fuentes','Francia 938',2,1000);

El disparador se ejecut, un texto en pantalla muestra su nombre.

8- Verifique que el disparador se ejecut consultando la tabla "empleados"

9- Intente ingresar un nuevo registro en "empleados" cuyo sueldo sea mayor al establecido
para la seccin
El disparador se ejecut mostrando un mensaje de error y la transaccin se deshizo.

10- Verifique que el registro no se agreg en "empleados"

11- Intente ingresar un empleado con cdigo de seccin inexistente


Aparece un mensaje de error porque se viola la restriccin "foreign key"; el trigger se ejecut,
aparece el mensaje de texto que lo indica.

12- Cree un disparador para que se ejecute cada vez que una instruccin "update" aumente el
sueldo de "empleados"; el mismo debe verificar que el sueldo del empleado no supere al
sueldo mximo establecido para la seccin, si lo es, debe mostrar un mensaje indicando tal
situacin y deshacer la transaccin

13- Modifique el sueldo de un empleado, debe ser menor o igual al establecido para la seccin
El trigger se dispar.

14- Verifique que el disparador se ejecut consultando la tabla "empleados"

15- Intente actualizar el sueldo de un empleado a un valor mayor al establecido para la


seccin
El disparador se ejecut mostrando un mensaje de error y la transaccin se deshizo.

16- Verifique que el registro no se modific en "empleados"

17- Disminuya el sueldo de un empleado


El trigger no se disparo (no se mostr el texto con su nombre) porque se estableci en la
condicin "when" que el sueldo nuevo fuera mayor al anterior.

18- Verifique que el registro se modific en "empleados"

19- Modifique el cdigo de seccin del empleado cuyo documento es "22222222" a "3"
Note que el cambio se realiz, y ahora existe un empleado de la seccin "Secretaria" con
sueldo "1350" cuando el mximo para esa seccin es de "1000". Debe crear el trigger
"tr_empleados_update_seccion", que se dispare cada vez que se modifique la seccion de un
empleado y verifique que el sueldo no supere el mximo de la nueva seccin, si lo supera, la
transaccin debe deshacerse

20- Modifique el cdigo de seccin del empleado cuyo documento es "22222222" a "1"
El trigger se dispar, como el sueldo no supera el mximo permitido para la nueva seccin, el
cambio se realiz.

21- Verifique que el cambio se realiz

22- Modifique el cdigo de seccin del empleado cuyo documento es "23333333" a "3"
El trigger se dispar y mostr el mensaje de error, la transaccin se deshizo.
23- Verifique que el cambio no se realiz

24- Modifique el sueldo del empleado cuyo documento es "23333333" a "1000" y el cdigo de
seccin a "3"
El trigger se dispar.

25- Verifique que el cambio se realiz

26- Si modificamos el sueldo mximo de una seccin de "secciones", disminuyndolo, pueden


quedar en "empleados" valores de sueldos superiores al permitido para la seccin. Para evitar
esto debe crear un disparador sobre "secciones" que se active cuando se disminuya el campo
"sueldomaximo" y modifique el sueldo (al mximo permitido para la seccin) de todos los
empleados de esa seccin cuyos sueldos superen el nuevo mximo establecido

27- Modifique el sueldo mximo para la seccin "Administracion" a 2000, es decir, aumntelo
Note que el trigger No se dispar, porque el trigger tiene una condicin "when" que especifica
que se active unicamente cuando el nuevo sueldo maximo sea menor al anterior.

28- Verifique que el sueldo mximo de "Administracion" se ha modificado

29- Modifique el sueldo mximo para la seccin "Administracion" a 1800, es decir, disminyalo
Note que el trigger se dispar, cumple con la condicin "when". Pero, como no hay en
"empleados", sueldos de tal seccin que superen tal valor, no se han modificado registros en
"empleados".

30- Verifique que se modific el sueldo mximo en "secciones" pero ningn registro en
"empleados"

31- Modifique el sueldo mximo para la seccin "Administracion" a 1200, es decir, disminyalo
Note que el trigger se dispar, cumple con la condicin "when". Como hay en "empleados" un
sueldo de 1350, de "Administracion", es decir supera el nuevo "sueldomaximo" que se intenta
establecer, se modifica tal registro en "empleados".

32- Verifique que se modific el sueldo mximo en "secciones" y un registro en "empleados"

33- Cree un trigger que no permita que se modifique el cdigo de "secciones"

34- Intente modificar el cdigo de una seccin de "secciones"


Note que el trigger se dispar y muestra el mensaje de error. El cdigo no se modific.
Verifquelo

35- Actualice en una misma sentencia "update", el sueldo a "1800" y el codigo de seccin a "2"
del empleado cuyo documento es "22222222"
Note que se activan 2 triggers.

36- Cree un trigger a nivel de sentencia sobre "empleados", que muestre un mensaje de error
para evitar que se actualice el campo "documento"

37- Consulte el diccionario "user_triggers" para ver cuntos trigger estn asociados a
"empleados" y a "secciones"

38- Elimine los 2 triggers asociados a la tabla "secciones"

39- Consulte el diccionario "user_triggers" para verificar que "secciones" ya no tiene


disparadores asociados a ella
40- Cree un trigger sobre "secciones", para el evento de actualizacin que realice todas las
acciones que ejecutaban los 2 triggers que "secciones" tena asociados anteriormente; es
decir:

- si se actualiza un sueldo mximo, modificar el sueldo, al mximo permitido, a todos los


empleados (de la seccin modificada) cuyos sueldos superen el nuevo sueldo mximo;

- definir un mensaje de error si se intenta actualizar un cdigo se seccin.

41- Probarlo. Disminuir el sueldo mximo de una seccin que no supere el sueldo de ningun
empleado:
Se activ el trigger de actualizacion de secciones pero ningn registro de "empleados" fue
modificado.

42- Disminuir el sueldo mximo de una seccin de modo que supere el sueldo de algn
empleado
Se activ el trigger de actualizacion de secciones y 2 registros de "empleados" fueron
modificados.

43- Intente modificar un cdigo de seccin


Mensaje de error.

44- Consulte el diccionario "user_triggers" para ver cuntos triggers estn asociados a las
tablas "secciones" y "empleados"

45- Elimine la tabla "empleados"

46- Consulte el diccionario "user_triggers" para verificar que al borrar la tabla "empleados" se
eliminaron todos los disparadores asociados a ella

47- Elimine la tabla "secciones" y consulte "user_triggers" para verificar que al borrar la tabla
"secciones" se eliminaron todos los desencadenadores asociados a ella

drop table empleados;


drop table secciones;

create table secciones(


codigo number(2),
nombre varchar2(30),
sueldomaximo number(8,2),
constraint PK_secciones primary key(codigo)
);

create table empleados(


documento char(8) not null,
nombre varchar2(30) not null,
domicilio varchar2(30),
codigoseccion number(2) not null,
sueldo number(8,2),
constraint PK_empleados primary key(documento),
constraint FK_empleados_seccion
foreign key (codigoseccion)
references secciones(codigo)
);
insert into secciones values(1,'Administracion',1500);
insert into secciones values(2,'Sistemas',2000);
insert into secciones values(3,'Secretaria',1000);

insert into empleados values('22222222','Ana Acosta','Avellaneda 88',1,1100);


insert into empleados values('23333333','Bernardo Bustos','Bulnes 345',1,1200);
insert into empleados values('24444444','Carlos Caseres','Colon 674',2,1800);
insert into empleados values('25555555','Diana Duarte','Colon 873',3,1000);

set serveroutput on;


execute dbms_output.enable (20000);

create or replace trigger tr_empleados_insertar


before insert
on empleados
for each row
declare
varsueldo number:=null;
varseccion varchar2(30):=null;
begin
dbms_output.put_line('Trigger de insercion de "empleados" activado');
select sueldomaximo into varsueldo from secciones where
codigo=:new.codigoseccion;
select nombre into varseccion from secciones where codigo=:new.codigoseccion;
if (:new.sueldo>varsueldo) then
raise_application_error(-20001,'Ud. intenta ingresar un sueldo de $
'||to_char(:new.sueldo)
|| ' y el mx. para ' || varseccion ||' es de '|| to_char(varsueldo));
end if;--sueldo mayor
end tr_empleados_insertar;

insert into empleados values('26666666','Federico Fuentes','Francia 938',2,1000);

select *from empleados;

insert into empleados values('27777777','Gaston Garcia','Guemes 366',3,1200);

select *from empleados;

insert into empleados values('27777777','Gaston Garcia','Guemes 366',9,1200);

create or replace trigger tr_empleados_update_sueldos


before update of sueldo
on empleados
for each row when (new.sueldo>old.sueldo)
declare
varsueldo number:=null;
varseccion varchar2(30):=null;
begin
dbms_output.put_line('Trigger de actualizacion de sueldo activado');
select sueldomaximo into varsueldo from secciones where
codigo=:new.codigoseccion;
select nombre into varseccion from secciones where codigo=:new.codigoseccion;
if (:new.sueldo>varsueldo) then
raise_application_error(-20002,'Ud. intenta cambiar el sueldo de $
'||to_char(:old.sueldo)||' por '
||to_char(:new.sueldo)||' y el mx. para ' || varseccion ||' es de '||
to_char(varsueldo));
end if;--sueldo mayor
end tr_empleados_update_sueldos;

update empleados set sueldo=1500 where documento='22222222';

select *from empleados;

update empleados set sueldo=1600 where documento='22222222';

select *from empleados;

update empleados set sueldo=sueldo-sueldo*0.1 where documento='22222222';

select *from empleados;

update empleados set codigoseccion=3 where documento='22222222';

create or replace trigger tr_empleados_update_seccion


before update of codigoseccion
on empleados
for each row
declare
varsueldo number:=null;
varseccion varchar2(30):=null;
begin
dbms_output.put_line('Trigger de actualizacion de codigo de seccion activado');
select sueldomaximo into varsueldo from secciones where
codigo=:new.codigoseccion;
select nombre into varseccion from secciones where codigo=:new.codigoseccion;
if (:new.sueldo>varsueldo) then
raise_application_error(-20003,'Intenta cambiar la seccin, pero el sueldo mx.
para '
|| varseccion ||' es de '|| to_char(varsueldo)|| ' y el sueldo actual de '||
to_char(:new.sueldo)|| ' lo supera');
end if;--sueldo mayor
end tr_empleados_update_seccion;

update empleados set codigoseccion=1 where documento='22222222';

select *from empleados;

update empleados set codigoseccion=3 where documento='23333333';

select *from empleados;

update empleados set sueldo=1000, codigoseccion=3 where


documento='23333333';

select *from empleados;

create or replace trigger tr_secciones_maximo


before update of sueldomaximo
on secciones
for each row when (new.sueldomaximo<old.sueldomaximo)
declare
existen number:=0;
begin
dbms_output.put_line('Trigger de actualizacion de maximo sueldo activado');
select count(*) into existen from empleados
where codigoseccion=:new.codigo
and sueldo>:new.sueldomaximo;
if (existen>0)Then
update empleados set sueldo=:new.sueldomaximo
where codigoseccion=:new.codigo
and sueldo>:new.sueldomaximo;
dbms_output.put_line(to_char(existen)|| ' registros de "empleados"
actualizados');
end if;
end tr_secciones_maximo;

update secciones set sueldomaximo=2000 where nombre='Administracion';

select sueldomaximo from secciones where nombre='Administracion';

update secciones set sueldomaximo=1800 where nombre='Administracion';

select sueldomaximo from secciones where nombre='Administracion';


select *from empleados where codigoseccion=1;

update secciones set sueldomaximo=1200 where nombre='Administracion';

select sueldomaximo from secciones where nombre='Administracion';


select *from empleados where codigoseccion=1;

create or replace trigger tr_secciones_update_codigo


before update of codigo
on secciones
for each row
begin
dbms_output.put_line('Trigger de actualizacion de codigo activado');
raise_application_error(-20004,'El cdigo de seccin no puede modificarse');
end tr_secciones_update_codigo;

update secciones set codigo=9 where codigo=1;

select *from secciones;

update empleados set sueldo=1800, codigoseccion=2 where


documento='22222222';

create or replace trigger tr_empleados_documento


before update of documento
on empleados
begin
dbms_output.put_line('Trigger de actualizacion de documento activado');
raise_application_error(-20005,'El documento no puede modificarse');
end tr_empleados_documento;

select table_name, trigger_name, triggering_event from user_triggers


where table_name ='EMPLEADOS' or table_name='SECCIONES';

drop trigger tr_secciones_maximo;


drop trigger tr_secciones_update_codigo;

select trigger_name, triggering_event from user_triggers


where table_name ='SECCIONES';

create or replace trigger tr_secciones


before update
on secciones
for each row
declare
existen number:=0;
begin
dbms_output.put_line('Trigger de actualizacion de secciones activado');
if (updating('sueldomaximo'))then
if (:new.sueldomaximo<:old.sueldomaximo) then
select count(*) into existen from empleados where codigoseccion=:new.codigo
and sueldo>:new.sueldomaximo;
if (existen>0)Then
update empleados set sueldo=:new.sueldomaximo
where codigoseccion=:new.codigo
and sueldo>:new.sueldomaximo;
end if; --existen
dbms_output.put_line(to_char(existen)|| ' registros de "empleados"
actualizados');
end if;--mayor
end if;--actualizacion de sueldo
if updating('codigo')then
raise_application_error(-20004,'El cdigo no puede modificarse');
end if;
end tr_secciones;

update secciones set sueldomaximo=1100 where codigo=1;

update secciones set sueldomaximo=1500 where codigo=2;

update secciones set codigo=10 where codigo=2;

select trigger_name, table_name, triggering_event from user_triggers


where table_name ='SECCIONES' or table_name ='EMPLEADOS';

drop table empleados;

select trigger_name, table_name, triggering_event from user_triggers


where table_name ='EMPLEADOS';

drop table secciones;


select *from user_triggers
where table_name ='SECCIONES';

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.

117 - Errores definidos por el usuario

Problema:

Una librera almacena en "libros" los datos de sus libros para la venta. En una tabla
denominada "control" almacena el nombre del usuario y la fecha, cada vez que se actualiza la
tabla "libros".

Eliminamos las tablas "libros" y "control":

drop table libros;


drop table control;

Creamos las tablas:

create table libros(


codigo number(5),
titulo varchar2(40),
autor varchar2(30),
editorial varchar2(20),
precio number(6,2)
);

create table control(


usuario varchar2(30),
fecha date
);

Ingresamos algunos registros en "libros":

insert into libros values (101,'Uno','Richard Bach','Planeta',25);


insert into libros values (102,'Matematica estas ahi','Paenza','Nuevo
siglo',12);
insert into libros values (103,'El aleph','Borges','Emece',28);
insert into libros values (104,'Aprenda PHP','Molina','Nuevo
siglo',55);
insert into libros values (105,'El experto en
laberintos','Gaskin','Planeta',23);

Creamos un trigger de actualizacin a nivel de fila sobre la tabla "libros" que se dispare antes
que se ejecute una actualizacin. 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;

Aumentamos el precio de todos los libros de editorial "Planeta":

update libros set precio=precio+precio*0.1 where


editorial='Planeta';

Controlamos que los precios se han modificado y el trigger se ha disparado almacenando en


"control" 2 registros:

select *from libros;


select *from control;

Intentamos modificar el cdigo de un libro:

update libros set codigo=109 where codigo=101;


Note que muestra el mensaje de error definido por nosotros. El trigger se dispar y se ejecut
"raise_application_error", por lo tanto, el cdigo no se modific. Controlamos que el cdigo
no se modific:

select *from libros;

Reemplazamos el trigger creado anteriormente para que ahora se dispare DESPUES (after) de
cualquier modificacin de los registros de "libros"; debe realizar lo mismo que el anterior,
ingresar en la tabla "control", el nombre del usuario que realiz la actualizacin y la fecha.
Pero, controlando que NO se permita modificar el campo "codigo", en caso de suceder, la
accin no debe revertirse y debe mostrarse un mensaje de error indicndolo:

create or replace trigger tr_actualizar_libros


after 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;

Intentamos modificar el cdigo de un libro:

update libros set codigo=109 where codigo=101;

Note que muestra el mensaje de error definido por nosotros. El trigger fue definido "after", es
decir, se dispar luego de ejecutarse la actualizacin, pero tambin se ejecut
"raise_application_error", por lo tanto, la sentencia "update" se deshizo.

Controlamos que el cdigo no se modific:

select *from libros;


117 - Errores definidos por el usuario

Primer problema:

Una empresa almacena los datos de sus empleados en una tabla denominada "empleados" y en
otra tabla llamada "control", guarda el nombre del usuario, la fecha y el tipo de operacin
que se realiza en la tabla "empleados".

1- Elimine las tablas "empleados" y "control":

drop table empleados;


drop table control;

2- Cree las tablas:

create table empleados(


documento char(8),
apellido varchar2(30),
nombre varchar2(30),
domicilio varchar2(30),
seccion varchar2(20),
sueldo number(8,2)
);

create table control(


usuario varchar2(30),
fecha date,
operacion varchar2(30)
);

3- Ingrese algunos registros:

insert into empleados values('22222222','Acosta','Ana','Avellaneda


11','Secretaria',1800);
insert into empleados values('23333333','Bustos','Betina','Bulnes
22','Gerencia',5000);
insert into empleados values('24444444','Caseres','Carlos','Colon
333','Contaduria',3000);

4- Cree un trigger de insercin sobre "empleados" que guarde en "control" el nombre del
usuario que ingresa datos, la fecha y "insercion", en el campo "operacion". Pero, si el sueldo
que se intenta ingresar supera los $5000, debe mostrarse un mensaje de error y deshacer la
transaccin

5- Cree un trigger de borrado sobre "empleados" que guarde en "control" los datos requeridos
(en "operacion" debe almacenar "borrado". Si se intenta eliminar un empleado de la seccin
"gerencia", debe aparecer un mensaje de error y deshacer la operacin

6- Cree un trigger de actualizacin. Ante cualquier modificacin de los registros de


"empleados", se debe ingresar en la tabla "control", el nombre del usuario que realiz la
actualizacin, la fecha y "actualizacion". Pero, controlamos que NO se permita modificar el
campo "documento", en caso de suceder, la accin no debe realizarse y debe mostrarse un
mensaje de error indicndolo

7- Intente ingresar un empleado con sueldo superior a $5000:

insert into empleados values('25555555','Duarte','Dario','Dominicana


444','Secretaria',5800);

Note que muestra el mensaje de error definido por usted.

8- Ingrese un empleado con valores permitidos:

insert into empleados values('25555555','Duarte','Dario','Dominicana


444','Secretaria',2800);

9- Intente borrar un empleado de "gerencia"


Aparece un mensaje de error.

10- Elimine un empleado que no sea de "Gerencia"

11- Intente modificar el documento de un empleado


Mensaje de error.

12- Modifique un campo diferente de "documento"


13- Vea que se ha almacenado hasta el momento en "control"
Debe haber 3 registros, de insercin, de borrado y actualizacin.

drop table empleados;


drop table control;

create table empleados(


documento char(8),
apellido varchar2(30),
nombre varchar2(30),
domicilio varchar2(30),
seccion varchar2(20),
sueldo number(8,2)
);

create table control(


usuario varchar2(30),
fecha date,
operacion varchar2(30)
);

insert into empleados values('22222222','Acosta','Ana','Avellaneda


11','Secretaria',1800);
insert into empleados values('23333333','Bustos','Betina','Bulnes
22','Gerencia',5000);
insert into empleados values('24444444','Caseres','Carlos','Colon
333','Contaduria',3000);

create or replace trigger tr_insertar_empleados


before insert
on empleados
for each row
begin
if (:new.sueldo>5000)then
raise_application_error(-20000,'El sueldo no puede superar los $5000');
end if;
insert into control values(user,sysdate,'insercion');
end tr_insertar_empleados;

create or replace trigger tr_eliminar_empleados


before delete
on empleados
for each row
begin
if (:old.seccion='Gerencia')then
raise_application_error(-20001,'No puede eliminar empleados de gerencia');
end if;
insert into control values(user,sysdate,'borrado');
end;

create or replace trigger tr_actualizar_empleados


before update
on empleados
for each row
begin
if updating('documento') then
raise_application_error(-20002,'No se puede modificar el documento de los
empleados');
else
insert into control values(user,sysdate,'actualizacion');
end if;
end;

insert into empleados values('25555555','Duarte','Dario','Dominicana


444','Secretaria',5800);

insert into empleados values('25555555','Duarte','Dario','Dominicana


444','Secretaria',2800);

delete from empleados where documento='23333333';

delete from empleados where documento='25555555';

update set documento='28888888' where documento='22222222';

update empleados set nombre='Ana Laura' where nombre='Ana';

select *from control;

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.

119 - Usuarios (crear)

Problema:

Sabemos que para crear un usuario debemos conectarnos a la base datos como
administradores (por ejemplo "system").

Necesitamos crear un usuario "ana"; antes vamos a eliminarlo por si existe (luego veremos
detenidamente cmo eliminar usuarios y explicaremos la siguiente sentencia):

drop user ana cascade;

Creamos un usuario denominado "ana" con la contrasea "anita":

create user ana identified by anita;

Aparece un mensaje indicando que el usuario "ana" ha sido creado.

Necesitamos crear un usuario denominado "juan"; antes vamos a eliminarlo por si existe:

drop user juan cascade;

Creamos el usuario "juan" con la contrasea "juancito", le asignamos un espacio de 100 mb en


"system":

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.

create user juan identified by juancito;

Mensaje de error.

Consultamos el diccionario "dba_users" y analizamos la informacin que nos muestra:

select username, password, default_tablespace, created from


dba_users;

El resultado nos muestra el nombre de usuario, si tiene o no contrasea, el espacio asignado


(tablespace) y fecha de creacin.

119 - Usuarios (crear)

Primer problema:
Una escuela necesita crear 2 usuarios diferentes en su base de datos. Uno denominado
"director" y otro "profesor". Luego se les concedern diferentes permisos para retringir el
acceso a los diferentes objetos. Conctese como administrador (por ejemplo "system").

1- Primero eliminamos el usuario "director", porque si existe, aparecer un mensaje de error:

drop user director cascade;

2- Cree un usuario "director", con contrasea "escuela" y 100M de espacio en "system"

3- Elimine el usuario "profesor":

drop user profesor cascade;

4- Cree un usuario "profesor", con contrasea "maestro" y espacio en "system"

5- Consulte el diccionario "dba_users" y analice la informacin que nos muestra

drop user director cascade;

create user director identified by escuela


default tablespace system
quota 100M on system;

drop user profesor cascade;

create user profesor identified by maestro


default tablespace system;

select username, password, default_tablespace, created from dba_users;

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;


120 - Permiso de conexin

Problema:

Creamos un usuario denominado "ana", con contrasea "anita", le asignamos espacio en


"system" (100M). Antes lo eliminamos por si existe:

drop user ana cascade;

create user ana identified by anita


default tablespace system
quota 100M on system;

Creamos un usuario denominado "juan", con contrasea "juancito", le asignamos espacio en


"system" (100M). Antes lo eliminamos por si existe:

drop user juan cascade;

create user juan identified by juancito


default tablespace system
quota 100M on system;

Consultamos el diccionario "dba_users" y analizamos la informacin que nos muestra:

select username, password, default_tablespace, created from


dba_users;

Verificamos que los usuarios "ana" y "juan" existen.

Consultamos el diccionario "dba_sys_privs" para encontrar los privilegios concedidos a


nuestros usuarios. Nos mostrar el nombre del usuario (grantee) y el permiso (si lo tiene):
select grantee, privilege from dba_sys_privs where GRANTEE='ANA' or
grantee='JUAN';

Nos muestra que estos usuarios no tienen ningn privilegio concedido.

Concedemos a "juan" permiso para conectarse:

grant create session


to juan;

Consultamos el diccionario "dba_sys_privs" para encontrar los privilegios concedidos a "juan":

select grantee,privilege from dba_sys_privs


where grantee='JUAN';

Tiene permiso "create session".

Abrimos una nueva conexin para "juan":

Presionamos el cono "new connection" en la solapa "connections"; se abre una ventana en la


cual colocamos:

- "connection name" (nombre de la conexin): juan;

- "username" (nombre del usuario): juan y

- "password" (contrasea): juancito.

Luego presionamos "connect"; se abre una nueva solapa (nueva conexin) con el nombre del
usuario (juan).

En la conexin de "juan" podemos consultar sus privilegios:

select username, privilege from user_sys_privs;

Note que nicamente aparecen los permisos del usuario actual.

Para obtener el nombre del usuario conectado, empleamos la siguiente sentencia:

select user from dual;

Aparece Juan.

Volvemos a la conexin "system" (la otra solapa).

Comprobamos el usuario actual:

select user from dual;

Aparece System.

Ya sabemos abrir una nueva sessin de usuario. Aprendimos que existen 3 razones por las
cuales una nueva sesin no se pueda iniciar; una de ellas es que el usuario no exista.
Intentemos abrir una nueva conexin para un usuario inexistente:
Presionamos el cono "new connection" en la solapa "connections"; se abre una ventana en la
cual colocamos:

- "connection name" (nombre de la conexin): pedro;

- "username" (nombre del usuario): pedro y

- "password" (contrasea): pedrito.

Luego presionamos "connect"; la sessin no se abre, un mensaje de error indica que el nombre
de usuario o la contrasea son invlidas y que la conexin se deniega.

Cancelamos.

Otra razn por la cual la apertura de una nueva sesin puede fallar es que el usuario no tenga
permiso de conexin. Intentemos abrir una nueva conexin para un usuario que no tenga tal
permiso, caso de "ana":

Presionamos el cono "new connection" en la solapa "connections"; se abre una ventana en la


cual colocamos:

- "connection name" (nombre de la conexin): ana;

- "username" (nombre del usuario): ana y

- "password" (contrasea): anita.

Luego presionamos "connect"; la sessin no se abre, un mensaje de error indica que el usuario
"ana" no tiene permiso "create session" por lo cual se deniega la conexin. Cancelamos.

Concedemos a "ana" permiso de conexin:

grant create session


to ana;

Consultamos el diccionario "dba_sys_privs" para encontrar los privilegios concedidos a "ana":

select grantee,privilege from dba_sys_privs


where grantee='ANA';

Tiene permiso "create session".

La tercera razn por la cual puede no iniciarse una nueva sesin es que coloquemos la
contrasea incorrecta. Intentemos abrir una nueva conexin para un usuario que tenga
permiso, pero le demos una contrasea incorrecta:

Presionamos el cono "new connection" en la solapa "connections"; se abre una ventana en la


cual colocamos:

- "connection name" (nombre de la conexin): ana;

- "username" (nombre del usuario): ana y

- "password" (contrasea): ana.


Luego presionamos "connect"; la sessin no se abre, un mensaje de error indica que el nombre
de usuario o la contrasea son invlidas y que la conexin se deniega.

Abramos una nueva conexin para "ana" colocando los datos correctos:

Presionamos el cono "new connection" en la solapa "connections"; se abre una ventana en la


cual colocamos:

- "connection name" (nombre de la conexin): ana;

- "username" (nombre del usuario): ana y

- "password" (contrasea): anita.

Presionamos "connect"; se abre una nueva solapa (nueva conexin) con el nombre del usuario
(ana).

Consultamos el diccionario "user_sys_privs":

select username,privilege from user_sys_privs;

Note que nicamente aparecen los permisos del usuario actual.

Comprobamos que estamos en la sesin de "ana":

select user from dual;


120 - Permiso de conexin

Primer problema:

Una escuela necesita crear 3 usuarios diferentes en su base de datos. Uno denominado
"director", otro "profesor" y un tercero "alumno".

Conctese como administrador (por ejemplo "system").

1- Elimine el usuario "director", porque si existe, aparecer un mensaje de error:

drop user director cascade;

2- Cree un usuario "director", con contrasea "dire" y 100M de espacio en "system"

3- Elimine el usuario "profesor":

drop user profesor cascade;

4- Cree un usuario "profesor", con contrasea "profe" y espacio en "system"

5- Elimine el usuario "alumno" y luego crelo con contrasea "alu" y espacio en "system"

6- Consulte el diccionario "dba_users" y analice la informacin que nos muestra


Deben aparecer los tres usuarios creados anteriormente.
7- Consulte el diccionario "dba_sys_privs" para encontrar los privilegios concedidos a nuestros
tres usuarios
Nos muestra que estos usuarios no tienen ningn privilegio concedido.

8- Conceda a "director" permiso para conectarse

9- Conceda a "profesor" permiso para conectarse

10- Consulte el diccionario "dba_sys_privs" para encontrar los privilegios concedidos a


nuestros 3 usuarios

11- Abra una nueva conexin para "director". Se debe abrir una nueva solapa (nueva conexin)
con el nombre del usuario (director)

12- En la conexin de "director" consulte sus privilegios

13- Obtenga el nombre del usuario conectado

14- Vuelva a la conexin "system" (la otra solapa) y compruebe el usuario actual

15- Intente abrir una nueva conexin para el usuario inexistente. Debe aparecer un mensaje
de error y denegarse la conexin. Cancele.

16- Intente abrir una nueva conexin para el usuario "profesor" colocando una contrasea
incorrecta. Debe aparecer un mensaje de error y denegarse la conexin. Cancele.

17- Abra una nueva conexin para "profesor" colocando los datos correctos. Se debe abrir una
nueva solapa (nueva conexin) con el nombre del usuario (profesor).

18- Intentemos abrir una nueva conexin para el usuario "alumno", el cual no tiene permiso.
Un mensaje de error indica que el usuario "alumno" no tiene permiso "create session" por lo
cual se deniega la conexin. Cancele.

19- Conceda a "alumno" permiso de conexin

20- Consulte el diccionario "dba_sys_privs" para encontrar los privilegios concedidos a


"alumno"

21- Abra una nueva conexin para "ALUMNO". Se debe abrir una nueva solapa (nueva
conexin) con el nombre del usuario (profesor)

22- Consulte el diccionario "user_sys_privs"

23- Compruebe que est en la sesin de "alumno"

drop user director cascade;

create user director identified by dire


default tablespace system
quota 100M on system;

drop user profesor cascade;


create user profesor identified by maestro
default tablespace system;

drop user alumno cascade;

create user alumno identified by alu


default tablespace system;

select username, password, default_tablespace, created from dba_users;

select grantee, privilege from dba_sys_privs where GRANTEE='DIRECTOR' or


grantee='PROFESOR' or grantee='ALUMNO';

grant create session


to director;

grant create session


to profesor;

select grantee,privilege from dba_sys_privs


where grantee='DIRECTOR' or grantee='PROFESOR' or grantee='ALUMNO';
"director" y "profesor" tienen permiso "create session".

select username, privilege from user_sys_privs;

select user from dual;

select user from dual;

grant create session


to alumno;

select grantee,privilege from dba_sys_privs


where grantee='ALUMNO';

select username,privilege from user_sys_privs;

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.

121 - Privilegios del sistema (conceder)

Problema:
Creamos un usuario denominado "ana", con contrasea "anita", le asignamos espacio en
"system" (100M). Antes lo eliminamos por si existe:

drop user ana cascade;

create user ana identified by anita


default tablespace system
quota 100M on system;

Creamos un usuario denominado "juan", con contrasea "juancito", le asignamos espacio en


"system" (100M). Antes lo eliminamos por si existe:

drop user juan cascade;

create user juan identified by juancito


default tablespace system
quota 100M on system;

Concedemos a ambos usuarios permiso para conectarse:

grant create session


to ana, juan;

Concedemos permiso para crear tablas y vistas al usuario "ana":

grant create table, create view


to ana;

Concedemos permiso para crear disparadores y procedimientos a ambos usuarios:

grant create trigger, create procedure


to juan, ana;

Consultamos el diccionario "dba_sys_privs" para ver los privilegios concedidos a "ana" y "juan":

select grantee, privilege from dba_sys_privs


where grantee='ANA' or grantee='JUAN'
order by grantee; Obtenemos la siguiente informacin:
GRANTEE PRIVILEGE
-------------------------------
ANA CREATE VIEW
ANA CREATE PROCEDURE
ANA CREATE TRIGGER
ANA CREATE SESSION
ANA CREATE TABLE
JUAN CREATE SESSION
JUAN CREATE PROCEDURE
JUAN CREATE TRIGGER

Iniciamos una nueva sesin como "ana". Como "ana" creamos una tabla:

create table prueba(


nombre varchar2(30),
apellido varchar2(30)
);

La tabla ha sido creada, porque "ana" tiene pivilegio "create table".


Podemos consultar el diccionario "user_sys_privs" para corroborar sus privilegios:

select privilege from user_sys_privs;Obtenemos la siguiente


informacin:
PRIVILEGE
---------
CREATE TRIGGER
CREATE TABLE
CREATE SESSION
CREATE VIEW
CREATE PROCEDURE

Iniciamos una nueva sesin como "juan". Como "juan" intentamos crear una tabla:

create table prueba(


nombre varchar2(30),
apellido varchar2(30)
);

Mensaje de error "privilegios insuficientes". Esto sucede porque "juan", no tiene permiso para
crear tablas.

Vemos los permisos de "juan":

select privilege from user_sys_privs;

No tiene permiso para crear tablas.

Cambiamos a la conexin "system" y concedemos a "juan" permiso para crear tablas:

grant create table


to juan;

Cambiamos a la solapa "juan" y creamos una tabla:

create table prueba(


nombre varchar2(30),
apellido varchar2(30)
);

Podemos hacerlo porque "juan" ahora tiene el permiso.

Vemos los permisos de "juan":

select privilege from user_sys_privs;

Cambiamos a la conexin "system". Veamos todas las tablas denominadas "PRUEBA":

select *from dba_objects where object_name='PRUEBA';

Note que hay una tabla propiedad de "ana" y otra que pertenece a "juan".

121 - Privilegios del sistema (conceder)


Primer problema:

Una escuela necesita crear 3 usuarios diferentes en su base de datos. Uno denominado
"director", otro "profesor" y otro "estudiante". Luego se les concedern diferentes permisos
para retringir el acceso a los diferentes objetos. Conctese como administrador (por ejemplo
"system").

1- Cree un usuario denominado "director", con contrasea "escuela", asignndole 100M de


espacio en "system" (100M). Antes elimnelo por si existe:

2- Intente iniciar una sesin como "director".


No es posible, no hemos concedido el permiso correspondiente. Aparece un mensaje
indicando que el usuario "director" no tiene permiso "create session" por lo tanto no puede
conectarse.

3- Vea los permisos de "director"


No tiene ningn permiso.

4- Conceda a "director" permiso para iniciar sesion y para crear tablas

5- Vea los permisos de "director"


Tiene permiso "create session" y para crear tablas.

6- Inicie una sesin como "director".

7- Como "administrador", elimine los usuarios "profesor" y "alumno", por si existen

8- Cree un usuario denominado "profesor", con contrasea "maestro", asigne espacio en


"system" (100M)

9- Cree un usuario denominado "estudiante", con contrasea "alumno" y tablespace "system"


(no asigne "quota")

10- Consulte el diccionario de datos correspondiente para ver si existen los 3 usuarios creados

11- Conceda a "profesor" y a "estudiante" permiso para conectarse

12- Conceda a "estudiante" permiso para crear tablas

13- Consulte el diccionario de datos "sys_privs" para ver los permisos de los 3 usuarios creados
"director" y "estudiante" tienen permisos para conectarse y para crear tablas, "profesor" tiene
permiso para conectarse.

14- Retome su sesin como "director" y cree una tabla:

create table prueba(


nombre varchar2(30),
apellido varchar2(30)
);

Podemos hacerlo poque "director" tiene el permiso necesario y espacio en "system".

15- Inicie una sesin como "profesor" e intente crear una tabla:

create table prueba(


nombre varchar2(30),
apellido varchar2(30)
);

Mensaje de error "privilegios insuficientes". Esto sucede porque "profesor" NO tiene permiso
para crear tablas.

16- Consulte los permisos de "profesor"


No tiene permiso para crear tablas, nicamente para crear sesin.

17- Cambie a la conexin de administrador y conceda a "profesor" permiso para crear tablas

18- Cambie a la sesin de "profesor" y cree una tabla


Ahora si podemos hacerlo, "profesor" tiene permiso "create table".

19- Consulte nuevamente los permisos de "profesor"


Tiene permiso para crear tablas y para crear sesin.

20- Inicie una sesin como "estudiante" e intente crear una tabla:

create table prueba(


nombre varchar2(30),
apellido varchar2(30)
);

Mensaje de error "no existen privilegios en tablespace SYSTEM". Esto sucede porque
"estudiante", si bien tiene permiso para crear tablas, no tiene asignado espacio (recuerde que
al crearlo no especificamos "quota", por lo tanto, por defecto es cero).

21- Vuelva a la conexin de "administrador" y consulte todas las tablas denominadas "PRUEBA"
Note que hay una tabla propiedad de "director" y otra que pertenece a "profesor".

drop user director cascade;

create user director identified by escuela


default tablespace system
quota 100M on system;

select *from dba_sys_privs where grantee='DIRECTOR';

grant create session, create table


to director;

select *from dba_sys_privs where grantee='DIRECTOR';

drop user profesor cascade;


drop user alumno cascade;

create user profesor identified by maestro


default tablespace system
quota 100M on system;

create user estudiante identified by alumno


default tablespace system;
select username, password, default_tablespace, created from dba_users;

grant create session


to profesor, estudiante;

grant create table


to estudiante;

select *from dba_sys_privs where grantee='DIRECTOR'


or grantee='PROFESOR'
or grantee='ESTUDIANTE';

create table prueba(


nombre varchar2(30),
apellido varchar2(30)
);

create table prueba(


nombre varchar2(30),
apellido varchar2(30)
);

select *from user_sys_privs;

grant create table


to profesor;

create table prueba(


nombre varchar2(30),
apellido varchar2(30)
);

select *from user_sys_privs;

create table prueba(


nombre varchar2(30),
apellido varchar2(30)
);

select *from dba_objects where object_name='PRUEBA';

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.

You might also like