Listado completo de tutoriales

131 - Procedimientos Almacenados (con join)


Hasta ahora, hemos creado procedimientos que incluyen una sola tabla o pocas instrucciones para aprender la sintaxis, pero la funcionalidad de un procedimiento consiste básicamente en que contengan muchas instrucciones o instrucciones complejas y así evitar tipear repetidamente dichas instrucciones; además si no queremos que el usuario conozca la estructura de las tablas involucradas, los procedimientos permiten el acceso a ellas.

Podemos crear procedimientos que incluyan combinaciones (join), subconsultas, varias instrucciones y llamadas a otros procedimientos.

Podemos crear todos los procedimientos que necesitemos para que realicen todas las operaciones y consultas.

Servidor de SQL Server instalado en forma local.

Ingresemos el siguiente lote de comandos en el SQL Server Management Studio:

/*
Vamos a crear procedimientos que incluyan combinaciones (join), subconsultas, varias instrucciones
y llamadas a otros procedimientos.
Un club dicta clases de distintos deportes. Almacena la información en varias tablas:

- deportes: codigo y nombre,
- cursos: numero de curso, codigo de deporte, documento del profesor que lo dicta 
  y dia de la semana,
- profesores: documento, nombre y domicilio,
- socios: documento, nombre y domicilio,
- inscriptos: documento del socio, número del curso y si la matricula está paga o no.

Una vez por semana se dicta cada curso.
Puede haber varios cursos de un mismo deporte que se dicten distintos días y/o por
distintos profesores. Por ejemplo: curso 1 de natación los lunes por Carlos Caseres,
curso 2 de natación los martes por Carlos Caseres y curso 3 de natación los miércoles por Ana Acosta.
Un profesor puede estar a cargo de distintos cursos, incluso de distintos deportes.
Por ejemplo: curso 1 de natación los lunes por Carlos Caseres y curso 4 de tenis los miércoles por Carlos Caseres.
Quien se inscriba debe ser socio, es decir, debe estar en la tabla "socios".
Un socio no puede inscribirse en un mismo curso.
*/

-- Eliminamos las tablas si existen y las creamos:
if (object_id('inscriptos')) is not null
  drop table inscriptos;
if (object_id('deportes')) is not null
  drop table deportes;
if (object_id('cursos')) is not null
  drop table cursos;
if (object_id('profesores')) is not null
  drop table profesores;
if (object_id('socios')) is not null
  drop table socios;

create table deportes(
  codigo tinyint identity,
  nombre varchar(30),
  primary key (codigo)
);

create table profesores(
  documento char(8),
  nombre varchar(30),
  domicilio varchar(30),
  primary key (documento)
);

create table socios(
  documento char(8),
  nombre varchar(30),
  domicilio varchar(30),
  primary key (documento)
);

create table cursos(
  numero tinyint identity,
  codigodeporte tinyint not null,
  documentoprofesor char(8) not null,
  dia varchar(15),
  constraint PK_cursos_numero
   primary key clustered (numero),
  constraint FK_cursos_documentoprofesor
   foreign key (documentoprofesor)
   references profesores(documento)
   on update cascade,
  constraint FK_cursos_codigodeporte
   foreign key (codigodeporte)
   references deportes(codigo)
);

create table inscriptos(
  documentosocio char(8) not null,
  numero tinyint not null,
  matricula char(1) --'s'=paga 'n'=impaga,
  constraint PK_inscriptos_documentosocio_numero
   primary key(documentosocio,numero),
  constraint FK_inscriptos_documentosocio
   foreign key (documentosocio)
   references socios(documento),
  constraint FK_inscriptos_numero
   foreign key (numero)
   references cursos(numero)
);

go

-- Ingresamos algunos registros para todas las tablas:
 insert into deportes values('tenis');
 insert into deportes values('natacion');
 insert into deportes values('basquet');
 insert into deportes values('futbol');
 
 insert into profesores values('22222222','Ana Acosta','Colon 123');
 insert into profesores values('23333333','Carlos Caseres','Sarmiento 847');
 insert into profesores values('24444444','Daniel Duarte','Avellaneda 284');
 insert into profesores values('25555555','Fabiola Fuentes','Caseros 456');
 insert into profesores values('26666666','Gaston Garcia','Bulnes 345');

 insert into cursos values(1,'22222222','jueves');
 insert into cursos values(1,'22222222','viernes');
 insert into cursos values(1,'23333333','miercoles');
 insert into cursos values(2,'22222222','miercoles');
 insert into cursos values(2,'23333333','lunes');
 insert into cursos values(2,'23333333','martes');
 insert into cursos values(3,'24444444','lunes');
 insert into cursos values(3,'24444444','jueves');
 insert into cursos values(3,'25555555','martes');
 insert into cursos values(3,'25555555','viernes');
 insert into cursos values(4,'24444444','martes');
 insert into cursos values(4,'24444444','miercoles');
 insert into cursos values(4,'24444444','viernes');

 insert into socios values('31111111','Luis Lopez','Colon 464');
 insert into socios values('30000000','Nora Nores','Bulnes 234');
 insert into socios values('33333333','Mariano Morales','Sucre 464');
 insert into socios values('32222222','Patricia Perez','Peru 1234');
 insert into socios values('34444444','Susana Suarez','Salta 765');

 insert into inscriptos values('30000000',1,'s');
 insert into inscriptos values('30000000',4,'n');
 insert into inscriptos values('31111111',1,'s');
 insert into inscriptos values('31111111',4,'s');
 insert into inscriptos values('31111111',7,'s');
 insert into inscriptos values('31111111',13,'s');
 insert into inscriptos values('32222222',1,'s');
 insert into inscriptos values('32222222',4,'s');

 -- Eliminamos el procedimiento "pa_inscriptos", si existe:
 if (object_id('pa_inscriptos')) is not null
  drop proc pa_inscriptos;

 go

-- Creamos un procedimiento que muestre el nombre del socio, el nombre del deporte,
-- el día, el profesor y la matrícula.
-- Si necesitamos esta información frecuentemente, este procedimiento nos evita tipear
-- este join repetidamente; además si no queremos que el usuario conozca la estructura
-- de las tablas involucradas, éste y otros procedimientos permiten el acceso a ellas.
 create procedure pa_inscriptos
  as
   select s.nombre, d.nombre, dia, p.nombre, matricula
   from socios as s
   join inscriptos as i
   on s.documento=i.documentosocio
   join cursos as c
   on c.numero=i.numero
   join deportes as d
   on c.codigodeporte=d.codigo
   join profesores as p
   on c.documentoprofesor=p.documento;

 go

-- Ejecutamos el procedimiento:
 exec pa_inscriptos;

-- Eliminamos el procedimiento "pa_documentovalido", si existe:
 if (object_id('pa_documentovalido')) is not null
  drop proc pa_documentovalido;

  go

-- Creamos un procedimiento que reciba un documento y nos retorne distintos valores según:
-- sea nulo (1), no sea válido (2), no esté en la tabla "socios" (3), sea un socio deudor 
--(4) o sea un socio sin deuda (0)
-- Este procedimiento recibe parámetro, emplea "return" e incluye subconsultas.
 create procedure pa_documentovalido
  @documento char(8)=null
  as
   if @documento is null return 1
   else 
    if len(@documento)<8 return 2
    else
     if not exists (select *from socios where documento=@documento) return 3
     else
     begin
      if exists (select *from inscriptos
                where documentosocio=@documento and
                matricula='n') return 4
      else return 0
     end;

 go

-- Eliminamos el procedimiento "pa_deportediavalido", si existe:
 if (object_id('pa_deportediavalido')) is not null
  drop proc pa_deportediavalido;

  go

-- Creamos un procedimiento al cual le enviamos el nombre de un deporte y el día y 
-- nos retorna un valor diferente según: el nombre del deporte o día sean nulos (1),
-- el día sea inválido (2), deporte no se dicte (3), el deporte se dicte pero no el
-- día ingresado (4) o el deporte se dicte el día ingresado (0):
 create procedure pa_deportediavalido
  @deporte varchar(30)=null,
  @dia varchar (15)=null
  as
   if @deporte is null or @dia is null return 1
   else
    if @dia not in ('lunes','martes','miercoles','jueves','viernes','sabado') return 2
    else
    begin
     declare @coddep tinyint
     select @coddep= codigo from deportes where nombre=@deporte
     if @coddep is null return 3
     else
      if not exists(select *from cursos where codigodeporte=@coddep and dia=@dia) return 4
      else return 0
    end;

 go

-- Eliminamos el procedimiento "pa_ingreso", si existe:
 if (object_id('pa_ingreso')) is not null
  drop proc pa_ingreso;

 go

-- Creamos un procedimiento que nos permita ingresar una inscripción con los siguientes datos:
-- documento del socio, nombre del deporte, dia y matrícula.
-- El procedimiento llamará a los procedimientos "pa_documentovalido" y "pa_deportediavalido"
-- y mostrará diferentes mensajes. Un socio que deba alguna matrícula NO debe poder 
-- inscribirse en ningún curso:
 create procedure pa_ingreso
  @documento char(8)=null,
  @deporte varchar(20)=null,
  @dia varchar(20)=null,
  @matricula char(1)=null
  as
   --verificamos el documento
   declare @doc int
   exec @doc=pa_documentovalido @documento
   if @doc=1 select 'Ingrese un documento'
   else
    if @doc=2 select 'Documento debe tener 8 digitos'
    else
     if @doc=3 select @documento+' no es socio'
     else
      if @doc=4 select 'Socio '+ @documento+' debe matriculas'
  --verificamos el deporte y el dia
   declare @depdia int
   exec @depdia=pa_deportediavalido @deporte, @dia
   if @depdia=1 select 'Ingrese deporte y dia'
   else
    if @depdia=2 select 'Ingrese día válido'
    else
     if @depdia=3 select @deporte+' no se dicta'
     else
      if @depdia=4 select @deporte+' no se dicta el '+ @dia
   
   --verificamos que el socio no esté inscripto ya en el deporte el día solicitado
   if @doc=0 and @depdia=0
   begin
     declare @codcurs int
     select @codcurs=c.numero from cursos as c
                     join deportes as d
                     on c.codigodeporte=d.codigo
	             where @deporte=d.nombre and
                     @dia=c.dia
     if exists (select *from inscriptos as i
                join cursos as c
                on i.numero=c.numero
                where @codcurs=i.numero and 
                i.documentosocio=@documento)
            select 'Ya está inscripto en '+@deporte+' el '+ @dia
     else
       if @matricula is null or @matricula='s' or @matricula='n'
       begin
        insert into inscriptos values(@documento,@codcurs,@matricula)
        print 'Inscripción del socio '+@documento+' para '+@deporte+' el '+@dia+' realizada'  
       end
       else select 'Matricula debe ser s, n o null'
   end;

   go

-- Podemos ejecutar el procedimiento "pa_ingreso" con distintos valores para ver el resultado.
-- Enviamos un documento que no está en "socios":
 exec pa_ingreso '22222222';

-- Enviamos un documento de un socio que tiene deudas:
 exec pa_ingreso '30000000';

-- Enviamos un documento de un socio que no tiene deudas, pero falta el deporte y el día:
 exec pa_ingreso '31111111';

-- Enviamos valor de día inválido:
 exec pa_ingreso '31111111','tenis','sabado';

-- Enviamos datos que ya están en la tabla "inscriptos":
 exec pa_ingreso '31111111','tenis','jueves';

-- Enviamos el documento de un socio y un deporte y día en el cual no está inscripto:
 exec pa_ingreso '33333333','tenis','jueves';

-- Podemos verificar este ingreso consultando "pa_inscriptos":
 exec pa_inscriptos;

-- Eliminamos el procedimiento "pa_profesor", si existe:
 if (object_id('pa_profesor')) is not null
  drop proc pa_profesor;

 go
 
-- Creamos un procedimiento que recibe el documento de un profesor y nos muestra los 
-- distintos deportes de los cuales está a cargo y los días en que se dictan: 
 create proc pa_profesor
  @documento char(8)=null
 as
  if @documento is null or len(@documento)<8
    select 'Ingrese un documento válido'
  else
  begin
   declare @nombre varchar(30)
   select @nombre=nombre from profesores where documento=@documento
   if @nombre is null select 'No es profesor'
   else
     if not exists(select *from cursos where documentoprofesor=@documento)
       select 'El profesor '+@nombre+' no tiene cursos asignados'
     else
       select d.nombre,c.dia
        from cursos as c
        join deportes as d
        on c.codigodeporte=d.codigo
        where c.documentoprofesor=@documento
  end;

 go

-- Ejecutamos el procedimiento creado anteriormente enviando un documento que 
-- no está en la tabla "profesores":
 exec pa_profesor '34343434';

-- Nuevamente ejecutamos el procedimiento creado anteriormente, esta vez con
-- un documento existente en "profesores": 
 exec pa_profesor '22222222';

-- Eliminamos el procedimiento "pa_inscriptos_por_curso", si existe:
 if (object_id('pa_inscriptos_por_curso')) is not null
  drop proc pa_inscriptos_por_curso;

 go

-- Creamos un procedimiento que recibe un parámetro correspondiente al nombre de un deporte
-- y muestra los distintos cursos (número, día y profesor) y la cantidad de inscriptos; 
-- en caso que el parámetro sea "null", muestra la información de todos los cursos:
 create procedure pa_inscriptos_por_curso
  @deporte varchar(20)=null
 as
  if @deporte is null
    select c.numero,d.nombre,dia,p.nombre,
     (select count(*)
     from inscriptos as i
     where i.numero=c.numero) as cantidad
     from cursos as c
     join deportes as d
     on c.codigodeporte=d.codigo
     join profesores as p 
     on p.documento=c.documentoprofesor
  else
    select c.numero,dia,p.nombre,
     (select count(*)
     from inscriptos as i
     where i.numero=c.numero) as cantidad
     from cursos as c
     join deportes as d
     on c.codigodeporte=d.codigo
     join profesores as p 
     on p.documento=c.documentoprofesor
     where d.nombre=@deporte;    

 go

-- Ejecutamos el procedimiento sin enviar valor para el parámetro:
 exec pa_inscriptos_por_curso;

 -- Ejecutamos el procedimiento enviando un valor:
 exec pa_inscriptos_por_curso 'tenis';

-- Ejecutamos el procedimiento enviando otro valor:
 exec pa_inscriptos_por_curso 'voley';

-- Veamos las dependencias. Ejecutamos "sp_depends" con distintos objetos:
 exec sp_depends socios;

 exec sp_depends profesores;

 exec sp_depends cursos;

 exec sp_depends deportes;

 exec sp_depends inscriptos;

-- Vemos las dependencias de los distintos procedimientos:
 exec sp_depends pa_documentovalido;

 exec sp_depends pa_inscriptos;

 exec sp_depends pa_deportediavalido;

 exec sp_depends pa_ingreso;

 exec sp_depends pa_profesor;

 exec sp_depends pa_inscriptos_por_curso;

Retornar