Explora Libros electrónicos
Categorías
Explora Audiolibros
Categorías
Explora Revistas
Categorías
Explora Documentos
Categorías
Un procedimiento puede tener uno o mas parmetros o tambin no tener ninguno. Puede
carecer de atributos o puede poseer varios. Y como ves, el cuerpo del procedimiento es un
bloque de instrucciones definido.
La sentencia DELIMITER cambia el carcter de terminacin ';' por cualquier otro carcter,
en este caso elegimos '//'. Se hace con el fin de que MySQL no termine el procedimiento
al encontrar el primer punto y coma. Al final restablecemos el valor original del caracter de
escape.
DELIMITER //
CREATE PROCEDURE insertar(id_cliente INT, nombre_cliente VARCHAR(100),
apellido_cliente VARCHAR(100))
COMMENT 'Procedimiento que inserta un cliente a la base de datos'
BEGIN
IF NOT EXISTS ( SELECT C.ID
FROM CLIENTE AS C
WHERE C.ID = id_cliente) THEN
INSERT INTO CLIENTE(ID, NOMBRE, APELLIDO)
VALUES ( id_cliente,nombre_cliente,apellido_cliente);
ELSE
SELECT 'Este cliente ya existe en la base de datos!';
END IF;
END//
DELIMITER ;
Sintaxis de un Procedimiento
CREATE [PROCEDURE|PROC] nombre_procedimiento [#|##] [(
parmetro1,parmetro2,... )]
[{FOR REPLICATION|WITH RECOMPILE}][WITH ENCRYPTION]
AS<bloque de sentencias>
Ejemplo de Procedimientos
A continuacin construiremos un procedimiento con respecto al siguiente enunciado:
Cree un procedimiento que imprima el total de una factura al ingresar el cdigo de la
factura.
Normalmente en un sistema de facturacin hay una tabla FACTURA y RENGLON. Donde
rengln es el detalle de cada articulo comprado y su precio. Por lo tanto una factura es
especificada por muchos renglones. Teniendo esto claro vamos a escribir nuestro
procedimiento, en el cual sumaremos el resultado de cada rengln en la factura con
respecto al parmetro de entrada.
CREATE PROCEDURE total_factura (@id_factura INT)
AS
BEGIN
SELECT SUM(UNIDADES*PRECIO) FROM RENGLON
WHERE RENGLON.IDFACTURA = @id_factura;
END;
Como ves, hemos hecho una sencilla consulta en la tabla RENGLON para sumar el subtotal
de cada producto en la factura. En el WHERE (Ver ms sobre esta sentencia) hemos hecho
una comparacin del ID de la factura con el parmetro ingresado al procedimiento.
Modificar un Procedimiento
Usaremos ALTER PROCEDURE para modificar procedimientos en SQL Server. Con
esta sentencia se busca cambiar el cuerpo y las caractersticas de un procedimiento ya
creado:
ALTER PROCEDURE nombre_procedimiento
<nuevas caractersticas>
AS
<nuevo bloque de instrucciones>
Como ves, no es posible visualizar el cuerpo del procedimiento, lo que indica que la
modificacin fue exitosa.
Borrar un Procedimiento
Para borrar un procedimiento en SQL Server se usa la sentencia DROP PROCEDURE:
DROP PROCEDURE nombre_procedimiento
Sencillo no?
Miremos un pequeo ejemplo. Borraremos un procedimiento llamado retiro_fondos:
DROP PROCEDURE retiro_fondos
IF THEN ELSE:
El condicional simple IF que tenemos en la mayora de los lenguajes de programacin, que
puede ser complementado o no con un ELSE para el caso de que no se cumpla. La sintaxis
es IF condicin THEN (el ELSE si hace falta) END IF. Podis ver un ejemplo:
1
2
delimiter $$
CREATE procedure ej(IN val int)
/* Parmetro de entrada */
begin
IF val = 0 then
end IF;
end$$
delimiter ;
10
CASE:
Condicional que nos permite evaluar el valor de una variable y realizar diversas acciones
segn varias posibilidades. Es una forma de abreviar un montn de IF anidados. En
este caso el ELSE nos permite definir un valor por defecto (como el default en un
switch/case de C, Java o PHP):
1
2
delimiter $$
CREATE procedure ej(IN val int)
/* Parmetro de entrada */
begin
case val
end$$
delimiter;
10
WHILE:
Un bucle que hace que un procedimiento se repita mientras se de una condicin. Si la
condicin ya no se da antes de entrar al bucle, no entra.
1
delimiter $$
begin
define i int;
set i = 0;
while i<5 do
INSERT INTO prueba VALUES (i);
set i=i+1;
end while;
end$$
10
delimiter ;
11
/* Parmetro de entrada */
REPEAT:
Lo contratio que WHILE, repeat es un bucle UNTIL, se realiza hasta que se de una
condicin. Si bien tambin comparte con el DOWHILE de C (y Java, y PHP) que
siempre se ejecuta al menos una vez.
1
delimiter $$
/* Parmetro de entrada */
begin
define i int;
set i = 0;
repeat
set i=i+1;
until i <= 5;
9
10
end repeat;
end$$
11
delimiter ;
12
6END $$
DELIMITER;
Esta tendr un mbito local y cuando se acabe el procedimiento no podr ser accedida. Una
vez la variable es declarada, para cambiar su valor usaremos la sentencia SET de este modo
:
set miVar = 56 ;
Para poder acceder a una variable a la finalizacin de un procedimiento se tiene que usar
parmetros de salida.
Vamos a ver unos ejemplos para comprobar lo sencillo que es :
IF THEN ELSE
delimiter //
create procedure miProc(in p1 int)
/* Parmetro de entrada */
begin
declare miVar int;
/* se declara variable local */
set miVar = p1 +1 ;
/* se establece la variable */
if miVar = 12 then
insert into lista values(55555);
else
insert into lista values(7665);
end if;
end;
//
SWITCH
delimiter //
create procedure miProc
begin
declare var int
set var = p1 +2
case var
when 2 then
when 3 then
else insert
end case;
end;
//
(in p1 int)
;
;
insert into lista values (66666);
insert into lista values (4545665);
into lista values (77777777);
La funcin strcmp devuelve 0 si las cadenas son iguales, si no devuelve 0 es que son
diferentes.
USO DE WHILE
delimiter //
create procedure p14()
begin
declare v int;
set v = 0;
while v < 5 do
insert into lista values (v);
set v = v +1 ;
end while;
end;
//
delimiter //
create procedure p16()
begin
declare v int;
set v = 0;
loop_label : loop
insert into lista values (v);
set v = v + 1;
if v >= 5 then
leave loop_label;
end if;
end loop;
end;
//
Este es otro tipo de loop, la verdad es que teniendo los anteriores no se me ocurre
aplicacin para usar este tipo de loop, pero es bueno saber que existe por si algn da te
encuentras algn procedimiento muy antiguo que lo use. El cdigo que haya entre
loop_label : loop y end loop; se ejecutara hasta que se encuentre la sentencia leave
loop_label; que hemos puesto en la condicin, por lo tanto el loop se repetir hasta que la
variable v sea >= que 5.
El loop puede tomar cualquier nombre, es decir puede llamarse miLoop: loop, en cuyo caso
se repetir hasta que se ejecute la sentencia leave miLoop.
Con esto ya podemos empezar a crear procedimientos medianamente complejos y
tiles.
RETURN HolaMundo;
END
//
Esta variable es de mbito local, y ser destruida una vez finalice la funcin. Cabe destacar
el uso de la sentencia DEFAULT en conjunto con DECLARE, que asigna un valor por
defecto al declarar la variable.
Ahora hemos creado una funcin que devuelve el mismo valor que le pasamos como
parmetro.
Si tecleamos :
mysql> select holaMundo("nosolocodigo")//
+---------------------------+
| holaMundo("nosolocodigo") |
+---------------------------+
| nosolocodigo
|
+---------------------------+
1 row in set (0.00 sec)
Obtenemos como resultado lo mismo que le hemos pasado como prametro, en este caso
nosolocodigo
Para finalizar, algo un poco ms complejo, vamos a crear una funcin que acepte un
dividendo y un divisor y haga una divisin sin usar el operador divisin:
create function divide(dividendo int,divisor int) returns int
begin
declare aux int;
declare contador int;
declare resto int;
set contador = 0;
set aux = 0;
while (aux + divisor) <= dividendo do
set aux = aux + divisor ;
set contador = contador + 1;
end while;
set resto = dividendo - aux ;
return contador;
end;
//
Para poner nombre a los triggers es conveniente seguir una convencin que har ms fcil
identificar sobre que evento y tabla acta el trigger. Esta sera una buena forma de nombrar
nuestros triggers:
NombreTabla + _ + abreviatura_tipo_tigger
Por lo tanto para nombrar un triger que se ejecuta sobre la tabla T1 despus de un update lo
haramos de la siguiente forma si seguimos esta convencin:
T1_BU
Esto puede ser til, pero no es necesario, puedes poner el nombre que quieras a tu trigger.
Para crear triggers en una tabla es necesario hacerlo desde un usuario con permisos para
ello. Para dar permiso a un usuario en una tabla para crear un trigger lo haramos de la
siguiente forma:
GRANT CREATE TRIGGER ON nombreTabla TO Usuario
Y despus creamos un trigger que va a crear una variable global con el nombre antiguo
antes de ejecutar el update y otra con el nombre nuevo que habr despus de ejecutar el
update.
delimiter //
create trigger miTabla_bu before update
on miTabla
for each row
begin
set @nombreViejo = OLD.nombre;
set @nombreNuevo = NEW.nombre;
end//
En esta ocasin, cada vez que se haga un insert sobre la tabla miTabla, se crear una
variable global con el valor Trigger activado y modificar el valor que se insertar en la
columna nombre, por lo que siempre se insertar el valor Valor introducido desde el
trigger.
Si lo que queremos es mantener el control de una tabla para ver quien la modifica y a que
hora, podemos crear una tabla donde iremos anotando quien hace cada modificacin y
anotar los cambios.
Creamos la tabla auxiliar
CREATE TABLE controlMiTabla
(
id int not null auto_increment,
id_registro int,
anterior_nombre varchar(50),
nuevo_nombre varchar(50),
usuario varchar(40),
modificado datetime,
primary key(id)
) ENGINE = InnoDB;
Y ahora vamos a crear un trigger que se encargue de llevar un log de quien actualiza la
tabla, que valores modifica y a que hora:
delimiter //
create trigger MiTabla_BU after update on miTabla
for each row
begin
insert into controlMiTabla (id_registro, anterior_nombre ,
nuevo_nombre, usuario , modificado ) values(OLD.id , OLD.nombre ,
NEW.nombre, CURRENT_USER(), NOW() );
end//