Instituto Tecnológico Superior de Comalcalco
Carlos Mario Carrillo Santos
Ing. En Sistemas Computacionales
Administración de Base de Datos
Ever Alcudia Fuentes
Sexto semestre
Grupo “B”
Manual de sql-server
parte IV
MANUAL DE SQL-SERVER PARTE II
Contenido
Introducción.......................................................................................................................................3
72 - Combinaciones y funciones de agrupamiento............................................................................4
73 - Combinación de más de dos tablas.............................................................................................9
74 - Combinaciones con update y delete.........................................................................................18
75 - Clave foránea............................................................................................................................22
76 - Restricciones (foreign key)........................................................................................................23
77 - Restricciones foreign key en la misma tabla.............................................................................35
78 - Restricciones foreign key (acciones).........................................................................................43
79 - Restricciones foreign key deshabilitar y eliminar (with check - nocheck).................................63
81 - Restricciones al crear la tabla....................................................................................................83
84 - Alterar campos (alter table - alter)..........................................................................................107
85 - Agregar campos y restricciones (alter table)...........................................................................116
86 - Campos calculados..................................................................................................................122
87 - Tipo de dato definido por el usuario (crear - informacion).....................................................128
88 - Tipo de dato definido por el usuario (asociación de reglas)....................................................132
89 - Tipo de dato definido por el usuario (valores predeterminados)............................................149
90 - Tipo de dato definido por el usuario (eliminar).......................................................................158
2
MANUAL DE SQL-SERVER PARTE II
Introducción
En este curso vamos a ver una introducción a las bases de datos. Esta
introducción les va a servir por cualquier tipo de base de datos que desea utilizar.
En este manual del alumno es una ayuda para el alumno, para tenga un recuerdo
del curso. Este manual contiene un resumen de las materias que se van a estudiar
durante el curso. Para captar mejor la teoría, se harán ejercicios con los alumnos,
para probar la teoría y verificar la integración de la materia.
3
MANUAL DE SQL-SERVER PARTE II
72 - Combinaciones y funciones de agrupamiento
Podemos usar "group by" y las funciones de agrupamiento con combinaciones de
tablas.
Para ver la cantidad de libros de cada editorial consultando la tabla "libros" y
"editoriales", tipeamos:
select nombre as editorial,
count(*) as cantidad
from editoriales as e
join libros as l
on codigoeditorial=e.codigo
group by e.nombre;
Note que las editoriales que no tienen libros no aparecen en la salida porque
empleamos un "join".
Empleamos otra función de agrupamiento con "left join". Para conocer el mayor
precio de los libros de cada editorial usamos la función "max()", hacemos un "left
join" y agrupamos por nombre de la editorial:
select nombre as editorial,
max(precio) as 'mayor precio'
from editoriales as e
left join libros as l
on codigoeditorial=e.codigo
group by nombre;
En la sentencia anterior, mostrará, para la editorial de la cual no haya libros, el
valor "null" en la columna calculada.
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),
codigoeditorial tinyint not null,
precio decimal(5,2)
4
MANUAL DE SQL-SERVER PARTE II
);
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',3,50);
insert into libros values('Uno','Richard Bach',3,15);
insert into libros values('Java en 10 minutos',default,4,45);
inserte pantalla
Contamos la cantidad de libros de cada editorial consultando ambas tablas:
select nombre as editorial,
count(*) as cantidad
from editoriales as e
join libros as l
on codigoeditorial=e.codigo
group by e.nombre;
inserte pantalla
5
MANUAL DE SQL-SERVER PARTE II
Buscamos el libro más costoso de cada editorial con un "left join":
select nombre as editorial,
max(precio) as 'mayor precio'
from editoriales as e
left join libros as l
on codigoeditorial=e.codigo
group by nombre;
inserte pantalla
Primer problema:
6
MANUAL DE SQL-SERVER PARTE II
Un comercio que tiene un stand en una feria registra en una tabla llamada
"visitantes" algunos datos
de las personas que visitan o compran en su stand para luego enviarle
publicidad de sus productos y
en otra tabla llamada "ciudades" los nombres de las ciudades.
1- Elimine las tablas si existen:
if object_id('visitantes') is not null
drop table visitantes;
if object_id('ciudades') is not null
drop table ciudades;
2- Cree las tablas:
create table visitantes(
nombre varchar(30),
edad tinyint,
sexo char(1) default 'f',
domicilio varchar(30),
codigociudad tinyint not null,
mail varchar(30),
montocompra decimal (6,2)
);
create table ciudades(
codigo tinyint identity,
nombre varchar(20)
);
3- Ingrese algunos registros:
insert into ciudades values('Cordoba');
insert into ciudades values('Carlos Paz');
insert into ciudades values('La Falda');
insert into ciudades values('Cruz del Eje');
insert into visitantes values
('Susana Molina', 35,'f','Colon 123', 1, null,59.80);
insert into visitantes values
('Marcos Torres', 29,'m','Sucre 56', 1, 'marcostorres@hotmail.com',150.50);
insert into visitantes values
('Mariana Juarez', 45,'f','San Martin 111',2,null,23.90);
insert into visitantes values
('Fabian Perez',36,'m','Avellaneda 213',3,'fabianperez@xaxamail.com',0);
insert into visitantes values
('Alejandra Garcia',28,'f',null,2,null,280.50);
insert into visitantes values
('Gaston Perez',29,'m',null,5,'gastonperez1@gmail.com',95.40);
insert into visitantes values
('Mariana Juarez',33,'f',null,2,null,90);
7
MANUAL DE SQL-SERVER PARTE II
4- Cuente la cantidad de visitas por ciudad mostrando el nombre de la ciudad
(3 filas)
inserte pantalla
5- Muestre el promedio de gastos de las visitas agrupados por ciudad y sexo (4
filas)
inserte pantalla
6- Muestre la cantidad de visitantes con mail, agrupados por ciudad (3 filas)
inserte pantalla
8
MANUAL DE SQL-SERVER PARTE II
7- Obtenga el monto de compra más alto de cada ciudad (3 filas)
inserte pantalla
73 - Combinación de más de dos tablas
Podemos hacer un "join" con más de dos tablas.
Cada join combina 2 tablas. Se pueden emplear varios join para enlazar varias
tablas. Cada resultado de un join es una tabla que puede combinarse con otro join.
La librería almacena los datos de sus libros en tres tablas: libros, editoriales y
autores.
9
MANUAL DE SQL-SERVER PARTE II
En la tabla "libros" un campo "codigoautor" hace referencia al autor y un campo
"codigoeditorial" referencia la editorial.
Para recuperar todos los datos de los libros empleamos la siguiente consulta:
select titulo,a.nombre,e.nombre
from autores as a
join libros as l
on codigoautor=a.codigo
join editoriales as e on codigoeditorial=e.codigo;
Analicemos la consulta anterior. Indicamos el nombre de la tabla luego del "from"
("autores"), combinamos esa tabla con la tabla "libros" especificando con "on" el
campo por el cual se combinarán; luego debemos hacer coincidir los valores para
el enlace con la tabla "editoriales" enlazándolas por los campos correspondientes.
Utilizamos alias para una sentencia más sencilla y comprensible.
Note que especificamos a qué tabla pertenecen los campos cuyo nombre se
repiten en las tablas, esto es necesario para evitar confusiones y ambiguedades al
momento de referenciar un campo.
Note que no aparecen los libros cuyo código de autor no se encuentra en
"autores" y cuya editorial no existe en "editoriales", esto es porque realizamos una
combinación interna.
Podemos combinar varios tipos de join en una misma sentencia:
select titulo,a.nombre,e.nombre
from autores as a
right join libros as l
on codigoautor=a.codigo
left join editoriales as e on codigoeditorial=e.codigo;
En la consulta anterior solicitamos el título, autor y editorial de todos los libros que
encuentren o no coincidencia con "autores" ("right join") y a ese resultado lo
combinamos con "editoriales", encuentren o no coincidencia.
Es posible realizar varias combinaciones para obtener información de varias
tablas. Las tablas deben tener claves externas relacionadas con las tablas a
combinar.
En consultas en las cuales empleamos varios "join" es importante tener en cuenta
el orden de las tablas y los tipos de "join"; recuerde que la tabla resultado del
primer join es la que se combina con el segundo join, no la segunda tabla
nombrada. En el ejemplo anterior, el "left join" no se realiza entre las tablas "libros"
y "editoriales" sino entre el resultado del "right join" y la tabla "editoriales".
10
MANUAL DE SQL-SERVER PARTE II
Problema:
Una librería almacena la información de sus libros para la venta en tres tablas, "libros",
"autores" y "editoriales".
Eliminamos las tablas, si existen y las creamos:
if object_id('libros') is not null
drop table libros;
if object_id('autores') is not null
drop table autores;
if object_id('editoriales') is not null
drop table editoriales;
create table libros(
codigo int identity,
titulo varchar(40),
codigoautor int not null,
codigoeditorial tinyint not null,
precio decimal(5,2),
primary key(codigo)
);
create table autores(
codigo int identity,
nombre varchar(20),
primary key (codigo)
);
create table editoriales(
codigo tinyint identity,
nombre varchar(20),
primary key (codigo)
);
Ingresamos algunos registros:
insert into editoriales values('Planeta');
insert into editoriales values('Emece');
insert into editoriales values('Siglo XXI');
insert into editoriales values('Plaza');
insert into autores values ('Richard Bach');
insert into autores values ('Borges');
insert into autores values ('Jose Hernandez');
insert into autores values ('Mario Molina');
insert into autores values ('Paenza');
insert into libros values('El aleph',2,2,20);
insert into libros values('Martin Fierro',3,1,30);
insert into libros values('Aprenda PHP',4,3,50);
insert into libros values('Uno',1,1,15);
insert into libros values('Java en 10 minutos',0,3,45);
insert into libros values('Matematica estas ahi',0,0,15);
insert into libros values('Java de la A a la Z',4,0,50);
Recuperamos todos los datos de los libros consultando las tres tablas:
select titulo,a.nombre,e.nombre,precio
from autores as a
11
MANUAL DE SQL-SERVER PARTE II
join libros as l
on codigoautor=a.codigo
join editoriales as e
on codigoeditorial=e.codigo;
inserte pantalla
Los libros cuyo código de autor no se encuentra en "autores" (caso de "Java en 10
minutos" y "Matematica estas ahi") y cuya editorial no existe en "editoriales" (caso de
"Matematica estas ahi" y "Java de la A a la Z"), no aparecen porque realizamos una
combinación interna.
Podemos combinar varios tipos de join en una misma sentencia:
select titulo,a.nombre,e.nombre,precio
from autores as a
right join libros as l
on codigoautor=a.codigo
left join editoriales as e
on codigoeditorial=e.codigo;
inserte pantalla
12
MANUAL DE SQL-SERVER PARTE II
En la consulta anterior solicitamos el título, autor y editorial de todos los libros que
encuentren o no coincidencia con "autores" ("right join") y a ese resultado lo combinamos
con "editoriales", encuentren o no coincidencia.
Primer problema:
Un club dicta clases de distintos deportes. En una tabla llamada "socios"
guarda los datos de los
socios, en una tabla llamada "deportes" la información referente a los
diferentes deportes que se
dictan y en una tabla denominada "inscriptos", las inscripciones de los socios a
los distintos
deportes.
Un socio puede inscribirse en varios deportes el mismo año. Un socio no puede
inscribirse en el
mismo deporte el mismo año. Distintos socios se inscriben en un mismo
deporte en el mismo año.
1- Elimine las tablas si existen:
if object_id('socios') is not null
drop table socios;
if object_id('deportes') is not null
drop table deportes;
if object_id('inscriptos') is not null
drop table inscriptos;
inserte pantalla
2- Cree las tablas con las siguientes estructuras:
create table socios(
documento char(8) not null,
13
MANUAL DE SQL-SERVER PARTE II
nombre varchar(30),
domicilio varchar(30),
primary key(documento)
);
create table deportes(
codigo tinyint identity,
nombre varchar(20),
profesor varchar(15),
primary key(codigo)
);
create table inscriptos(
documento char(8) not null,
codigodeporte tinyint not null,
anio char(4),
matricula char(1),--'s'=paga, 'n'=impaga
primary key(documento,codigodeporte,anio)
);
inserte pantalla
3- Ingrese algunos registros en "socios":
insert into socios values('22222222','Ana Acosta','Avellaneda 111');
insert into socios values('23333333','Betina Bustos','Bulnes 222');
insert into socios values('24444444','Carlos Castro','Caseros 333');
insert into socios values('25555555','Daniel Duarte','Dinamarca 44');
4- Ingrese algunos registros en "deportes":
insert into deportes values('basquet','Juan Juarez');
insert into deportes values('futbol','Pedro Perez');
insert into deportes values('natacion','Marina Morales');
insert into deportes values('tenis','Marina Morales');
5- Inscriba a varios socios en el mismo deporte en el mismo año:
14
MANUAL DE SQL-SERVER PARTE II
insert into inscriptos values ('22222222',3,'2006','s');
insert into inscriptos values ('23333333',3,'2006','s');
insert into inscriptos values ('24444444',3,'2006','n');
inserte pantalla
6- Inscriba a un mismo socio en el mismo deporte en distintos años:
insert into inscriptos values ('22222222',3,'2005','s');
insert into inscriptos values ('22222222',3,'2007','n');
inserte pantalla
7- Inscriba a un mismo socio en distintos deportes el mismo año:
insert into inscriptos values ('24444444',1,'2006','s');
insert into inscriptos values ('24444444',2,'2006','s');
inserte pantalla
15
MANUAL DE SQL-SERVER PARTE II
8- Ingrese una inscripción con un código de deporte inexistente y un
documento de socio que no
exista en "socios":
insert into inscriptos values ('26666666',0,'2006','s');
inserte pantalla
9- Muestre el nombre del socio, el nombre del deporte en que se inscribió y el
año empleando
diferentes tipos de join.
inserte pantalla
16
MANUAL DE SQL-SERVER PARTE II
10- Muestre todos los datos de las inscripciones (excepto los códigos)
incluyendo aquellas
inscripciones cuyo código de deporte no existe en "deportes" y cuyo
documento de socio no se
encuentra en "socios".
inserte pantalla
11- Muestre todas las inscripciones del socio con documento "22222222".
inserte pantalla
17
MANUAL DE SQL-SERVER PARTE II
74 - Combinaciones con update y delete
Las combinaciones no sólo se utilizan con la sentencia "select", también podemos
emplearlas con "update" y "delete".
Podemos emplear "update" o "delete" con "join" para actualizar o eliminar registros
de una tabla consultando otras tablas.
En el siguiente ejemplo aumentamos en un 10% los precios de los libros de cierta
editorial, necesitamos un "join" para localizar los registros de la editorial "Planeta"
en la tabla "libros":
update libros set precio=precio+(precio*0.1)
from libros
join editoriales as e
on codigoeditorial=e.codigo
where nombre='Planeta';
Eliminamos todos los libros de editorial "Emece":
delete libros
from libros
join editoriales
on codigoeditorial = editoriales.codigo
where editoriales.nombre='Emece';
Problema:
18
MANUAL DE SQL-SERVER PARTE II
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);
inserte pantalla
19
MANUAL DE SQL-SERVER PARTE II
Aumentamos en un 10% los precios de los libros de editorial "Planeta":
update libros set precio=precio+(precio*0.1)
from libros
join editoriales as e
on codigoeditorial=e.codigo
where nombre='Planeta';
inserte pantalla
Veamos el resultado:
select titulo,autor,e.nombre,precio
from libros as l
join editoriales as e
on codigoeditorial=e.codigo;
inserte pantalla
20
MANUAL DE SQL-SERVER PARTE II
Eliminamos todos los libros de editorial "Emece":
delete libros
from libros
join editoriales
on codigoeditorial = editoriales.codigo
where editoriales.nombre='Emece';
inserte pantalla
Veamos si se eliminaron:
select titulo,autor,e.nombre,precio
21
MANUAL DE SQL-SERVER PARTE II
from libros as l
join editoriales as e
on codigoeditorial=e.codigo;
inserte pantalla
75 - Clave foránea
Un campo que no es clave primaria en una tabla y sirve para enlazar sus valores
con otra tabla en la cual es clave primaria se denomina clave foránea, externa o
ajena.
En el ejemplo de la librería en que utilizamos las tablas "libros" y "editoriales" con
estos campos:
libros: codigo (clave primaria), titulo, autor,
codigoeditorial, precio y
editoriales: codigo (clave primaria), nombre.
el campo "codigoeditorial" de "libros" es una clave foránea, se emplea para
enlazar la tabla "libros" con "editoriales" y es clave primaria en "editoriales" con el
nombre "codigo".
Las claves foráneas y las claves primarias deben ser del mismo tipo para poder
enlazarse. Si modificamos una, debemos modificar la otra para que los valores se
correspondan.
Cuando alteramos una tabla, debemos tener cuidado con las claves foráneas. Si
modificamos el tipo, longitud o atributos de una clave foránea, ésta puede quedar
inhabilitada para hacer los enlaces.
22
MANUAL DE SQL-SERVER PARTE II
inserte pantalla
Entonces, una clave foránea es un campo (o varios) empleados para enlazar
datos de 2 tablas, para establecer un "join" con otra tabla en la cual es clave
primaria.
76 - Restricciones (foreign key)
Hemos visto que una de las alternativas que SQL Server ofrece para asegurar la
integridad de datos es el uso de restricciones (constraints). Aprendimos que las
restricciones se establecen en tablas y campos asegurando que los datos sean
válidos y que las relaciones entre las tablas se mantengan; vimos que existen
distintos tipos de restricciones:
1) de los campos: default y check
2) de la tabla: primary key y unique.
3) referencial: foreign key, la analizaremos ahora.
Con la restricción "foreign key" se define un campo (o varios) cuyos valores
coinciden con la clave primaria de la misma tabla o de otra, es decir, se define una
referencia a un campo con una restricción "primary key" o "unique" de la misma
tabla o de otra.
La integridad referencial asegura que se mantengan las referencias entre las
claves primarias y las externas. Por ejemplo, controla que si se agrega un código
de editorial en la tabla "libros", tal código exista en la tabla "editoriales".
También controla que no pueda eliminarse un registro de una tabla ni modificar la
clave primaria si una clave externa hace referencia al registro. Por ejemplo, que no
se pueda eliminar o modificar un código de "editoriales" si existen libros con dicho
código.
La siguiente es la sintaxis parcial general para agregar una restricción "foreign
key":
alter table NOMBRETABLA1
add constraint NOMBRERESTRICCION
foreign key (CAMPOCLAVEFORANEA)
references NOMBRETABLA2 (CAMPOCLAVEPRIMARIA);
inserte pantalla
Analicémosla:
23
MANUAL DE SQL-SERVER PARTE II
- NOMBRETABLA1 referencia el nombre de la tabla a la cual le aplicamos la
restricción,
- NOMBRERESTRICCION es el nombre que le damos a la misma,
- luego de "foreign key", entre paréntesis se coloca el campo de la tabla a la que le
aplicamos la restricción que será establecida como clave foránea,
- luego de "references" indicamos el nombre de la tabla referenciada y el campo
que es clave primaria en la misma, a la cual hace referencia la clave foránea. La
tabla referenciada debe tener definida una restricción "primary key" o "unique"; si
no la tiene, aparece un mensaje de error.
Para agregar una restricción "foreign key" al campo "codigoeditorial" de "libros",
tipeamos:
alter table libros
add constraint FK_libros_codigoeditorial
foreign key (codigoeditorial)
references editoriales(codigo);
En el ejemplo implementamos una restricción "foreign key" para asegurarnos que
el código de la editorial de la de la tabla "libros" ("codigoeditorial") esté asociada
con un código válido en la tabla "editoriales" ("codigo").
Cuando agregamos cualquier restricción a una tabla que contiene información,
SQL Server controla los datos existentes para confirmar que cumplen con la
restricción, si no los cumple, la restricción no se aplica y aparece un mensaje de
error. Por ejemplo, si intentamos agregar una restricción "foreign key" a la tabla
"libros" y existe un libro con un valor de código para editorial que no existe en la
tabla "editoriales", la restricción no se agrega.
Actúa en inserciones. Si intentamos ingresar un registro (un libro) con un valor de
clave foránea (codigoeditorial) que no existe en la tabla referenciada (editoriales),
SQL server muestra un mensaje de error. Si al ingresar un registro (un libro), no
colocamos el valor para el campo clave foránea (codigoeditorial), almacenará
"null", porque esta restricción permite valores nulos (a menos que se haya
especificado lo contrario al definir el campo).
Actúa en eliminaciones y actualizaciones. Si intentamos eliminar un registro o
modificar un valor de clave primaria de una tabla si una clave foránea hace
referencia a dicho registro, SQL Server no lo permite (excepto si se permite la
acción en cascada, tema que veremos posteriormente). Por ejemplo, si intentamos
eliminar una editorial a la que se hace referencia en "libros", aparece un mensaje
de error.
24
MANUAL DE SQL-SERVER PARTE II
Esta restricción (a diferencia de "primary key" y "unique") no crea índice
automaticamente.
La cantidad y tipo de datos de los campos especificados luego de "foreign key"
DEBEN coincidir con la cantidad y tipo de datos de los campos de la cláusula
"references".
Esta restricción se puede definir dentro de la misma tabla (lo veremos más
adelante) o entre distintas tablas.
Una tabla puede tener varias restricciones "foreign key".
No se puede eliminar una tabla referenciada en una restricción "foreign key",
aparece un mensaje de error.
Una restriccion "foreign key" no puede modificarse, debe eliminarse y volverse a
crear.
Para ver información acerca de esta restricción podemos ejecutar el procedimiento
almacenado "sp_helpconstraint" junto al nombre de la tabla. Nos muestra el tipo,
nombre, la opción para eliminaciones y actualizaciones, el estado (temas que
veremos más adelante), el nombre del campo y la tabla y campo que referencia.
También informa si la tabla es referenciada por una clave foránea.
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),
codigoeditorial tinyint
);
create table editoriales(
codigo tinyint,
nombre varchar(20),
primary key (codigo)
);
Ingresamos algunos registros en ambas tablas:
25
MANUAL DE SQL-SERVER PARTE II
insert into editoriales values(1,'Emece');
insert into editoriales values(2,'Planeta');
insert into editoriales values(3,'Siglo XXI');
insert into libros values('El aleph','Borges',1);
insert into libros values('Martin Fierro','Jose Hernandez',2);
insert into libros values('Aprenda PHP','Mario Molina',2);
inserte pantalla
Agregamos una restricción "foreign key" a la tabla "libros":
alter table libros
add constraint FK_libros_codigoeditorial
foreign key (codigoeditorial)
references editoriales(codigo);
Ingresamos un libro sin especificar valores:
insert into libros default values;
inserte pantalla
26
MANUAL DE SQL-SERVER PARTE II
Note que en "codigoeditorial" almacenó "null", porque esta restricción permite valores
nulos (a menos que se haya especificado lo contrario al definir el campo).
Veamos las restricciones de "libros":
sp_helpconstraint libros;
inserte pantalla
aparece la restricción "foreign key".
Veamos las restricciones de "editoriales":
27
MANUAL DE SQL-SERVER PARTE II
sp_helpconstraint editoriales;
inserte pantalla
aparece la restricción "primary key" y nos informa que la tabla es rerenciada por una
"foreign key" de la tabla "libros" llamada "FK_libros_codigoeditorial".
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 créelas:
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
);
create table provincias(
codigo tinyint not null,
nombre varchar(20)
);
28
MANUAL DE SQL-SERVER PARTE II
En este ejemplo, el campo "codigoprovincia" de "clientes" es una clave
foránea, se emplea para
enlazar la tabla "clientes" con "provincias".
2- Intente agregar una restricción "foreign key" a la tabla "clientes" que haga
referencia al campo
"codigo" de "provincias":
alter table clientes
add constraint FK_clientes_codigoprovincia
foreign key (codigoprovincia)
references provincias(codigo);
No se puede porque "provincias" no tiene restricción "primary key" ni "unique".
inserte pantalla
3- Establezca una restricción "primary key" al campo "codigo" de "provincias":
alter table provincias
add constraint PK_provincias_codigo
primary key (codigo);
29
MANUAL DE SQL-SERVER PARTE II
4- Ingrese algunos registros para ambas tablas:
insert into provincias values(1,'Cordoba');
insert into provincias values(2,'Santa Fe');
insert into provincias values(3,'Misiones');
insert into provincias values(4,'Rio Negro');
insert into clientes values('Perez Juan','San Martin 123','Carlos Paz',1);
insert into clientes values('Moreno Marcos','Colon 234','Rosario',2);
insert into clientes values('Acosta Ana','Avellaneda 333','Posadas',3);
insert into clientes values('Luisa Lopez','Juarez 555','La Plata',6);
inserte pantalla
5- Intente agregar la restricción "foreign key" del punto 2 a la tabla "clientes":
alter table clientes
30
MANUAL DE SQL-SERVER PARTE II
add constraint FK_clientes_codigoprovincia
foreign key (codigoprovincia)
references provincias(codigo);
No se puede porque hay un registro en "clientes" cuyo valor de
"codigoprovincia" no existe en
"provincias".
inserte pantalla
6- Elimine el registro de "clientes" que no cumple con la restricción y
establezca la restricción
nuevamente:
delete from clientes where codigoprovincia=6;
alter table clientes
add constraint FK_clientes_codigoprovincia
foreign key (codigoprovincia)
references provincias(codigo);
inserte pantalla
31
MANUAL DE SQL-SERVER PARTE II
7- Intente agregar un cliente con un código de provincia inexistente en
"provincias".
No se puede.
inserte pantalla
8- Intente eliminar el registro con código 3, de "provincias".
No se puede porque hay registros en "clientes" al cual hace referencia.
inserte pantalla
32
MANUAL DE SQL-SERVER PARTE II
9- Elimine el registro con código "4" de "provincias".
Se permite porque en "clientes" ningún registro hace referencia a él.
inserte pantalla
10- Intente modificar el registro con código 1, de "provincias".
No se puede porque hay registros en "clientes" al cual hace referencia.
inserte pantalla
33
MANUAL DE SQL-SERVER PARTE II
11- Vea las restricciones de "clientes".
aparece la restricción "foreign key".
inserte pantalla
12- Vea las restricciones de "provincias".
aparece la restricción "primary key" y nos informa que la tabla es rerenciada
por una "foreign key"
de la tabla "clientes" llamada "FK_clientes_codigoprovincia".
inserte pantalla
34
MANUAL DE SQL-SERVER PARTE II
77 - Restricciones foreign key en la misma tabla
La restricción "foreign key", que define una referencia a un campo con una
restricción "primary key" o "unique" se puede definir entre distintas tablas (como
hemos aprendido) o dentro de la misma tabla.
Veamos un ejemplo en el cual definimos esta restricción dentro de la misma tabla.
Una mutual almacena los datos de sus afiliados en una tabla llamada "afiliados".
Algunos afiliados inscriben a sus familiares. La tabla contiene un campo que hace
referencia al afiliado que lo incorporó a la mutual, del cual dependen.
La estructura de la tabla es la siguiente:
create table afiliados(
numero int identity not null,
documento char(8) not null,
nombre varchar(30),
afiliadotitular int,
primary key (documento),
unique (numero)
);
En caso que un afiliado no haya sido incorporado a la mutual por otro afiliado, el
campo "afiliadotitular" almacenará "null".
35
MANUAL DE SQL-SERVER PARTE II
Establecemos una restricción "foreign key" para asegurarnos que el número de
afiliado que se ingrese en el campo "afiliadotitular" exista en la tabla "afiliados":
alter table afiliados
add constraint FK_afiliados_afiliadotitular
foreign key (afiliadotitular)
references afiliados (numero);
La sintaxis es la misma, excepto que la tabla se autoreferencia.
Luego de aplicar esta restricción, cada vez que se ingrese un valor en el campo
"afiliadotitular", SQL Server controlará que dicho número exista en la tabla, si no
existe, mostrará un mensaje de error.
Problema:
Una mutual almacena los datos de sus afiliados en una tabla llamada "afiliados". Algunos
afiliados inscriben a sus familiares. La tabla contiene un campo que hace referencia al
afiliado que lo incorporó a la mutual, del cual dependen.
Eliminamos la tabla "afiliados" si existe y la creamos:
if object_id('afiliados') is not null
drop table afiliados;
create table afiliados(
numero int identity not null,
documento char(8) not null,
nombre varchar(30),
afiliadotitular int,
primary key (documento),
unique (numero)
);
inserte pantalla
36
MANUAL DE SQL-SERVER PARTE II
En caso que un afiliado no haya sido incorporado a la mutual por otro afiliado, el campo
"afiliadotitular" almacenará "null".
Establecemos una restricción "foreign key" para asegurarnos que el número de afiliado
que se ingrese en el campo "afiliadotitular" exista en la tabla "afiliados":
alter table afiliados
add constraint FK_afiliados_afiliadotitular
foreign key (afiliadotitular)
references afiliados (numero);
inserte pantalla
Ingresamos algunos registros:
insert into afiliados values('22222222','Perez Juan',null);
insert into afiliados values('23333333','Garcia Maria',null);
insert into afiliados values('24444444','Lopez Susana',null);
insert into afiliados values('30000000','Perez Marcela',1);
insert into afiliados values('31111111','Morales Luis',1);
insert into afiliados values('32222222','Garcia Maria',2);
Podemos eliminar un afiliado, siempre que no haya otro afiliado que haga referencia a él
en "afiliadotitular", es decir, si el "numero" del afiliado está presente en algún registro en el
campo "afiliadotitular":
delete from afiliados where numero=5;
Veamos la información referente a "afiliados":
sp_helpconstraint afiliados;
inserte pantalla
37
MANUAL DE SQL-SERVER PARTE II
Primer problema:
Una empresa registra los datos de sus clientes en una tabla llamada "clientes".
Dicha tabla contiene
un campo que hace referencia al cliente que lo recomendó denominado
"referenciadopor". Si un cliente
no ha sido referenciado por ningún otro cliente, tal campo almacena "null".
1- Elimine la tabla si existe y créela:
if object_id('clientes') is not null
drop table clientes;
create table clientes(
codigo int not null,
nombre varchar(30),
domicilio varchar(30),
ciudad varchar(20),
referenciadopor int,
primary key(codigo)
);
2- Ingresamos algunos registros:
insert into clientes values (50,'Juan Perez','Sucre 123','Cordoba',null);
insert into clientes values(90,'Marta Juarez','Colon 345','Carlos Paz',null);
insert into clientes values(110,'Fabian Torres','San Martin 987','Cordoba',50);
insert into clientes values(125,'Susana Garcia','Colon 122','Carlos Paz',90);
insert into clientes values(140,'Ana Herrero','Colon 890','Carlos Paz',9);
inserte pantalla
38
MANUAL DE SQL-SERVER PARTE II
3- Intente agregar una restricción "foreign key" para evitar que en el campo
"referenciadopor" se
ingrese un valor de código de cliente que no exista.
No se permite porque existe un registro que no cumple con la restricción que
se intenta establecer.
inserte pantalla
4- Cambie el valor inválido de "referenciadopor" del registro que viola la
restricción por uno
válido.
inserte pantalla
39
MANUAL DE SQL-SERVER PARTE II
5- Agregue la restricción "foreign key" que intentó agregar en el punto 3.
inserte pantalla
6- Vea la información referente a las restricciones de la tabla "clientes".
inserte pantalla
40
MANUAL DE SQL-SERVER PARTE II
7- Intente agregar un registro que infrinja la restricción.
No lo permite.
inserte pantalla
8- Intente modificar el código de un cliente que está referenciado en
"referenciadopor".
No se puede.
inserte pantalla
41
MANUAL DE SQL-SERVER PARTE II
9- Intente eliminar un cliente que sea referenciado por otro en
"referenciadopor".
No se puede.
10- Cambie el valor de código de un cliente que no referenció a nadie.
inserte pantalla
42
MANUAL DE SQL-SERVER PARTE II
11- Elimine un cliente que no haya referenciado a otros.
inserte pantalla
78 - Restricciones foreign key (acciones)
Continuamos con la restricción "foreign key".
Si intentamos eliminar un registro de la tabla referenciada por una restricción
"foreign key" cuyo valor de clave primaria existe referenciada en la tabla que tiene
dicha restricción, la acción no se ejecuta y aparece un mensaje de error. Esto
sucede porque, por defecto, para eliminaciones, la opción de la restricción "foreign
key" es "no action". Lo mismo sucede si intentamos actualizar un valor de clave
43
MANUAL DE SQL-SERVER PARTE II
primaria de una tabla referenciada por una "foreign key" existente en la tabla
principal.
La restricción "foreign key" tiene las cláusulas "on delete" y "on update" que son
opcionales.
Estas cláusulas especifican cómo debe actuar SQL Server frente a eliminaciones y
modificaciones de las tablas referenciadas en la restricción.
Las opciones para estas cláusulas son las siguientes:
- "no action": indica que si intentamos eliminar o actualizar un valor de la clave
primaria de la tabla referenciada (TABLA2) que tengan referencia en la tabla
principal (TABLA1), se genere un error y la acción no se realice; es la opción
predeterminada.
- "cascade": indica que si eliminamos o actualizamos un valor de la clave primaria
en la tabla referenciada (TABLA2), los registros coincidentes en la tabla principal
(TABLA1), también se eliminen o modifiquen; es decir, si eliminamos o
modificamos un valor de campo definido con una restricción "primary key" o
"unique", dicho cambio se extiende al valor de clave externa de la otra tabla
(integridad referencial en cascada).
La sintaxis completa para agregar esta restricción a una tabla es la siguiente:
alter table TABLA1
add constraint NOMBRERESTRICCION
foreign key (CAMPOCLAVEFORANEA)
references TABLA2(CAMPOCLAVEPRIMARIA)
on delete OPCION
on update OPCION;
Sintetizando, si al agregar una restricción foreign key:
- no se especifica acción para eliminaciones (o se especifica "no_action"), y se
intenta eliminar un registro de la tabla referenciada (editoriales) cuyo valor de
clave primaria (codigo) existe en la tabla principal (libros), la acción no se realiza.
- se especifica "cascade" para eliminaciones ("on delete cascade") y elimina un
registro de la tabla referenciada (editoriales) cuyo valor de clave primaria (codigo)
existe en la tabla principal(libros), la eliminación de la tabla referenciada
(editoriales) se realiza y se eliminan de la tabla principal (libros) todos los registros
cuyo valor coincide con el registro eliminado de la tabla referenciada (editoriales).
- no se especifica acción para actualizaciones (o se especifica "no_action"), y se
intenta modificar un valor de clave primaria (codigo) de la tabla referenciada
(editoriales) que existe en el campo clave foránea (codigoeditorial) de la tabla
principal (libros), la acción no se realiza.
44
MANUAL DE SQL-SERVER PARTE II
- se especifica "cascade" para actualizaciones ("on update cascade") y se modifica
un valor de clave primaria (codigo) de la tabla referenciada (editoriales) que existe
en la tabla principal (libros), SQL Server actualiza el registro de la tabla
referenciada (editoriales) y todos los registros coincidentes en la tabla principal
(libros).
Veamos un ejemplo. Definimos una restricción "foreign key" a la tabla "libros"
estableciendo el campo "codigoeditorial" como clave foránea que referencia al
campo "codigo" de la tabla "editoriales". La tabla "editoriales" tiene como clave
primaria el campo "codigo". Especificamos la acción en cascada para las
actualizaciones y eliminaciones:
alter table libros
add constraint FK_libros_codigoeditorial
foreign key (codigoeditorial)
references editoriales(codigo)
on update cascade
on delete cascade;
inserte pantalla
Si luego de establecer la restricción anterior, eliminamos una editorial de
"editoriales" de las cuales hay libros, se elimina dicha editorial y todos los libros de
tal editorial. Y si modificamos el valor de código de una editorial de "editoriales", se
modifica en "editoriales" y todos los valores iguales de "codigoeditorial" de libros
también se modifican.
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 not null,
titulo varchar(40),
autor varchar(30),
codigoeditorial tinyint,
primary key (codigo)
);
create table editoriales(
codigo tinyint not null,
nombre varchar(20),
primary key (codigo)
);
45
MANUAL DE SQL-SERVER PARTE II
inserte pantalla
Ingresamos algunos registros en ambas tablas:
insert into editoriales values(1,'Emece');
insert into editoriales values(2,'Planeta');
insert into editoriales values(3,'Siglo XXI');
insert into libros values(1,'El aleph','Borges',1);
insert into libros values(2,'Martin Fierro','Jose Hernandez',2);
insert into libros values(3,'Aprenda PHP','Mario Molina',2);
Establecemos una restricción "foreign key" para evitar que se ingrese en "libros" un código
de editorial inexistente en "editoriales" con la opción "on cascade" para actualizaciones y
eliminaciones:
alter table libros
add constraint FK_libros_codigoeditorial
foreign key (codigoeditorial)
references editoriales(codigo)
on update cascade
on delete cascade;
inserte pantalla
46
MANUAL DE SQL-SERVER PARTE II
Si actualizamos un valor de código de "editoriales", la modificación se extiende a todos los
registros de la tabla "libros" que hacen referencia a ella en "codigoeditorial":
update editoriales set codigo=10 where codigo=1;
inserte pantalla
Veamos si la actualización se extendió a "libros":
select titulo, autor, e.codigo,nombre
from libros as l
join editoriales as e
on codigoeditorial=e.codigo;
inserte pantalla
47
MANUAL DE SQL-SERVER PARTE II
Si eliminamos una editorial, se borra tal editorial de "editoriales" y todos los registros de
"libros" de dicha editorial:
delete from editoriales where codigo=2;
inserte pantalla
Veamos si la eliminación se extendió a "libros":
select *from libros;
48
MANUAL DE SQL-SERVER PARTE II
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;
inserte pantalla
49
MANUAL DE SQL-SERVER PARTE II
2- Créelas con las siguientes estructuras:
create table clientes (
codigo int identity,
nombre varchar(30),
domicilio varchar(30),
ciudad varchar(20),
codigoprovincia tinyint,
primary key(codigo)
);
create table provincias(
codigo tinyint,
nombre varchar(20),
primary key (codigo)
);
inserte pantalla
50
MANUAL DE SQL-SERVER PARTE II
3- Ingrese algunos registros para ambas tablas:
insert into provincias values(1,'Cordoba');
insert into provincias values(2,'Santa Fe');
insert into provincias values(3,'Misiones');
insert into provincias values(4,'Rio Negro');
insert into clientes values('Perez Juan','San Martin 123','Carlos Paz',1);
insert into clientes values('Moreno Marcos','Colon 234','Rosario',2);
insert into clientes values('Acosta Ana','Avellaneda 333','Posadas',3);
4- Establezca una restricción "foreign key" especificando la acción "en cascade"
para actualizaciones y "no_action" para eliminaciones.
inserte pantalla
51
MANUAL DE SQL-SERVER PARTE II
5- Intente eliminar el registro con código 3, de "provincias".
No se puede porque hay registros en "clientes" al cual hace referencia y la
opción para eliminaciones se estableció como "no action".
inserte pantalla
6- Modifique el registro con código 3, de "provincias".
7- Verifique que el cambio se realizó en cascada, es decir, que se modificó en
la tabla "provincias" y en "clientes":
select *from provincias;
select *from clientes;
inserte pantalla
8- Intente modificar la restricción "foreign key" para que permita eliminación
en cascada.
52
MANUAL DE SQL-SERVER PARTE II
Mensaje de error, no se pueden modificar las restricciones.
inserte pantalla
9- Intente eliminar la tabla "provincias".
No se puede eliminar porque una restricción "foreign key" hace referencia a
ella.
Segundo problema:
Un club dicta clases de distintos deportes. En una tabla llamada "deportes"
guarda la información de
los distintos deportes que se enseñan; en una tabla "socios", los datos de los
socios y en una tabla
53
MANUAL DE SQL-SERVER PARTE II
"inscripciones" almacena la información necesaria para las inscripciones de los
distintos socios a
los distintos deportes.
1- Elimine las tablas si existen:
if object_id('inscripciones') is not null
drop table inscripciones;
if object_id('deportes') is not null
drop table deportes;
if object_id('socios') is not null
drop table socios;
2- Cree las tablas:
create table deportes(
codigo tinyint,
nombre varchar(20),
primary key(codigo)
);
create table socios(
documento char(8),
nombre varchar(30),
primary key(documento)
);
create table inscripciones(
documento char(8),
codigodeporte tinyint,
matricula char(1),-- 's' si está paga, 'n' si no está paga
primary key(documento,codigodeporte)
);
3- Establezca una restricción "foreign key" para "inscripciones" que haga
referencia al campo
"codigo" de "deportes" que permita la actualización en cascada:
alter table inscripciones
add constraint FK_inscripciones_codigodeporte
foreign key (codigodeporte)
references deportes(codigo)
on update cascade;
inserte pantalla
54
MANUAL DE SQL-SERVER PARTE II
4- Establezca una restricción "foreign key" para "inscripciones" que haga
referencia al campo "documento" de "socios" que permita la eliminación en
cascada (Recuerde que se pueden establecer varias retricciones "foreign key" a
una tabla):
alter table inscripciones
add constraint FK_inscripciones_documento
foreign key (documento)
references socios(documento)
on delete cascade;
inserte pantalla
5- Ingrese algunos registros en las tablas:
insert into deportes values(1,'basquet');
insert into deportes values(2,'futbol');
55
MANUAL DE SQL-SERVER PARTE II
insert into deportes values(3,'natacion');
insert into deportes values(4,'tenis');
insert into socios values('30000111','Juan Lopez');
insert into socios values('31111222','Ana Garcia');
insert into socios values('32222333','Mario Molina');
insert into socios values('33333444','Julieta Herrero');
insert into inscripciones values ('30000111',1,'s');
insert into inscripciones values ('30000111',2,'s');
insert into inscripciones values ('31111222',1,'s');
insert into inscripciones values ('32222333',3,'n');
6- Intente ingresar una inscripción con un código de deporte inexistente:
insert into inscripciones values('30000111',6,'s');
Mensaje de error.
inserte pantalla
7- Intente ingresar una inscripción con un documento inexistente en "socios":
insert into inscripciones values('40111222',1,'s');
Mensaje de error.
inserte pantalla
56
MANUAL DE SQL-SERVER PARTE II
8- Elimine un registro de "deportes" que no tenga inscriptos:
delete from deportes where nombre='tenis';
Se elimina porque no hay inscriptos en dicho deporte.
inserte pantalla
9- Intente eliminar un deporte para los cuales haya inscriptos:
delete from deportes where nombre='natacion';
No se puede porque al no especificarse acción para eliminaciones, por defecto
es "no action" y hay inscriptos en dicho deporte.
inserte pantalla
57
MANUAL DE SQL-SERVER PARTE II
10- Modifique el código de un deporte para los cuales haya inscriptos.
La opción para actualizaciones se estableció en cascada, se modifica el código
en "deportes" y en "inscripciones".
inserte pantalla
11- Verifique los cambios:
select *from deportes;
select *from inscripciones;
inserte pantalla
58
MANUAL DE SQL-SERVER PARTE II
12- Elimine el socio que esté inscripto en algún deporte.
Se elimina dicho socio de "socios" y la acción se extiende a la tabla
"inscripciones".
inserte pantalla
13- Verifique que el socio eliminado ya no aparece en "inscripciones":
select *from socios;
select *from inscripciones;
inserte pantalla
59
MANUAL DE SQL-SERVER PARTE II
14- Modifique el documento de un socio que esté inscripto.
No se puede porque la acción es "no action" para actualizaciones.
inserte pantalla
15- Intente eliminar la tabla "deportes":
drop table deportes;
No se puede porque una restricción "foreign key" hace referencia a ella.
inserte pantalla
60
MANUAL DE SQL-SERVER PARTE II
16- Vea las restricciones de la tabla "socios":
sp_helpconstraint socios;
Muestra la restricción "primary key" y la referencia de una "foreign key" de la
tabla "inscripciones".
inserte pantalla
17- Vea las restricciones de la tabla "deportes":
sp_helpconstraint deportes;
Muestra la restricción "primary key" y la referencia de una "foreign key" de la
tabla "inscripciones".
inserte pantalla
61
MANUAL DE SQL-SERVER PARTE II
18- Vea las restricciones de la tabla "inscripciones":
sp_helpconstraint inscripciones;
Muestra 3 restricciones. Una "primary key" y dos "foreign key", una para el
campo "codigodeporte" que especifica "no action" en la columna
"delete_action" y "cascade" en la columna "update_action";
la otra, para el campo "documento" especifica "cascade" en la columna
"delete_action" y "no action" en "update_action".
inserte pantalla
79 - Restricciones foreign key deshabilitar y eliminar (with check - nocheck)
62
MANUAL DE SQL-SERVER PARTE II
Sabemos que si agregamos una restricción a una tabla que contiene datos, SQL
Server los controla para asegurarse que cumplen con la restricción; es posible
deshabilitar esta comprobación.
Podemos hacerlo al momento de agregar la restricción a una tabla con datos,
incluyendo la opción "with nocheck" en la instrucción "alter table"; si se emplea
esta opción, los datos no van a cumplir la restricción.
Se pueden deshabilitar las restricciones "check" y "foreign key", a las demás se las
debe eliminar.
La sintaxis básica al agregar la restriccción "foreign key" es la siguiente:
alter table NOMBRETABLA1
with OPCIONDECHEQUEO
add constraint NOMBRECONSTRAINT
foreign key (CAMPOCLAVEFORANEA)
references NOMBRETABLA2 (CAMPOCLAVEPRIMARIA)
on update OPCION
on delete OPCION;
La opción "with OPCIONDECHEQUEO" especifica si se controlan los datos
existentes o no con "check" y "nocheck" respectivamente. Por defecto, si no se
especifica, la opción es "check".
En el siguiente ejemplo agregamos una restricción "foreign key" que controla que
todos los códigos de editorial tengan un código válido, es decir, dicho código
exista en "editoriales". La restricción no se aplica en los datos existentes pero si en
los siguientes ingresos, modificaciones y actualizaciones:
alter table libros
with nocheck
add constraint FK_libros_codigoeditorial
foreing key (codigoeditorial)
references editoriales(codigo);
La comprobación de restricciones se puede deshabilitar para modificar, eliminar o
agregar datos a una tabla sin comprobar la restricción. La sintaxis general es:
alter table NOMBRETABLA
OPCIONDECHEQUEO constraint NOMBRERESTRICCION;
En el siguiente ejemplo deshabilitamos la restricción creada anteriormente:
alter table libros
nocheck constraint FK_libros_codigoeditorial;
63
MANUAL DE SQL-SERVER PARTE II
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 FK_libros_codigoeditorial;
Si se emplea "check constraint all" no se coloca nombre de restricciones, habilita
todas las restricciones que tiene la tabla nombrada ("check" y "foreign key").
Para saber si una restricción está habilitada o no, podemos ejecutar el
procedimiento almacenado "sp_helpconstraint" y entenderemos lo que informa la
columna "status_enabled".
Entonces, las cláusulas "check" y "nocheck" permiten habilitar o deshabilitar
restricciones "foreign key" (y "check"). Pueden emplearse para evitar la
comprobación de datos existentes al crear la restricción o para deshabilitar la
comprobación de datos al ingresar, actualizar y eliminar algún registro que infrinja
la restricción.
Podemos eliminar una restricción "foreign key" con "alter table". La sintaxis básica
es la misma que para cualquier otra restricción:
alter table TABLA
drop constraint NOMBRERESTRICCION;
Eliminamos la restricción de "libros":
alter table libros
drop constraint FK_libros_codigoeditorial;
No se puede eliminar una tabla si una restricción "foreign key" hace referencia a
ella.
Cuando eliminamos una tabla que tiene una restricción "foreign key", la restricción
también se elimina.
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:
64
MANUAL DE SQL-SERVER PARTE II
create table libros(
codigo int not null,
titulo varchar(40),
autor varchar(30),
codigoeditorial tinyint,
primary key (codigo)
);
create table editoriales(
codigo tinyint not null,
nombre varchar(20),
primary key (codigo)
);
Ingresamos algunos registros:
insert into editoriales values(1,'Planeta');
insert into editoriales values(2,'Emece');
insert into editoriales values(3,'Paidos');
insert into libros values(1,'Uno','Richard Bach',1);
insert into libros values(2,'El aleph','Borges',2);
insert into libros values(3,'Aprenda PHP','Mario Molina',5);
Agregamos una restricción "foreign key" a la tabla "libros" para evitar que se ingresen
códigos de editoriales inexistentes en "editoriales". Incluimos la opción "with nocheck"
para evitar la comprobación de la restricción en los datos existentes (note que hay un libro
que tiene un código de editorial inválido):
alter table libros
with nocheck
add constraint FK_libros_codigoeditorial
foreign key (codigoeditorial)
references editoriales(codigo);
inserte pantalla
65
MANUAL DE SQL-SERVER PARTE II
La deshabilitación de la comprobación de la restricción no afecta a los siguientes
ingresos, modificaciones y actualizaciones. Para poder ingresar, modificar o eliminar
datos a una tabla sin que SQL Server compruebe la restricción debemos deshabilitarla:
alter table libros
nocheck constraint FK_libros_codigoeditorial;
Veamos si la restricción está habilitada o no:
sp_helpconstraint libros;
En la columna "status_enabled" de la restricción "foreign key" aparece "Disabled".
Veamos las restricciones de "editoriales":
sp_helpconstraint editoriales;
Aparece la restricción "primary key" y nos informa que hay una restricción "foreign key"
que hace referencia a ella de la tabla "libros" (aunque esté deshabilitada).
Ahora podemos ingresar un registro en "libros" con código inválido:
insert into libros values(4,'Ilusiones','Richard Bach',6);
También podemos modificar:
update editoriales set codigo=8 where codigo=1;
También realizar eliminaciones:
delete from editoriales where codigo=2;
Habilitamos la restricción:
alter table libros
check constraint FK_libros_codigoeditorial;
inserte pantalla
66
MANUAL DE SQL-SERVER PARTE II
Veamos si la restricción está habilitada o no:
sp_helpconstraint libros;
inserte pantalla
En la columna "status_enabled" aparece "Enabled".
Eliminamos la restricción:
alter table libros
drop constraint FK_libros_codigoeditorial;
67
MANUAL DE SQL-SERVER PARTE II
Ejecutamos el procedimiento almacenado sp_helpconstraint para ver si la restricción se
eliminó:
sp_helpconstraint libros;
inserte pantalla
No aparece la restricción "foreign key".
Vemos las restricciones de "editoriales":
sp_helpconstraint editoriales;
68
MANUAL DE SQL-SERVER PARTE II
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;
inserte pantalla
2- Créelas con las siguientes estructuras:
create table clientes (
codigo int identity,
nombre varchar(30),
domicilio varchar(30),
ciudad varchar(20),
codigoprovincia tinyint,
primary key(codigo)
);
create table provincias(
codigo tinyint,
nombre varchar(20),
primary key (codigo)
);
3- Ingrese algunos registros para ambas tablas:
insert into provincias values(1,'Cordoba');
insert into provincias values(2,'Santa Fe');
69
MANUAL DE SQL-SERVER PARTE II
insert into provincias values(3,'Misiones');
insert into provincias values(4,'Rio Negro');
insert into clientes values('Perez Juan','San Martin 123','Carlos Paz',1);
insert into clientes values('Moreno Marcos','Colon 234','Rosario',2);
insert into clientes values('Garcia Juan','Sucre 345','Cordoba',1);
insert into clientes values('Lopez Susana','Caseros 998','Posadas',3);
insert into clientes values('Marcelo Moreno','Peru 876','Viedma',4);
insert into clientes values('Lopez Sergio','Avellaneda 333','La Plata',5);
4- Intente agregar una restricción "foreign key" para que los códigos de
provincia de "clientes" existan en "provincias" con acción en cascada para
actualizaciones y eliminaciones, sin especificar la opción de comprobación de
datos:
alter table clientes
add constraint FK_clientes_codigoprovincia
foreign key (codigoprovincia)
references provincias(codigo)
on update cascade
on delete cascade;
No se puede porque al no especificar opción para la comprobación de datos,
por defecto es "check" y hay un registro que no cumple con la restricción.
inserte pantalla
5- Agregue la restricción anterior pero deshabilitando la comprobación de
datos existentes:
alter table clientes
with nocheck
add constraint FK_clientes_codigoprovincia
foreign key (codigoprovincia)
references provincias(codigo)
70
MANUAL DE SQL-SERVER PARTE II
on update cascade
on delete cascade;
inserte pantalla
6- Vea las restricciones de "clientes":
sp_helpconstraint clientes;
Aparece la restricción "primary key" y "foreign key", las columnas
"delete_action" y "update_action" contienen "cascade" y la columna
"status_enabled" contiene "Enabled".
inserte pantalla
7- Vea las restricciones de "provincias":
Aparece la restricción "primary key" y la referencia a esta tabla de la
restricción "foreign key" de
la tabla "clientes.
71
MANUAL DE SQL-SERVER PARTE II
inserte pantalla
8- Deshabilite la restricción "foreign key" de "clientes":
alter table clientes
nocheck constraint FK_clientes_codigoprovincia;
inserte pantalla
9- Vea las restricciones de "clientes":
sp_helpconstraint clientes;
la restricción "foreign key" aparece inhabilitada.
inserte pantalla
72
MANUAL DE SQL-SERVER PARTE II
10- Vea las restricciones de "provincias":
sp_helpconstraint provincias;
informa que la restricción "foreign key" de "clientes" hace referencia a ella, aún
cuando está deshabilitada.
inserte pantalla
11- Agregue un registro que no cumpla la restricción "foreign key":
insert into clientes values('Garcia Omar','San Martin 100','La Pampa',6);
Se permite porque la restricción está deshabilitada.
inserte pantalla
73
MANUAL DE SQL-SERVER PARTE II
12- Elimine una provincia de las cuales haya clientes:
delete from provincias where codigo=2;
inserte pantalla
13- Corrobore que el registro se eliminó de "provincias" pero no se extendió a
"clientes":
select *from clientes;
select *from provincias;
inserte pantalla
74
MANUAL DE SQL-SERVER PARTE II
14- Modifique un código de provincia de la cual haya clientes:
update provincias set codigo=9 where codigo=3;
inserte pantalla
15- Verifique que el cambio se realizó en "provincias" pero no se extendió a
"clientes":
select *from clientes;
select *from provincias;
inserte pantalla
75
MANUAL DE SQL-SERVER PARTE II
16- Intente eliminar la tabla "provincias":
drop table provincias;
No se puede porque la restricción "FK_clientes_codigoprovincia" la referencia,
aunque esté deshabilitada.
inserte pantalla
17- Habilite la restricción "foreign key":
alter table clientes
check constraint FK_clientes_codigoprovincia;
inserte pantalla
76
MANUAL DE SQL-SERVER PARTE II
18- Intente agregar un cliente con código de provincia inexistente en
"provincias":
insert into clientes values('Hector Ludueña','Paso 123','La Plata',8);
No se puede.
inserte pantalla
19- Modifique un código de provincia al cual se haga referencia en "clientes":
Actualización en cascada.
inserte pantalla
77
MANUAL DE SQL-SERVER PARTE II
20- Vea que se modificaron en ambas tablas:
select *from clientes;
select *from provincias;
inserte pantalla
21- Elimine una provincia de la cual haya referencia en "clientes":
delete from provincias where codigo=1;
Acción en cascada.
inserte pantalla
78
MANUAL DE SQL-SERVER PARTE II
22- Vea que los registros de ambas tablas se eliminaron:
select *from clientes;
select *from provincias;
inserte pantalla
23- Elimine la restriccion "foreign key":
alter table clientes
drop constraint FK_clientes_codigoprovincia;
inserte pantalla
79
MANUAL DE SQL-SERVER PARTE II
24- Vea las restriciones de la tabla "provincias":
sp_helpconstraint provincias;
Solamente aparece la restricción "primary key", ya no hay una "foreign key"
que la referencie.
inserte pantalla
25- Elimine la tabla "provincias":
Puede eliminarse porque no hay restricción "foreign key" que la referencie.
inserte pantalla
80
MANUAL DE SQL-SERVER PARTE II
80 - Restricciones foreign key (información)
El procedimiento almacenado "sp_helpconstraint" 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. Si es una "foreign key" lo indica.
- constraint_name: nombre de la restricción.
- delete_action: solamente es aplicable para restricciones de tipo "foreign key".
Indica si la acción de eliminación actúa, no actúa o es en cascada. Indica "n/a" en
cualquier restricción para la que no se aplique; "No Action" si no actúa y
"Cascade" si es en cascada.
- update_action: sólo es aplicable para restricciones de tipo "foreign key". Indica si
la acción de actualización es: No Action, Cascade, or n/a. Indica "n/a" en cualquier
restricción para la que no se aplique.
- 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.
- 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 "default" muestra la condición de chequeo;
si es una restricción "default", el valor por defecto; si es una "primary key",
81
MANUAL DE SQL-SERVER PARTE II
"unique" o "foreign key" muestra el/ los campos a los que se aplicaron la
restricción. En caso de valores predeterminados y reglas, el texto que lo define.
81 - Restricciones al crear la tabla
Hasta el momento hemos agregado restricciones a tablas existentes con "alter
table" (manera aconsejada), también pueden establecerse al momento de crear
una tabla (en la instrucción "create table").
Podemos aplicar restricciones a nivel de campo (restricción de campo) o a nivel de
tabla (restricción de tabla).
En el siguiente ejemplo creamos la tabla "libros" con varias restricciones:
create table libros(
codigo int identity,
titulo varchar(40),
codigoautor int not null,
codigoeditorial tinyint not null,
precio decimal(5,2)
constraint DF_precio default (0),
constraint PK_libros_codigo
primary key clustered (codigo),
constraint UQ_libros_tituloautor
unique (titulo,codigoautor),
constraint FK_libros_editorial
foreign key (codigoeditorial)
references editoriales(codigo)
on update cascade,
constraint FK_libros_autores
foreign key (codigoautor)
references autores(codigo)
on update cascade,
constraint CK_precio_positivo check (precio>=0)
);
En el ejemplo anterior creamos:
- una restricción "default" para el campo "precio" (restricción a nivel de campo);
- una restricción "primary key" con índice agrupado para el campo "codigo" (a nivel
de tabla);
- una restricción "unique" con índice no agrupado (por defecto) para los campos
"titulo" y "codigoautor" (a nivel de tabla);
82
MANUAL DE SQL-SERVER PARTE II
- una restricción "foreign key" para establecer el campo "codigoeditorial" como
clave externa que haga referencia al campo "codigo" de "editoriales y permita
actualizaciones en cascada y no eliminaciones (por defecto "no action");
- una restricción "foreign key" para establecer el campo "codigoautor" como clave
externa que haga referencia al campo "codigo" de "autores" y permita
actualizaciones en cascada y no eliminaciones;
- una restricción "check" para el campo "precio" que no admita valores negativos;
Si definimos una restricción "foreign key" al crear una tabla, la tabla referenciada
debe existir.
Problema:
Trabajamos con las tablas "libros", "autores" y "editoriales" de una librería:
Eliminamos las tablas si existen:
if object_id('libros') is not null
drop table libros;
if object_id('editoriales') is not null
drop table editoriales;
if object_id('autores') is not null
drop table autores;
Creamos la tabla "editoriales" con una restricción "primary key":
create table editoriales(
codigo tinyint not null,
nombre varchar(30),
constraint PK_editoriales primary key (codigo)
);
Creamos la tabla "autores" con una restricción "primary key", una "unique" y una "check":
create table autores(
codigo int not null
constraint CK_autores_codigo check (codigo>=0),
nombre varchar(30) not null,
constraint PK_autores_codigo
primary key (codigo),
constraint UQ_autores_nombre
unique (nombre),
);
Aplicamos varias restricciones cuando creamos la tabla "libros":
create table libros(
codigo int identity,
titulo varchar(40),
codigoautor int not null,
codigoeditorial tinyint not null,
83
MANUAL DE SQL-SERVER PARTE II
precio decimal(5,2)
constraint DF_libros_precio default (0),
constraint PK_libros_codigo
primary key clustered (codigo),
constraint UQ_libros_tituloautor
unique (titulo,codigoautor),
constraint FK_libros_editorial
foreign key (codigoeditorial)
references editoriales(codigo)
on update cascade,
constraint FK_libros_autores
foreign key (codigoautor)
references autores(codigo)
on update cascade,
constraint CK_libros_precio_positivo check (precio>=0)
);
inserte pantalla
Veamos las restricciones de "editoriales":
sp_helpconstraint editoriales;
inserte pantalla
84
MANUAL DE SQL-SERVER PARTE II
Aparece la restricción "primary key" para el campo "codigo" y la restricción "foreign key"
de "libros" "FK_libros_editorial" que referencia esta tabla.
Veamos las restricciones de "autores":
sp_helpconstraint autores;
inserte pantalla
Aparecen 4 restricciones: una restricción "check" para el campo "codigo", una restricción
"primary key" para el campo "codigo", una restricción "unique" para el campo "nombre" y
la restricción "foreign key" de "libros" "FK_libros_autores" que referencia esta tabla.
85
MANUAL DE SQL-SERVER PARTE II
Veamos las restricciones de "libros":
sp_helpconstraint libros;
inserte pantalla
Aparecen 6 restricciones: una restricción "check" sobre el campo "precio", una "default"
sobre el campo "precio", una restricción "foreign key" que establece el campo
"codigoeditorial" como clave externa que hace referencia al campo "codigo" de
"editoriales" y permite actualizaciones en cascada y no eliminaciones, una restricción
"foreign key" que establece el campo "codigoautor" como clave externa que hace
referencia al campo "codigo" de "autores" y permite actualizaciones en cascada y no
eliminaciones, una restricción "primary key" con índice agrupado para el campo "codigo" y
una restricción "unique" con índice no agrupado para los campos "titulo" y "codigoautor".
Recuerde que si definimos una restricción "foreign key" al crear una tabla, la tabla
referenciada debe existir, por ello creamos las tablas "editoriales" y "autores" antes que
"libros".
También debemos ingresar registros en las tablas "autores" y "editoriales" antes que en
"libros", a menos que deshabilitemos la restricción "foreign key".
Primer problema:
Un club de barrio tiene en su sistema 4 tablas:
- "socios": en la cual almacena documento, número, nombre y domicilio de
cada socio;
- "deportes": que guarda un código, nombre del deporte, día de la semana que
se dicta y documento
del profesor instructor;
- "profesores": donde se guarda el documento, nombre y domicilio de los
profesores e
86
MANUAL DE SQL-SERVER PARTE II
- "inscriptos": que almacena el número de socio, el código de deporte y si la
matricula está paga o
no.
1- Elimine las tablas si existen:
if object_id('inscriptos') is not null
drop table inscriptos;
if object_id('socios') is not null
drop table socios;
if object_id('profesores') is not null
drop table profesores;
if object_id('deportes') is not null
drop table deportes;
2- Considere que:
- un socio puede inscribirse en varios deportes, pero no dos veces en el
mismo.
- un socio tiene un documento único y un número de socio único.
- el documento del socio debe contener 8 dígitos.
- un deporte debe tener asignado un profesor que exista en "profesores" o
"null" si aún no tiene un
instructor definido.
- el campo "dia" de "deportes" puede ser: lunes, martes, miercoles, jueves,
viernes o sabado.
- el campo "dia" de "deportes" por defecto debe almacenar 'sabado'.
- un profesor puede ser instructor de varios deportes o puede no dictar ningún
deporte.
- un profesor no puede estar repetido en "profesores".
- el documento del profesor debe contener 8 dígitos.
- un inscripto debe ser socio, un socio puede no estar inscripto en ningún
deporte.
- una inscripción debe tener un valor en socio existente en "socios" y un
deporte que exista en
"deportes".
- el campo "matricula" de "inscriptos" debe aceptar solamente los caracteres 's'
o 'n'.
3- Cree las tablas con las restricciones necesarias:
create table profesores(
documento char(8) not null,
nombre varchar(30),
domicilio varchar(30),
constraint CK_profesores_documento_patron check (documento like '[0-9][0-
9][0-9][0-9][0-9][0-9][0-9][0-9]'),
constraint PK_profesores_documento
primary key (documento)
);
create table deportes(
87
MANUAL DE SQL-SERVER PARTE II
codigo tinyint identity,
nombre varchar(20) not null,
dia varchar(30)
constraint DF_deportes_dia default('sabado'),
profesor char(8),--documento del profesor
constraint CK_deportes_dia_lista check (dia in
('lunes','martes','miercoles','jueves','viernes','sabado')),
constraint PK_deportes_codigo
primary key (codigo)
);
create table socios(
numero int identity,
documento char(8),
nombre varchar(30),
domicilio varchar(30),
constraint CK_documento_patron check (documento like '[0-9][0-9][0-9][0-
9][0-9][0-9][0-9][0-9]'),
constraint PK_socios_numero
primary key nonclustered(numero),
constraint UQ_socios_documento
unique clustered(documento)
);
create table inscriptos(
numerosocio int not null,
codigodeporte tinyint,
matricula char(1),
constraint PK_inscriptos_numerodeporte
primary key clustered (numerosocio,codigodeporte),
constraint FK_inscriptos_deporte
foreign key (codigodeporte)
references deportes(codigo)
on update cascade,
constraint FK_inscriptos_socios
foreign key (numerosocio)
references socios(numero)
on update cascade
on delete cascade,
constraint CK_matricula_valores check (matricula in ('s','n'))
);
inserte pantalla
88
MANUAL DE SQL-SERVER PARTE II
4- Ingrese registros en "profesores":
insert into profesores values('21111111','Andres Acosta','Avellaneda 111');
insert into profesores values('22222222','Betina Bustos','Bulnes 222');
insert into profesores values('23333333','Carlos Caseros','Colon 333');
inserte pantalla
5- Ingrese registros en "deportes". Ingrese el mismo día para distintos
deportes, un deporte sin día confirmado, un deporte sin profesor definido:
insert into deportes values('basquet','lunes',null);
insert into deportes values('futbol','lunes','23333333');
insert into deportes values('natacion',null,'22222222');
insert into deportes values('padle',default,'23333333');
insert into deportes (nombre,dia) values('tenis','jueves');
inserte pantalla
89
MANUAL DE SQL-SERVER PARTE II
6- Ingrese registros en "socios":
insert into socios values('30111111','Ana Acosta','America 111');
insert into socios values('30222222','Bernardo Bueno','Bolivia 222');
insert into socios values('30333333','Camila Conte','Caseros 333');
insert into socios values('30444444','Daniel Duarte','Dinamarca 444');
inserte pantalla
7- Ingrese registros en "inscriptos". Inscriba a un socio en distintos deportes,
inscriba varios socios en el mismo deporte.
insert into inscriptos values(1,3,'s');
insert into inscriptos values(1,5,'s');
insert into inscriptos values(2,1,'s');
insert into inscriptos values(4,1,'n');
insert into inscriptos values(4,4,'s');
90
MANUAL DE SQL-SERVER PARTE II
inserte pantalla
8- Realice un "join" (del tipo que sea necesario) para mostrar todos los datos
del socio junto con el nombre de los deportes en los cuales está inscripto, el
día que tiene que asistir y el nombre del profesor que lo instruirá.
5 registros.
inserte pantalla
9- Realice la misma consulta anterior pero incluya los socios que no están
inscriptos en ningún deporte.
6 registros.
inserte pantalla
91
MANUAL DE SQL-SERVER PARTE II
10- Muestre todos los datos de los profesores, incluido el deporte que dicta y el
día, incluyendo
los profesores que no tienen asignado ningún deporte.
4 registros.
inserte pantalla
11- Muestre todos los deportes y la cantidad de inscriptos, incluyendo aquellos
deportes para los
cuales no hay inscriptos.
5 registros.
inserte pantalla
92
MANUAL DE SQL-SERVER PARTE II
12- Muestre las restricciones de "socios".
3 restricciones y 1 "foreign key" de "inscriptos" que la referencia.
inserte pantalla
13- Muestre las restricciones de "deportes".
3 restricciones y 1 "foreign key" de "inscriptos" que la referencia.
inserte pantalla
93
MANUAL DE SQL-SERVER PARTE II
14- Muestre las restricciones de "profesores".
2 restricciones.
inserte pantalla
15- Muestre las restricciones de "inscriptos".
4 restricciones.
inserte pantalla
94
MANUAL DE SQL-SERVER PARTE II
82 - Unión
El operador "union" combina el resultado de dos o más instrucciones "select" en
un único resultado.
Se usa cuando los datos que se quieren obtener pertenecen a distintas tablas y no
se puede acceder a ellos con una sola consulta.
Es necesario que las tablas referenciadas tengan tipos de datos similares, la
misma cantidad de campos y el mismo orden de campos en la lista de selección
de cada consulta. No se incluyen las filas duplicadas en el resultado, a menos que
coloque la opción "all".
Se deben especificar los nombres de los campos en la primera instrucción
"select".
Puede emplear la cláusula "order by".
Puede dividir una consulta compleja en varias consultas "select" y luego emplear
el operador "union" para combinarlas.
Una academia de enseñanza almacena los datos de los alumnos en una tabla
llamada "alumnos" y los datos de los profesores en otra denominada "profesores".
La academia necesita el nombre y domicilio de profesores y alumnos para
enviarles una tarjeta de invitación.
Para obtener los datos necesarios de ambas tablas en una sola consulta
necesitamos realizar una unión:
95
MANUAL DE SQL-SERVER PARTE II
select nombre, domicilio from alumnos
union
select nombre, domicilio from profesores;
El primer "select" devuelve el nombre y domicilio de todos los alumnos; el
segundo, el nombre y domicilio de todos los profesores.
Los encabezados del resultado de una unión son los que se especifican en el
primer "select".
Problema:
Una academia de enseñanza almacena los datos de los alumnos en una tabla llamada
"alumnos" y los datos de los profesores en otra denominada "profesores".
Eliminamos las tablas si existen:
if object_id('alumnos') is not null
drop table alumnos;
if object_id('profesores') is not null
drop table profesores;
Creamos las tablas:
create table profesores(
documento varchar(8) not null,
nombre varchar (30),
domicilio varchar(30),
primary key(documento)
);
create table alumnos(
documento varchar(8) not null,
nombre varchar (30),
domicilio varchar(30),
primary key(documento)
);
Ingresamos algunos registros:
insert into alumnos values('30000000','Juan Perez','Colon 123');
insert into alumnos values('30111111','Marta Morales','Caseros 222');
insert into alumnos values('30222222','Laura Torres','San Martin 987');
insert into alumnos values('30333333','Mariano Juarez','Avellaneda 34');
insert into alumnos values('23333333','Federico Lopez','Colon 987');
insert into profesores values('22222222','Susana Molina','Sucre 345');
insert into profesores values('23333333','Federico Lopez','Colon 987');
La academia necesita el nombre y domicilio de profesores y alumnos para enviarles una
tarjeta de invitación.
Empleamos el operador "union" para obtener dicha información de ambas tablas:
select nombre, domicilio from alumnos
union
select nombre, domicilio from profesores;
96
MANUAL DE SQL-SERVER PARTE II
Note que existe un profesor que también está presente en la tabla "alumnos"; dicho
registro aparece una sola vez en el resultado de "union". Si queremos que las filas
duplicadas aparezcan, debemos emplear "all":
select nombre, domicilio from alumnos
union all
select nombre, domicilio from profesores;
Ordenamos por domicilio:
select nombre, domicilio from alumnos
union
select nombre, domicilio from profesores
order by domicilio;
Podemos agregar una columna extra a la consulta con el encabezado "condicion" en la
que aparezca el literal "profesor" o "alumno" según si la persona es uno u otro:
select nombre, domicilio, 'alumno' as condicion from alumnos
union
select nombre, domicilio,'profesor' from profesores
order by condicion;
Primer problema:
Un supermercado almacena en una tabla denominada "proveedores" los datos
de las compañías que le
proveen de mercaderías; en una tabla llamada "clientes", los datos de los
comercios que le compran y
en otra tabla "empleados" los datos de los empleados.
1- Elimine las tablas si existen:
if object_id('clientes') is not null
drop table clientes;
if object_id('proveedores') is not null
drop table proveedores;
if object_id('empleados') is not null
drop table empleados;
2- Cree las tablas:
create table proveedores(
codigo int identity,
nombre varchar (30),
domicilio varchar(30),
primary key(codigo)
);
create table clientes(
codigo int identity,
nombre varchar (30),
domicilio varchar(30),
primary key(codigo)
97
MANUAL DE SQL-SERVER PARTE II
);
create table empleados(
documento char(8) not null,
nombre varchar(20),
apellido varchar(20),
domicilio varchar(30),
primary key(documento)
);
inserte pantalla
3- Ingrese algunos registros:
insert into proveedores values('Bebida cola','Colon 123');
insert into proveedores values('Carnes Unica','Caseros 222');
insert into proveedores values('Lacteos Blanca','San Martin 987');
insert into clientes values('Supermercado Lopez','Avellaneda 34');
insert into clientes values('Almacen Anita','Colon 987');
insert into clientes values('Garcia Juan','Sucre 345');
insert into empleados values('23333333','Federico','Lopez','Colon 987');
insert into empleados values('28888888','Ana','Marquez','Sucre 333');
insert into empleados values('30111111','Luis','Perez','Caseros 956');
4- El supermercado quiere enviar una tarjeta de salutación a todos los
proveedores, clientes y empleados y necesita el nombre y domicilio de todos
ellos. Emplee el operador "union" para obtener dicha información de las tres
tablas.
inserte pantalla
98
MANUAL DE SQL-SERVER PARTE II
5- Agregue una columna con un literal para indicar si es un proveedor, un
cliente o un empleado y
ordene por dicha columna.
inserte pantalla
83 - Agregar y eliminar campos ( alter table - add - drop)
"alter table" permite modificar la estructura de una tabla.
Podemos utilizarla para agregar, modificar y eliminar campos de una tabla.
Para agregar un nuevo campo a una tabla empleamos la siguiente sintaxis básica:
alter table NOMBRETABLA
99
MANUAL DE SQL-SERVER PARTE II
add NOMBRENUEVOCAMPO DEFINICION;
En el siguiente ejemplo agregamos el campo "cantidad" a la tabla "libros", de tipo
tinyint, que acepta valores nulos:
alter table libros
add cantidad tinyint;
Puede verificarse la alteración de la estructura de la tabla ejecutando el
procedimiento almacenado "sp_columns".
SQL Server no permite agregar campos "not null" a menos que se especifique un
valor por defecto:
alter table libros
add autor varchar(20) not null default 'Desconocido';
En el ejemplo anterior, se agregó una restricción "default" para el nuevo campo,
que puede verificarse ejecutando el procedimiento almacenado
"sp_helpconstraint".
Al agregar un campo puede especificarse que sea "identity" (siempre que no
exista otro campo identity).
Para eliminar campos de una tabla la sintaxis básica es la siguiente:
alter table NOMBRETABLA
drop column NOMBRECAMPO;
En el siguiente ejemplo eliminamos el campo "precio" de la tabla "libros":
alter table libros
drop column precio;
No pueden eliminarse los campos que son usados por un índice o tengan
restricciones. No puede eliminarse un campo si es el único en la tabla.
Podemos eliminar varios campos en una sola sentencia:
alter table libros
drop column editorial,edicion;
Primer problema:
Trabaje con una tabla llamada "empleados".
1- Elimine la tabla, si existe, créela y cargue un registro:
if object_id('empleados') is not null
10
MANUAL DE SQL-SERVER PARTE II
drop table empleados;
create table empleados(
apellido varchar(20),
nombre varchar(20),
domicilio varchar(30),
fechaingreso datetime
);
insert into empleados(apellido,nombre) values ('Rodriguez','Pablo');
2- Agregue el campo "sueldo", de tipo decimal(5,2).
inserte pantalla
3- Verifique que la estructura de la tabla ha cambiado.
inserte pantalla
10
MANUAL DE SQL-SERVER PARTE II
4- Agregue un campo "codigo", de tipo int con el atributo "identity".
inserte pantalla
5- Intente agregar un campo "documento" no nulo.
No es posible, porque SQL Server no permite agregar campos "not null" a menos que
se especifique un valor por defecto.
inserte pantalla
10
MANUAL DE SQL-SERVER PARTE II
6- Agregue el campo del punto anterior especificando un valor por defecto:
alter table empleados
add documento char(8) not null default '00000000';
inserte pantalla
7- Verifique que la estructura de la tabla ha cambiado.
inserte pantalla
10
MANUAL DE SQL-SERVER PARTE II
8- Elimine el campo "sueldo".
inserte pantalla
9- Verifique la eliminación:
sp_columns empleados;
inserte pantalla
10
MANUAL DE SQL-SERVER PARTE II
10- Intente eliminar el campo "documento".
no lo permite.
inserte pantalla
11- Elimine los campos "codigo" y "fechaingreso" en una sola sentencia.
inserte pantalla
10
MANUAL DE SQL-SERVER PARTE II
12- Verifique la eliminación de los campos:
sp_columns empleados;
inserte pantalla
84 - Alterar campos (alter table - alter)
Hemos visto que "alter table" permite modificar la estructura de una tabla. También
podemos utilizarla para modificar campos de una tabla.
La sintaxis básica para modificar un campo existente es la siguiente:
alter table NOMBRETABLA
alter column CAMPO NUEVADEFINICION;
10
MANUAL DE SQL-SERVER PARTE II
Modificamos el campo "titulo" extendiendo su longitud y para que NO admita
valores nulos:
alter table libros
alter column titulo varchar(40) not null;
En el siguiente ejemplo alteramos el campo "precio" de la tabla "libros" que fue
definido "decimal(6,2) not null" para que no acepte valores nulos:
alter table libros
alter column precio decimal(6,2) null;
SQL Server tiene algunas excepciones al momento de modificar los campos. No
permite modificar:
- campos de tipo text, image, ntext y timestamp.
- un campo que es usado en un campo calculado.
- campos que son parte de índices o tienen restricciones, a menos que el cambio
no afecte al índice o a la restricción, por ejemplo, se puede ampliar la longitud de
un campo de tipo caracter.
- agregando o quitando el atributo "identity".
- campos que afecten a los datos existentes cuando una tabla contiene registros
(ejemplo: un campo contiene valores nulos y se pretende redefinirlo como "not
null"; un campo int guarda un valor 300 y se pretende modificarlo a tinyint, etc.).
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;
Creamos la tabla:
create table libros(
codigo int identity,
titulo varchar(30),
autor varchar(30),
editorial varchar(15),
precio decimal(6,2) not null default 0
);
Ingresamos algunos registros:
10
MANUAL DE SQL-SERVER PARTE II
insert into libros
values('El aleph','Borges','Planeta',20);
insert into libros
values('Java en 10 minutos',null,'Siglo XXI',30);
insert into libros
values('Uno','Richard Bach','Planeta',15);
insert into libros
values('Martin Fierro','Jose Hernandez',null,30);
insert into libros
values('Aprenda PHP','Mario Molina','Emece',25);
Vamos a efectuar diferentes modificaciones a los campos de esta tabla. Luego de cada
una podemos ver la estructura de la tabla para controlar si los cambios se realizaron o no
empleando el procedimiento almacenado "sp_columns".
Modificamos el campo "titulo" para que acepte una cadena más larga y no admita valores
nulos:
alter table libros
alter column titulo varchar(40) not null;
Si intentamos modificar el campo "autor" para que no admita valores nulos SQL Server no
lo permite porque hay registros con valor nulo en "autor".
Eliminamos tal registro y realizamos la modificación:
delete from libros where autor is null;
alter table libros
alter column autor varchar(30) not null;
Intentamos quitar el atributo "identity" del campo "codigo" y lo redefinimos como "smallint":
alter table libros
alter column codigo smallint;
No aparece mensaje de error pero no se realizó el cambio completo, controlémoslo:
sp_columns libros;
el campo "codigo" es "smallint pero aún es "identity".
Aprendimos que no se puede modificar el tipo de dato o atributos de un campo que tiene
una restricción si el cambio afecta a la restricción; pero si el cambio no afecta a la
restricción, si se realiza:
alter table libros
alter column precio decimal(6,2) null;
El campo "precio" fue alterado para que acepte valores nulos:
Primer problema:
Trabaje con una tabla llamada "empleados".
10
MANUAL DE SQL-SERVER PARTE II
1- Elimine la tabla, si existe y créela:
if object_id('empleados') is not null
drop table empleados;
create table empleados(
legajo int not null,
documento char(7) not null,
nombre varchar(10),
domicilio varchar(30),
ciudad varchar(20) default 'Buenos Aires',
sueldo decimal(6,2),
cantidadhijos tinyint default 0,
primary key(legajo)
);
2- Modifique el campo "nombre" extendiendo su longitud.
3- Controle la modificación:
sp_columns empleados;
inserte pantalla
4- Modifique el campo "sueldo" para que no admita valores nulos.
inserte pantalla
10
MANUAL DE SQL-SERVER PARTE II
4- Modifique el campo "documento" ampliando su longitud a 8 caracteres.
inserte pantalla
5- Intente modificar el tipo de datos del campo "legajo" a "tinyint":
alter table empleados
alter column legajo tinyint not null;
No se puede porque tiene una restricción.
inserte pantalla
11
MANUAL DE SQL-SERVER PARTE II
6- Ingrese algunos registros, uno con "nombre" nulo:
insert into empleados values(1,'22222222','Juan Perez','Colon
123','Cordoba',500,3);
insert into empleados values(2,'30000000',null,'Sucre 456','Cordoba',600,2);
inserte pantalla
7- Intente modificar el campo "nombre" para que no acepte valores nulos:
alter table empleados
alter column nombre varchar(30) not null;
No se puede porque hay registros con ese valor.
inserte pantalla
11
MANUAL DE SQL-SERVER PARTE II
8- Elimine el registro con "nombre" nulo y realice la modificación del punto 7:
delete from empleados where nombre is null;
alter table empleados
alter column nombre varchar(30) not null;
inserte pantalla
9- Modifique el campo "ciudad" a 10 caracteres.
inserte pantalla
11
MANUAL DE SQL-SERVER PARTE II
10- Intente agregar un registro con el valor por defecto para "ciudad":
insert into empleados values(3,'33333333','Juan Perez','Sarmiento
856',default,500,4);
No se puede porque el campo acepta 10 caracteres y el valor por defecto tiene
12 caracteres.
inserte pantalla
11- Modifique el campo "ciudad" sin que afecte la restricción dándole una
longitud de 15 caracteres.
inserte pantalla
11
MANUAL DE SQL-SERVER PARTE II
12- Agregue el registro que no pudo ingresar en el punto 10:
insert into empleados values(3,'33333333','Juan Perez','Sarmiento
856',default,500,4);
inserte pantalla
13- Intente agregar el atributo identity de "legajo".
No se puede agregar este atributo.
inserte pantalla
11
MANUAL DE SQL-SERVER PARTE II
85 - Agregar campos y restricciones (alter table)
Podemos agregar un campo a una tabla y en el mismo momento aplicarle una
restricción.
Para agregar un campo y establecer una restricción, la sintaxis básica es la
siguiente:
alter table TABLA
add CAMPO DEFINICION
constraint NOMBRERESTRICCION TIPO;
Agregamos a la tabla "libros", el campo "titulo" de tipo varchar(30) y una restricción
"unique" con índice agrupado:
alter table libros
add titulo varchar(30)
constraint UQ_libros_autor unique clustered;
Agregamos a la tabla "libros", el campo "codigo" de tipo int identity not null y una
restricción "primary key" con índice no agrupado:
alter table libros
add codigo int identity not null
constraint PK_libros_codigo primary key nonclustered;
Agregamos a la tabla "libros", el campo "precio" de tipo decimal(6,2) y una
restricción "check":
alter table libros
11
MANUAL DE SQL-SERVER PARTE II
add precio decimal(6,2)
constraint CK_libros_precio check (precio>=0);
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;
Creamos la tabla con la siguiente estructura:
create table libros(
autor varchar(30),
editorial varchar(15)
);
Agregamos el campo "titulo" de tipo varchar(30) y una restricción "unique" con índice
agrupado:
alter table libros
add titulo varchar(30)
constraint UQ_libros_autor unique clustered;
Veamos si la estructura cambió:
sp_columns libros;
Agregamos el campo "codigo" de tipo int identity not null y en la misma sentencia una
restricción "primary key" con índice no agrupado:
alter table libros
add codigo int identity not null
constraint PK_libros_codigo primary key nonclustered;
Agregamos el campo "precio" de tipo decimal(6,2) y una restricción "check" que no
permita valores negativos para dicho campo:
alter table libros
add precio decimal(6,2)
constraint CK_libros_precio check (precio>=0);
Vemos las restricciones:
sp_helpconstraint libros;
inserte pantalla
11
MANUAL DE SQL-SERVER PARTE II
Primer problema:
Trabaje con una tabla llamada "empleados".
1- Elimine la tabla, si existe y créela:
if object_id('empleados') is not null
drop table empleados;
create table empleados(
documento char(8) not null,
nombre varchar(10),
domicilio varchar(30),
ciudad varchar(20) default 'Buenos Aires'
);
2- Agregue el campo "legajo" de tipo int identity y una restricción "primary
key":
alter table empleados
add legajo int identity
constraint PK_empleados_legajo primary key;
3- Vea si la estructura cambió y si se agregó la restricción:
sp_columns empleados;
exec sp_helpconstraint empleados;
inserte pantalla
11
MANUAL DE SQL-SERVER PARTE II
4- Agregue el campo "hijos" de tipo tinyint y en la misma sentencia una
restricción "check" que no permita valores superiores a 30:
alter table empleados
add hijos tinyint
constraint CK_empleados_hijos check (hijos<=30);
inserte pantalla
5- Ingrese algunos registros:
insert into empleados values('22222222','Juan Lopez','Colon
123','Cordoba',2);
insert into empleados values('23333333','Ana Garcia','Sucre
435','Cordoba',3);
inserte pantalla
11
MANUAL DE SQL-SERVER PARTE II
6- Intente agregar el campo "sueldo" de tipo decimal(6,2) no nulo y una
restricción "check" que no permita valores negativos para dicho campo:
alter table empleados
add sueldo decimal(6,2) not null
constraint CK_empleados_sueldo check (sueldo>=0);
No lo permite porque no damos un valor por defecto para dicho campo no nulo
y los registros existentes necesitan cargar un valor.
inserte pantalla
7- Agregue el campo "sueldo" de tipo decimal(6,2) no nulo, una restricción
"check" que no permita valores negativos para dicho campo y una restricción
"default" que almacene el valor "0":
alter table empleados
add sueldo decimal(6,2) not null
11
MANUAL DE SQL-SERVER PARTE II
constraint CK_empleados_sueldo check (sueldo>=0)
constraint DF_empleados_sueldo default 0;
inserte pantalla
8- Recupere los registros:
select *from empleados;
inserte pantalla
9- Vea la nueva estructura de la tabla:
sp_columns empleados;
inserte pantalla
12
MANUAL DE SQL-SERVER PARTE II
10- Vea las restricciones:
sp_helpconstraint empleados;
inserte pantalla
86 - Campos calculados
Un campo calculado es un campo que no se almacena físicamente en la tabla.
SQL Server emplea una fórmula que detalla el usuario al definir dicho campo para
calcular el valor según otros campos de la misma tabla.
Un campo calculado no puede:
12
MANUAL DE SQL-SERVER PARTE II
- definirse como "not null".
- ser una subconsulta.
- tener restricción "default" o "foreign key".
- insertarse ni actualizarse.
Puede ser empleado como llave de un índice o parte de restricciones "primary
key" o "unique" si la expresión que la define no cambia en cada consulta.
Creamos un campo calculado denominado "sueldototal" que suma al sueldo
básico de cada empleado la cantidad abonada por los hijos (100 por cada hijo):
create table empleados(
documento char(8),
nombre varchar(10),
domicilio varchar(30),
sueldobasico decimal(6,2),
cantidadhijos tinyint default 0,
sueldototal as sueldobasico + (cantidadhijos*100)
);
También se puede agregar un campo calculado a una tabla existente:
alter table NOMBRETABLA
add NOMBRECAMPOCALCULADO as EXPRESION;
alter table empleados
add sueldototal as sueldo+(cantidadhijos*100);
Los campos de los cuales depende el campo calculado no pueden eliminarse, se
debe eliminar primero el campo calculado.
Problema:
Trabajamos con la tablas "empleados".
Eliminamos la tabla, si existe, y la creamos:
if object_id('empleados') is not null
drop table empleados;
create table empleados(
documento char(8),
nombre varchar(10),
domicilio varchar(30),
sueldobasico decimal(6,2),
hijos tinyint not null default 0,
sueldototal as sueldobasico + (hijos*100)
);
12
MANUAL DE SQL-SERVER PARTE II
El campo "sueldototal" es un campo calculado que suma al sueldo básico de cada
empleado y la cantidad abonada por los hijos (100 por cada hijo).
No puede ingresarse valor para dicho campo:
insert into empleados values('22222222','Juan Perez','Colon 123',300,2);
insert into empleados values('23333333','Ana Lopez','Sucre 234',500,0);
Veamos los registros:
select *from empleados;
Veamos lo que sucede si actualizamos un registro:
update empleados set hijos=1 where documento='23333333';
select *from empleados;
Recuperamos los registros:
select *from empleados;
el campo calculado "sueldototal" recalcula los valores para cada registro
automáticamente.
Agregamos un campo calculado:
alter table empleados
add salariofamiliar as hijos*100;
Veamos la estructura de la tabla:
sp_columns empleados;
Recuperemos los registros:
select *from empleados;
Primer problema:
Un comercio almacena los datos de los artículos para la venta en una tabla
denominada "articulos".
1- Elimine la tabla, si existe y créela nuevamente:
if object_id('articulos') is not null
drop table articulos;
create table articulos(
codigo int identity,
descripcion varchar(30),
precio decimal(5,2) not null,
cantidad smallint not null default 0,
12
MANUAL DE SQL-SERVER PARTE II
montototal as precio *cantidad
);
El campo "montototal" es un campo calculado que multiplica el precio de cada
artículo por la
cantidad disponible.
2- Intente ingresar un registro con valor para el campo calculado:
insert into articulos values('birome',1.5,100,150);
No lo permite.
inserte pantalla
3- Ingrese algunos registros:
insert into articulos values('birome',1.5,100);
insert into articulos values('cuaderno 12 hojas',4.8,150);
insert into articulos values('lapices x 12',5,200);
inserte pantalla
12
MANUAL DE SQL-SERVER PARTE II
4- Recupere los registros:
select *from articulos;
inserte pantalla
5- Actualice un precio y recupere los registros:
update articulos set precio=2 where descripcion='birome';
select *from articulos;
el campo calculado "montototal" recalcula los valores para cada registro
automáticamente.
inserte pantalla
12
MANUAL DE SQL-SERVER PARTE II
6- Actualice una cantidad y vea el resultado:
update articulos set cantidad=200 where descripcion='birome';
select *from articulos;
el campo calculado "montototal" recalcula sus valores.
inserte pantalla
7- Intente actualizar un campo calculado:
update articulos set montototal=300 where descripcion='birome';
No lo permite.
inserte pantalla
12
MANUAL DE SQL-SERVER PARTE II
87 - Tipo de dato definido por el usuario (crear - informacion)
Cuando definimos un campo de una tabla debemos especificar el tipo de datos,
sabemos que los tipos de datos especifican el tipo de información (caracteres,
números, fechas) que pueden almacenarse en un campo. SQL Server proporciona
distintos tipos de datos del sistema (char, varchar, int, decimal, datetime, etc.) y
permite tipos de datos definidos por el usuario siempre que se basen en los tipos
de datos existentes.
Se pueden crear y eliminar tipos de datos definidos por el usuario.
Se emplean cuando varias tablas deben almacenar el mismo tipo de datos en un
campo y se quiere garantizar que todas tengan el mismo tipo y longitud.
Para darle un nombre a un tipo de dato definido por el usuario debe considerar las
mismas reglas que para cualquier identificador. No puede haber dos objetos con
igual nombre en la misma base de datos.
Para crear un tipo de datos definido por el usuario se emplea el procedimiento
almacenado del sistema "sp_addtype". Sintaxis básica:
exec sp_addtype NOMBRENUEVOTIPO, 'TIPODEDATODELSISTEMA',
'OPCIONNULL';
Creamos un tipo de datos definido por el usuario llamado "tipo_documento" que
admite valores nulos:
12
MANUAL DE SQL-SERVER PARTE II
exec sp_addtype tipo_documento, 'char(8)', 'null';
Ejecutando el procedimiento almacenado "sp_help" junto al nombre del tipo de
dato definido por el usuario se obtiene información del mismo (nombre, el tipo de
dato en que se basa, la longitud, si acepta valores nulos, si tiene valor por defecto
y reglas asociadas).
También podemos consultar la tabla "systypes" en la cual se almacena
información de todos los tipos de datos:
select name from systypes;
Problema:
Una academia de enseñanza almacena los datos de sus alumnos en una tabla llamada
"alumnos".
Borramos la tabla alumno por si otro usuario creo tipos de datos definidos para la misma:
if object_id('alumnos') is not null
drop table alumnos;
Queremos definir un nuevo tipo de dato llamado "tipo_documento". Primero debemos
eliminarlo, si existe para volver a crearlo. Para ello empleamos esta sentencia que
explicaremos en el siguiente capítulo:
if exists (select *from systypes
where name = 'tipo_documento')
exec sp_droptype tipo_documento;
Creamos un tipo de dato definido por el usuario llamado "tipo_documento" basado en el
tipo "char" que permita 8 caracteres y valores nulos:
exec sp_addtype tipo_documento, 'char(8)', 'null';
Ejecutamos el procedimiento almacenado "sp_help" junto al nombre del tipo de dato
definido anteriormente para obtener información del mismo:
sp_help tipo_documento;
Aparecen varias columnas: el nombre, el tipo de dato en que se basa, la longitud, si
acepta valores nulos; las columnas "default_name" y "rule_name" muestran "none" porque
no tiene valores predeterminados ni reglas asociados.
Creamos la tabla "alumnos" con 2 campos: documento (del tipo de dato definido
anteriormente) y nombre (30 caracteres). Antes la eliminamos (si existe):
create table alumnos(
documento tipo_documento,
nombre varchar(30)
);
12
MANUAL DE SQL-SERVER PARTE II
Ingresamos un registro con valor para "documento" permitido por el tipo de dato:
insert into alumnos values('12345678','Ana Acosta');
No podríamos ingresar en "documento" una cadena de 9 caracteres.
Primer problema:
Un comercio almacena los datos de sus empleados en una tabla denominada
"empleados".
1- Elimine la tabla si existe:
if object_id ('empleados') is not null
drop table empleados;
2- Defina un nuevo tipo de dato llamado "tipo_legajo". Primero debe eliminarlo
(si existe) para volver a crearlo. Para ello emplee esta sentencia que
explicaremos en el siguiente capítulo:
if exists (select name from systypes
where name = 'tipo_legajo')
exec sp_droptype tipo_legajo;
3- Cree un tipo de dato definido por el usuario llamado "tipo_legajo" basado en
el tipo "char" de 4 caracteres que no permita valores nulos.
inserte pantalla
4- Ejecute el procedimiento almacenado "sp_help" junto al nombre del tipo de
dato definido
anteriormente para obtener información del mismo.
inserte pantalla
12
MANUAL DE SQL-SERVER PARTE II
5- Cree la tabla "empleados" con 3 campos: legajo (tipo_legajo), documento
(char de 8) y nombre (30
caracteres):
create table empleados(
legajo tipo_legajo,
documento char(8),
nombre varchar(30)
);
inserte pantalla
6- Intente ingresar un registro con valores por defecto:
insert into empleados default values;
No se puede porque el campo "tipo_legajo" no admite valores nulos y no tiene
definido un valor por
13
MANUAL DE SQL-SERVER PARTE II
defecto.
inserte pantalla
7- Ingrese un registro con valores válidos.
inserte pantalla
88 - Tipo de dato definido por el usuario (asociación de reglas)
Se puede asociar una regla a un tipo de datos definido por el usuario. Luego de
crear la regla se establece la asociación; la sintaxis es la siguiente:
exec sp_bindrule NOMBREREGLA,
'TIPODEDATODEFINIDOPORELUSUARIO', 'futureonly';
13
MANUAL DE SQL-SERVER PARTE II
El parámetro "futureonly" es opcional, especifica que si existen campos (de
cualquier tabla) con este tipo de dato, no se asocien a la regla; si creamos una
nueva tabla con este tipo de dato, si deberán cumplir la regla. Si no se especifica
este parámetro, todos los campos de este tipo de dato, existentes o que se creen
posteriormente (de cualquier tabla), quedan asociados a la regla.
Recuerde que SQL Server NO controla los datos existentes para confirmar que
cumplen con la regla, si no los cumple, la regla se asocia igualmente; pero al
ejecutar una instrucción "insert" o "update" muestra un mensaje de error.
Si asocia una regla a un tipo de dato definido por el usuario que tiene otra regla
asociada, esta última la reemplaza.
Para quitar la asociación, empleamos el mismo procedimiento almacenado que
aprendimos cuando quitamos asociaciones a campos, ejecutamos el
procedimiento almacenado "sp_unbindrule" seguido del nombre del tipo de dato al
que está asociada la regla:
exec sp_unbindrule 'TIPODEDATODEFINIDOPORELUSUARIO';
Si asocia una regla a un campo cuyo tipo de dato definido por el usuario ya tiene
una regla asociada, la nueva regla se aplica al campo, pero el tipo de dato
continúa asociado a la regla. La regla asociada al campo prevalece sobre la
asociada al tipo de dato. Por ejemplo, tenemos un campo "precio" de un tipo de
dato definido por el usuario "tipo_precio", este tipo de dato tiene asociada una
regla "RG_precio0a99" (precio entre 0 y 99), luego asociamos al campo "precio" la
regla "RG_precio100a500" (precio entre 100 y 500); al ejecutar una instrucción
"insert" admitirá valores entre 100 y 500, es decir, tendrá en cuenta la regla
asociada al campo, aunque vaya contra la regla asociada al tipo de dato.
Un tipo de dato definido por el usuario puede tener una sola regla asociada.
Cuando obtenemos información del tipo da dato definido por el usuario ejecutando
"sp_help", en la columna "rule_name" se muestra el nombre de la regla asociada a
dicho tipo de dato; muestran "none" cuando no tiene regla asociada.
Problema:
Una academia de enseñanza almacena los datos de sus alumnos en una tabla llamada
"alumnos" y en otra tabla denominada "docentes" los datos de los profesores.
Eliminamos ambas tablas, si existen:
if object_id('alumnos') is not null
drop table alumnos;
if object_id('docentes') is not null
drop table docentes;
13
MANUAL DE SQL-SERVER PARTE II
Queremos definir un nuevo tipo de dato llamado "tipo_documento". Primero debemos
eliminarlo, si existe para volver a crearlo. Para ello empleamos esta sentencia que
explicaremos próximamente:
if exists (select *from systypes
where name = 'tipo_documento')
exec sp_droptype tipo_documento;
Creamos un tipo de dato definido por el usuario llamado "tipo_documento" basado en el
tipo "char" que permita 8 caracteres y valores nulos:
exec sp_addtype tipo_documento, 'char(8)', 'null';
Ejecutamos el procedimiento almacenado "sp_help" junto al nombre del tipo de dato
definido anteriormente para obtener información del mismo:
sp_help tipo_documento;
Aparecen varias columnas que nos informan, entre otras cosas: el nombre
(tipo_documento), el tipo de dato en que se basa (char), la longitud (8), si acepta valores
nulos (yes); las columnas "default_name" y "rule_name" muestran "none" porque no tiene
valores predeterminados ni reglas asociados.
Creamos la tabla "alumnos" con 2 campos: documento (del tipo de dato definido
anteriormente) y nombre (30 caracteres):
create table alumnos(
documento tipo_documento,
nombre varchar(30)
);
Eliminamos si existe, la regla "RG_documento":
if object_id ('RG_documento') is not null
drop rule RG_documento;
Creamos la regla que permita 8 caracteres que solamente pueden ser dígitos del 0 al 5
para el primer dígito y de 0 al 9 para los siguientes:
create rule RG_documento
as @documento like '[0-5][0-9][0-9][0-9][0-9][0-9][0-9][0-9]';
Asociamos la regla al tipo de datos "tipo_documento" especificando que solamente se
aplique a los futuros campos de este tipo:
exec sp_bindrule RG_documento, 'tipo_documento', 'futureonly';
Ejecutamos el procedimiento almacenado "sp_helpconstraint" para verificar que no se
aplicó a la tabla "alumnos" porque especificamos la opción "futureonly":
sp_helpconstraint alumnos;
13
MANUAL DE SQL-SERVER PARTE II
Creamos la tabla "docentes" con 2 campos: documento (del tipo de dato definido
anteriormente) y nombre (30 caracteres):
create table docentes(
documento tipo_documento,
nombre varchar(30)
);
Verificamos que se aplicó la regla en la nueva tabla:
sp_helpconstraint docentes;
Ingresamos registros en "alumnos" con valores para documento que infrinjan la regla:
insert into alumnos values('a111111','Ana Acosta');
Lo acepta porque en esta tabla no se aplica la regla. Pero no podríamos ingresar un valor
como el anterior en la tabla "docentes" la cual si tiene asociada la regla.
Quitamos la asociación:
exec sp_unbindrule 'tipo_documento';
Volvemos a asociar la regla, ahora sin el parámetro "futureonly":
exec sp_bindrule RG_documento, 'tipo_documento';
Note que hay valores que no cumplen la regla, recuerde que SQL Server NO controla los
datos existentes al momento de asociar una regla; pero si al ejecutar un "insert" o
"update".
Verificamos que se aplicó la regla en ambas tablas:
sp_helpconstraint docentes;
exec sp_helpconstraint alumnos;
Eliminamos si existe, la regla "RG_documento2":
if object_id ('RG_documento2') is not null
drop rule RG_documento2;
Creamos la regla llamada "RG_documento2" que permita 8 caracteres que solamente
pueden ser dígitos del 0 al 9 para todas las posiciones:
create rule RG_documento2
as @documento like '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]';
Asociamos la regla al tipo de datos "tipo_documento" (ya tiene una regla asociada):
exec sp_bindrule RG_documento2, 'tipo_documento';
Veamos si la asociación fue reemplazada en el tipo de datos:
13
MANUAL DE SQL-SERVER PARTE II
sp_help tipo_documento;
Note que ahora en la columna "Rule_name" muestra "RG_documento2".
Veamos si la asociación fue reemplazada en las tablas:
sp_helpconstraint alumnos;
exec sp_helpconstraint docentes;
Note que ahora la regla asociada es "RG_documento2".
Asociamos la regla "RG_documento" al campo "documento" de "alumnos":
exec sp_bindrule RG_documento, 'alumnos.documento';
Verificamos que "documento" de "alumnos" tiene asociada la regla "RG_documento":
sp_helpconstraint alumnos;
Verificamos que el tipo de dato "tipo_documento" tiene asociada la regla
"RG_documento2":
sp_help tipo_documento;
Intente ingresar un valor para "documento" aceptado por la regla asociada al tipo de dato
pero no por la regla asociada al campo:
insert into alumnos values ('77777777','Juan Lopez');
No lo permite.
Ingrese un valor para "documento" aceptado por la regla asociada al campo:
insert into alumnos values ('55555555','Juan Lopez');
Primer problema:
Un comercio almacena los datos de sus empleados en una tabla denominada
"empleados" y en otra
llamada "clientes" los datos de sus clientes".
1- Elimine ambas tablas, si existen:
if object_id ('empleados') is not null
drop table empleados;
if object_id ('clientes') is not null
drop table clientes;
2- Defina un nuevo tipo de dato llamado "tipo_año". Primero debe eliminarlo,
si existe, para volver a crearlo. Para ello emplee esta sentencia que
explicaremos en el siguiente capítulo:
if exists (select *from systypes
13
MANUAL DE SQL-SERVER PARTE II
where name = 'tipo_año')
exec sp_droptype tipo_año;
inserte pantalla
3- Cree un tipo de dato definido por el usuario llamado "tipo_año" basado en el
tipo "int" que permita valores nulos:
exec sp_addtype tipo_año, 'int','null';
inserte pantalla
4- Ejecute el procedimiento almacenado "sp_help" junto al nombre del tipo de
dato definido anteriormente para obtener información del mismo:
sp_help tipo_año;
13
MANUAL DE SQL-SERVER PARTE II
5- Cree la tabla "empleados" con 3 campos: documento (char de 8), nombre
(30 caracteres) y
añoingreso (tipo_año):
create table empleados(
documento char(8),
nombre varchar(30),
añoingreso tipo_año
);
inserte pantalla
6- Elimine la regla llamada "RG_año" si existe:
if object_id ('RG_año') is not null
drop rule RG_año;
13
MANUAL DE SQL-SERVER PARTE II
inserte pantalla
7- Cree la regla que permita valores integer desde 1990 (año en que se
inauguró el comercio) y el
año actual:
create rule RG_año
as @año between 1990 and datepart(year,getdate());
inserte pantalla
8- Asocie la regla al tipo de datos "tipo_año" especificando que solamente se
aplique a los futuros campos de este tipo:
exec sp_bindrule RG_año, 'tipo_año', 'futureonly';
inserte pantalla
13
MANUAL DE SQL-SERVER PARTE II
9- Vea si se aplicó a la tabla empleados:
sp_helpconstraint empleados;
No se aplicó porque especificamos la opción "futureonly":
inserte pantalla
10- Cree la tabla "clientes" con 3 campos: nombre (30 caracteres), añoingreso
(tipo_año) y domicilio
(30 caracteres):
create table clientes(
documento char(8),
nombre varchar(30),
añoingreso tipo_año
);
inserte pantalla
13
MANUAL DE SQL-SERVER PARTE II
11- Vea si se aplicó la regla en la nueva tabla:
sp_helpconstraint clientes;
Si aparece.
inserte pantalla
12- Ingrese registros con valores para el año que infrinjan la regla en la tabla
"empleados":
insert into empleados values('11111111','Ana Acosta',2050);
select *from empleados;
Lo acepta porque en esta tabla no se aplica la regla.
inserte pantalla
14
MANUAL DE SQL-SERVER PARTE II
13- Intente ingresar en la tabla "clientes" un valor de fecha que infrinja la
regla:
insert into clientes values('22222222','Juan Perez',2050);
No lo permite.
inserte pantalla
14- Quite la asociación de la regla con el tipo de datos:
exec sp_unbindrule 'tipo_año';
inserte pantalla
14
MANUAL DE SQL-SERVER PARTE II
15- Vea si se quitó la asociación:
sp_helpconstraint clientes;
Si se quitó.
inserte pantalla
16- Vuelva a asociar la regla, ahora sin el parámetro "futureonly":
exec sp_bindrule RG_año, 'tipo_año';
Note que hay valores que no cumplen la regla pero SQL Server NO lo verifica al
momento de asociar una regla.
inserte pantalla
14
MANUAL DE SQL-SERVER PARTE II
17- Intente agregar una fecha de ingreso fuera del intervalo que admite la
regla en cualquiera de las tablas (ambas tienen la asociación):
insert into empleados values('33333333','Romina Guzman',1900);
Mensaje de error.
inserte pantalla
18- Vea la información del tipo de dato:
exec sp_help tipo_año;
En la columna que hace referencia a la regla asociada aparece "RG_año".
inserte pantalla
14
MANUAL DE SQL-SERVER PARTE II
19- Elimine la regla llamada "RG_añonegativo", si existe:
if object_id ('RG_añonegativo') is not null
drop rule RG_añonegativo;
inserte pantalla
20- Cree una regla llamada "RG_añonegativo" que admita valores entre -2000
y -1:
create rule RG_añonegativo
as @año between -2000 and -1;
inserte pantalla
14
MANUAL DE SQL-SERVER PARTE II
21- Asocie la regla "RG_añonegativo" al campo "añoingreso" de la tabla
"clientes":
exec sp_bindrule RG_añonegativo, 'clientes.añoingreso';
inserte pantalla
22- Vea si se asoció:
sp_helpconstraint clientes;
Se asoció.
inserte pantalla
14
MANUAL DE SQL-SERVER PARTE II
23- Verifique que no está asociada al tipo de datos "tipo_año":
sp_help tipo_año;
No, tiene asociada la regla "RG_año".
inserte pantalla
24- Intente ingresar un registro con valor '-1900' para el campo "añoingreso"
de "empleados":
insert into empleados values('44444444','Pedro Perez',-1900);
No lo permite por la regla asociada al tipo de dato.
inserte pantalla
14
MANUAL DE SQL-SERVER PARTE II
25- Ingrese un registro con valor '-1900' para el campo "añoingreso" de
"clientes" y recupere los
registros de dicha tabla:
insert into clientes values('44444444','Pedro Perez',-1900);
select *from clientes;
Note que se ingreso, si bien el tipo de dato de "añoingreso" tiene asociada una
regla que no admite
tal valor, el campo tiene asociada una regla que si lo admite y ésta prevalece.
inserte pantalla
89 - Tipo de dato definido por el usuario (valores predeterminados)
14
MANUAL DE SQL-SERVER PARTE II
Se puede asociar un valor predeterminado a un tipo de datos definido por el
usuario. Luego de crear un valor predeterminado, se puede asociar a un tipo de
dato definido por el usuario con la siguiente sintaxis:
exec sp_bindefault NOMBREVALORPREDETERMINADO,
'TIPODEDATODEFINIDOPORELUSUARIO','futureonly';
El parámetro "futureonly" es opcional, especifica que si existen campos (de
cualquier tabla) con este tipo de dato, no se asocien al valor predeterminado; si
creamos una nueva tabla con este tipo de dato, si estará asociado al valor
predeterminado. Si no se especifica este parámetro, todos los campos de este tipo
de dato, existentes o que se creen posteriormente (de cualquier tabla), quedan
asociados al valor predeterminado.
Si asocia un valor predeterminado a un tipo de dato definido por el usuario que
tiene otro valor predeterminado asociado, el último lo reemplaza.
Para quitar la asociación, empleamos el mismo procedimiento almacenado que
aprendimos cuando quitamos asociaciones a campos:
sp_unbindefault 'TIPODEDATODEFINIDOPORELUSUARIO';
Debe tener en cuenta que NO se puede aplicar una restricción "default" en un
campo con un tipo de datos definido por el usuario si dicho campo o tipo de dato
tienen asociado un valor predeterminado.
Si un campo de un tipo de dato definido por el usuario tiene una restricción
"default" y luego se asocia un valor predeterminado al tipo de dato, el valor
predeterminado no queda asociado en el campo que tiene la restricción "default".
Un tipo de dato definido por el usuario puede tener un solo valor predeterminado
asociado.
Cuando obtenemos información del tipo da dato definido por el usuario ejecutando
"sp_help", en la columna "default_name" se muestra el nombre del valor
predeterminado asociado a dicho tipo de dato; muestra "none" cuando no tiene
ningún valor predeterminado asociado.
Problema:
Una academia de enseñanza almacena los datos de sus alumnos en una tabla llamada
"alumnos" y en otra tabla denominada "docentes" los datos de los profesores.
Eliminamos ambas tablas, si existen:
if object_id('alumnos') is not null
drop table alumnos;
if object_id('docentes') is not null
drop table docentes;
14
MANUAL DE SQL-SERVER PARTE II
Queremos definir un nuevo tipo de dato llamado "tipo_documento". Primero debemos
eliminarlo, si existe para volver a crearlo. Para ello empleamos esta sentencia que
explicaremos próximamente:
if exists (select *from systypes
where name = 'tipo_documento')
exec sp_droptype tipo_documento;
Creamos un tipo de dato definido por el usuario llamado "tipo_documento" basado en el
tipo "char" que permita 8 caracteres y valores nulos:
exec sp_addtype tipo_documento, 'char(8)', 'null';
Ejecutamos el procedimiento almacenado "sp_help" junto al nombre del tipo de dato
definido anteriormente para obtener información del mismo:
sp_help tipo_documento;
Aparecen varias columnas que nos informan, entre otras cosas: el nombre
(tipo_documento), el tipo de dato en que se basa (char), la longitud (8), si acepta valores
nulos (yes); las columnas "default_name" y "rule_name" muestran "none" porque no tiene
valores predeterminados ni reglas asociados.
Creamos la tabla "alumnos" con 2 campos: documento (del tipo de dato definido
anteriormente) y nombre (30 caracteres):
create table alumnos(
documento tipo_documento,
nombre varchar(30)
);
Eliminamos si existe, el valor predeterminado "VP_documento0":
if object_id ('VP_documento0') is not null
drop default VP_documento0;
inserte pantalla
14
MANUAL DE SQL-SERVER PARTE II
Cr eamos el valor predeterminado "VP_documento0" que almacene el valor '00000000':
create default VP_documento0
as '00000000';
Asociamos el valor predeterminado al tipo de datos "tipo_documento" especificando que
solamente se aplique a los futuros campos de este tipo:
exec sp_bindefault VP_documento0, 'tipo_documento', 'futureonly';
Ejecutamos el procedimiento almacenado "sp_helpconstraint" para verificar que no se
aplicó a la tabla "alumnos" porque especificamos la opción "futureonly":
sp_helpconstraint alumnos;
inserte pantalla
15
MANUAL DE SQL-SERVER PARTE II
Creamos la tabla "docentes" con 2 campos: documento (del tipo de dato definido
anteriormente) y nombre (30 caracteres):
create table docentes(
documento tipo_documento,
nombre varchar(30)
);
Verificamos que se aplicó el valor predeterminado creado anteriormente al campo
"documento" de la nueva tabla:
sp_helpconstraint docentes;
Ingresamos un registro en "alumnos" sin valor para documento y vemos qué se almacenó:
insert into alumnos default values;
select *from alumnos;
En esta tabla no se aplica el valor predeterminado por ello almacena "null", que es el valor
por defecto.
Si ingresamos en la tabla "docentes" un registro con valores por defecto:
insert into docentes default values;
select *from docentes;
Si se almacena el valor predeterminado porque está asociado.
Quitamos la asociación:
exec sp_unbindefault 'tipo_documento';
15
MANUAL DE SQL-SERVER PARTE II
Volvemos a asociar el valor predeterminado, ahora sin el parámetro "futureonly":
exec sp_bindefault VP_documento0, 'tipo_documento';
Ingresamos un registro en "alumnos" y en "docentes" sin valor para documento y vemos
qué se almacenó:
insert into alumnos default values;
select *from alumnos;
insert into docentes default values;
select *from docentes;
inserte pantalla
En ambas se almacenó '00000000'.
Eliminamos si existe, el valor predeterminado "VP_documentoDesconocido":
if object_id ('VP_documentoDesconocido') is not null
drop default VP_documentoDesconocido;
inserte pantalla
15
MANUAL DE SQL-SERVER PARTE II
Creamos el valor predeterminado llamado "VP_documentoDesconocido" que almacene el
valor 'SinDatos':
create default VP_documentoDesconocido
as 'SinDatos';
inserte pantalla
Asociamos el valor predeterminado al tipo de datos "tipo_documento" (ya tiene otro valor
predeterminado asociado):
exec sp_bindefault VP_DocumentoDesconocido, 'tipo_documento';
15
MANUAL DE SQL-SERVER PARTE II
Veamos si la asociación fue reemplazada en el tipo de datos:
exec sp_help tipo_documento;
Note que ahora en la columna "default_name" muestra "VP_documentoDesconocido".
Veamos si la asociación fue reemplazada en la tabla "alumnos":
sp_helpconstraint alumnos;
inserte pantalla
Note que ahora el valor predeterminado asociado es "VP_documentoDesconocido".
Quitamos la asociación del valor predeterminado:
sp_unbindefault 'tipo_documento';
inserte pantalla
Veamos si se quitó de ambas tablas:
exec sp_helpconstraint alumnos;
exec sp_helpconstraint docentes;
Ingresamos un registro en "alumnos" y vemos qué se almacenó en el campo
"documento":
insert into alumnos default values;
select *from alumnos;
Agregue a la tabla "docentes" una restricción "default" para el campo "documento":
alter table docentes
15
MANUAL DE SQL-SERVER PARTE II
add constraint DF_docentes_documento
default '--------'
for documento;
Ingrese un registro en "docentes" con valores por defecto y vea qué se almacenó en
"documento" recuperando los registros:
insert into docentes default values;
select *from docentes;
Asocie el valor predeterminado "VP_documento0" al tipo de datos "tipo_documento":
exec sp_bindefault VP_documento0, 'tipo_documento';
Vea qué informa "sp_helpconstraint" acerca de la tabla "docentes":
sp_helpconstraint docentes;
Tiene asociado el valor por defecto establecido con la restricción "default".
Ingrese un registro en "docentes" con valores por defecto y vea qué se almacenó en
"documento":
insert into docentes default values;
select *from docentes;
Note que guarda el valor por defecto establecido con la restricción.
Eliminamos la restricción:
alter table docentes
drop DF_docentes_documento;
inserte pantalla
15
MANUAL DE SQL-SERVER PARTE II
Vea qué informa "sp_helpconstraint" acerca de la tabla "docentes":
sp_helpconstraint docentes;
inserte pantalla
No tiene ningún valor por defecto asociado.
Asociamos el valor predeterminado "VP_documento0" al tipo de datos "tipo_documento":
exec sp_bindefault VP_documento0, 'tipo_documento';
Intente agregar una restricción "default" al campo "documento" de "docentes":
alter table docentes
add constraint DF_docentes_documento
default '--------'
for documento;
inserte pantalla
15
MANUAL DE SQL-SERVER PARTE II
SQL Server no lo permite porque el tipo de dato de ese campo ya tiene un valor
predeterminado asociado.
90 - Tipo de dato definido por el usuario (eliminar)
Podemos eliminar un tipo de dato definido por el usuario con el procedimiento
almacenado "sp_droptype":
exec sp_droptype TIPODEDATODEFINIDOPORELUSUARIO;
Eliminamos el tipo de datos definido por el usuario llamado "tipo_documento":
exec sp_droptype tipo_documento;
Si intentamos eliminar un tipo de dato inexistente, aparece un mensaje indicando
que no existe.
Los tipos de datos definidos por el usuario se almacenan en la tabla del sistema
"systypes".
Podemos averiguar si un tipo de dato definido por el usuario existe para luego
eliminarlo:
if exists (select *from systypes
where name = 'NOMBRETIPODEDATODEFINIDOPORELUSUARIO')
exec sp_droptype TIPODEDATODEFINIDOPORELUSUARIO;
15
MANUAL DE SQL-SERVER PARTE II
Consultamos la tabla "systypes" para ver si existe el tipo de dato
"tipo_documento", si es así, lo eliminamos:
if exists (select *from systypes
where name = 'tipo_documento')
exec sp_droptype tipo_documento;
No se puede eliminar un tipo de datos definido por el usuario si alguna tabla (u
otro objeto) hace uso de él; por ejemplo, si una tabla tiene un campo definido con
tal tipo de dato.
Si eliminamos un tipo de datos definido por el usuario, desaparecen las
asociaciones de las reglas y valores predeterminados, pero tales reglas y valores
predeterminados, no se eliminan, siguen existiendo en la base de datos.
Problema:
Una academia de enseñanza almacena los datos de sus alumnos en una tabla llamada
"alumnos".
Eliminamos la tabla si existe:
if object_id('alumnos') is not null
drop table alumnos;
Definimos un nuevo tipo de dato llamado "tipo_documento". Primero debemos eliminarlo,
si existe, para volver a crearlo:
if exists (select *from systypes
where name = 'tipo_documento')
exec sp_droptype tipo_documento;
Creamos un tipo de dato definido por el usuario llamado "tipo_documento" basado en el
tipo "char" que permita 8 caracteres y valores nulos:
exec sp_addtype tipo_documento, 'char(8)', 'null';
Eliminamos la regla "RG_documento" si existe:
if object_id ('RG_documento') is not null
drop rule RG_documento;
Creamos la regla que permita 8 caracteres que solamente serán dígitos:
create rule RG_documento
as @documento like '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]';
Asociamos la regla al tipo de datos "tipo_documento":
exec sp_bindrule RG_documento, 'tipo_documento';
15
MANUAL DE SQL-SERVER PARTE II
Creamos la tabla "alumnos":
create table alumnos(
nombre varchar(30),
documento tipo_documento
);
No podemos eliminar el tipo de dato "tipo_documento" porque hay una tabla "alumnos"
que lo utiliza. Entonces eliminamos la tabla:
drop table alumnos;
Ahora podemos eliminar el tipo de datos:
exec sp_droptype tipo_documento;
Note que no quitamos la asociación de la regla al tipo de datos, pero la asociación se
quitó al eliminar el tipo de dato.
Volvemos a crear el tipo de dato:
exec sp_addtype tipo_documento, 'char(8)', 'null';
inserte pantalla
Note que no tiene reglas asociadas:
sp_help tipo_documento;
Asociamos la regla nuevamente:
exec sp_bindrule RG_documento, 'tipo_documento';
inserte pantalla
15
MANUAL DE SQL-SERVER PARTE II
Note que no hemos vuelto a crear la regla porque la regla subsiste.
Primer problema:
Un comercio almacena los datos de sus empleados en una tabla denominada
"empleados".
1- Elimine la tabla si existe:
if object_id ('empleados') is not null
drop table empleados;
2- Defina un nuevo tipo de dato llamado "tipo_año". Primero debe eliminarlo,
si existe para volver a
crearlo:
if exists (select *from systypes
where name = 'tipo_año')
exec sp_droptype tipo_año;
inserte pantalla
16
MANUAL DE SQL-SERVER PARTE II
3- Cree un tipo de dato definido por el usuario llamado "tipo_año" basado en el
tipo "int" que
permita valores nulos:
exec sp_addtype tipo_año, 'int','null';
inserte pantalla
4- Elimine la regla llamada "RG_año" si existe:
if object_id ('RG_año') is not null
drop rule RG_año;
inserte pantalla
16
MANUAL DE SQL-SERVER PARTE II
5- Cree la regla que permita valores integer desde 1990 (fecha en que se
inauguró el comercio) y el
año actual:
create rule RG_año
as @año between 1990 and datepart(year,getdate());
inserte pantalla
6- Asocie la regla al tipo de datos "tipo_año":
exec sp_bindrule RG_año, 'tipo_año';
inserte pantalla
16
MANUAL DE SQL-SERVER PARTE II
7- Cree la tabla "empleados" con un campo del tipo creado anteriormente:
create table empleados(
documento char(8),
nombre varchar(30),
añoingreso tipo_año
);
inserte pantalla
8- Intente ingresar un registro con un valor inválido para el campo
"añoingreso":
insert into empleados values('22222222','Juan Lopez',1980);
No lo permite.
16
MANUAL DE SQL-SERVER PARTE II
9- Ingrese un registro con un valor válido para el campo "añoingreso":
insert into empleados values('22222222','Juan Lopez',2000);
inserte pantalla
10- Intente eliminar la regla asociada al tipo de datos:
drop rule RG_año;
No se puede porque está asociada a un tipo de datos.
inserte pantalla
16
MANUAL DE SQL-SERVER PARTE II
11- Elimine la asociación:
exec sp_unbindrule 'tipo_año';
inserte pantalla
12- Verifique que la asociación ha sido eliminada pero la regla sigue
existiendo:
sp_helpconstraint empleados;
exec sp_help tipo_año;
inserte pantalla
16
MANUAL DE SQL-SERVER PARTE II
13- Elimine la regla:
drop rule RG_año;
inserte pantalla
14- Verifique que la regla ya no existe:
sp_help RG_año;
inserte pantalla
16
MANUAL DE SQL-SERVER PARTE II
15- Ingrese el registro que no pudo ingresar en el punto 8:
insert into empleados values('22222222','Juan Lopez',1980);
Lo permite porque el tipo de dato ya no tiene asociada la regla.
inserte pantalla
16- Intente eliminar el tipo de datos "tipo_año":
exec sp_droptype tipo_año;
No lo permite porque hay una tabla que lo utiliza.
inserte pantalla
16
MANUAL DE SQL-SERVER PARTE II
17- Elimine la tabla "empleados":
drop table empleados;
inserte pantalla
18- Verifique que el tipo de dato "tipo_año" aún existe:
sp_help tipo_año;
inserte pantalla
16
MANUAL DE SQL-SERVER PARTE II
19- Elimine el tipo de datos:
exec sp_droptype tipo_año;
inserte pantalla
20- Verifique que el tipo de dato "tipo_año" ya no existe:
sp_help tipo_año;
inserte pantalla
16
MANUAL DE SQL-SERVER PARTE II
17