Está en la página 1de 97

MANUAL DE SQL-SERVER PARTE II

42 - Cláusulas compute y compute by

Las cláusulas "compute" y "compute by" generan totales que aparecen en columnas extras al final del resultado.

Produce filas de detalle y un valor único para una columna.

Se usa con las funciones de agrupamiento: avg(), count(), max(), min(), sum().

La sintaxis básica y general es la siguiente:

select CAMPOS
from TABLA
compute FUNCION(CAMPO);

El campo que se coloque en la cláusula "compute" debe estar incluida en la lista de campos del "select".

Para ver todos los datos de los visitantes y el promedio del monto de compra de nuestra tabla "visitantes":

select *from visitantes


compute avg(montocompra);

Produce la misma salida que las siguientes 2 sentencias:

select *from visitantes;


select avg(montocompra) from visitantes;

En una misma instrucción se pueden colocar varias cláusulas "compute":

select edad,ciudad,montocompra
from visitantes
compute avg(edad),sum(montocompra);

"Compute by" genera cortes de control y subtotales. Se generan filas de detalle y varios valores de resumen cuando
cambian los valores del campo.

Con "compute by" se DEBE usar también la cláusula "order by" y los campos que se incluyan luego de "by" deben estar en
el "order by". Listando varios campos luego del "by" corta un grupo en subgrupos y aplica la función de agregado en cada
nivel de agrupamiento:

select nombre,ciudad,provincia
from visitantes
order by provincia
compute count(provincia)
by provincia;

select nombre,ciudad,provincia
from visitantes
order by provincia,ciudad
compute count(provincia)
by provincia,ciudad;

Los campos que aparecen luego de la cláusula "compute by" DEBEN ser idénticos a un subconjunto de los campos que
aparecen después de "order by" y estar en el mismo orden. Si la cláusula "order by" tiene los siguientes campos:

... order by a,b,c...

la cláusula "compute by" puede incluir los siguientes subconjuntos de campos:

... compute ...


by a...

1
MANUAL DE SQL-SERVER PARTE II

o
... compute ...
by a,b...
o
... compute ...
by a,b,c...

En una misma instrucción se pueden colocar varias cláusulas "compute" combinadas con varias cláusulas "compute by":

select *from visitantes


order by provincia,ciudad
compute avg(edad), sum(montocompra)
compute avg(montocompra),count(provincia)
by provincia,ciudad;

El resultado de la consulta anterior muestra el promedio de la compra y la cantidad al final de cada subgrupo de provincia y
ciudad (compute by) y el promedio de las edades y el total del monto de compras de todos (compute).

Los tipos de datos ntext, text e image no se pueden incluir en una cláusula "compute " o "compute by".

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 si existe:

if object_id('visitantes') is not null


drop table visitantes;

La creamos con la siguiente estructura:

create table visitantes(


nombre varchar(30),
edad tinyint,
ciudad varchar(20),
provincia varchar(20),
mail varchar(30),
montocompra decimal(6,2)
);

Ingresamos algunos registros:

insert into visitantes


values ('Susana Molina',28,'Cordoba','Cordoba','susanamolina@gmail.com',50);
insert into visitantes
values ('Marcela Mercado',36,'Carlos Paz','Cordoba',null,20);
insert into visitantes
values ('Alberto Garcia',35,'La Falda','Cordoba','albertgomgarcia@hotmail.com',30);
insert into visitantes
values ('Teresa Garcia',33,'Alta Gracia','Cordoba',null,120);
insert into visitantes
values ('Roberto Perez',45,'Alta Gracia','Cordoba','robertomarioperez@hotmail.com',30);
insert into visitantes
values ('Marina Torres',22,'Rosario','Santa Fe','marinatorres@xaxamail.com',90);
insert into visitantes
values ('Julieta Gomez',24,'Rosario','Santa Fe',null,50);
insert into visitantes
values ('Roxana Lopez',20,'Alta Gracia','Cordoba',null,200);
insert into visitantes
values ('Liliana Garcia',50,'Capital Federal','Buenos
Aires','lilianagarcia@hotmail.com',40);
insert into visitantes

2
MANUAL DE SQL-SERVER PARTE II

values ('Juan Torres',43,'Carlos Paz','Cordoba',null,10);

Veamos todos los datos de los visitantes y el promedio del monto de compra:

select *from visitantes


compute avg(montocompra);

Empleamos dos cláusulas "compute" en una misma instrucción para averiguar el promedio de las
edades y el total de los montos de las compras:

select edad,ciudad,montocompra
from visitantes
compute avg(edad),sum(montocompra);

Veamos la cantidad de visitantes por provincia y ciudad empleando "compute by". Recuerde que
DEBE usarse "order by" y los campos que se incluyan luego de "by" deben estar en el "order by":

select nombre,ciudad,provincia
from visitantes
order by provincia,ciudad
compute count(provincia)
by provincia,ciudad;

Combinamos dos cláusulas "compute" con dos cláusulas "compute by" para averiguar el promedio
de la compra y la cantidad por provincia y ciudad y el promedio de las edades y el total del monto
de compras de todos los visitantes:

select *from visitantes


order by provincia,ciudad
compute avg(edad), sum(montocompra)
compute avg(montocompra),count(provincia)
by provincia,ciudad;

Primer 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 si existe:
if object_id('inmuebles') is not null
drop table inmuebles;

2- Créela con la siguiente estructura:


create table inmuebles (
documento varchar(8) not null,
nombre varchar(30),
domicilio varchar(20),
barrio varchar(20),
ciudad varchar(20),
tipo char(1),--b=baldio, e: edificado
superficie decimal (8,2),
monto decimal (8,2)
);

3- Ingrese algunos registros:


insert into inmuebles

3
MANUAL DE SQL-SERVER PARTE II

values ('11111111','Alberto Acosta','Avellaneda 800','Centro','Cordoba','e',100,1200);


insert into inmuebles
values ('11111111','Alberto Acosta','Sarmiento 245','Gral.
Paz','Cordoba','e',200,2500);
insert into inmuebles
values ('22222222','Beatriz Barrios','San Martin 202','Centro','Cordoba','e',250,1900);
insert into inmuebles
values ('33333333','Carlos Caseres','Paso 1234','Alberdi','Cordoba','b',200,1000);
insert into inmuebles
values ('33333333','Carlos Caseres','Guemes 876','Alberdi','Cordoba','b',300,1500);
insert into inmuebles
values ('44444444','Diana Dominguez','Calderon
456','Matienzo','Cordoba','b',200,800);
insert into inmuebles
values ('55555555','Estela Fuentes','San Martin 321','Flores','Carlos
Paz','e',500,4500);
insert into inmuebles
values ('55555555','Estela Fuentes','Lopez y Planes
853','Alberdi','Cordoba','e',350,2200);

4- Muestre todos los datos y el promedio del monto empleando "compute" (1 resultado
parcial)

Inserte pantalla

5- Empleando cláusulas "compute" consulte el promedio de las superficies y el total de


los montos (2
columnas extras)
Inserte pantalla

6- Realice la misma consulta anterior pero empleando "compute by" para obtener
resultados parciales
por documento,barrio y ciudad.
Inserte pantalla

7- Realice la misma consulta anterior pero con resultados parciales por documento y
barrio (6
resultados parciales dobles)
Inserte pantalla

8- Realice la misma consulta anterior pero con resultados parciales por documento (4
resultados
parciales dobles)
Inserte pantalla

9- Intente realizar la misma consulta anterior pero con resultados parciales por
documento y ciudad.
Aparece un mensaje de error indicando que el subgrupo de campos listados luego del
"by" no es
correcto.
Inserte pantalla

4
MANUAL DE SQL-SERVER PARTE II

10- Combine cláusulas "compute" con "compute by" para averiguar el total de monto a
pagar por
propietario y el promedio de monto de todos (4 resultados parciales y 1 general)
Inserte pantalla

44 - Cláusula top

La palabra clave "top" se emplea para obtener sólo una cantidad limitada de registros, los
primeros n registros de una consulta.

Con la siguiente consulta obtenemos todos los datos de los primeros 2 libros de la tabla:

select top 2 *from libros;

Es decir, luego del "select" se coloca "top" seguido de un número entero positivo y luego
se continúa con la consulta.

Se puede combinar con "order by":

select top 3 titulo,autor


from libros
order by autor;

En la consulta anterior solicitamos los títulos y autores de los 3 primeros libros, ordenados
por autor.

Cuando se combina con "order by" es posible emplear también la cláusula "with ties". Esta
cláusula permite incluir en la seleccion, todos los registros que tengan el mismo valor del
campo por el que se ordena, que el último registro retornado si el último registro retornado
(es decir, el número n) tiene un valor repetido en el registro n+1. Es decir, si el valor del
campo por el cual se ordena del último registro retornado (el número n) está repetido en
los siguientes registros (es decir, el n+1 tiene el mismo valor que n, y el n+2, etc.), lo
incluye en la selección.

Veamos un ejemplo:

select top 3 with ties


*from libros
order by autor;

Esta consulta solicita el retorno de los primeros 3 registros; en caso que el registro
número 4 (y los posteriores), tengan el mismo valor en "autor" que el último registro
retornado (número 3), también aparecerán en la selección.

Si colocamos un valor para "top" que supera la cantidad de registros de la tabla, SQL
Server muestra todos los registros.

Problema:

5
MANUAL DE SQL-SERVER PARTE II

Trabajamos con la tabla "libros" de una librería.


Eliminamos la tabla, si existe:

if object_id('libros') is not null


drop table libros;

Creamos la tabla:

create table libros(


codigo int identity,
titulo varchar(40),
autor varchar(20),
editorial varchar(20)
);

Ingresamos algunos registros:

insert into libros values ('Uno','Richard Bach','Planeta');


insert into libros values ('El aleph','Borges','Emece');
insert into libros values ('Alicia en el pais...','Carroll','Planeta');
insert into libros values ('Aprenda PHP','Mario Molina','Siglo XXI');
insert into libros values ('Java en 10 minutos','Mario Molina','Siglo XXI');
insert into libros values ('Java desde cero','Mario Molina','Emece');
insert into libros values ('Ilusiones','Richard Bach','Planeta');

Obtenemos todos los datos de los primeros 2 libros de la tabla:

select top 2 *from libros;

6
MANUAL DE SQL-SERVER PARTE II

Mostramos los títulos y autores de los 3 primeros libros ordenados por autor:

select top 3 titulo,autor


from libros
order by autor;

Realizamos la misma consulta anterior pero empleamos la cláusula "with ties", con lo cual
incluiremos en la selección, todos los registros que tengan el mismo autor que el último registro
retornado, aunque pasemos de 3:

select top 3 with ties titulo,autor


from libros
order by autor;

7
MANUAL DE SQL-SERVER PARTE II

Note que retorna los 5 primeros registros porque incluye los dos siguientes que tienen el mismo
valor que el último en el campo "autor" (por el cual se ordena).

Primer problema:

Una empresa tiene registrados sus empleados en una tabla llamada "empleados".
1- Elimine la tabla si existe:
if object_id('empleados') is not null
drop table empleados;

2- Créela con la siguiente estructura:


create table empleados (
documento varchar(8) not null,
nombre varchar(30),
estadocivil char(1),--c=casado, s=soltero,v=viudo
seccion varchar(20)
);

3- Ingrese algunos registros:


insert into empleados
values ('22222222','Alberto Lopez','c','Sistemas');
insert into empleados
values ('23333333','Beatriz Garcia','c','Administracion');
insert into empleados
values ('24444444','Carlos Fuentes','s','Administracion');
insert into empleados
values ('25555555','Daniel Garcia','s','Sistemas');
insert into empleados
values ('26666666','Ester Juarez','c','Sistemas');
insert into empleados
values ('27777777','Fabian Torres','s','Sistemas');
insert into empleados
values ('28888888','Gabriela Lopez',null,'Sistemas');
insert into empleados
values ('29999999','Hector Garcia',null,'Administracion');

4- Muestre los 5 primeros registros (5 registros)

8
MANUAL DE SQL-SERVER PARTE II

5- Muestre nombre y seccion de los 4 primeros registros ordenados por sección (4


registros)

6- Realice la misma consulta anterior pero incluya todos los registros que tengan el
mismo valor en
"seccion" que el último (8 registros)

9
MANUAL DE SQL-SERVER PARTE II

7- Muestre nombre, estado civil y seccion de los primeros 4 empleados ordenados por
estado civil y
sección (4 registros)

8- Realice la misma consulta anterior pero incluya todos los valores iguales al último
registro
retornado (5 registros)

10
MANUAL DE SQL-SERVER PARTE II

Inserte pantalla

45 - Clave primaria compuesta

Las claves primarias pueden ser simples, formadas por un solo campo o compuestas,
más de un campo.

Recordemos que una clave primaria identifica 1 solo registro en una tabla.

Para un valor del campo clave existe solamente 1 registro. Los valores no se repiten ni
pueden ser nulos.

Existe una playa de estacionamiento que almacena cada día los datos de los vehículos
que ingresan en la tabla llamada "vehiculos" con los siguientes campos:

- patente char(6) not null,


- tipo char (1), 'a'= auto, 'm'=moto,
- horallegada datetime,
- horasalida datetime,

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 más de una
vez en el día 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 ningún campo, por si sólo cumple con la condición para ser clave, es decir, debe
identificar un solo registro, el valor no puede repetirse, debemos usar 2 campos.

11
MANUAL DE SQL-SERVER PARTE II

Definimos una clave compuesta cuando ningún campo por si solo cumple con la condición
para ser clave.

En este ejemplo, un auto puede ingresar varias veces en un día a la playa, pero siempre
será a distinta hora.

Usamos 2 campos como clave, la patente junto con la hora de llegada, así identificamos
unívocamente cada registro.

Para establecer más 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 datetime,
horasalida datetime,
primary key(patente,horallegada)
);

Nombramos los campos que formarán parte de la clave separados por comas.

Al ingresar los registros, SQL Server controla que los valores para los campos
establecidos como clave primaria no estén repetidos en la tabla; si estuviesen repetidos,
muestra un mensaje y la inserción no se realiza. Lo mismo sucede si realizamos una
actualización.

Entonces, si un solo campo no identifica unívocamente un registro podemos definir una


clave primaria compuesta, es decir formada por más de un campo.

Problema:

Una playa de estacionamiento almacena cada día los datos de los vehículos que ingresan en la
tabla llamada "vehiculos".
Eliminamos la tabla, si existe:

if object_id('vehiculos') is not null


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 datetime,
horasalida datetime,
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);

12
MANUAL DE SQL-SERVER PARTE II

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 inserción 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);

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 actualización 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 definición de la tabla:

insert into vehiculos values('HUO690','m',null,null);

Si mostramos la estructura de la tabla:

sp_columns vehiculos;

vemos que los campos que forman parte de la clave primaria (patente y horallegada) tienen "NO"
en la columna "IS_NULLABLE", es decir, no admiten valores nulos.

Primer problema:

Un consultorio médico en el cual trabajan 3 médicos registra las consultas de los


pacientes en una
tabla llamada "consultas".
1- Elimine la tabla si existe:
if object_id('consultas') is not null
drop table consultas;

2- La tabla contiene los siguientes datos:


- fechayhora: datetime not null, fecha y hora de la consulta,
- medico: varchar(30), not null, nombre del médico (Perez,Lopez,Duarte),
- documento: char(8) not null, documento del paciente,
- paciente: varchar(30), nombre del paciente,
- obrasocial: varchar(30), nombre de la obra social (IPAM,PAMI, etc.).
);

3- Un médico sólo puede atender a un paciente en una fecha y hora determinada. En


una fecha y hora
determinada, varios médicos atienden a distintos pacientes. Cree la tabla definiendo
una clave

13
MANUAL DE SQL-SERVER PARTE II

primaria compuesta:
create table consultas(
fechayhora datetime not null,
medico varchar(30) not null,
documento char(8) not null,
paciente varchar(30),
obrasocial varchar(30),
primary key(fechayhora,medico)
);

4- Ingrese varias consultas para un mismo médico en distintas horas el mismo día.

5- Ingrese varias consultas para diferentes médicos en la misma fecha y hora.

14
MANUAL DE SQL-SERVER PARTE II

6- Intente ingresar una consulta para un mismo médico en la misma hora el mismo
día.

Primer problema:

Un consultorio médico en el cual trabajan 3 médicos registra las consultas de los


pacientes en una
tabla llamada "consultas".
1- Elimine la tabla si existe:
if object_id('consultas') is not null
drop table consultas;

2- La tabla contiene los siguientes datos:


- fechayhora: datetime not null, fecha y hora de la consulta,
- medico: varchar(30), not null, nombre del médico (Perez,Lopez,Duarte),
- documento: char(8) not null, documento del paciente,
- paciente: varchar(30), nombre del paciente,
- obrasocial: varchar(30), nombre de la obra social (IPAM,PAMI, etc.).
);

3- Un médico sólo puede atender a un paciente en una fecha y hora determianada. En


una fecha y hora
determinada, varios médicos atienden a distintos pacientes. Cree la tabla definiendo
una clave
primaria compuesta:
create table consultas(
fechayhora datetime not null,
medico varchar(30) not null,
documento char(8) not null,
paciente varchar(30),
obrasocial varchar(30),

15
MANUAL DE SQL-SERVER PARTE II

primary key(fechayhora,medico)
);

4- Ingrese varias consultas para un mismo médico en distintas horas el mismo día.

5- Ingrese varias consultas para diferentes médicos en la misma fecha y hora.

6- Intente ingresar una consulta para un mismo médico en la misma hora el mismo
día.

16
MANUAL DE SQL-SERVER PARTE II

46 - Integridad de los datos

Es importante, al diseñar una base de datos y las tablas que contiene, tener en cuenta la
integridad de los datos, esto significa que la información almacenada en las tablas debe
ser válida, 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, numéricos, etc.), la aceptación o no de
valores nulos, el valor por defecto. También hemos asegurado que cada registro de una
tabla sea único definiendo una clave primaria y empleando la propiedad identity.

SQL Server ofrece más alternativas, además 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 método para mantener la integridad de los datos,
asegurando que los valores ingresados sean válidos y que las relaciones entre las tablas
se mantenga. Se establecen a los campos y las tablas.

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. Se aconseja crear
las tablas y luego agregar las restricciones.

Se pueden crear, modificar y eliminar las restricciones sin eliminar la tabla y volver a
crearla.

El procedimiento almacenado del sistema "sp_helpconstraint" junto al nombre de la tabla,


nos muestra información acerca de las restricciones de dicha tabla.

17
MANUAL DE SQL-SERVER PARTE II

Cuando se agrega una restricción a una tabla, SQL Server comprueba los datos
existentes.
Hay varios tipos de restricciones.

48 - Restricción check

La restricción "check" especifica los valores que acepta un campo, evitando que
se ingresen valores inapropiados.

La sintaxis básica es la siguiente:


alter table NOMBRETABLA
add constraint NOMBRECONSTRAINT
check CONDICION;

Trabajamos con la tabla "libros" de una librería 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 decimal(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 restricción "check":
alter table libros
add constraint CK_libros_precio_positivo
check (preciomin>=0 and preciomay>=0);

Este tipo de restricción verifica los datos cada vez que se ejecuta una sentencia
"insert" o "update", es decir, actúa en inserciones y actualizaciones.

Si la tabla contiene registros que no cumplen con la restricción que se va a


establecer, la restricción no se puede establecer, hasta que todos los registros
cumplan con dicha restricción.

La condición 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 convención, 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 fácilmente de qué se trata
la restricción, por si tenemos varias restricciones "check" para el mismo campo.

18
MANUAL DE SQL-SERVER PARTE II

Un campo puede tener varias restricciones restricciones "check" y una restricción


"check" puede incluir varios campos.

Las condiciones para restricciones "check" también pueden pueden incluir un


patrón o una lista de valores. Por ejemplo establecer que cierto campo conste de 4
caracteres, 2 letras y 2 dígitos:
...
check (CAMPO like '[A-Z][A-Z][0-9][0-9]');

O establecer que cierto campo asuma sólo los valores que se listan:
...
check (CAMPO in ('lunes','miercoles','viernes'));

No se puede aplicar esta restricción junto con la propiedad "identity".

Si un campo permite valores nulos, "null" es un valor aceptado aunque no esté


incluido en la condición de restricción.

Si intentamos establecer una restricción "check" para un campo que entra en


conflicto con otra restricción "check" establecida al mismo campo, SQL Server no
lo permite.

Pero si establecemos una restricción "check" para un campo que entra en conflicto
con una restricción "default" establecida para el mismo campo, SQL Server lo
permite; pero al intentar ingresar un registro, aparece un mensaje de error.

Primer problema:

Una empresa tiene registrados datos de sus empleados en una tabla llamada
"empleados".
1- Elimine la tabla si existe:
if object_id('empleados') is not null
drop table empleados;

2- Créela con la siguiente estructura:


create table empleados (
documento varchar(8),
nombre varchar(30),
fechanacimiento datetime,
cantidadhijos tinyint,
seccion varchar(20),
sueldo decimal(6,2)
);

3- Agregue una restricción "check" para asegurarse que no se ingresen valores


negativos para el
sueldo:
alter table empleados

19
MANUAL DE SQL-SERVER PARTE II

add constraint CK_empelados_sueldo_positivo


check (sueldo>0);

4- Ingrese algunos registros válidos:


insert into empleados values ('22222222','Alberto
Lopez','1965/10/05',1,'Sistemas',1000);
insert into empleados values ('33333333','Beatriz
Garcia','1972/08/15',2,'Administracion',3000);
insert into empleados values ('34444444','Carlos
Caseres','1980/10/05',0,'Contaduría',6000);

5- Intente agregar otra restricción "check" al campo sueldo para asegurar que ninguno
supere el
valor 5000:

20
MANUAL DE SQL-SERVER PARTE II

alter table empleados


add constraint CK_empleados_sueldo_maximo
check (sueldo<=5000);
La sentencia no se ejecuta porque hay un sueldo que no cumple la restricción.

6- Elimine el registro infractor y vuelva a crear la restricción:


delete from empleados where sueldo=6000;

7- Establezca una restricción para controlar que la fecha de nacimiento que se ingresa
no supere la
fecha actual:
alter table empleados
add constraint CK_fechanacimiento_actual

21
MANUAL DE SQL-SERVER PARTE II

check (fechanacimiento<="" pre="">

49 - Deshabilitar restricciones (with check - nocheck)

Sabemos que si agregamos una restricción a una tabla que contiene datos, SQL Server
los controla para asegurarse que cumplen con la condición de la restricción, si algún
registro no la cumple, la restricción no se establecece.

Es posible deshabilitar esta comprobación en caso de restricciones "check".

Podemos hacerlo cuando agregamos la restricción "check" a una tabla para que SQL
Server acepte los valores ya almacenados que infringen la restricción. Para ello debemos
incluir la opción "with nocheck" en la instrucción "alter table":

alter table libros


with nocheck
add constraint CK_libros_precio
check (precio>=0);

La restricción no se aplica en los datos existentes, pero si intentamos ingresar un nuevo


valor que no cumpla la restricción, SQL Server no lo permite.

Entonces, para evitar la comprobación de datos existentes al crear la restricción, la


sintaxis básica es la siguiente:

alter table TABLA


with nocheck

22
MANUAL DE SQL-SERVER PARTE II

add constraint NOMBRERESTRICCION


check (CONDICION);

Por defecto, si no especificamos, la opción es "with check".

También podemos deshabilitar las restricciones para agregar o actualizar datos sin
comprobarla:

alter table libros


nocheck constraint CK_libros_precio;

En el ejemplo anterior deshabilitamos la restricción "CK_libros_precio" para poder


ingresar un valor negativo para "precio".

Para habilitar una restricción deshabilitada se ejecuta la misma instrucción pero con la
cláusula "check" o "check all":

alter table libros


check constraint CK_libros_precio;

Si se emplea "check constraint all" no se coloca nombre de restricciones, habilita todas las
restricciones que tiene la tabla nombrada.

Para habilitar o deshabilitar restricciones la comprobación de datos en inserciones o


actualizaciones, la sintaxis básica es:

alter table NOMBRETABLA


OPCIONdeRESTRICCION constraint NOMBRERESTRICCION;

Para saber si una restricción está habilitada o no, podemos ejecutar el procedimiento
almacenado "sp_helpconstraint" y fijarnos lo que informa la columna "status_enabled".

Entonces, las cláusulas "check" y "nocheck" permiten habilitar o deshabilitar restricciones


"check" (también las restricciones "foreign key" que veremos más adelante), a las demás
se las debe eliminar ("default" y las que veremos posteriormente).

Problema:

Trabajamos con la tabla "libros" de una librería.


Eliminamos la tabla, si existe:

if object_id('libros') is not null


drop table libros;

La creamos e ingresamos algunos registros:

create table libros(


codigo int identity,
titulo varchar(40),
autor varchar(30),
editorial varchar(15),

23
MANUAL DE SQL-SERVER PARTE II

preciomin decimal(5,2),
preciomay decimal(5,2)
);

insert into libros values ('Uno','Bach','Planeta',22,20);


insert into libros values ('El quijote','Cervantes','Emece',15,13);
insert into libros values ('Aprenda PHP','Mario Molina','Siglo XXI',48,53);
insert into libros values ('Java en 10 minutos','Garcia','Siglo XXI',35,40);

Agregamos una restricción "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);

Si intentamos ingresar un valor inválido para algún campo correspondiente al precio, que vaya en
contra de la restricción, por ejemplo el valor "-15" aparecerá un mensaje de error indicando que hay
conflicto con la restricción creada anteriormente y la inserción no se realiza. Igualmente si
intentamos actualizar un precio, que vaya en contra de la restricción.

Si intentamos agregar una restricción que no permita que el precio mayorista supere el precio
minorista, aparece un mensaje de error y la sentencia no se ejecuta, porque hay registros que no
cumplen con la restricción que intentamos establecer. Podemos modificar los datos que no
cumplen la condición de la restricción o eliminar los registros:

update libros set preciomay=48


where titulo='Aprenda PHP';
delete from libros where titulo='Java en 10 minutos';

Ahora SQL Server si nos permite agregar la restricción "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:

sp_helpconstraint libros;

Ingresamos un registro con valores por defecto:

insert into libros default values;

Note que los campos correspondientes a precios admiten valores 0 y 999.99 (por el tipo de dato y
la restricción), además del valor "null".

Primer problema:

Una empresa tiene registrados datos de sus empleados en una tabla llamada
"empleados".
1- Elimine la tabla (si existe):
if object_id('empleados') is not null
drop table empleados;

24
MANUAL DE SQL-SERVER PARTE II

2- Créela con la siguiente estructura e ingrese los registros siguientes:


create table empleados (
documento varchar(8),
nombre varchar(30),
seccion varchar(20),
sueldo decimal(6,2)
);

insert into empleados


values ('22222222','Alberto Acosta','Sistemas',-10);
insert into empleados
values ('33333333','Beatriz Benitez','Recursos',3000);
insert into empleados
values ('34444444','Carlos Caseres','Contaduria',4000);

3- Intente agregar una restricción "check" para asegurarse que no se ingresen valores
negativos para
el sueldo:
alter table empleados
add constraint CK_empleados_sueldo_positivo
check (sueldo>=0);
No se permite porque hay un valor negativo almacenado.

5- Vuelva a intentarlo agregando la opción "with nocheck":


alter table empleados
with nocheck
add constraint CK_empleados_sueldo_positivo
check (sueldo>=0);

25
MANUAL DE SQL-SERVER PARTE II

6- Intente ingresar un valor negativo para sueldo:


insert into empleados
values ('35555555','Daniel Duarte','Administracion',-2000);
No es posible a causa de la restricción.

7- Deshabilite la restricción e ingrese el registro anterior:


alter table empleados
nocheck constraint CK_empleados_sueldo_positivo;
insert into empleados
values ('35555555','Daniel Duarte','Administracion',2000);

26
MANUAL DE SQL-SERVER PARTE II

8- Establezca una restricción "check" para "seccion" que permita solamente los valores
"Sistemas",
"Administracion" y "Contaduría":
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 restricción anterior evitando que se controlen los datos existentes.


Inserte pantalla

10- Vea si las restricciones de la tabla están o no habilitadas:


sp_helpconstraint empleados;
Muestra 2 filas, una por cada restricción.

27
MANUAL DE SQL-SERVER PARTE II

Inserte pantalla

11- Habilite la restricción deshabilitada.


Inserte pantalla

12- Intente modificar la sección del empleado "Carlos Caseres" a "Recursos".


No lo permite.
Inserte pantalla

13- Deshabilite la restricción para poder realizar la actualización del punto precedente.
Inserte pantalla

50 - Restricción primary key

Hemos visto las restricciones que se aplican a los campos, "default" y "check".

Ahora veremos las restricciones que se aplican a las tablas, que aseguran valores únicos
para cada registro.

Hay 2 tipos: 1) primary key y 2) unique.

Anteriormente, para establecer una clave primaria para una tabla empleábamos 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 establecíamos la clave primaria para la tabla, SQL Server creaba
automáticamente una restricción "primary key" para dicha tabla. Dicha restricción, a la
cual no le dábamos un nombre, recibía un nombre dado por SQL Server que comienza
con "PK" (por primary key), seguido del nombre de la tabla y una serie de letras y
números aleatorios.

Podemos agregar una restricción "primary key" a una tabla existente con la sintaxis básica
siguiente:

alter table NOMBRETABLA


add constraint NOMBRECONSTRAINT
primary key (CAMPO,...);

En el siguiente ejemplo definimos una restricción "primary key" para nuestra tabla "libros"
para asegurarnos que cada libro tendrá un código diferente y único:

alter table libros

28
MANUAL DE SQL-SERVER PARTE II

add constraint PK_libros_codigo


primary key(codigo);

Con esta restricción, 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 convención, cuando demos el nombre a las restricciones "primary key" seguiremos el
formato "PK_NOMBRETABLA_NOMBRECAMPO".

Sabemos que cuando agregamos una restricción a una tabla que contiene información,
SQL Server controla los datos existentes para confirmar que cumplen las exigencias de la
restricción, si no los cumple, la restricción no se aplica y aparece un mensaje de error. Por
ejemplo, si intentamos definir la restricción "primary key" para "libros" y hay registros con
códigos repetidos o con un valor "null", la restricción no se establece.

Cuando establecíamos una clave primaria al definir la tabla, automáticamente SQL Server
redefinía el campo como "not null"; pero al agregar una restricción "primary key", los
campos que son clave primaria DEBEN haber sido definidos "not null" (o ser
implícitamente "not null" si se definen identity).

SQL Server permite definir solamente una restricción "primary key" por tabla, que asegura
la unicidad de cada registro de una tabla.

Si ejecutamos el procedimiento almacenado "sp_helpconstraint" junto al nombre de la


tabla, podemos ver las restricciones "primary key" (y todos los tipos de restricciones) de
dicha tabla.

Un campo con una restricción "primary key" puede tener una restricción "check".

Un campo "primary key" también acepta una restricción "default" (excepto si es identity),
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.

Problema:

Trabajamos con la tabla "libros" de una librería.


Eliminamos la tabla, si existe:

if object_id('libros') is not null


drop table libros;

La creamos estableciendo el campo código como clave primaria:

create table libros(


codigo int not null,
titulo varchar(40),
autor varchar(30),
editorial varchar(15),
primary key (codigo)
);

29
MANUAL DE SQL-SERVER PARTE II

Veamos la restricción "primary key" que creó automáticamente SQL Server:

sp_helpconstraint libros;

Aparece la siguiente información:

constraint_type constraint_name constraint_keys


-----------------------------------------------------------------------
PRIMARY KEY (clustered) PK__libros__571DF1D5 codigo

Vamos a eliminar la tabla y la crearemos nuevamente, sin establecer la clave primaria:

drop table libros;


create table libros(
codigo int not null,
titulo varchar(40),
autor varchar(30),
editorial varchar(15)
);

Definimos una restricción "primary key" para nuestra tabla "libros" para asegurarnos que cada libro
tendrá un código diferente y único:

alter table libros


add constraint PK_libros_codigo
primary key(codigo);

Veamos la información respecto a ella:

sp_helpconstraint libros;

Si intentamos ingresar un registro con un valor para el campo "codigo" que ya existe, no lo permite.
Tampoco permite modificar un código colocando uno existente.

Si intentamos definir otra restricción "primary key", SQL Server no lo permite.

Primer problema:

Una empresa tiene registrados datos de sus empleados en una tabla llamada
"empleados".
1- Elimine la tabla si existe:
if object_id('empleados') is not null
drop table empleados;

2- Créela con la siguiente estructura:


create table empleados (
documento varchar(8) not null,
nombre varchar(30),
seccion varchar(20)
);

3- Ingrese algunos registros, dos de ellos con el mismo número de documento:


insert into empleados
values ('22222222','Alberto Lopez','Sistemas');
insert into empleados
values ('23333333','Beatriz Garcia','Administracion');

30
MANUAL DE SQL-SERVER PARTE II

insert into empleados


values ('23333333','Carlos Fuentes','Administracion');

4- Intente establecer una restricción "primary key" para la tabla para que el
documento no se repita
ni admita valores nulos:
alter table empleados
add constraint PK_empleados_documento
primary key(documento);
No lo permite porque la tabla contiene datos que no cumplen con la restricción,
debemos eliminar (o modificar) el registro que tiene documento duplicado:
delete from empleados
where nombre='Carlos Fuentes';

5- Establezca la restricción "primary key" del punto 4.


Inserte pantalla

6- Intente actualizar un documento para que se repita.


No lo permite porque va contra la restricción.
Inserte pantalla

7-Intente establecer otra restricción "primary key" con el campo "nombre".


No lo permite, sólo puede haber una restricción "primary key" por tabla.
Inserte pantalla

8- Intente ingresar un registro con valor nulo para el documento.


No lo permite porque la restricción no admite valores nulos.
Inserte pantalla

9- Establezca una restricción "default" para que almacene "00000000" en el


documento en caso de omitirlo en un "insert".
Inserte pantalla

10- Ingrese un registro sin valor para el documento.


Inserte pantalla

11- Vea el registro:


select *from empleados;
Inserte pantalla

12- Intente ingresar otro empleado sin documento explícito.


No lo permite porque se duplicaría la clave.
Inserte pantalla

13- Vea las restricciones de la tabla empleados (2 filas):


sp_helpconstraint empleados;
Inserte pantalla

51 - Restricción unique

31
MANUAL DE SQL-SERVER PARTE II

Hemos visto que las restricciones aplicadas a tablas aseguran valores únicos para cada
registro.
Anteriormente aprendimos la restricción "primary key", otra restricción para las tablas es
"unique".

La restricción "unique" impide la duplicación 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 número de legajo) pero
se necesita asegurar que otros datos también sean únicos y no se repitan (como número
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 restricción "unique" sobre el campo "documento" de


la tabla "alumnos", esto asegura que no se pueda ingresar un documento si ya existe.
Esta restricción permite valores nulos, asi que si se ingresa el valor "null" para el campo
"documento", se acepta.

Por convención, 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 restricción a una tabla que contiene información,
SQL Server controla los datos existentes para confirmar que cumplen la condición de la
restricción, si no los cumple, la restricción no se aplica y aparece un mensaje de error. En
el caso del ejemplo anterior, si la tabla contiene números de documento duplicados, la
restricción no podrá establecerse; si podrá establecerse si tiene valores nulos.

SQL Server controla la entrada de datos en inserciones y actualizaciones evitando que se


ingresen valores duplicados.

Problema:

Trabajamos con la tabla "alumnos".


Eliminamos la tabla, si existe:

32
MANUAL DE SQL-SERVER PARTE II

if object_id('alumnos') is not null


drop table alumnos;

Creamos la tabla:

create table alumnos(


legajo char(4) not null,
apellido varchar(20),
nombre varchar(20),
documento char(8)
);

Agregamos una restricción "primary" para el campo "legajo":

alter table alumnos


add constraint PK_alumnos_legajo
primary key(legajo);

Agregamos una restricción "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');

Si intentamos ingresar un legajo o ducumento repetido, aparece un mensaje de error.

Veamos las restricciones:

sp_helpconstraint alumnos;

Aparecen las dos restricciones creadas anteriormente.

Primer problema:

Una empresa de remises tiene registrada la información de sus vehículos en una tabla
llamada
"remis".
1- Elimine la tabla si existe:
if object_id('remis') is not null
drop table remis;

2- Cree la tabla con la siguiente estructura:


create table remis(
numero tinyint identity,
patente char(6),
marca varchar(15),
modelo char(4)
);

3- Ingrese algunos registros, 2 de ellos con patente repetida y alguno con patente
nula:

33
MANUAL DE SQL-SERVER PARTE II

insert into remis values('ABC123','Renault clio','1990');


insert into remis values('DEF456','Peugeot 504','1995');
insert into remis values('DEF456','Fiat Duna','1998');
insert into remis values('GHI789','Fiat Duna','1995');
insert into remis values(null,'Fiat Duna','1995');

4- Intente agregar una restricción "unique" para asegurarse que la patente del remis
no tomará
valores repetidos.
No se puede porque hay valores duplicados.

5- Elimine el registro con patente duplicada y establezca la restricción.


Note que hay 1 registro con valor nulo en "patente".
Inserte pantalla

6- Intente ingresar un registro con patente repetida (no lo permite)


Inserte pantalla

7- Intente ingresar un registro con valor nulo para el campo "patente".


No lo permite porque la clave estaría duplicada.
Inserte pantalla

8- Muestre la información de las restricciones:


sp_helpconstraint remis;
Inserte pantalla

2 - Información de restricciones (sp_helpconstraint)

El procedimiento almacenado "sp_helpconstraint" seguido del nombre de una


tabla muestra la información referente a todas las restricciones establecidas en
dicha tabla, devuelve las siguientes columnas:

- constraint_type: tipo de restricción. Si es una restricción de campo (default o


check) indica sobre qué campo fue establecida. Si es de tabla (primary key o
unique) indica el tipo de índice creado (tema que veremos posteriormente).

- constraint_name: nombre de la restricción.

- delete_action: solamente es aplicable para restricciones de tipo "foreign key" (la


veremos posteriormente).

- update_action: sólo es aplicable para restricciones de tipo "foreign key" (la


veremos posteriormente).

- status_enabled: solamente es aplicable para restricciones de tipo "check" y


"foreign key". Indica si está habilitada (Enabled) o no (Disabled). Indica "n/a" en
cualquier restricción para la que no se aplique.

34
MANUAL DE SQL-SERVER PARTE II

- status_for_replication: solamente es aplicable para restricciones de tipo "check" y


"foreign key". Indica "n/a" en cualquier restricción para la que no se aplique.

- constraint_keys: Si es una restricción "check" muestra la condición de chequeo;


si es una restricción "default", el valor por defecto; si es una "primary key" o
"unique" muestra el/ los campos a los que se aplicaron la restricción.

Problema:

Trabajamos con la tabla "alumnos".


Eliminamos la tabla, si existe:

if object_id('alumnos') is not null


drop table alumnos;

Creamos la tabla:

create table alumnos(


legajo char(4) not null,
apellido varchar(20),
nombre varchar(20),
documento char(8),
domicilio varchar(30),
ciudad varchar(30),
notafinal decimal(4,2)
);

Agregamos una restricción "primary" para el campo "legajo":

alter table alumnos


add constraint PK_alumnos_legajo
primary key(legajo);

Agregamos una restricción "unique" para el campo "documento":

alter table alumnos


add constraint UQ_alumnos_documento
unique (documento);

Agregamos una restricción "check" para que el campo "notafinal" admita solamente valores entre 0
y 10:

alter table alumnos


add constraint CK_alumnos_nota
check (notafinal>=0 and notafinal<=10);

Agregamos una restricción "default" para el campo "ciudad":

alter table alumnos


add constraint DF_alumnos_ciudad
default 'Cordoba'
for ciudad;

Veamos las restricciones:

35
MANUAL DE SQL-SERVER PARTE II

sp_helpconstraint alumnos;

Aparece la siguiente información:

constraint_type constraint_name status_enabled


constraint_keys
-------------------------------------------------------------------------------------------
CHECK on column notafinal CK_alumos_nota Enabled ([notafinal]>=0
and [notafinal<=10])
DEFAULT on column ciudad DF_alumnos_ciudad (n/a) ('Cordoba')
PRIMARY KEY (clustered) PK_alumnos_legajo (n/a) legajo
UNIQUE (NON-clustered) UQ_alumnos_documento (n/a)
documento

Deshabilitamos la restricción "check":

alter table alumnos


nocheck constraint CK_alumnos_nota;

Veamos la información que nos retorna "sp_helpconstraint":

sp_helpconstraint alumnos;
constraint_type constraint_name status_enabled
constraint_keys
------------------------------------------------------------------------------------------
CHECK on column notafinal CK_alumos_nota Disabled ([notafinal]>=0...

Note que la restricción esta deshabilitada.

53 - Eliminar restricciones (alter table - drop)

Para eliminar una restricción, la sintaxis básica es la siguiente:

alter table NOMBRETABLA


drop NOMBRERESTRICCION;

Para eliminar la restricción "DF_libros_autor" de la tabla libros tipeamos:

alter table libros


drop DF_libros_autor;

Pueden eliminarse varias restricciones con una sola instrucción separándolas por comas.

Cuando eliminamos una tabla, todas las restricciones que fueron establecidas en ella, se
eliminan también.

Problema:

Trabajamos con la tabla "libros" de una librería.


Eliminamos la tabla, si existe:

if object_id('libros') is not null


drop table libros;

36
MANUAL DE SQL-SERVER PARTE II

La creamos estableciendo el campo código como clave primaria:

create table libros(


codigo int not null,
titulo varchar(40),
autor varchar(30),
editorial varchar(15),
precio decimal(6,2)
);

Definimos una restricción "primary key" para nuestra tabla "libros" para asegurarnos que cada libro
tendrá un código diferente y único:

alter table libros


add constraint PK_libros_codigo
primary key(codigo);

Definimos una restricción "check" para asegurarnos que el precio no será negativo:

alter table libros


add constraint CK_libros_precio
check (precio>=0);

Definimos una restricción "default" para el campo "autor" para que almacene "Desconocido":

alter table libros


add constraint DF_libros_autor
default 'Desconocido'
for autor;

Definimos una restricción "default" para el campo "precio" para que almacene 0:

alter table libros


add constraint DF_libros_precio
default 0
for precio;

Vemos las restricciones:

sp_helpconstraint libros;

Aparecen 4 restricciones, 1 "check", 2 "default" y 1 "primary key".

Eliminamos la restricción "DF_libros_autor":

alter table libros


drop DF_libros_autor;

Eliminamos la restricción "PK_libros_codigo":

alter table libros


drop PK_libros_codigo;

Vemos si se eliminaron:

sp_helpconstraint libros;

Aparecen 2 restricciones.

37
MANUAL DE SQL-SERVER PARTE II

Primer problema:

Una playa de estacionamiento almacena cada día los datos de los vehículos que
ingresan en la tabla
llamada "vehiculos".
1- Elimine la tabla, si existe:
if object_id('vehiculos') is not null
drop table vehiculos;

2- Cree la tabla:
create table vehiculos(
patente char(6) not null,
tipo char(1),--'a'=auto, 'm'=moto
horallegada datetime not null,
horasalida datetime
);

3- Establezca una restricción "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- Establezca una restricción "default" para el campo "tipo" que almacene el valor "a"
en caso de no
ingresarse valor para dicho campo:
alter table vehiculos
add constraint DF_vehiculos_tipo
default 'a'
for tipo;
Inserte pantalla

5- Establezca una restricción "check" para el campo "patente" para que acepte 3 letras
seguidas de 3
dígitos:
alter table vehiculos
add constraint CK_vehiculos_patente_patron
check (patente like '[A-Z][A-Z][A-Z][0-9][0-9][0-9]');
Inserte pantalla

6- Agregue una restricción "primary key" que incluya los campos "patente" y
"horallegada":
alter table vehiculos
add constraint PK_vehiculos_patentellegada
primary key(patente,horallegada);
Inserte pantalla

7- Ingrese un vehículo:
insert into vehiculos values('SDR456','a','2005/10/10 10:10',null);
Inserte pantalla

8- Intente ingresar un registro repitiendo la clave primaria:

38
MANUAL DE SQL-SERVER PARTE II

insert into vehiculos values('SDR456','m','2005/10/10 10:10',null);


No se permite.
Inserte pantalla

9- Ingrese un registro repitiendo la patente pero no la hora de llegada:


insert into vehiculos values('SDR456','m','2005/10/10 12:10',null);
Inserte pantalla

10- Ingrese un registro repitiendo la hora de llegada pero no la patente:


insert into vehiculos values('SDR111','m','2005/10/10 10:10',null);
Inserte pantalla

11- Vea todas las restricciones para la tabla "vehiculos":


sp_helpconstraint vehiculos;
aparecen 4 filas, 2 correspondientes a restricciones "check", 1 a "default" y 1 a
"primary key".
Inserte pantalla

12- Elimine la restricción "default" del campo "tipo".


Inserte pantalla

13- Vea si se ha eliminado:


sp_helpconstraint vehiculos;
Inserte pantalla

14- Elimine la restricción "primary key" y "check".


Inserte pantalla

15- Vea si se han eliminado:


sp_helpconstraint vehiculos;
Inserte pantalla

54 - Crear y asociar reglas (create rule - sp_bindrule)

Vimos que SQL Server ofrece varias alternativas para asegurar la integridad de datos,
mediante el uso de:

1. RESTRICCIONES (constraints), que se establecen en tablas y campos y son


controlados automáticamente por SQL Server. Hay 3 tipos:

I) DE LOS CAMPOS (hace referencia a los valores válidos para un campo


determinado). Pueden ser:

a) DEFAULT: especifica un valor por defecto para un campo cuando no se inserta


explícitamente en un comando "insert".

b) CHECK: especifica un rango de valores que acepta un campo, se emplea en


inserciones y actualizaciones ("insert" y "update").

39
MANUAL DE SQL-SERVER PARTE II

II) DE LA TABLA (asegura un identificador único para cada registro de una tabla).
Hay 2 tipos:

a) PRIMARY KEY: identifica unívocamente cada uno de los registros; asegura que
no haya valores duplicados ni valores nulos. Se crea un índice automáticamente.

b) UNIQUE: impide la duplicación de claves alternas (no primarias). Se permiten


valores nulos. Se crea un índice automáticamente.

III) REFERENCIAL: lo veremos más adelante.

2. REGLAS (rules) y
3. VALORES PREDETERMINADOS (defaults).

Veamos las reglas.

Las reglas especifican los valores que se pueden ingresar en un campo, asegurando que
los datos se encuentren en un intervalo de valores específico, coincidan con una lista de
valores o sigan un patrón.

Una regla se asocia a un campo de una tabla (o a un tipo de dato definido por el usuario,
tema que veremos posteriormente).

Un campo puede tener solamente UNA regla asociado a él.

Sintaxis básica es la siguiente:

create rule NOMBREREGLA


as @VARIABLE CONDICION

Entonces, luego de "create rule" se coloca el nombre de la regla, luego la palabra clave
"as" seguido de una variable (a la cual la precede el signo arroba) y finalmente la
condición.

Por convención, nombraremos las reglas comenzando con "RG", el nombre del campo al
que se asocia y alguna palabra que haga referencia a la condición.

La variable puede tener cualquier nombre, pero debe estar precedido por el signo arroba
(@), dicha variable será reemplazada por el valor del campo cuando se asocie.

La condición se refiere a los valores permitidos para inserciones y actualizaciones y


puede contener cualquier expresión válida para una cláusula "where"; no puede hacer
referencia a los campos de una tabla.

Creamos una regla para restringir los valores que se pueden ingresar en un campo
"sueldo" de una tabla llamada "empleados", estableciendo un intervalo de valores:

40
MANUAL DE SQL-SERVER PARTE II

create rule RG_sueldo_intervalo


as @sueldo between 100 and 1000

Luego de crear la regla, debemos asociarla a un campo ejecutando un procedimiento


almacenado del sistema empleando la siguiente sintaxis básica:

exec sp_bindrule NOMBREREGLA, 'TABLA.CAMPO';

Asociamos la regla creada anteriormente al campo "sueldo" de la tabla "empleados":

exec sp_bindrule RG_sueldo_intervalo, 'empleados.sueldo';

Si intentamos agregar (o actualizar) un registro con valor para el campo "sueldo" que no
esté en el intervalo de valores especificado en la regla, aparece un mensaje de error
indicando que hay conflicto con la regla y la inserción (o actualización) no se realiza.

SQL Server NO controla los datos existentes para confirmar que cumplen con la regla
como lo hace al aplicar restricciones; si no los cumple, la regla se asocia igualmente; pero
al ejecutar una instrucción "insert" o "update" muestra un mensaje de error, es decir, actúa
en inserciones y actualizaciones.

La regla debe ser compatible con el tipo de datos del campo al cual se asocia; si esto no
sucede, SQL Server no lo informa al crear la regla ni al asociarla, pero al ejecutar una
instrucción "insert" o "update" muestra un mensaje de error.

No se puede crear una regla para campos de tipo text, image, o timestamp.

Si asocia una nueva regla a un campo que ya tiene asociada otra regla, la nueva regla
reeemplaza la asociación anterior; pero la primera regla no desaparece, solamente se
deshace la asociación.

La sentencia "create rule" no puede combinarse con otras sentencias en un lote.

La función que cumple una regla es básicamente la misma que una restricción "check",
las siguientes características explican algunas diferencias entre ellas:

- podemos definir varias restricciones "check" sobre un campo, un campo solamente


puede tener una regla asociada a él;

- una restricción "check" se almacena con la tabla, cuando ésta se elimina, las
restricciones también se borran. Las reglas son objetos diferentes e independientes de las
tablas, si eliminamos una tabla, las asociaciones desaparecen, pero las reglas siguen
existiendo en la base de datos;

- una restricción "check" puede incluir varios campos; una regla puede asociarse a
distintos campos (incluso de distintas tablas);

- una restricción "check" puede hacer referencia a otros campos de la misma tabla, una
regla no.

41
MANUAL DE SQL-SERVER PARTE II

Un campo puede tener reglas asociadas a él y restricciones "check". Si hay conflicto entre
ellas, SQL Server no lo informa al crearlas y/o asociarlas, pero al intentar ingresar un valor
que alguna de ellas no permita, aparece un mensaje de error.

Con "sp_helpconstraint" podemos ver las reglas asociadas a los campos de una tabla.

Con "sp_help" podemos ver todos los objetos de la base de datos activa, incluyendo las
reglas, en tal caso en la columna "Object_type" aparece "rule".

Problema:

Una empresa tiene registrados datos de sus empleados en una tabla llamada "empleados".
Eliminamos la tabla si existe:

if object_id('empleados') is not null


drop table empleados;

La creamos con la siguiente estructura:

create table empleados (


documento varchar(8) not null,
nombre varchar(30),
seccion varchar(20),
fechaingreso datetime,
fechanacimiento datetime,
hijos tinyint,
sueldo decimal(6,2)
);

Recuerde que las reglas son objetos independientes de las tablas (no se eliminan al borrar la
tabla), así que debemos eliminarlas con las siguientes intrucciones (en el siguiente capítulo
explicaremos este tema):

if object_id ('RG_documento_patron') is not null


drop rule RG_documento_patron;
if object_id ('RG_empleados_seccion') is not null
drop rule RG_empleados_seccion;
if object_id ('RG_empleados_fechaingreso') is not null
drop rule RG_empleados_fechaingreso;
if object_id ('RG_hijos') is not null
drop rule RG_hijos;
if object_id ('RG_empleados_sueldo') is not null
drop rule RG_empleados_sueldo;
if object_id ('RG_empleados_sueldo2') is not null
drop rule RG_empleados_sueldo2;

Ingresamos algunos registros:

insert into empleados


values('22222222','Ana Acosta','Contaduria','1990-10-10','1972-10-10',2,700);
insert into empleados
values('23333333','Carlos Costa','Contaduria','1990-12-10','1972-05-04',0,750);
insert into empleados
values('24444444','Daniel Duarte','Sistemas','1995-05-05','1975-10-06',1,880);
insert into empleados
values('25555555','Fabiola Fuentes','Secretaria','1998-02-25','1978-02-08',3,550);
insert into empleados
values('26666666','Gaston Garcia','Secretaria','1999-05-08','1981-01-01',3,670);
insert into empleados
values('27777777','Ines Irala','Gerencia','2000-04-10','1985-12-12',0,6000);

42
MANUAL DE SQL-SERVER PARTE II

Creamos una regla que establezca un patrón para el documento:

create rule RG_documento_patron


as @documento like '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]';

Ejecutamos el procedimiento almacenado del sistema "sp_help" para ver si la regla creada
anteriormente fue creada:

sp_help;

Ejecutamos el procedimiento almacenado del sistema "sp_helpconstraint" para ver si está asociada
la regla a algún campo de "empleados":

sp_helpconstraint empleados;

No aparece porque aún no la asociamos.

Si ingresamos un registro con un documento que no cumpla la regla, SQL Server lo acepta porque
la regla aún no está asociada al campo:

insert into empleados


values('ab888888','Juan Juarez','Secretaria','2001-04-11','1986-11-12',0,600);

Asociamos la regla "RG_documento_patron" al campo "documento":

exec sp_bindrule RG_documento_patron, 'empleados.documento';

Note que hay un documento que no cumple la regla, pero SQL Server no controla los datos
existentes, actúa en inserciones y actualizaciones, si intentamos ingresar un valor para
"documento" en el cual incluyamos caracteres, aparecerá un mensaje de error.

Volvemos a ejecutar "sp_helpconstraint":

sp_helpconstraint empleados;

Aparece la regla.

Creamos una regla para restringir los valores que se pueden ingresar en un campo "seccion":

create rule RG_empleados_seccion


as @seccion in ('Secretaria','Contaduria','Sistemas','Gerencia');

La asociamos al campo "seccion":

exec sp_bindrule RG_empleados_seccion, 'empleados.seccion';

Creamos una regla para restringir los valores que se pueden ingresar en el campo "fechaingreso",
para que no sea posterior a la fecha actual:

create rule RG_empleados_fechaingreso


as @fecha <= getdate();

Asociamos la regla anteriormente creada a los campos "fechaingreso" y "fechanacimiento":

43
MANUAL DE SQL-SERVER PARTE II

exec sp_bindrule RG_empleados_fechaingreso, 'empleados.fechaingreso';


exec sp_bindrule RG_empleados_fechaingreso, 'empleados.fechanacimiento';

Creamos una regla para restringir los valores que se pueden ingresar en el campo "hijos":

create rule RG_hijos


as @hijos between 0 and 20;

La asociamos al campo "hijos":

exec sp_bindrule RG_hijos, 'empleados.hijos';

Creamos una regla para restringir los valores que se pueden ingresar en un campo "sueldo":

create rule RG_empleados_sueldo


as @sueldo>0 and @sueldo<= 5000;

La asociamos al campo "sueldo":

exec sp_bindrule RG_empleados_sueldo, 'empleados.sueldo';

Si intentamos ingresar (o actualizar) un registro con el valor "6000" para "sueldo", SQL Server
muestra un mensaje de error y la acción no se realiza.

Creamos otra regla para restringir los valores que se pueden ingresar en un campo "sueldo":

create rule RG_empleados_sueldo2


as @sueldo>0 and @sueldo<= 7000;

La asociamos al campo "sueldo":

exec sp_bindrule RG_empleados_sueldo2, 'empleados.sueldo';

La nueva regla reeemplaza la asociación anterior. Ahora podemos ingresar el valor "6000" en el
campo "sueldo":

insert into empleados


values('29999999','Luis Lopez','Secretaria','2002-03-03','1990-09-09',0,6000);

La regla "RG_empleados_sueldo" no desaparece, solamente se deshizo la asociación, veámoslo:

sp_help;

La regla "RG_empleados_sueldo" aún existe en la base de datos.

Veamos las reglas asociadas:

sp_helpconstraint empleados;

La regla "RG_empleados_sueldo" ya no está asociada a ningún campo de la tabla "empleados" así


que no aparece; la regla "RG_empleados_sueldo2" si, junto con las otras 5 reglas asociadas.

Primer problema:

44
MANUAL DE SQL-SERVER PARTE II

Una playa de estacionamiento almacena cada día los datos de los vehículos que
ingresan en la tabla
llamada "vehiculos".
1- Elimine la tabla, si existe:
if object_id('vehiculos') is not null
drop table vehiculos;

2- Elimine las siguientes reglas:


if object_id ('RG_patente_patron') is not null
drop rule RG_patente_patron;
if object_id ('RG_horallegada') is not null
drop rule RG_horallegada;
if object_id ('RG_vehiculos_tipo') is not null
drop rule RG_vehiculos_tipo;
if object_id ('RG_vehiculos_tipo2') is not null
drop rule RG_vehiculos_tipo2;
if object_id ('RG_menor_fechaactual') is not null
drop rule RG_menor_fechaactual;

3- Cree la tabla:
create table vehiculos(
patente char(6) not null,
tipo char(1),--'a'=auto, 'm'=moto
horallegada datetime not null,
horasalida datetime
);

4- Ingrese algunos registros:


insert into vehiculos values ('AAA111','a','1990-02-01 08:10',null);
insert into vehiculos values ('BCD222','m','1990-02-01 08:10','1990-02-01 10:10');
insert into vehiculos values ('BCD222','m','1990-02-01 12:00',null);
insert into vehiculos values ('CC1234','a','1990-02-01 12:00',null);

5- Cree una regla para restringir los valores que se pueden ingresar en un campo
"patente" (3 letras
seguidas de 3 dígitos):
create rule RG_patente_patron
as @patente like '[A-Z][A-Z][A-Z][0-9][0-9][0-9]'
Inserte pantalla

6- Ejecute el procedimiento almacenado del sistema "sp_help" para ver que la regla
creada
anteriormente existe:
sp_help;
Inserte pantalla

7- Ejecute el procedimiento almacenado del sistema "sp_helpconstraint" para ver que


la regla creada
anteriormente no está asociada aún a ningún campo de la tabla "vehiculos".
Inserte pantalla

8- Asocie la regla al campo "patente":

45
MANUAL DE SQL-SERVER PARTE II

Note que hay una patente que no cumple la regla, SQL Server NO controla los datos
existentes, pero
si controla las inserciones y actualizaciones:
select *from empleados;
Inserte pantalla

9- Intente ingresar un registro con valor para el campo "patente" que no cumpla con la
regla.
aparece un mensaje de error indicando que hay conflicto con la regla y la inserción no
se realiza.
Inserte pantalla

10- Cree otra regla que controle los valores para el campo "tipo" para que solamente
puedan
ingresarse los caracteres "a" y "m".
Inserte pantalla

11- Asocie la regla al campo "tipo".


Inserte pantalla

12- Intente actualizar un registro cambiando el valor de "tipo" a un valor que no


cumpla con la
regla anterior.
No lo permite.

13- Cree otra regla llamada "RG_vehiculos_tipo2" que controle los valores para el
campo "tipo" para que solamente puedan ingresarse los caracteres "a", "c" y "m".
Inserte pantalla

14- Si la asociamos a un campo que ya tiene asociada otra regla, la nueva regla
reeemplaza la asociación anterior. Asocie la regla creada en el punto anterior al campo
"tipo".
Inserte pantalla

15- Actualice el registro que no pudo actualizar en el punto 12:


update vehiculos set tipo='c' where patente='AAA111';
Inserte pantalla

16- Cree una regla que permita fechas menores o iguales a la actual.
Inserte pantalla

17- Asocie la regla anterior a los campos "horallegada" y "horasalida":


exec sp_bindrule RG_menor_fechaactual, 'vehiculos.horallegada';
exec sp_bindrule RG_menor_fechaactual, 'vehiculos.horasalida';
Inserte pantalla

18- Ingrese un registro en el cual la hora de entrada sea posterior a la hora de salida:
insert into vehiculos values ('NOP555','a','1990-02-01 10:10','1990-02-01 08:30');
Inserte pantalla

19- Intente establecer una restricción "check" que asegure que la fecha y hora de
llegada a la playa
no sea posterior a la fecha y hora de salida:

46
MANUAL DE SQL-SERVER PARTE II

alter table vehiculos


add constraint CK_vehiculos_llegada_salida
check(horallegada<=horasalida);
No lo permite porque hay un registro que no cumple la restricción.
Inserte pantalla

20- Elimine dicho registro:


delete from vehiculos where patente='NOP555';
Inserte pantalla

21- Establezca la restricción "check" que no pudo establecer en el punto 19:


alter table vehiculos
add constraint CK_vehiculos_llegada_salida
check(horallegada<=horasalida);
Inserte pantalla

22- Cree una restricción "default" que almacene el valor "b" en el campo "tipo:
alter table vehiculos
add constraint DF_vehiculos_tipo
default 'b'
for tipo;
Note que esta restricción va contra la regla asociada al campo "tipo" que solamente
permite los
valores "a", "c" y "m". SQL Server no informa el conflicto hasta que no intenta ingresar
el valor
por defecto.
Inserte pantalla

23- Intente ingresar un registro con el valor por defecto para el campo "tipo":
insert into vehiculos values ('STU456',default,'1990-02-01 10:10','1990-02-01
15:30');
No lo permite porque va contra la regla asociada al campo "tipo".

24- Vea las reglas asociadas a "empleados" y las restricciones aplicadas a la misma
tabla ejecutando
"sp_helpconstraint".
Muestra 1 restricción "check", 1 restricción "default" y 4 reglas asociadas.
Inserte pantalla

55 - Eliminar y dasasociar reglas (sp_unbindrule - drop rule)

Para eliminar una regla, primero se debe deshacer la asociación, ejecutando el


procedimiento almacenado del sistema "sp_unbindrule":

exec sp_unbindrule 'TABLA.CAMPO';

No es posible eliminar una regla si está asociada a un campo. Si intentamos hacerlo,


aparece un mensaje de error y la eliminación no se realiza.

Con la instrucción "drop rule" eliminamos la regla:

47
MANUAL DE SQL-SERVER PARTE II

drop rule NOMBREREGLA;

Quitamos la asociación de la regla "RG_sueldo_intervalo" con el campo "sueldo" de la


tabla "empleados" tipeando:

exec sp_unbindrule 'empleados.sueldo';

Luego de quitar la asociación la eliminamos:

drop rule RG_sueldo_100a1000;

Si eliminamos una tabla, las asociaciones de reglas de sus campos desaparecen, pero las
reglas siguen existiendo.

Primer problema:

Una playa de estacionamiento almacena cada día los datos de los vehículos que
ingresan en la tabla
llamada "vehiculos".
1- Elimine la tabla, si existe:
if object_id('vehiculos') is not null
drop table vehiculos;

2- Elimine las siguientes reglas, si existen:


if object_id ('RG_patente_patron') is not null
drop rule RG_patente_patron;
if object_id ('RG_vehiculos_tipo') is not null
drop rule RG_vehiculos_tipo;
if object_id ('RG_vehiculos_tipo2') is not null
drop rule RG_vehiculos_tipo2;

3- Cree la tabla:
create table vehiculos(
patente char(6) not null,
tipo char(1),--'a'=auto, 'm'=moto
horallegada datetime not null,
horasalida datetime
);

4- Cree una regla para restringir los valores que se pueden ingresar en un campo
"patente" (3 letras
seguidas de 3 dígitos):
create rule RG_patente_patron
as @patente like '[A-Z][A-Z][A-Z][0-9][0-9][0-9]';

5-Asocie la regla al campo "patente":


sp_bindrule RG_patente_patron,'vehiculos.patente';
Inserte pantalla

6- Intente ingresar un registro con valor para el campo "patente" que no cumpla con la
regla:
insert into vehiculos values ('FGHIJK','a','1990-02-01 18:00',null);

48
MANUAL DE SQL-SERVER PARTE II

aparece un mensaje de error indicando que hay conflicto con la regla y la inserción no
se realiza.
Inserte pantalla

7- Cree otra regla que controle los valores para el campo "tipo" para que solamente
puedan
ingresarse los caracteres "a" y "m":
create rule RG_vehiculos_tipo
as @tipo in ('a','m')
Inserte pantalla

8- Asocie la regla al campo "tipo":


sp_bindrule RG_vehiculos_tipo, 'vehiculos.tipo';
Inserte pantalla

9- Intente ingresar un registro con el valor 'c' para "tipo":


insert into vehiculos values('AAA111','c','2001-10-10 10:10',NULL);
No lo permite.
Inserte pantalla

10- Cree otra regla llamada "RG_vehiculos_tipo2" que controle los valores para el
campo "tipo" para
que solamente puedan ingresarse los caracteres "a", "c" y "m":
create rule RG_vehiculos_tipo2
as @tipo in ('a','c','m');
Inserte pantalla

11- Si la asociamos a un campo que ya tiene asociada otra regla, la nueva regla
reeemplaza la
asociación anterior. Asocie la regla creada en el punto anterior al campo "tipo".
Inserte pantalla

12- Ingrese el registro que no pudo ingresar en el punto 9.


Inserte pantalla

13- Intente eliminar la regla "RG_vehiculos_tipo2".


No es posible porque está asociada a un campo de "vehiculos".
Inserte pantalla

14- Elimine la regla "RG_vehiculos_tipo".


Es posible porque no está asociada a ningún campo.
Inserte pantalla

15- Intente eliminar la regla "RG_patente_patron".


No es posible porque está asociada.
Inserte pantalla

16- Quite la asociación de la regla con el campo "patente" de "vehiculos".


Inserte pantalla

17- Vea si la regla "RG_patente_patron" está asociada a algún campo de "vehiculos".


No lo está.
Inserte pantalla

49
MANUAL DE SQL-SERVER PARTE II

18- Verifique que la regla aún existe en la base de datos activa:


sp_help;
aparece la regla.
Inserte pantalla

19- Elimine la regla que no pudo eliminar en el punto 15.


Inserte pantalla

20- Verifique que la regla ya no existe en la base de datos activa.


No aparece la regla "RG_patente_patron".
Inserte pantalla

56 - Información de reglas (sp_help - sp_helpconstraint)

Podemos utilizar el procedimiento almacenado "sp_help" con el nombre del objeto del
cual queremos información, en este caso el nombre de una regla:

sp_help NOMBREREGLA;

muestra nombre, propietario, tipo y fecha de creación.

Con "sp_help", no sabemos si las reglas existentes están o no asociadas a algún campo.

"sp_helpconstraint" retorna una lista de todas las restricciones que tiene una tabla.
Podemos ver las reglas asociadas a una tabla con este procedimiento almacenado:

sp_helpconstraint NOMBRETABLA;

muestra la siguiente información:

- constraint_type: indica que es una regla con "RULE", nombrando el campo al que está
asociada.

- constraint_name: nombre de la regla.

- constraint_keys: muestra el texto de la regla.

Para ver el texto de una regla empleamos el procedimiento almacenado "sp_helptext"


seguido del nombre de la regla:

sp_helptext NOMBREREGLA;

También se puede consultar la tabla del sistema "sysobjects", que nos muestra el nombre
y varios datos de todos los objetos de la base de datos actual. La columna "xtype" indica
el tipo de objeto, en caso de ser una regla aparece el valor "R":

select *from sysobjects;

50
MANUAL DE SQL-SERVER PARTE II

Si queremos ver todas las reglas creadas por nosotros, podemos tipear:

select *from sysobjects


where xtype='R' and-- tipo regla
name like 'RG%';--búsqueda con comodín

Problema:

Una empresa registra los datos de sus empleados en una tabla llamada "empleados".
Eliminamos la tabla "empleados" (si existe) y las reglas:

if object_id ('empleados') is not null


drop table empleados;
if object_id ('RG_sueldo') is not null
drop rule RG_sueldo;
if object_id ('RG_seccion_lista') is not null
drop rule RG_seccion_lista;

Creamos la tabla:

create table empleados(


documento char(8) not null,
nombre varchar(30) not null,
seccion varchar(20),
sueldo decimal(6,2),
primary key(documento)
);

Creamos una regla para el campo "sueldo":

create rule RG_sueldo


as @sueldo between 100 and 1000;

Asociamos la regla creada anteriormente al campo "sueldo":

exec sp_bindrule RG_sueldo, 'empleados.sueldo';

Creamos una regla con una lista de valores para "seccion":

create rule RG_seccion_lista


as @seccion in ('Sistemas','Secretaria','Contaduria');

No la asociamos.

Llamemos al procedimiento almacenado "sp_help" junto al nombre de la regla de la cual queremos


información:

sp_help RG_sueldo;

muestra el nombre, propietario, tipo y fecha de creación.

Para ver las reglas asociadas a la tabla "empleados" tipeamos:

sp_helpconstraint empleados;

51
MANUAL DE SQL-SERVER PARTE II

retorna una lista de todas las restricciones que tiene una tabla. También las reglas asociadas.
Aparecen 2 filas: una con información de la restricción "primary key" y otra con información de la
regla asociada, esta última muestra:

- constraint_type: indica que es una regla con "RULE", nombrando el campo al que está asociada.

- constraint_name: nombre de la regla.

- constraint_keys: el texto de la regla.

- las otras columnas no tienen información.

Note que no aparece la regla "RG_seccion_lista" porque no fue asociada a la tabla.

Si asociamos la regla a la tabla:

exec sp_bindrule RG_seccion_lista, 'empleados.seccion';

y ejecutamos el procedimiento nuevamente:

sp_helpconstraint empleados;

Aparecen ambas reglas.

También podemos ver el texto de una regla empleando "sp_helptext":

sp_helptext "RG_seccion_lista";

Deshacemos la asociación de la regla "RG_sueldo" y la eliminamos:

exec sp_unbindrule 'empleados.sueldo';


drop rule RG_sueldo;

Verificamos que ya no existe tal regla:

sp_help RG_sueldo;

Vemos si la regla "RG_seccion_lista" existe consultando la tabla "sysobjects":

select *from sysobjects


where xtype='R' and
name like '%seccion%';

57 - Valores predeterminados (create default)

Hemos visto que para mantener la integridad declarativa se emplean restricciones,


reglas (que hemos estudiado en secciones anteriores) y valores predeterminados.

Veamos los valores predeterminados.

52
MANUAL DE SQL-SERVER PARTE II

Los valores predeterminados se asocian con uno o varios campos (o tipos de


datos definidos por el usuario); se definen una sola vez y se pueden usar muchas
veces.

Si no se coloca un valor cuando se ingresan datos, el valor predeterminado


especifica el valor del campo al que está asociado.

Sintaxis básica:
create default NOMBREVALORPREDETERMINADO
as VALORPREDETERMINADO;

"VALORPREDETERMINADO" no puede hacer referencia a campos de una tabla


(u otros objetos) y debe ser compatible con el tipo de datos y longitud del campo al
cual se asocia; si esto no sucede, SQL Server no lo informa al crear el valor
predeterminado ni al asociarlo, pero al ejecutar una instrucción "insert" muestra un
mensaje de error.

En el siguiente ejemplo creamos un valor predeterminado llamado


"VP_datodesconocido' con el valor "Desconocido":
create default VP_datodesconocido
as 'Desconocido'

Luego de crear un valor predeterminado, debemos asociarlo a un campo (o a un


tipo de datos definido por el usuario) ejecutando el procedimiento almacenado del
sistema "sp_bindefault":
exec sp_bindefault NOMBRE, 'NOMBRETABLA.CAMPO';

La siguiente sentencia asocia el valor predeterminado creado anteriormente al


campo "domicilio" de la tabla "empleados":
exec sp_bindefault VP_datodesconocido, 'empleados.domicilio';

Podemos asociar un valor predeterminado a varios campos. Asociamos el valor


predeterminado "VP_datodesconocido" al campo "barrio" de la tabla "empleados":
exec sp_bindefault VP_datodesconocido, 'empleados.barrio';

La función que cumple un valor predeterminado es básicamente la misma que una


restricción "default", las siguientes características explican algunas semejanzas y
diferencias entre ellas:

- un campo solamente puede tener definida UNA restricción "default", un campo


solamente puede tener UN valor predeterminado asociado a él,

- una restricción "default" se almacena con la tabla, cuando ésta se elimina, las
restricciones también. Los valores predeterminados son objetos diferentes e

53
MANUAL DE SQL-SERVER PARTE II

independientes de las tablas, si eliminamos una tabla, las asociaciones


desaparecen, pero los valores predeterminados siguen existiendo en la base de
datos.

- una restricción "default" se establece para un solo campo; un valor


predeterminado puede asociarse a distintos campos (inclusive, de diferentes
tablas).

- una restricción "default" no puede establecerse sobre un campo "identity",


tampoco un valor predeterminado.

No se puede asociar un valor predeterminado a un campo que tiene una


restricción "default".

Un campo con un valor predeterminado asociado puede tener reglas asociadas a


él y restricciones "check". Si hay conflicto entre ellas, SQL Server no lo informa al
crearlas y/o asociarlas, pero al intentar ingresar un valor que alguna de ellas no
permita, aparece un mensaje de error.

La sentencia "create default" no puede combinarse con otra sentencia en un


mismo lote.

Si asocia a un campo que ya tiene asociado un valor predeterminado otro valor


predeterminado, la nueva asociación reemplaza a la anterior.

Veamos otros ejemplos.


Creamos un valor predeterminado que inserta el valor "0" en un campo de tipo
numérico:
create default VP_cero
as 0;

En el siguiente creamos un valor predeterminado que inserta ceros con el formato


válido para un número de teléfono:
create default VP_telefono
as '(0000)0-000000';

Con "sp_helpconstraint" podemos ver los valores predeterminados asociados a los


campos de una tabla.

Con "sp_help" podemos ver todos los objetos de la base de datos activa,
incluyendo los valores predeterminados, en tal caso en la columna "Object_type"
aparece "default".

Primer problema:

54
MANUAL DE SQL-SERVER PARTE II

Una empresa registra los datos de sus clientes en una tabla llamada "clientes".
1- Elimine la tabla si existe:
if object_id ('clientes') is not null
drop table clientes;

2- Recuerde que si elimina una tabla, las asociaciones de reglas y valores


predeterminados de sus
campos desaparecen, pero las reglas y valores predeterminados siguen existiendo. Si
intenta crear
una regla o un valor predeterminado con igual nombre que uno existente, aparecerá
un mensaje
indicándolo, por ello, debe eliminarlos (si existen) para poder crearlos nuevamente:
if object_id ('VP_legajo_patron') is not null
drop default VP_legajo_patron;
if object_id ('RG_legajo_patron') is not null
drop rule RG_legajo_patron;
if object_id ('RG_legajo') is not null
drop rule RG_legajo;
if object_id ('VP_datodesconocido') is not null
drop default VP_datodesconocido;
if object_id ('VP_fechaactual') is not null
drop default VP_fechaactual;

3- Cree la tabla:
create table clientes(
legajo char(4),
nombre varchar(30),
domicilio varchar(30),
ciudad varchar(15),
provincia varchar(20) default 'Cordoba',
fechaingreso datetime
);

4- Cree una regla para establecer un patrón para los valores que se ingresen en el
campo "legajo" (2
letras seguido de 2 cifras) llamada "RG_legajo_patron":
Inserte pantalla

5- Asocie la regla al campo "legajo".


Inserte pantalla

6- Cree un valor predeterminado para el campo "legajo" ('AA00') llamado


"VP_legajo_patron".
Inserte pantalla

7- Asócielo al campo "legajo".


Recuerde que un campo puede tener un valor predeterminado y reglas asociados.
Inserte pantalla

8- Cree un valor predeterminado con la cadena "??" llamado "VP_datodesconocido".


Inserte pantalla

9- Asócielo al campo "domicilio".

55
MANUAL DE SQL-SERVER PARTE II

Inserte pantalla

10- Asócielo al campo "ciudad".


Recuerde que un valor predeterminado puede asociarse a varios campos.
Inserte pantalla

11- Ingrese un registro con valores por defecto para los campos "domicilio" y "ciudad"
y vea qué almacenaron.
Inserte pantalla

12- Intente asociar el valor predeterminado "VP_datodesconocido" al campo


"provincia".
No se puede porque dicho campo tiene una restricción "default".
Inserte pantalla

13- Cree un valor predeterminado con la fecha actual llamado "VP_fechaactual".


Inserte pantalla

14- Asócielo al campo "fechaingreso".


Inserte pantalla

15- Ingrese algunos registros para ver cómo se almacenan los valores para los cuales
no se insertan datos.
Inserte pantalla

16- Asocie el valor predeterminado "VP_datodesconocido" al campo "fechaingreso".


Note que se asoció un valor predeterminado de tipo caracter a un campo de tipo
"datetime"; SQL Server lo permite, pero al intentar ingresar el valor aparece un
mensaje de error.
Inserte pantalla

17- Ingrese un registro con valores por defecto.


No lo permite porque son de distintos tipos.
Inserte pantalla

18- Cree una regla que entre en conflicto con el valor predeterminado
"VP_legajo_patron".
Inserte pantalla

19- Asocie la regla al campo "legajo".


Note que la regla especifica que el campo "legajo" debe comenzar con la letra "B",
pero el valor predeterminado tiene el valor "AA00"; SQL Server realiza la asociación,
pero al intentar ingresar el
valor predeterminado, no puede hacerlo y muestra un mensaje de error.
Inserte pantalla

20- Intente ingresar un registro con el valor "default" para el campo "legajo".
No lo permite porque al intentar ingresar el valor por defecto establecido con el valor
predeterminado entra en conflicto con la regla "RG_legajo".
Inserte pantalla

56
MANUAL DE SQL-SERVER PARTE II

58 - Desasociar y eliminar valores predeterminados

Un valor predeterminado no puede eliminarse si no se ha desasociado previamente.

Para deshacer una asociación empleamos el procedimiento almacenado


"sp_unbindefault" seguido de la tabla y campo al que está asociado:

sp_unbindefault 'TABLA.CAMPO';

Quitamos la asociación al campo "sueldo" de la tabla "empleados":

sp_unbindefault 'empleados.sueldo';

Con la instrucción "drop default" podemos eliminar un valor predeterminado:

drop default NOMBREVALORPREDETERMINADO;

Eliminamos el valor predeterminado llamado "VP_cero":

drop default VP_cero;

Si eliminamos una tabla, las asociaciones de valores predeterminados de sus campos


desaparecen, pero los valores predeterminados siguen existiendo.

Problema:

Una empresa registra los datos de sus empleados en una tabla llamada "empleados".
Eliminamos la tabla "empleados" si existe:

if object_id ('empleados') is not null


drop table empleados;

Recordemos que si eliminamos una tabla, las asociaciones de los valores predeterminados a sus
campos desaparecen, pero los valores predeterminados siguen existiendo. Si intentamos crear un
valor predeterminado con igual nombre que uno existente, aparecerá un mensaje indicándolo, por
ello, debemos eliminar los valores predeterminados (si existen) para poder crearlos nuevamente:

if object_id ('VP_cero') is not null


drop default VP_cero;
if object_id ('VP_datodesconocido') is not null
drop default VP_datodesconocido;

Creamos la tabla:

create table empleados(


nombre varchar(30),
domicilio varchar(30),
barrio varchar(15),
sueldo decimal(6,2)
);

Creamos un valor predeterminado que inserta el valor "0":

57
MANUAL DE SQL-SERVER PARTE II

create default VP_cero


as 0;

Lo asociamos al campo "sueldo":

exec sp_bindefault VP_cero, 'empleados.sueldo';

Creamos un valor predeterminado con el valor "Desconocido":

create default VP_datodesconocido


as 'Desconocido';

Lo asociamos al campo "domicilio" y al campo "barrio":

exec sp_bindefault VP_datodesconocido, 'empleados.domicilio';


exec sp_bindefault VP_datodesconocido, 'empleados.barrio';

Veamos los valores predeterminados asociados a los campos de la tabla "empleados":

sp_helpconstraint empleados;

Aparecen 3 filas, correspondientes a las asociaciones de valores predeterminados a los campos


"sueldo", "domicilio" y "barrio".

Quitamos la asociación al campo "barrio":

sp_unbindefault 'empleados.barrio';

Ejecutamos nuevamente el procedimiento "sp_helpconstraint":

sp_helpconstraint empleados;

Note que el valor predeterminado "VP_datodesconocido" ya no está asociado al campo "barrio".


Pero dicho valor predeterminado aún existe en la base de datos, verifiquémoslo:

sp_help;

aparece en la lista.

Aun no podemos eliminarlo porque está asociado al campo "domicilio", quitamos la asociación y
luego lo eliminamos:

sp_unbindefault 'empleados.domicilio';
drop default VP_datodesconocido;

Primer problema:

Una librería almacena los datos de sus libros en una tabla llamada "libros".
1- Elimine la tabla si existe:
if object_id ('libros') is not null
drop table libros;

2- Recuerde que si elimina una tabla, las asociaciones de reglas y valores


predeterminados de sus

58
MANUAL DE SQL-SERVER PARTE II

campos desaparecen, pero las reglas y valores predeterminados siguen existiendo. Si


intenta crear
una regla o un valor predeterminado con igual nombre que uno existente, aparecerá
un mensaje
indicándolo, por ello, debe eliminarlos (si existen) para poder crearlos nuevamente:
if object_id ('VP_cero') is not null
drop default VP_cero;
if object_id ('VP_desconocido') is not null
drop default VP_desconocido;
if object_id ('RG_positivo') is not null
drop rule RG_positivo;

3- Cree la tabla:
create table libros(
codigo int identity,
titulo varchar(40) not null,
autor varchar(30),
editorial varchar(20),
precio decimal(5,2),
cantidad smallint
);

4- Cree una regla para impedir que se ingresen valores negativos, llamada
"RG_positivo".
Inserte pantalla

5- Asocie la regla al campo "precio".


Inserte pantalla

6- Asocie la regla al campo "cantidad".


Inserte pantalla

7- Cree un valor predeterminado para que almacene el valor cero, llamado "VP_cero".
Inserte pantalla

8- Asócielo al campo "precio".


Inserte pantalla

9- Asócielo al campo "cantidad".


Inserte pantalla

10- Cree un valor predeterminado con la cadena "Desconocido" llamado


"VP_desconocido".
Inserte pantalla

11- Asócielo al campo "autor".


Inserte pantalla

12- Asócielo al campo "editorial".


Inserte pantalla

13- Vea las reglas y valores predeterminados con "sp_help":


sp_help;

59
MANUAL DE SQL-SERVER PARTE II

Inserte pantalla

14- Vea las reglas y valores predeterminados asociados a "libros".


Aparecen 6 filas, 2 corresponden a la regla "RG_positivo" asociadas a los campos
"precio" y "cantidad"; 2 al valor predeterminado "VP_cero" asociados a los campos
"precio" y "cantidad" y 2 al valor predeterminado "VP_desconocido" asociados a los
campos "editorial" y "autor".
Inserte pantalla

15- Ingrese un registro con valores por defecto para todos los campos, excepto "titulo"
y vea qué se almacenó.
Inserte pantalla

15- Quite la asociación del valor predeterminado "VP_cero" al campo "precio".


Inserte pantalla

16- Ingrese otro registro con valor predeterminado para el campo "precio" y vea cómo
se almacenó.
Inserte pantalla

17- Vea las reglas y valores predeterminados asociados a "libros".


5 filas; el valor predeterminado "VP_cero" ya no está asociado al campo "precio".
Inserte pantalla

18- Verifique que el valor predeterminado "VP_cero" existe aún en la base de datos.
Inserte pantalla

19- Intente eliminar el valor predeterminado "VP_cero".


No se puede porque está asociado al campo "cantidad".
Inserte pantalla

20- Quite la asociación del valor predeterminado "VP_cero" al campo "cantidad".


Inserte pantalla

21- Verifique que ya no existe asociación de este valor predeterminado con la tabla
"libros".
4 filas.
Inserte pantalla

22- Verifique que el valor predeterminado "VP_cero" aun existe en la base de datos.
Inserte pantalla

23- Elimine el valor predeterminado "VP_cero".


Inserte pantalla

24- Verifique que ya no existe en la base de datos.


Inserte pantalla

59 - Información de valores predeterminados

60
MANUAL DE SQL-SERVER PARTE II

Para obtener información de los valores predeterminados podemos emplear los mismos
procedimientos almacenados que usamos para las reglas.

Si empleamos "sp_help", vemos todos los objetos de la base de datos activa (incluyendo
los valores predeterminados); en la columna "Object_type" (tipo de objeto) muestra
"default".

Si al procedimiento almacenado "sp_help" le agregamos el nombre de un valor


predeterminado, nos muestra el nombre, propietario, tipo y fecha de creación:

sp_help NOMBREVALORPREDETERMINADO;

Con "sp_help", no sabemos si los valores predeterminados existentes están o no


asociadas a algún campo.

"sp_helpconstraint" retorna una lista de todas las restricciones que tiene una tabla.
También los valores predeterminados asociados; muestra la siguiente información:

- constraint_type: indica que es un valor predeterminado con "DEFAULT", nombrando el


campo al que está asociado.

- constraint_name: nombre del valor predeterminado.

- constraint_keys: muestra el texto del valor predeterminado.

Con "sp_helptext" seguido del nombre de un valor predeterminado podemos ver el texto
de cualquier valor predeterminado:

sp_helptext NOMBREVALORPREDETERMINADO;

También se puede consultar la tabla del sistema "sysobjects", que nos muestra el nombre
y varios datos de todos los objetos de la base de datos actual. La columna "xtype" indica
el tipo de objeto, en caso de ser un valor predeterminado aparece el valor "D":

select *from sysobjects;

Si queremos ver todos los valores predeterminados creados por nosotros, podemos
tipear:

select *from sysobjects


where xtype='D' and-- tipo valor predeterminado
name like 'VP%';--búsqueda con comodín

Problema:

Una empresa registra los datos de sus empleados en una tabla llamada "empleados".
Eliminamos la tabla "empleados" (si existe) y los valores predeterminados:

if object_id ('empleados') is not null

61
MANUAL DE SQL-SERVER PARTE II

drop table empleados;


if object_id ('VP_sueldo') is not null
drop default VP_sueldo;
if object_id ('VP_seccion') is not null
drop default Vp_seccion;

Creamos la tabla:

create table empleados(


documento char(8) not null,
nombre varchar(30) not null,
seccion varchar(20),
sueldo decimal(6,2),
primary key(documento)
);

Creamos un valor predeterminado para el campo "sueldo":

create default VP_sueldo


as 500;

Asociamos el valor predeterminado creado anteriormente al campo "sueldo":

exec sp_bindefault VP_sueldo, 'empleados.sueldo';

Creamos un valor predeterminado para "seccion":

create default VP_seccion


as 'Secretaria';

No la asociamos.

Veamos todos los objetos de la base de datos activa:

sp_help;

Aparece una tabla con todos los objetos de la base de datos activa, incluyendo los dos valores
predeterminados creados anteriormente; se muestra el nombre, el propietario del objeto y, en caso
de los valores predeterminados, aparece "default".

Si agregamos al procedimiento almacenado "sp_help" el nombre del valor predeterminado del cual
queremos información:

sp_help VP_sueldo;

muestra el nombre, propietario, tipo y fecha de creación.

Para ver los valores predeterminados asociados a la tabla "empleados" tipeamos:

sp_helpconstraint empleados;

retorna una lista de todas las restricciones que tiene una tabla. También los valores
predeterminados asociados. Aparecen 2 filas: una con información de la restricción "primary key" y
otra con información del valor predeterminado asociado, este último muestra:

62
MANUAL DE SQL-SERVER PARTE II

- constraint_type: indica que es un valor predeterminado con "DEFAULT", nombrando el campo al


que está asociado.

- constraint_name: nombre del valor predeterminado.

- constraint_keys: el texto del valor predeterminado.

- las otras columnas no tienen información.

Note que no aparece el valor predeterminado "VP_seccion" porque no fue asociado a la tabla.

Si asociamos el valor predeterminado a la tabla:

exec sp_bindefault VP_seccion, 'empleados.seccion';

y ejecutamos el procedimiento nuevamente:

sp_helpconstraint empleados;

Aparecen ambos valores predeterminados.

Veamos el texto que define el valor predeterminado "VP_seccion" empleando "sp_helptext":

sp_helptext VP_seccion;

Deshacemos la asociación del valor predeterminado "VP_sueldo" y lo eliminamos:

exec sp_unbindefault'empleados.sueldo';
drop default VP_sueldo;

Verificamos que ya no existe tal valor predeterminado:

sp_help VP_sueldo;

Vemos si el valor predeterminado "VP_seccion" existe consultando la tabla "sysobjects":

select *from sysobjects


where xtype='D' and
name like '%seccion%';

60 - Indices

SQL Server 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.
2. empleando índices; recorriendo la estructura de árbol del índice para localizar los
registros y extrayendo los que cumplen las condiciones de la consulta.

Los índices se emplean para facilitar la obtención de información de una tabla. El indice
de una tabla desempeña la misma función que el índice de un libro: permite encontrar
datos rápidamente; en el caso de las tablas, localiza registros.

63
MANUAL DE SQL-SERVER PARTE II

Una tabla se indexa por un campo (o varios).

Un índice posibilita el acceso directo y rápido haciendo más eficiente las búsquedas. Sin
índice, SQL Server debe recorrer secuencialmente toda la tabla para encontrar un
registro.

El objetivo de un indice es acelerar la recuperación de información. La indexación es una


técnica 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 más adelante).

La desventaja es que consume espacio en el disco en disco y genera costo de


mantenimiento (tiempo y recursos).

Los índices más adecuados son aquellos creados con campos que contienen valores
únicos.

Es importante identificar el o los campos por los que sería útil crear un índice, aquellos
campos por los cuales se realizan búsqueda con frecuencia: claves primarias, claves
externas o campos que combinan tablas.

No se recomienda crear índices por campos que no se usan con frecuencia en consultas
o no contienen valores únicos.

SQL Server permite crear dos tipos de índices: 1) agrupados y 2) no agrupados.

61 - Indices agrupados y no agrupados (clustered y nonclustered)

Dijimos que SQL Server permite crear dos tipos de índices: 1) agrupados (clustered) y 2)
no agrupados (nonclustered).

1) Un INDICE AGRUPADO es similar a una guía telefónica, los registros con el mismo
valor de campo se agrupan juntos. Un índice agrupado determina la secuencia de
almacenamiento de los registros en una tabla.
Se utilizan para campos por los que se realizan busquedas con frecuencia o se accede
siguiendo un orden.
Una tabla sólo puede tener UN índice agrupado.
El tamaño medio de un índice agrupado es aproximadamente el 5% del tamaño de la
tabla.

2) Un INDICE NO AGRUPADO es como el índice de un libro, los datos se almacenan en


un lugar diferente al del índice, los punteros indican el lugar de almacenamiento de los
elementos indizados en la tabla.
Un índice no agrupado se emplea cuando se realizan distintos tipos de busquedas
frecuentemente, con campos en los que los datos son únicos.
Una tabla puede tener hasta 249 índices no agrupados.

Si no se especifica un tipo de índice, de modo predeterminado será no agrupado.

64
MANUAL DE SQL-SERVER PARTE II

Los campos de tipo text, ntext e image no se pueden indizar.

Es recomendable crear los índices agrupados antes que los no agrupados, porque los
primeros modifican el orden físico de los registros, ordenándolos secuencialmente.

La diferencia básica entre índices agrupados y no agrupados es que los registros de un


índice agrupado están ordenados y almacenados de forma secuencial en función de su
clave.

SQL Server crea automaticamente índices cuando se crea una restricción "primary key" o
"unique" en una tabla.
Es posible crear índices en las vistas.

Resumiendo, los índices facilitan la recuperación de datos, permitiendo el acceso directo y


acelerando las búsquedas, consultas y otras operaciones que optimizan el rendimiento
general.

62 - Creación de índices
Problema:

Trabajamos con la tabla "libros" de una librería.


Eliminamos la tabla si existe y la creamos:

if object_id('libros') is not null


drop table libros;
create table libros(
codigo int identity,
titulo varchar(40),
autor varchar(30),
editorial varchar(15)
);

Creamos un índice agrupado único para el campo "codigo" de la tabla "libros":

create unique clustered index I_libros_codigo


on libros(codigo);

Creamos un índice no agrupado para el campo "titulo":

create nonclustered index I_libros_titulo


on libros(titulo);

Veamos los indices de "libros":

sp_helpindex libros;

Aparecen 2 filas, uno por cada índice. Muestra el nombre del índice, si es agrupado (o no), primary
(o unique) y el campo por el cual se indexa.

Creamos una restricción "primary key" al campo "codigo" especificando que cree un índice NO
agrupado:

alter table libros


add constraint PK_libros_codigo

65
MANUAL DE SQL-SERVER PARTE II

primary key nonclustered (codigo);

Verificamos que creó un índice automáticamente:

sp_helpindex libros;

El nuevo índice es agrupado, porque no se especificó.

Analicemos la información que nos muestra "sp_helpconstraint":

sp_helpconstraint libros;

En la columna "constraint_type" aparece "PRIMARY KEY" y entre paréntesis, el tipo de índice


creado.

Creamos un índice compuesto para el campo "autor" y "editorial":

create index I_libros_autoreditorial


on libros(autor,editorial);

Se creará uno no agrupado porque no especificamos el tipo, además, ya existe uno agrupado y
solamente puede haber uno por tabla.

Consultamos la tabla "sysindexes":

select name from sysindexes;

Veamos los índices de la base de datos activa creados por nosotros podemos tipear la siguiente
consulta:

select name from sysindexes


where name like 'I_%';

Primer problema:

Un profesor guarda algunos datos de sus alumnos en una tabla llamada "alumnos".
1- Elimine la tabla si existe y créela con la siguiente estructura:
if object_id('alumnos') is not null
drop table alumnos;
create table alumnos(
legajo char(5) not null,
documento char(8) not null,
apellido varchar(30),
nombre varchar(30),
notafinal decimal(4,2)
);

2- Ingresamos algunos registros:


insert into alumnos values ('A123','22222222','Perez','Patricia',5.50);
insert into alumnos values ('A234','23333333','Lopez','Ana',9);
insert into alumnos values ('A345','24444444','Garcia','Carlos',8.5);
insert into alumnos values ('A348','25555555','Perez','Daniela',7.85);
insert into alumnos values ('A457','26666666','Perez','Fabian',3.2);

66
MANUAL DE SQL-SERVER PARTE II

insert into alumnos values ('A589','27777777','Gomez','Gaston',6.90);

3- Intente crear un índice agrupado único para el campo "apellido".


No lo permite porque hay valores duplicados.

4- Cree un índice agrupado, no único, para el campo "apellido".


Inserte pantalla

5- Intente establecer una restricción "primary key" al campo "legajo" especificando


que cree un
índice agrupado.
No lo permite porque ya existe un índice agrupado y solamente puede haber uno por
tabla.
Inserte pantalla

6- Establezca la restricción "primary key" al campo "legajo" especificando que cree un


índice NO agrupado.
Inserte pantalla

7- Vea los índices de "alumnos":


sp_helpindex alumnos;
2 índices: uno "I_alumnos_apellido", agrupado, con "apellido" y otro
"PK_alumnos_legajo", no
agrupado, unique, con "legajo" que se creó automáticamente al crear la restricción
"primary key".
Inserte pantalla

8- Analice la información que muestra "sp_helpconstraint":


sp_helpconstraint libros;
En la columna "constraint_type" aparece "PRIMARY KEY" y entre paréntesis, el tipo de
índice creado.
Inserte pantalla

9- Cree un índice unique no agrupado para el campo "documento".


Inserte pantalla

10- Intente ingresar un alumno con documento duplicado.


No lo permite.
Inserte pantalla

11- Veamos los indices de "alumnos".


Aparecen 3 filas, uno por cada índice.
Inserte pantalla

12- Cree un índice compuesto para el campo "apellido" y "nombre".


Se creará uno no agrupado porque no especificamos el tipo, además, ya existe uno
agrupado y
solamente puede haber uno por tabla.
Inserte pantalla

13- Consulte la tabla "sysindexes", para ver los nombres de todos los índices creados
para
"alumnos":

67
MANUAL DE SQL-SERVER PARTE II

select name from sysindexes


where name like '%alumnos%';
4 índices.

14- Cree una restricción unique para el campo "documento".


Inserte pantalla

15- Vea la información de "sp_helpconstraint".


Inserte pantalla

16- Vea los índices de "alumnos".


Aparecen 5 filas, uno por cada índice.
Inserte pantalla

17- Consulte la tabla "sysindexes", para ver los nombres de todos los índices creados
para
"alumnos":
select name from sysindexes
where name like '%alumnos%';
5 índices.
Inserte pantalla

18- Consulte la tabla "sysindexes", para ver los nombres de todos los índices creados
por usted:
select name from sysindexes
where name like 'I_%';
3 índices. Recuerde que los índices que crea SQL Server automáticamente al agregarse
una restricción
"primary" o "unique" no comienzan con "I_".
Inserte pantalla

Primer problema:

Un profesor guarda algunos datos de sus alumnos en una tabla llamada "alumnos".
1- Elimine la tabla si existe y créela con la siguiente estructura:
if object_id('alumnos') is not null
drop table alumnos;
create table alumnos(
legajo char(5) not null,
documento char(8) not null,
apellido varchar(30),
nombre varchar(30),
notafinal decimal(4,2)
);

2- Ingresamos algunos registros:


insert into alumnos values ('A123','22222222','Perez','Patricia',5.50);
insert into alumnos values ('A234','23333333','Lopez','Ana',9);
insert into alumnos values ('A345','24444444','Garcia','Carlos',8.5);
insert into alumnos values ('A348','25555555','Perez','Daniela',7.85);
insert into alumnos values ('A457','26666666','Perez','Fabian',3.2);
insert into alumnos values ('A589','27777777','Gomez','Gaston',6.90);

68
MANUAL DE SQL-SERVER PARTE II

3- Intente crear un índice agrupado único para el campo "apellido".


No lo permite porque hay valores duplicados.

4- Cree un índice agrupado, no único, para el campo "apellido".

5- Intente establecer una restricción "primary key" al campo "legajo" especificando


que cree un
índice agrupado.
No lo permite porque ya existe un índice agrupado y solamente puede haber uno por
tabla.

6- Establezca la restricción "primary key" al campo "legajo" especificando que cree un


índice NO
agrupado.
Inserte pantalla

7- Vea los índices de "alumnos":


sp_helpindex alumnos;
Inserte pantalla

2 índices: uno "I_alumnos_apellido", agrupado, con "apellido" y otro


"PK_alumnos_legajo", no
agrupado, unique, con "legajo" que se creó automáticamente al crear la restricción
"primary key".

8- Analice la información que muestra "sp_helpconstraint":


sp_helpconstraint libros;
En la columna "constraint_type" aparece "PRIMARY KEY" y entre paréntesis, el tipo de
índice creado.
Inserte pantalla

9- Cree un índice unique no agrupado para el campo "documento".


Inserte pantalla

10- Intente ingresar un alumno con documento duplicado.


No lo permite.
Inserte pantalla

11- Veamos los indices de "alumnos".


Aparecen 3 filas, uno por cada índice.
Inserte pantalla

12- Cree un índice compuesto para el campo "apellido" y "nombre".


Se creará uno no agrupado porque no especificamos el tipo, además, ya existe uno
agrupado y
solamente puede haber uno por tabla.
Inserte pantalla

13- Consulte la tabla "sysindexes", para ver los nombres de todos los índices creados
para
"alumnos":
select name from sysindexes

69
MANUAL DE SQL-SERVER PARTE II

where name like '%alumnos%';


4 índices.
Inserte pantalla

14- Cree una restricción unique para el campo "documento".


Inserte pantalla

15- Vea la información de "sp_helpconstraint".


Inserte pantalla

16- Vea los índices de "alumnos".


Aparecen 5 filas, uno por cada índice.
Inserte pantalla

17- Consulte la tabla "sysindexes", para ver los nombres de todos los índices creados
para
"alumnos":
select name from sysindexes
where name like '%alumnos%';
5 índices.
Inserte pantalla

18- Consulte la tabla "sysindexes", para ver los nombres de todos los índices creados
por usted:
select name from sysindexes
where name like 'I_%';
3 índices. Recuerde que los índices que crea SQL Server automáticamente al agregarse
una restricción
"primary" o "unique" no comienzan con "I_".
Inserte pantalla

63 - Regenerar índices

Vimos que para crear índices empleamos la instrucción "create index".

Empleando la opción "drop_existing" junto con "create index" permite regenerar un índice,
con ello evitamos eliminarlo y volver a crearlo. La sintaxis es la siguiente:

create TIPODEINDICE index NOMBREINDICE


on TABLA(CAMPO)
with drop_existing;

También podemos modificar alguna de las características de un índice con esta opción, a
saber:

- tipo: cambiándolo de no agrupado a agrupado (siempre que no exista uno agrupado


para la misma tabla). No se puede convertir un índice agrupado en No agrupado.

- campo: se puede cambiar el campo por el cual se indexa, agregar campos, eliminar
algún campo de un índice compuesto.

70
MANUAL DE SQL-SERVER PARTE II

- único: se puede modificar un índice para que los valores sean únicos o dejen de serlo.

En este ejemplo se crea un índice no agrupado para el campo "titulo" de la tabla "libros":

create nonclustered index I_libros


on libros(titulo);

Regeneramos el índice "I_libros" y lo convertimos a agrupado:

create clustered index I_libros


on libros(titulo)
with drop_existing;

Agregamos un campo al índice "I_libros":

create clustered index I_libros


on libros(titulo,editorial)
with drop_existing;

Esta opción no puede emplearse con índices creados a partir de una restricción "primary
key" o "unique".

Problema:

Trabajamos con la tabla "libros" de una librería.


Eliminamos la tabla si existe y la creamos:

if object_id('libros') is not null


drop table libros;
create table libros(
codigo int identity,
titulo varchar(40),
autor varchar(30),
editorial varchar(15)
);

Creamos un índice no agrupado para el campo "titulo":

create nonclustered index I_libros_titulo


on libros(titulo);

Veamos la información:

sp_helpindex libros;

Vamos a agregar el campo "autor" al índice "I_libros_titulo" y vemos si se modificó:

create index I_libros_titulo


on libros(titulo,autor)
with drop_existing;

exec sp_helpindex libros;

Lo convertimos en agrupado y ejecutamos "sp_helpindex":

71
MANUAL DE SQL-SERVER PARTE II

create clustered index I_libros_titulo


on libros(titulo,autor)
with drop_existing;

exec sp_helpindex libros;

Quitamos un campo "autor" y verificamos la modificación:

create clustered index I_libros_titulo


on libros(titulo)
with drop_existing;

exec sp_helpindex libros;

Primer problema:

Un profesor guarda algunos datos de sus alumnos en una tabla llamada "alumnos".
1- Elimine la tabla si existe y créela con la siguiente estructura:
if object_id('alumnos') is not null
drop table alumnos;
create table alumnos(
legajo char(5) not null,
documento char(8) not null,
apellido varchar(30),
nombre varchar(30),
notafinal decimal(4,2)
);

2- Cree un índice no agrupado para el campo "apellido".


Inserte pantalla

3- Vea la información de los índices de "alumnos".


Inserte pantalla

4- Modifíquelo agregando el campo "nombre".


Inserte pantalla

5- Verifique que se modificó:


exec sp_helpindex alumnos;
Inserte pantalla

6- Establezca una restricción "unique" para el campo "documento".


Inserte pantalla

7- Vea la información que muestra "sp_helpindex":


sp_helpindex alumnos;
Inserte pantalla

8- Intente modificar con "drop_existing" alguna característica del índice que se creó
automáticamente al agregar la restricción "unique":
create clustered index UQ_alumnos_documento
on alumnos(documento)
with drop_existing;
No se puede emplear "drop_existing" con índices creados a partir de una restricción.
Inserte pantalla

72
MANUAL DE SQL-SERVER PARTE II

9- Cree un índice no agrupado para el campo "legajo".


Inserte pantalla

10- Muestre todos los índices:


sp_helpindex alumnos;
Inserte pantalla

11- Convierta el índice creado en el punto 9 a agrupado conservando las demás


características.
Inserte pantalla

12- Verifique que se modificó:


exec sp_helpindex alumnos;
Inserte pantalla

13- Intente convertir el índice "I_alumnos_legajo" a no agrupado:


create nonclustered index I_alumnos_legajo
on alumnos(legajo)
with drop_existing;
No se puede convertir un índice agrupado en no agrupado.
Inserte pantalla

14- Modifique el índice "I_alumnos_apellido" quitándole el campo "nombre".


Inserte pantalla

15- Intente convertir el índice "I_alumnos_apellido" en agrupado:


create clustered index I_alumnos_apellido
on alumnos(apellido)
with drop_existing;
No lo permite porque ya existe un índice agrupado.
Inserte pantalla

16- Modifique el índice "I_alumnos_legajo" para que sea único y conserve todas las
otras
características.
Inserte pantalla

17- Verifique la modificación:


sp_helpindex alumnos;
Inserte pantalla

18- Modifique nuevamente el índice "I_alumnos_legajo" para que no sea único y


conserve las demás
características.
Inserte pantalla

19- Verifique la modificación:


sp_helpindex alumnos;
Inserte pantalla

64 - Eliminar índices

73
MANUAL DE SQL-SERVER PARTE II

Los índices creados con "create index" se eliminan con "drop index"; la siguiente es la
sintaxis básica:

drop index NOMBRETABLA.NOMBREINDICE;

Eliminamos el índice "I_libros_titulo":

drop index libros.I_libros_titulo;

Los índices que SQL Server crea automáticamente al establecer una restricción "primary
key" o "unique" no pueden eliminarse con "drop index", se eliminan automáticamente
cuando quitamos la restricción.

Podemos averiguar si existe un índice para eliminarlo, consultando la tabla del sistema
"sysindexes":

if exists (select name from sysindexes


where name = 'NOMBREINDICE')
drop index NOMBRETABLA.NOMBREINDICE;

Eliminamos el índice "I_libros_titulo" si existe:

if exists (select *from sysindexes


where name = 'I_libros_titulo')
drop index libros.I_libros_titulo;

Problema:

Trabajamos con la tabla "libros" de una librería.


Eliminamos la tabla si existe y la creamos:

if object_id('libros') is not null


drop table libros;

create table libros(


codigo int identity,
titulo varchar(40),
autor varchar(30),
editorial varchar(15)
);

Creamos un índice para el campo "titulo":

create index I_libros_titulo


on libros(titulo);

Verifiquemos que se creó:

sp_helpindex libros;

Eliminamos el índice "I_libros_titulo":

74
MANUAL DE SQL-SERVER PARTE II

drop index libros.I_libros_titulo;

Corroboremos que se eliminó:

sp_helpindex libros;

Solicitamos que se elimine el índice "I_libros_titulo" si existe:

if exists (select name from sysindexes


where name = 'I_libros_titulo')
drop index libros.I_libros_titulo;

Primer problema:

Un profesor guarda algunos datos de sus alumnos en una tabla llamada "alumnos".
1- Elimine la tabla si existe y créela con la siguiente estructura:
if object_id('alumnos') is not null
drop table alumnos;
create table alumnos(
legajo char(5) not null,
documento char(8) not null,
apellido varchar(30),
nombre varchar(30),
notafinal decimal(4,2)
);

2- Cree un índice no agrupado para el campo "apellido".

3- Establezca una restricción "primary" para el campo "legajo" y especifique que cree
un índice
"agrupado".

4- Vea la información que muestra "sp_helpindex":


sp_helpindex alumnos;

5- Intente eliminar el índice "PK_alumnos_legajo" con "drop index":


drop index PK_alumnos_legajo;
No se puede.

6- Intente eliminar el índice "I_alumnos_apellido" sin especificar el nombre de la tabla:


drop index I_alumnos_apellido;
Mensaje de error.
Inserte pantalla

7- Elimine el índice "I_alumnos_apellido" especificando el nombre de la tabla.


Inserte pantalla

8- Verifique que se eliminó:


sp_helpindex alumnos;
Inserte pantalla

9- Solicite que se elimine el índice "I_alumnos_apellido" si existe:


if exists (select name from sysindexes

75
MANUAL DE SQL-SERVER PARTE II

where name = 'I_alumnos_apellido')


drop index alumnos.I_alumnos_apellido;
Inserte pantalla

10- Elimine el índice "PK_alumnos_legajo" (quite la restricción).


Inserte pantalla

11- Verifique que el índice "PK_alumnos_legajo" ya no existe:


sp_helpindex alumnos;
Inserte pantalla

65 - Trabajar con varias tablas

Hasta el momento hemos trabajado con una sola tabla, pero generalmente, se trabaja con
más de una.

Para evitar la repetición de datos y ocupar menos espacio, se separa la información en


varias tablas. Cada tabla almacena parte de la información que necesitamos registrar.

Por ejemplo, los datos de nuestra tabla "libros" podrían separarse en 2 tablas, una
llamada "libros" y otra "editoriales" que guardará la información de las editoriales.
En nuestra tabla "libros" haremos referencia a la editorial colocando un código que la
identifique.

Veamos:

create table libros(


codigo int identity,
titulo varchar(40) not null,
autor varchar(30) not null default 'Desconocido',
codigoeditorial tinyint not null,
precio decimal(5,2),
primary key (codigo)
);

create table editoriales(


codigo tinyint identity,
nombre varchar(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 código de la editorial en la tabla
"libros" y en "editoriales".

Al recuperar los datos de los libros con la siguiente instrucción:

select* from libros;

76
MANUAL DE SQL-SERVER PARTE II

vemos que en el campo "editorial" aparece el código, 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 información de las dos.

Cuando obtenemos información de más de una tabla decimos que hacemos un "join"
(combinación).

Veamos un ejemplo:

select *from libros


join editoriales
on libros.codigoeditorial=editoriales.codigo;

Resumiendo: si distribuimos la información en varias tablas evitamos la redundancia de


datos y ocupamos menos espacio físico en el disco. Un join es una operación que
relaciona dos o más tablas para obtener un resultado que incluya datos (campos y
registros) de ambas; las tablas participantes se combinan según los campos comunes a
ambas tablas.

Hay hay tres tipos de combinaciones. En los siguientes capítulos explicamos cada una de
ellas.

66 - Combinación interna (inner join)

Un join es una operación que relaciona dos o más tablas para obtener un resultado que
incluya datos (campos y registros) de ambas; las tablas participantes se combinan según
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.

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

La combinación interna emplea "join", que es la forma abreviada de "inner join". Se


emplea para obtener información de dos tablas y combinar dicha información en una
salida.

La sintaxis básica es la siguiente:

select CAMPOS
from TABLA1
join TABLA2
on CONDICIONdeCOMBINACION;

77
MANUAL DE SQL-SERVER PARTE II

Ejemplo:

select *from libros


join editoriales
on codigoeditorial=editoriales.codigo;

Analicemos la consulta anterior.

- especificamos los campos que aparecerán en el resultado en la lista de selección;

- 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 cómo;

- cuando se combina información 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 condición para enlazarlas, es decir, el campo por el cual se combinarán, que tienen en
común.
"on" hace coincidir registros de ambas tablas basándose en el valor de tal campo, en el
ejemplo, el campo "codigoeditorial" de "libros" y el campo "codigo" de "editoriales" son los
que enlazarán ambas tablas. Se emplean campos comunes, que deben tener tipos de
datos iguales o similares.

La condicion de combinación, es decir, el o los campos por los que se van a combinar
(parte "on"), se especifica según las claves primarias y externas.

Note que en la consulta, al nombrar el campo usamos el nombre de la tabla también.


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", SQL Server 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
cláusula "on" se debe hacer referencia a la clave completa, es decir, la condición
referenciará a todos los campos clave que identifican al registro.

Se puede incluir en la consulta join la cláusula "where" para restringir los registros que
retorna el resultado; también "order by", "distinct", etc..

Se emplea este tipo de combinación para encontrar registros de la primera tabla que se
correspondan con los registros de la otra, es decir, que cumplan la condición del "on". Si
un valor de la primera tabla no se encuentra en la segunda tabla, el registro no aparece.

78
MANUAL DE SQL-SERVER PARTE II

Para simplificar la sentencia podemos usar un alias para cada tabla:

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

En algunos casos (como en este ejemplo) el uso de alias es para fines de simplificación y
hace más legible la consulta si es larga y compleja, pero en algunas consultas es
absolutamente necesario.

Problema:

Una librería almacena la información de sus libros para la venta en dos tablas, "libros" y
"editoriales".

Eliminamos ambas tablas, si existen:

if object_id('libros') is not null


drop table libros;
if object_id('editoriales') is not null
drop table editoriales;

Creamos las tablas:

create table libros(


codigo int identity,
titulo varchar(40),
autor varchar(30) default 'Desconocido',
codigoeditorial tinyint not null,
precio decimal(5,2)
);
create table editoriales(
codigo tinyint identity,
nombre varchar(20),
primary key (codigo)
);

Ingresamos algunos registros en ambas tablas:

insert into editoriales values('Planeta');


insert into editoriales values('Emece');
insert into editoriales values('Siglo XXI');

insert into libros values('El aleph','Borges',2,20);


insert into libros values('Martin Fierro','Jose Hernandez',1,30);
insert into libros values('Aprenda PHP','Mario Molina',3,50);
insert into libros values('Java en 10 minutos',default,3,45);

Recuperamos los datos de libros:

select* from libros;

vemos que en el campo "editorial" aparece el código, pero no sabemos el nombre de la editorial.

Realizamos un join para obtener datos de ambas tablas (titulo, autor y nombre de la editorial):

79
MANUAL DE SQL-SERVER PARTE II

select titulo, autor, nombre


from libros
join editoriales
on codigoeditorial=editoriales.codigo;

Mostramos el código del libro, título, autor, nombre de la editorial y el precio realizando un join y
empleando alias:

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

Note que al listar el campo "codigo" especificamos a qué tabla pertenece; si no lo hacemos SQL
Server no sabrá si nos referimos al de la tabla "libros" o "editoriales". Los demás 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,precio
from libros as l
join editoriales as e
on codigoeditorial=e.codigo
where e.nombre='Siglo XXI';

Obtenemos título, autor y nombre de la editorial, esta vez ordenados por título:

select titulo,autor,nombre
from libros as l
join editoriales as e
on codigoeditorial=e.codigo
order by titulo;
Primer problema:

Una empresa tiene registrados sus clientes en una tabla llamada "clientes", también
tiene una tabla
"provincias" donde registra los nombres de las provincias.
1- Elimine las tablas "clientes" y "provincias", si existen:
if (object_id('clientes')) is not null
drop table clientes;
if (object_id('provincias')) is not null
drop table provincias;

2- Créelas con las siguientes estructuras:


create table clientes (
codigo int identity,
nombre varchar(30),
domicilio varchar(30),
ciudad varchar(20),
codigoprovincia tinyint not null,
primary key(codigo)
);

create table provincias(


codigo tinyint identity,
nombre varchar(20),

80
MANUAL DE SQL-SERVER PARTE II

primary key (codigo)


);

3- Ingrese algunos registros para ambas tablas:


insert into provincias (nombre) values('Cordoba');
insert into provincias (nombre) values('Santa Fe');
insert into provincias (nombre) values('Corrientes');

insert into clientes values ('Lopez Marcos','Colon 111','Córdoba',1);


insert into clientes values ('Perez Ana','San Martin 222','Cruz del Eje',1);
insert into clientes values ('Garcia Juan','Rivadavia 333','Villa Maria',1);
insert into clientes values ('Perez Luis','Sarmiento 444','Rosario',2);
insert into clientes values ('Pereyra Lucas','San Martin 555','Cruz del Eje',1);
insert into clientes values ('Gomez Ines','San Martin 666','Santa Fe',2);
insert into clientes values ('Torres Fabiola','Alem 777','Ibera',3);

4- Obtenga los datos de ambas tablas, usando alias:


select c.nombre,domicilio,ciudad,p.nombre
from clientes as c
join provincias as p
on c.codigoprovincia=p.codigo;
Inserte pantalla

5- Obtenga la misma información anterior pero ordenada por nombre de provincia.


Inserte pantalla

6- Recupere los clientes de la provincia "Santa Fe" (2 registros devueltos)


Inserte pantalla

Segundo problema:

Un club dicta clases de distintos deportes. Almacena la información 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 si existen y cree las tablas:
if (object_id('inscriptos')) is not null
drop table inscriptos;
if (object_id('inasistencias')) is not null
drop table inasistencias;

create table inscriptos(


nombre varchar(30),
documento char(8),
deporte varchar(15),
matricula char(1), --'s'=paga 'n'=impaga
primary key(documento,deporte)
);

create table inasistencias(

81
MANUAL DE SQL-SERVER PARTE II

documento char(8),
deporte varchar(15),
fecha datetime
);

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','2006-12-01');


insert into inasistencias values('22222222','tenis','2006-12-08');
insert into inasistencias values('23333333','tenis','2006-12-01');
insert into inasistencias values('24444444','tenis','2006-12-08');
insert into inasistencias values('22222222','natacion','2006-12-02');
insert into inasistencias values('23333333','natacion','2006-12-02');

3- Muestre el nombre, el deporte y las fechas de inasistencias, ordenado por nombre y


deporte.
Note que la condición es compuesta porque para identificar los registros de la tabla
"inasistencias"
necesitamos ambos campos.
Inserte pantalla

4- Obtenga el nombre, deporte y las fechas de inasistencias de un determinado


inscripto en un
determinado deporte (3 registros)
Inserte pantalla

5- Obtenga el nombre, deporte y las fechas de inasistencias de todos los inscriptos que
pagaron la
matrícula(4 registros)
Inserte pantalla

67 - Combinación externa izquierda (left join)

Vimos que una combinación interna (join) encuentra registros de la primera tabla que se
correspondan con los registros de la segunda, es decir, que cumplan la condición 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 combinación,
"outer join" (combinación externa).

82
MANUAL DE SQL-SERVER PARTE II

Las combinaciones externas combinan registros de dos tablas que cumplen la condición,
más los registros de la segunda tabla que no la cumplen; es decir, muestran todos los
registros de las tablas relacionadas, aún cuando no haya valores coincidentes entre ellas.

Este tipo de combinación se emplea cuando se necesita una lista completa de los datos
de una de las tablas y la información que cumple con la condición. 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 combinación 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 título y nombre de la editorial de los libros:

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

El resultado mostrará el título y nombre de la editorial; las editoriales de las cuales no hay
libros, es decir, cuyo código de editorial no está presente en "libros" aparece en el
resultado, pero con el valor "null" en el campo "titulo".

Es importante la posición 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 básica es la
siguiente:

select CAMPOS
from TABLAIZQUIERDA
left join TABLADERECHA
on CONDICION;

En el siguiente ejemplo solicitamos el título 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 as l
left join editoriales as e
on codigoeditorial = e.codigo;

83
MANUAL DE SQL-SERVER PARTE II

El resultado mostrará el título del libro y el nombre de la editorial; los títulos cuyo código
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 código está presente en "libros":

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

También podemos mostrar las editoriales que NO están presentes en "libros", es decir,
que NO encuentran coincidencia en la tabla de la derecha:

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

Primer problema:

Una empresa tiene registrados sus clientes en una tabla llamada "clientes", también
tiene una tabla
"provincias" donde registra los nombres de las provincias.
1- Elimine las tablas "clientes" y "provincias", si existen y cree las tablas:
if (object_id('clientes')) is not null
drop table clientes;
if (object_id('provincias')) is not null
drop table provincias;

create table clientes (


codigo int identity,
nombre varchar(30),
domicilio varchar(30),
ciudad varchar(20),
codigoprovincia tinyint not null,
primary key(codigo)
);

create table provincias(


codigo tinyint identity,
nombre varchar(20),
primary key (codigo)
);

2- Ingrese algunos registros para ambas tablas:


insert into provincias (nombre) values('Cordoba');

84
MANUAL DE SQL-SERVER PARTE II

insert into provincias (nombre) values('Santa Fe');


insert into provincias (nombre) values('Corrientes');

insert into clientes values ('Lopez Marcos','Colon 111','Córdoba',1);


insert into clientes values ('Perez Ana','San Martin 222','Cruz del Eje',1);
insert into clientes values ('Garcia Juan','Rivadavia 333','Villa Maria',1);
insert into clientes values ('Perez Luis','Sarmiento 444','Rosario',2);
insert into clientes values ('Gomez Ines','San Martin 666','Santa Fe',2);
insert into clientes values ('Torres Fabiola','Alem 777','La Plata',4);
insert into clientes values ('Garcia Luis','Sucre 475','Santa Rosa',5);

3- Muestre todos los datos de los clientes, incluido el nombre de la provincia:


select c.nombre,domicilio,ciudad, p.nombre
from clientes as c
left join provincias as p
on codigoprovincia = p.codigo;

4- Realice la misma consulta anterior pero alterando el orden de las tablas:


select c.nombre,domicilio,ciudad, p.nombre
from provincias as p
left join clientes as c
on codigoprovincia = p.codigo;

5- Muestre solamente los clientes de las provincias que existen en "provincias" (5


registros):
select c.nombre,domicilio,ciudad, p.nombre
from clientes as c
left join provincias as p
on codigoprovincia = p.codigo
where p.codigo is not null;

6- Muestre todos los clientes cuyo código de provincia NO existe en "provincias"


ordenados por
nombre del cliente (2 registros):
select c.nombre,domicilio,ciudad, p.nombre
from clientes as c
left join provincias as p
on codigoprovincia = p.codigo
where p.codigo is null
order by c.nombre;

7- Obtenga todos los datos de los clientes de "Cordoba" (3 registros):


select c.nombre,domicilio,ciudad, p.nombre
from clientes as c
left join provincias as p
on codigoprovincia = p.codigo
where p.nombre='Cordoba';

68 - Combinación externa derecha (right join)

Vimos que una combinación 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

85
MANUAL DE SQL-SERVER PARTE II

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 combinación externa derecha ("right outer join" o "right join") opera del mismo modo
sólo que la tabla derecha es la que localiza los registros en la tabla izquierda.

En el siguiente ejemplo solicitamos el título y nombre de la editorial de los libros


empleando un "right join":

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

El resultado mostrará el título y nombre de la editorial; las editoriales de las cuales no hay
libros, es decir, cuyo código 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 posición 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 as e
left join libros as 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 básica es la siguiente:

select CAMPOS
from TABLAIZQUIERDA
right join TABLADERECHA
on CONDICION;

Un "right join" también puede tener cláusula "where" que restringa el resultado de la
consulta considerando solamente los registros que encuentran coincidencia en la tabla
izquierda:

select titulo,nombre
from libros as l

86
MANUAL DE SQL-SERVER PARTE II

right join editoriales as e


on e.codigo=codigoeditorial
where codigoeditorial is not null;

Mostramos las editoriales que NO están presentes en "libros", es decir, que NO


encuentran coincidencia en la tabla de la derecha empleando un "right join":

select titulo,nombre
from libros as l
rightjoin editoriales as e
on e.codigo=codigoeditorial
where codigoeditorial is null;
Primer problema:

Una empresa tiene registrados sus clientes en una tabla llamada "clientes", también
tiene una
tabla "provincias" donde registra los nombres de las provincias.
1- Elimine las tablas "clientes" y "provincias", si existen y cree las tablas:
if (object_id('clientes')) is not null
drop table clientes;
if (object_id('provincias')) is not null
drop table provincias;

create table clientes (


codigo int identity,
nombre varchar(30),
domicilio varchar(30),
ciudad varchar(20),
codigoprovincia tinyint not null,
primary key(codigo)
);

create table provincias(


codigo tinyint identity,
nombre varchar(20),
primary key (codigo)
);

2- Ingrese algunos registros para ambas tablas:


insert into provincias (nombre) values('Cordoba');
insert into provincias (nombre) values('Santa Fe');
insert into provincias (nombre) values('Corrientes');

insert into clientes values ('Lopez Marcos','Colon 111','Córdoba',1);


insert into clientes values ('Perez Ana','San Martin 222','Cruz del Eje',1);
insert into clientes values ('Garcia Juan','Rivadavia 333','Villa Maria',1);
insert into clientes values ('Perez Luis','Sarmiento 444','Rosario',2);
insert into clientes values ('Gomez Ines','San Martin 666','Santa Fe',2);
insert into clientes values ('Torres Fabiola','Alem 777','La Plata',4);
insert into clientes values ('Garcia Luis','Sucre 475','Santa Rosa',5);

87
MANUAL DE SQL-SERVER PARTE II

3- Muestre todos los datos de los clientes, incluido el nombre de la provincia


empleando un "right
join".
Inserte pantalla

4- Obtenga la misma salida que la consulta anterior pero empleando un "left join".
Inserte pantalla

5- Empleando un "right join", muestre solamente los clientes de las provincias que
existen en
"provincias" (5 registros)
Inserte pantalla

6- Muestre todos los clientes cuyo código de provincia NO existe en "provincias"


ordenados por
ciudad (2 registros)
Inserte pantalla

68 - Combinación externa derecha (right join)

Vimos que una combinación 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 combinación externa derecha ("right outer join" o "right join") opera del mismo modo
sólo que la tabla derecha es la que localiza los registros en la tabla izquierda.

En el siguiente ejemplo solicitamos el título y nombre de la editorial de los libros


empleando un "right join":

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

El resultado mostrará el título y nombre de la editorial; las editoriales de las cuales no hay
libros, es decir, cuyo código 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 posición 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 as e

88
MANUAL DE SQL-SERVER PARTE II

left join libros as 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 básica es la siguiente:

select CAMPOS
from TABLAIZQUIERDA
right join TABLADERECHA
on CONDICION;

Un "right join" también puede tener cláusula "where" que restringa el resultado de la
consulta considerando solamente los registros que encuentran coincidencia en la tabla
izquierda:

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

Mostramos las editoriales que NO están presentes en "libros", es decir, que NO


encuentran coincidencia en la tabla de la derecha empleando un "right join":

select titulo,nombre
from libros as l
rightjoin editoriales as e
on e.codigo=codigoeditorial
where codigoeditorial is null;
Primer problema:

Una empresa tiene registrados sus clientes en una tabla llamada "clientes", también
tiene una
tabla "provincias" donde registra los nombres de las provincias.
1- Elimine las tablas "clientes" y "provincias", si existen y cree las tablas:
if (object_id('clientes')) is not null
drop table clientes;
if (object_id('provincias')) is not null
drop table provincias;

create table clientes (


codigo int identity,
nombre varchar(30),
domicilio varchar(30),
ciudad varchar(20),
codigoprovincia tinyint not null,

89
MANUAL DE SQL-SERVER PARTE II

primary key(codigo)
);

create table provincias(


codigo tinyint identity,
nombre varchar(20),
primary key (codigo)
);

2- Ingrese algunos registros para ambas tablas:


insert into provincias (nombre) values('Cordoba');
insert into provincias (nombre) values('Santa Fe');
insert into provincias (nombre) values('Corrientes');

insert into clientes values ('Lopez Marcos','Colon 111','Córdoba',1);


insert into clientes values ('Perez Ana','San Martin 222','Cruz del Eje',1);
insert into clientes values ('Garcia Juan','Rivadavia 333','Villa Maria',1);
insert into clientes values ('Perez Luis','Sarmiento 444','Rosario',2);
insert into clientes values ('Gomez Ines','San Martin 666','Santa Fe',2);
insert into clientes values ('Torres Fabiola','Alem 777','La Plata',4);
insert into clientes values ('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".
Inserte pantalla

4- Obtenga la misma salida que la consulta anterior pero empleando un "left join".
Inserte pantalla

5- Empleando un "right join", muestre solamente los clientes de las provincias que
existen en
"provincias" (5 registros)
Inserte pantalla

6- Muestre todos los clientes cuyo código de provincia NO existe en "provincias"


ordenados por
ciudad (2 registros)
Inserte pantalla

69 - Combinación 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 también que un "right join" opera del mismo modo sólo que
la tabla derecha es la que localiza los registros en la tabla izquierda.

Una combinación 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

90
MANUAL DE SQL-SERVER PARTE II

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 as e
full join libros as l
on codigoeditorial = e.codigo;

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

Problema:

Una librería almacena la información de sus libros para la venta en dos tablas, "libros" y
"editoriales".
Eliminamos ambas tablas, si existen y las creamos:

if object_id('libros') is not null


drop table libros;
if object_id('editoriales') is not null
drop table editoriales;

create table libros(


codigo int identity,
titulo varchar(40),
autor varchar(30) default 'Desconocido',
codigoeditorial tinyint not null,
precio decimal(5,2)
);
create table editoriales(
codigo tinyint identity,
nombre varchar(20),
primary key (codigo)
);

Ingresamos algunos registros en ambas tablas:

insert into editoriales values('Planeta');


insert into editoriales values('Emece');
insert into editoriales values('Siglo XXI');

insert into libros values('El aleph','Borges',1,20);


insert into libros values('Martin Fierro','Jose Hernandez',1,30);
insert into libros values('Aprenda PHP','Mario Molina',2,50);
insert into libros values('Java en 10 minutos',default,4,45);

Realizamos una combinación externa completa para obtener todos los registros de ambas tablas,
incluyendo los libros cuyo código de editorial no existe en la tabla "editoriales" y las editoriales de
las cuales no hay correspondencia en "libros":

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

91
MANUAL DE SQL-SERVER PARTE II

Primer problema:

Un club dicta clases de distintos deportes. Almacena la información 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 si existen y cree las tablas:
if (object_id('deportes')) is not null
drop table deportes;
if (object_id('inscriptos')) is not null
drop table inscriptos;
create table deportes(
codigo tinyint identity,
nombre varchar(30),
profesor varchar(30),
primary key (codigo)
);
create table inscriptos(
documento char(8),
codigodeporte tinyint not null,
matricula char(1) --'s'=paga 'n'=impaga
);

2- Ingrese algunos registros para ambas tablas:


insert into deportes values('tenis','Marcelo Roca');
insert into deportes values('natacion','Marta Torres');
insert into deportes values('basquet','Luis Garcia');
insert into deportes values('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 información de la tabla "inscriptos", y consulte la tabla "deportes"


para
obtener el nombre de cada deporte (6 registros)
Inserte pantalla

4- Empleando un "left join" con "deportes" obtenga todos los datos de los inscriptos (7
registros)
Inserte pantalla

5- Obtenga la misma salida anterior empleando un "rigth join".


Inserte pantalla

92
MANUAL DE SQL-SERVER PARTE II

6- Muestre los deportes para los cuales no hay inscriptos, empleando un "left join" (1
registro)
Inserte pantalla

7- Muestre los documentos de los inscriptos a deportes que no existen en la tabla


"deportes" (1
registro)
Inserte pantalla

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)
Inserte pantalla

70 - Combinaciones cruzadas (cross join)

Vimos que hay tres tipos de combinaciones: 1) combinaciones internas (join), 2)


combinaciones externas (left, right 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 condición de
enlace. Se genera el producto cartesiano en el que el número de filas del resultado es
igual al número de registros de la primera tabla multiplicado por el número de registros de
la segunda tabla, es decir, si hay 5 registros en una tabla y 6 en la otra, retorna 30 filas.

La sintaxis básica es ésta:

select CAMPOS
from TABLA1
cross join TABLA2;

Veamos un ejemplo. Un pequeño 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 as c
cross join postres as p;

La salida muestra cada plato combinado con cada uno de los postres.

Como cualquier tipo de "join", puede emplearse una cláusula "where" que condicione la
salida.

93
MANUAL DE SQL-SERVER PARTE II

Problema:

Un pequeño 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, si existen:

if object_id('comidas') is not null


drop table comidas;
if object_id('postres') is not null
drop table postres;

Creamos las tablas:

create table comidas(


codigo tinyint identity,
nombre varchar(30),
precio decimal(4,2)
);

create table postres(


codigo tinyint identity,
nombre varchar(30),
precio decimal(4,2)
);

Ingresamos algunos registros:

insert into comidas values('ravioles',5);


insert into comidas values('tallarines',4);
insert into comidas values('milanesa',7);
insert into comidas values('cuarto de pollo',6);

insert into postres values('flan',2.5);


insert into postres values('porcion torta',3.5);

El restaurante quiere combinar los registros de ambas tablas para mostrar los distintos menúes que
ofrece. Lo hacemos usando un "cross join":

select c.nombre as 'plato principal',


p.nombre as 'postre',
c.precio+p.precio as 'total'
from comidas as c
cross join postres as p;

La salida muestra cada plato combinado con cada uno de los postres, agregamos una columna
que calcula el precio total de cada menú. Se obtienen 8 registros.

Primer problema:

Una agencia matrimonial almacena la información 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 si existen y créelas:
if object_id('mujeres') is not null
drop table mujeres;
if object_id('varones') is not null
drop table varones;
create table mujeres(
nombre varchar(30),

94
MANUAL DE SQL-SERVER PARTE II

domicilio varchar(30),
edad int
);
create table varones(
nombre varchar(30),
domicilio varchar(30),
edad int
);

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 combinación de todas las personas de sexo femenino con las
de sexo
masculino. Use un "cross join" (12 registros)
Inserte pantalla

4- Realice la misma combinación pero considerando solamente las personas mayores


de 40 años (6
registros)
Inserte pantalla

5- Forme las parejas pero teniendo en cuenta que no tengan una diferencia superior a
10 años (8
registros)
Inserte pantalla

71 - Autocombinación

Dijimos que es posible combinar una tabla consigo misma.

Un pequeño 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 combinación de platos empleando un "cross join" con una sola tabla:

select c1.nombre as 'plato principal',


c2.nombre as postre,
c1.precio+c2.precio as total

95
MANUAL DE SQL-SERVER PARTE II

from comidas as c1
cross join comidas as c2;

En la consulta anterior aparecen 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 as c1
cross join comidas as 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 autocombinación 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".

También se puede realizar una autocombinación con "join":

select c1.nombre as 'plato principal',


c2.nombre as postre,
c1.precio+c2.precio as total
from comidas as c1
join comidas as c2
on c1.codigo<>c2.codigo
where c1.rubro='plato' and
c2.rubro='postre';

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

Primer problema:

Una agencia matrimonial almacena la información de sus clientes en una tabla llamada
"clientes".
1- Elimine la tabla si existe y créela:
if object_id('clientes') is not null
drop table clientes;

create table clientes(


nombre varchar(30),
sexo char(1),--'f'=femenino, 'm'=masculino
edad int,
domicilio varchar(30)
);

2- Ingrese los siguientes registros:

96
MANUAL DE SQL-SERVER PARTE II

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 combinación de todas las personas de sexo femenino con las
de sexo
masculino. Use un "cross join" (12 registros)
Inserte pantalla

4- Obtenga la misma salida enterior pero realizando un "join".


Inserte pantalla

5- Realice la misma autocombinación que el punto 3 pero agregue la condición que las
parejas no
tengan una diferencia superior a 5 años (5 registros)
Inserte pantalla

97