November 10, 2022 | Author: Anonymous | Category: N/A
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...................... Introducción....... ............................. ............................. .............................. ............................. ............................. ............................. ............................. .......................... ........... 3 72 - Combinaciones y funciones de agrupamiento............................. agrupamiento............................................ ............................................... ................................ 4 73 - Combinación de más de dos tablas............................ tablas........................................... ............................. ............................. .................................... ..................... 9 74 - Combinaciones con update y delete........................... delete.......................................... ............................. ............................................... .................................18 18 75 - Clave foránea.......................... foránea......................................... .............................. ............................. ............................. ............................. ................................... ......................... .... 22 76 - Restricciones (foreign key)............................... key)............................................. ............................. .............................. ............................................23 .............................23 77 - Restricciones foreign fore ign key en la misma tabla................................. tabla................................................ .................................. ............................. ..........35 35 78 - Restricciones foreign key (acciones)............ (acciones)........................... ............................. ............................. ............................................. .................................43 ...43 79 - Restricciones foreign key deshabilitar y eliminar (with check - nocheck).................................63 81 - Restricciones al crear la tabla............ tabla........................... .............................. ............................. ............................. ............................. .............................83 ...............83 84 - Alterar campos (alter table - alter) alter)............. ............................ ............................. ............................. .............................. .................................107 ..................107 85 - Agregar campos y restricciones (alter table) table)............. ............................ ............................. ............................. .................................116 ..................116 86 - Campos calculados........................ calculados....................................... ............................. ............................. .............................. ............................. ............................... ................. 122 87 - Tipo de dato denido por el usuario (crear - informacion)............................ informacion)............................................... .........................128 ......128 88 - Tipo de dato denido por el usuario (asociación de reglas)................................. reglas)....................................................132 ...................132 89 - Tipo de dato denido por el usuario (valores predeterminados).............................. predeterminados)............................................149 ..............149 90 - Tipo de dato denido por el usuario (eliminar)............................... (eliminar).............................................. .............................. .........................158 ..........158
2
MANUAL DE SQL-SERVER PARTE II
Introducción
En este este cu curs rso o va vamo mos s a ver ver una una intr introd oduc ucci ción ón a las las base bases s de dato datos. s. Esta Esta introducción introducc ión les va a servir por cualquier 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 ejercici ejercicios os 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 agrupamos por nombre 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 insert insert insert insert
into into into into into
libros libros libros libros libros
values('El aleph','Borges',1,20); values('Martin Fierro','Jose Hernandez',1,30); values('Aprenda PHP','Mario Molina',3,50); values('Uno','Richard Bach',3,15); 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') object_id('ciudades') is not null drop table ciudades; 2- Cree las tablas: create table visitantes( nombre varchar(30), varchar(30) , edad tinyint, sexo char(1) default 'f', domicilio varchar(30), codigociudad codigociudad tinyint tinyint not not null, 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 values('Carlos Paz'); insert into ciudades values('La Falda'); insert into ciudades values('Cruz 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, '
[email protected]',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 Perez',36,'m','Avellaneda 213',3,'fabianperez@xaxama 213',3,'
[email protected]',0); il.com',0); insert into visitantes values ('Alejandra Garcia',28,'f',null,2,null,2 Garcia',28,'f',null,2,null,280.50); 80.50); insert into visitantes values ('Gaston Perez',29,'m',null,5,'
[email protected]',95.40); insert into visitantes values ('Mariana Juarez',33,'f',null,2,null, Juarez',33,'f',null,2,null,90); 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 Analicemos consulta anterior. anterior. Indicamos Indicamos el el nombre de de la tabla tabla luego del 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 insert insert insert
into into into into
editoriales editoriales editoriales editoriales
insert insert insert insert insert
into into into into into
autores autores autores autores autores
insert insert insert insert insert insert insert
into into into into into into into
libros libros libros libros libros libros libros
values('Planeta'); values('Emece'); values('Siglo XXI'); values('Plaza');
values values values values values
('Richard Bach'); ('Borges'); ('Jose Hernandez'); ('Mario Molina'); ('Paenza');
values('El aleph',2,2,20); values('Martin Fierro',3,1,30); values('Aprenda PHP',4,3,50); values('Uno',1,1,15); values('Java en 10 minutos',0,3,45); values('Matematica estas ahi',0,0,15); 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,p titulo,a.nombre,e.nombre,precio recio 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,p titulo,a.nombre,e.nombre,precio recio 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 ("right join") y a ese resultado lo combinamos con "editoriales", encuentren ocon no "autores" 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", "inscriptos", las inscripciones 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') object_id('socios') is not null drop table socios; if object_id('deportes') is not null drop table deportes; if object_id('inscriptos') object_id('inscriptos') is not null drop table inscriptos; inserte pantalla
2- Cree las tablas con las siguientes estructuras: estructuras: create table socios( documento char(8) not null,
13
MANUAL DE SQL-SERVER PARTE II
nombre varchar(30), varchar(30) , domicilio varchar(30), primary key(documento) ); create table deportes( codigo tinyint identity, nombre varchar(20), varchar(20) , profesor varchar(15), 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, char(1),--'s'=paga, 'n'=impaga primary key(documento,codigodeporte, key(documento, codigodeporte,anio) anio) ); inserte pantalla
3- Ingrese algunos registros en "socios": insert into socios values('22222222','Ana values('22222222','Ana Acosta','Avellaneda Acosta','Avellaneda 111'); insert into socios values('23333333','Betina values('23333333','Betina Bustos','Bulnes Bustos','Bulnes 222'); insert into socios values('24444444','Carlos values('24444444','Carlos Castro','Caseros Castro','Caseros 333'); insert into socios values('25555555','Daniel values('25555555','Daniel Duarte','Dinamarca Duarte','Dinamarca 44'); 4- Ingrese algunos registros en "deportes": insert into deportes values('basquet','Juan Juarez'); insert into deportes values('futbol','Pedro 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 ('22222222',3,'2006','s'); '); insert into inscriptos values ('23333333',3,'2006','s ('23333333',3,'2006','s'); '); insert into inscriptos values ('24444444',3,'2006','n ('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 ('22222222',3,'2005','s'); '); insert into inscriptos values ('22222222',3,'2007','n ('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 ('24444444',1,'2006','s'); '); insert into inscriptos values ('24444444',2,'2006','s ('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 ('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 código documento decuyo socio no sede deporte no existe en "deportes" y cuyo 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 insert insert insert
into into into into
libros libros libros libros
inserte pantalla
values('El aleph','Borges',2,20); values('Martin Fierro','Jose Hernandez',1,30); values('Aprenda PHP','Mario Molina',3,50); values('Java en 10 minutos',default,3,45);
19
MANUAL DE SQL-SERVER PARTE II
Aumentamos Aumentam os en un 10% los precios precios de los los libros de editorial "Planeta": "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,prec titulo,autor,e.nombre,precio io 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' editoriales.nombre='Emece'; ;
inserte pantalla
Veamos si se eliminaron: select titulo,autor,e.nombre,prec titulo,autor,e.nombre,precio io
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: Analicém osla:
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 en inserciones. inserciones. Si intentamos intentamos ingresar ingresar un registro registro (un libro) con con un valor 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 en eliminaciones eliminaciones y actualiza actualizaciones. ciones. Si Si intentamos intentamos eliminar eliminar un registro 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 yalactualizaciones, nombre de la tabla. Nos muestra el tipo, nombre, la opción para eliminaciones 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 Agregamo s una restricción restricción "foreign "foreign key" a la tabla "libros": "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') object_id('clientes') is not null drop table clientes; if object_id('provincias') object_id('provincias') is not null drop table provincias; create table clientes ( codigo int identity, nombre varchar(30), varchar(30) , domicilio varchar(30), ciudad varchar(20), codigoprovincia 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_codigoprovin FK_clientes_codigoprovincia cia foreign key (codigoprovincia) (codigoprovincia) references provincias(codigo); 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 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 provincias values(3,'Misiones'); values(2,'Santa values(2,'Santa Fe'); insert into into provincias values(3,'Misiones') ; insert into provincias values(4,'Rio Negro'); insert insert insert insert
into clientes values('Perez Juan','San Martin 123','Carlos Paz',1); into clientes values('Moreno Marcos','Colon 234','Rosario',2); into clientes values('Acosta values('Acosta Ana','Avellaneda 333','Posadas',3); 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_codigoprovin FK_clientes_codigoprovincia cia foreign key (codigoprovincia) (codigoprovincia) references provincias(codigo); 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_codigoprovin FK_clientes_codigoprovincia cia foreign key (codigoprovincia) (codigoprovincia) references provincias(codigo); 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 l lamada "FK_clientes_co "FK_clientes_codigoprovincia digoprovincia". ". 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 afiliados inscriben inscriben a sus familiares. familiares. La tabla tabla contiene contiene un campo 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 constraint FK_afiliados_afiliadotitula FK_afiliados_afiliadotitular r add 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') object_id('clientes') is not null drop table clientes; create table clientes( codigo int not null, nombre varchar(30), varchar(30) , domicilio varchar(30), ciudad varchar(20), referenciadopor referenciadopor int, primary key(codigo) ); 2- Ingresamos algunos registros: insert into clientes values (50,'Juan Perez','Sucre Perez','Sucre 123','Cordoba',null); 123','Cordoba',null); insert into clientes values(90,'Marta Juarez','Colon 345','Carlos Paz',null); insert into clientes values(110,'Fabian values(110,'Fabian Torres','San Martin 987','Cordoba',50); 987','Cordoba',50); insert into clientes values(125,'Susana Garcia','Colo Garcia','Colon n 122','Carlos Paz',90); insert into clientes values(140,'Ana 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 "referen "referenciadopor" ciadopor" 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 información referente a las restricciones 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 on join editoriales as e 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') object_id('clientes') is not null drop table clientes; if object_id('provincias') 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), varchar(30) , domicilio varchar(30), ciudad varchar(20), codigoprovincia codigoprovincia tinyint, primary key(codigo) ); create table provincias( codigo tinyint, nombre varchar(20), 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 values(2,'Santa Fe'); insert into provincias values(3,'Misiones'); 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 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" "no_action" para eliminaciones. 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" "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 object_id('inscripciones') ') is not null drop table inscripciones; inscripciones; if object_id('deportes') is not null drop table deportes; if object_id('socios') object_id('socios') is not null drop table socios; 2- Cree las tablas: create table deportes( codigo tinyint, nombre varchar(20), varchar(20) , primary key(codigo) ); create table socios( documento char(8), nombre varchar(30), varchar(30) , primary key(documento) ); create table inscripciones( documento char(8), codigodeporte codigodep orte tinyint, matricula char(1),-char(1),-- 's' si si está paga, 'n' 'n' si no está está paga primary key(documento,codigodeporte) 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 inscripciones add constraint FK_inscripciones_codigodepor FK_inscripci ones_codigodeporte te foreign key (codigodeporte) (codigodeport e) references deportes(codigo) deportes(codig o) 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 inscripciones add constraint FK_inscripciones_documento FK_inscripci ones_documento foreign key (documento) references socios(documento) on delete cascade; inserte pantalla
5Ingrese en las tablas: insert into algunos deportesregistros values(1,'basquet'); values(1,'basquet '); insert into deportes values(2,'futbol');
55
MANUAL DE SQL-SERVER PARTE II
insert into deportes values(3,'natacion'); values(3,'natacion'); insert into deportes values(4,'tenis'); insert insert insert insert
into socios values('30000111','Juan values('30000111','Juan Lopez'); into socios values('31111222','Ana values('31111222','Ana Garcia'); into socios values('32222333','Mario values('32222333','Mario Molina'); into socios values('33333444','Julieta values('33333444','Julieta Herrero');
insert insert insert insert
into inscripciones values ('30000111',1,'s'); ('30000111',1,'s'); into inscripciones values ('30000111',2,'s'); ('30000111',2,'s'); into inscripciones values ('31111222',1,'s'); ('31111222',1,'s'); into inscripciones values ('32222333',3,'n'); ('32222333',3,'n');
6- Intente ingresar una inscripción con un código de deporte inexistente: insert into inscripciones values('30000111',6,'s'); 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'); 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; 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; 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 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 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 restricciones de la tabla "inscripciones": "inscripciones": sp_helpconstraint sp_helpconstraint inscripciones; 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 se nombrada coloca nombre de restricciones, habilita todas las restricciones que tieneall" la no tabla ("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 Agregamo s una restricción restricción "foreign "foreign key" a la tabla "libros" "libros" para evitar evitar que se ingresen 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 la restricción restricción "primary key" key" y nos informa informa que hay una restricción "foreign "foreign key" key" que hace referencia a ella de la tabla "libros" (aunque esté deshabilitada). Ahora podemos podemos ingresar ingresar un registro registro en "libros" con código inválido: 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 Habilitamo s la restricción r estricció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') object_id('clientes') is not null drop table clientes; if object_id('provincias') 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), varchar(30) , domicilio varchar(30), ciudad varchar(20), codigoprovincia codigoprovincia tinyint, primary key(codigo) ); create table provincias( codigo tinyint, nombre varchar(20), varchar(20) , primary key (codigo) ); 3- Ingrese algunos registros para ambas tablas: insert into provincias values(1,'Cordoba'); insert into provincias values(2,'Santa values(2,'Santa Fe');
69
MANUAL DE SQL-SERVER PARTE II
insert into provincias values(3,'Misiones'); values(3,'Misiones'); insert into provincias values(4,'Rio Negro'); insert insert insert insert insert insert
into clientes values('Perez Juan','San Martin 123','Carlos Paz',1); into clientes values('Moreno Marcos','Colon 234','Rosario',2); into clientes values('Garcia Juan','Sucre 345','Cordoba',1); 345','Cordoba',1); into clientes values('Lopez values('Lopez Susana','Caseros 998','Posadas',3); 998','Posadas',3); into clientes values('Marcelo values('Marcelo Moreno','Peru 876','Viedma',4); 876','Viedma',4); into clientes values('Lopez Sergio','Avellaneda 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 constraint FK_clientes_c FK_clientes_codigoprovinc odigoprovincia ia foreign key (codigoprovincia) (codigoprovincia) references provincias(codigo) 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 constraint FK_clientes_c FK_clientes_codigoprovinc odigoprovincia ia foreign key (codigoprovincia) (codigoprovincia) references provincias(codigo) 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 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 "foreign restricción "prim "primary restricción key" de ary key" y la referencia a esta tabla de la la tabla "clientes.
71
MANUAL DE SQL-SERVER PARTE II
inserte pantalla
8- Deshabilite la restricc restricción ión "foreign key" de "clientes": "clientes": alter table clientes nocheck constraint FK_clientes_codigoprovincia; FK_clientes_codigoprovincia; inserte pantalla
9- Vea las restricciones de "clientes": sp_helpconstraint 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 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 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 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 l os registros de ambas tablas se eliminaron: select *from clientes; select *from provincias; inserte pantalla
23- Elimine la restriccion restriccion "foreign key": alter table clientes drop constraint constraint FK_clientes_codigopro FK_clientes_codigoprovincia; vincia; inserte pantalla
79
MANUAL DE SQL-SERVER PARTE II
24- Vea las restriciones restriciones de la tabla "provincias": sp_helpconstraint 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 - Restriccione Restriccioness foreign key (información (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 varias restricciones restricciones cuando cuando creamos creamos la tabla 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 la restricción restricción "primary key" key" para el campo campo "codigo" "codigo" y la restricción restricción "foreign "foreign key" de "libros" "FK_libros_editorial" que referencia esta tabla. Veamos las restricciones de "autores": sp_helpconstraint autores;
inserte pantalla
Aparecen 4 restricciones: restricciones: una restricción "check" para el campo "codigo", una una restricción restricción "primary key" "foreign para el campo una restricción "unique" para el campo y la restricción key" de"codigo", "libros" "FK_libros_autores" que referencia esta "nombre" tabla.
85
MANUAL DE SQL-SERVER PARTE II
Veamos las restricciones de "libros": sp_helpconstraint libros;
inserte pantalla
Aparecen 6 restricciones: restricciones: una restricción "check" sobre sobre el campo campo "precio", una "default" "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 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') object_id('inscriptos') is not null drop table inscriptos; object_id('socios') object_id('s ocios') is not null ifdrop table socios; if object_id('profesores') 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" "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), varchar(30) , domicilio varchar(30), constraint CK_profesores_documento_patron check (documento like '[0-9][0'[0-9][0 9][0-9][0-9][0-9][0-9][0-9][0-9]'), constraint PK_profesores_documento PK_profesores_documen to 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 constraint DF_deportes_dia DF_deportes_dia default('sabado'), default('sabado'), profesor char(8),--documento char(8),-- documento del profesor constraint CK_deportes_dia_lista CK_deportes_dia_lista check check (dia in
('lunes','m ('lunes','martes','mier coles','jueves','viernes ','sabado')), constraintartes','miercoles','jue PK_deportes_codigo PK_deportes_cod igoves','viernes','sabado')), primary key (codigo) ); create table socios( numero int identity, documento char(8), nombre varchar(30), varchar(30) , domicilio varchar(30), constraint CK_documento_patron check (documento like '[0-9][0'[0-9][0-9][0-9][09][0-9][09][0-9][0-9][0-9][0-9]'), constraint PK_socios_numero constraint primary key nonclustered(numero), nonclustered( numero), UQ_socios_documento UQ_socios_document o unique clustered(documento) clustered(d ocumento) ); create table inscriptos( numerosocio numerosocio int not null, codigodeporte codigodeporte tinyint, matricula char(1), constraint PK_inscriptos_numerodeporte PK_inscripto s_numerodeporte primary key clustered (numerosocio,codigodeporte), (numerosocio,codi godeporte), constraint FK_inscriptos_deporte FK_inscriptos_deporte foreign key (codigodeporte) (codigodeporte ) references deportes(codigo) deportes(codi go) on update cascade, constraint FK_inscriptos_socios FK_inscriptos_ socios foreign key (numerosocio) references socios(numero) on update cascade on delete cascade, constraint CK_matricula_ CK_matricula_valores valores check check (matricula in ('s','n')) ); inserte pantalla
88
MANUAL DE SQL-SERVER PARTE II
4- Ingrese registros en "profesores": insert into profesores profesores values('21111111','Andres values('21111111','Andres Acosta','Avellaneda 111'); insert into profesores values('22222222','Betina 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',nu values('basquet','lunes',null); ll); insert into deportes values('futbol','lunes','2333 values('futbol','lunes','23333333'); 3333'); insert into deportes values('natacion',null,'222222 values('natacion',null,'22222222'); 22'); insert into deportes values('padle',default,'2333333 values('padle',default,'23333333'); 3'); insert into deportes (nombre,dia) values('tenis','jueves'); values('tenis','jueves'); inserte pantalla
89
MANUAL DE SQL-SERVER PARTE II
6- Ingrese registros en "socios": insert into socios values('30111111','Ana values('30111111','Ana Acosta','America Acosta','America 111'); insert into socios values('30222222','Berna values('30222222','Bernardo rdo Bueno','Bolivia 222'); insert into socios values('30333333','Camila values('30333333','Camila Conte','Caseros Conte','Caseros 333'); insert into socios values('30444444','Daniel values('30444444','Daniel Duarte','Dinamarca 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) 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 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. restricciones. inserte pantalla
15- Muestre las restricciones de "inscriptos". 4 restricciones. 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 insert insert insert insert insert insert
into into into into into into into
alumnos values('30000000','Juan Perez','Colon 123'); alumnos values('30111111','Marta Morales','Caseros 222'); alumnos values('30222222','Laura Torres','San Martin 987'); alumnos values('30333333','Mariano Juarez','Avellaneda 34'); alumnos values('23333333','Federico Lopez','Colon 987'); profesores values('22222222','Susana Molina','Sucre 345'); 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" "empleados" los datos de los empleados. 1- Elimine las tablas si existen: if object_id('clientes') object_id('clientes') is not null drop table clientes; if object_id('proveedores') object_id('proveedores') is not null drop table proveedores; if object_id('empleados') 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), varchar(20) , apellido varchar(20), domicilio varchar(30), ); primary key(documento) inserte pantalla
3- Ingrese algunos registros: insert into proveedores values('Bebida cola','Colon cola','Colon 123'); insert into proveedores values('Carnes Unica','Caseros Unica','Caseros 222'); insert into proveedores values('Lacteos values('Lacteos Blanca','San Martin 987'); insert into clientes values('Supermercado values('Supermercado Lopez','Avellaneda Lopez','Avellaneda 34'); insert into clientes values('Almacen Anita','Colon 987'); insert into clientes values('Garcia Juan','Sucre 345'); insert into i nto empleados values('23333333','Feder values('23333333','Federico','Lopez ico','Lopez','Colon ','Colon 987'); insert into empleados values('28888888','Ana','M values('28888888','Ana','Marquez','Suc arquez','Sucre re 333'); insert into empleados values('30111111','Luis','P values('30111111','Luis','Perez','Caser erez','Caseros os 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 agregar un campo campo puede puede especificarse especificarse que sea "identity" "identity" (siempre (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 drop table columnlibros 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), varchar(20), nombre varchar(20), varchar(20), domicilio varchar(30), 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 especificando un valor por defecto: alter table empleados add documento documento char(8) not null default 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', aleph','Borges','Planeta',20); 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 n null; ull;
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 Aprendimos dato o atributos atributos de un campo que tiene 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". "empleados".
10
MANUAL DE SQL-SERVER PARTE II
1- Elimine la tabla, si existe y créela: if object_id('empleados') object_id('empleados') is not null drop table empleados; create table empleados( legajo int not null, documento char(7) not null, nombre varchar(10), varchar(10) , domicilio varchar(30), ciudad varchar(20) varchar(20) default default 'Buenos 'Buenos Aires', Aires', sueldo decimal(6,2), decimal(6,2 ), cantidadhijos tinyint default 0, primary key(legajo) ); 2- Modifique el campo "nombre" extendiendo su longitud. 3- Controle la modificación: 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 column legajo 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: 123','Cordoba',500,3); insert into empleados values(1,'22222222','Juan values(1,'22222222','Juan Perez','Colon insert into i nto empleados values(2,'30000000',null, values(2,'30000000',null,'Sucre 'Sucre 456','Cordoba',600,2); 456','Cordoba',600,2); inserte pantalla
7- Intente modificar el campo "nombre" para que no acepte valores nulos: alter table empleados alter column column nombre nombre varchar(30) 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 fromempleados empleados where nombre is null; alter table alter column column nombre nombre varchar(30) 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": 856',default,500,4); insert into empleados values(3,'33333333','Juan values(3,'33333333','Juan Perez','Sarmiento Perez','Sarmiento 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. caracteres. inserte pantalla
11
MANUAL DE SQL-SERVER PARTE II
12- Agregue el registro que no pudo ingresar en el punto 10: 856',default,500,4); insert into empleados values(3,'33333333','Juan values(3,'33333333','Juan Perez','Sarmiento Perez','Sarmiento 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 Agregamos tabla "libros", "libros", el campo campo "titulo" "titulo" de tipo tipo varchar(30) varchar(30) y una restricción restricción "unique" con índice agrupado: alter table libros add titulo varchar(30) constraint UQ_libros_autor unique clustered;
Agregamos a la tabla Agregamos tabla "libros", "libros", el campo campo "codigo" "codigo" de tipo int identity not 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 Agregamo s a la tabla tabla "libros", "libros", el campo campo "precio" "precio" de tipo decimal(6,2) 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) Agregamos varchar(30) y una una restricción "unique" "unique" con índice í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 Agregamos de tipo int int identity not 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 Agregamos de tipo decimal(6,2) decimal(6,2) y una restricción restricción "check" "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". "empleados". 1- Elimine la tabla, si existe y créela: if object_id('empleados') object_id('empleados') is not null drop table empleados; create table empleados( documento char(8) not null, nombre varchar(10), varchar(10) , domicilio varchar(30), ciudad varchar(20) varchar(20) default default 'Buenos 'Buenos Aires' Aires' ); 2- Agregue el campo "legajo" de tipo int identity y una restricción "primary "primary key": alter table empleados add legajo int identity constraint PK_empleados_legajo PK_empleados_legajo primary key; 3- Vea si la estructura 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 sentencia una restricción que no permita valores superiores a 30: alter table"check" empleados add hijos tinyint constraint CK_empleados_hijos CK_empleados_hi jos check (hijos=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 los cuales depende el campo calculado no pueden eliminarse, se debecampos eliminarde 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 Agregamo s un campo campo calculado: 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 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 descripcion varchar(30), precio decimal(5,2) not null, null,
cantidad smallint not not null default 0, 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) values('birome',1.5,100,150);; No lo permite. inserte pantalla
3- Ingrese algunos registros: insert into articulos values('birome',1.5,100) 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: 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) in formacion) 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: columnas: el nombre, nombre, el el tipo de dato dato en que que se basa, basa, la longitud, 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 sentenc sentencia ia que explicaremos en el siguiente capítulo: if exists (select name from systypes where name = 'tipo_legajo') 'tipo_legajo') exec sp_droptype sp_droptype tipo_legajo; tipo_legajo; 3- Cree un tipo de dato definido por el usuario llamado "tipo_lega "tipo_legajo" jo" 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 inserte pantalla para obtener información del mismo.
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 (asocia ció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 columnas que nos informan, informan, entre entre otras cosas: cosas: el nombre nombre (tipo_documento), el tipo de dato en que se basa (char), la longitud (8), si acepta valores nulos (yes); las columnasni "default_name" y "rule_name" muestran "none" porque no tiene valores predeterminados 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-5][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'; 0-9][0-9][0-9]';
Asociamos la regla al tipo de datos datos "tipo_docume "tipo_documento" nto" especificando especificando que que solamente 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][0-9][0-9][0-9][0-9][0-9]'; 0-9][0-9][0-9]';
Asociamos la regla al tipo de datos datos "tipo_docume "tipo_documento" nto" (ya tiene tiene una regla asociada): 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_docume "RG_documento" nto" al campo campo "documento" "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 sentenc sentencia ia que
explicaremos en el siguiente capítulo: if exists (select *from systypes
13
MANUAL DE SQL-SERVER PARTE II
where name = 'tipo_año') '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), 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 between 1990 1990 and datepart(year,getdat datepart(year,getdate()); e()); 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 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: 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): caracteres): create table clientes( documento char(8), nombre varchar(30), 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 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 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 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 sp_helpconstraint clientes; Si se quitó. inserte pantalla
16- Vuelva a asociar la regla, ahora sin el parámetro "futureonly": "futureonly": exec sp_bindrule 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): asociación): insert into empleados values('33333333','Romina values('33333333','Romina Guzman',1900); 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", "RG_añonegativo", si existe: if object_id ('RG_añonegativo') ('RG_añonegativo') is not null drop rule RG_añonegativo; RG_añonegati vo; inserte pantalla
20- Cree una regla llamada "RG_añonegativo" "RG_añonegativo" que admita valores entre -2000 y -1: create rule RG_añonegativo 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" "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 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 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 values('44444444','Pedro Perez',-1900); 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 columnas que nos informan, informan, entre entre otras cosas: cosas: el nombre nombre (tipo_documento), el tipo de dato en que se basa (char), la longitud (8), si acepta valores nulos (yes); las columnasni "default_name" y "rule_name" muestran "none" porque no tiene valores predeterminados 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 predetermina predeterminado do al tipo de datos datos "tipo_documento "tipo_documento"" especificando 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 select insert select
into alumnos default values; *from alumnos; into docentes default values; *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 predetermina predeterminado do al tipo de datos datos "tipo_documento "tipo_documento"" (ya tiene otro valor 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" "docentes" una restricción restricción "default" "default" para el campo "document "documento": o":
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 valor predeterminad predeterminado o "VP_documento0 "VP_documento0"" al tipo de datos "tipo_docu "tipo_documento": mento": 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 predetermina predeterminado do "VP_documento "VP_documento0" 0" al tipo de datos datos "tipo_documento "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][0-9][0-9][0-9][0-9][0-9]'; 0-9][0-9][0-9]';
Asociamos la regla al tipo de datos datos "tipo_docume "tipo_documento": nto":
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 podemos eliminar eliminar el tipo de datos: 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 nuevament nuevamente: e:
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') '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 between 1990 1990 and datepart(year,getdat datepart(year,getdate()); e()); inserte pantalla
6- Asocie la regla al tipo de datos "tipo_año": exec sp_bindrule 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), 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 Juan Lopez ,1980); ,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 values('22222222','Juan Lopez',2000); 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 values('22222222','Juan Lopez',1980); 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