Group: Hackerss Member
Posts: 1,607
Joined: 22-March 06
From: UnderHouse
Member No.: 8
Qué es un dispador? Los disparadores (también conocido como triggers) son conjunto de instrucciones (sql claro) que se ejecutan cuando se produce una de las siguientes acciones: INSERT, DELETE o UPDATE de ahí su utilidad. Para quién quiera saber más mirar:
Con ellos podemos ahorrar algunas líneas de programación si estamos usando MySQL y dejar el trabajo al propio manejador de Base de Datos. Veamos un ejemplo rápido y ustedes decidan si son útiles o no.
Para empezar necesitamos usar tablas tipo InnoDB, para saber si tenemos esa posibilidad podemos teclear desde la consola de MySQL:
+---------------------------------+---------------------------------+ 35 rows in SET (0.00 sec)
Por defecto creo desde MySQL 5.0 las tablas se crean de tipo InnoDB.
El escenario es el siguiente: Diseñamos una base de datos para poder controlar la facturación de una tienda, entonces realizamos la base de datos de la siguiente forma:
MySQL:
CODE
CREATE DATABASE FACTURA;
USE FACTURA;
CREATE TABLE VENTA (
Folio CHAR(30) NOT NULL UNIQUE,
Fecha DATETIME NOT NULL,
PRIMARY KEY (Folio)
);
CREATE TABLE PRODUCTO (
Codigo INTEGER NOT NULL UNIQUE,
Descripccion CHAR(30) NOT NULL,
Precio FLOAT NOT NULL,
Existencia INTEGER DEFAULT 0 NOT NULL,
PRIMARY KEY (Codigo)
);
CREATE TABLE DETALLE_DE_VENTA (
Folio CHAR(30) NOT NULL,
Codigo INTEGER NOT NULL,
Cantidad INTEGER NOT NULL,
Precio FLOAT NOT NULL,
PRIMARY KEY (Folio,Codigo)
);
ALTER TABLE DETALLE_DE_VENTA add FOREIGN key(Folio) REFERENCES VENTA (Folio);
ALTER TABLE DETALLE_DE_VENTA add FOREIGN key(Codigo) REFERENCES PRODUCTO (Codigo);
Creación de la base de datos:
CODE:
CODE
UnderHouse sql # mysql -p < db.sql
Ingresamos algunos datos ficticios para el ejercicio:
MySQL:
CODE
INSERT INTO PRODUCTO (Codigo, Descripccion,Precio) VALUES (01,'MEMORIA RAM',500);
INSERT INTO PRODUCTO (Codigo, Descripccion,Precio) VALUES (02,'MEMORIA USB',500);
INSERT INTO PRODUCTO (Codigo, Descripccion,Precio) VALUES (03,'GABINETE',80);
INSERT INTO PRODUCTO (Codigo, Descripccion,Precio) VALUES (04,'TARJETA DE VIDEO',1000);
INSERT INTO VENTA VALUES('200716100001','2007-10-16');
INSERT INTO VENTA VALUES('200716100002','2007-10-16');
INSERT INTO VENTA VALUES('200716100003','2007-10-16');
UPDATE PRODUCTO SET existencia='10' WHERE codigo=01;
UPDATE PRODUCTO SET existencia='20' WHERE codigo=02;
UPDATE PRODUCTO SET existencia='5' WHERE codigo=03;
Lógicamente analizando detenidamente la base de datos podemos crear un trigger cuando se presenta la siguiente situación:
Cuando una venta se lleva a cabo es necesario restar la cantidad de producto que se vendió a la existencia que tenemos del mismo, en caso de no haber existencia suficiente del producto, no permitir que el registro de la nueva venta se lleve a cabo.
El trigger correspondiente que soluciona la situación anterior es:
MySQL:
CODE
USE FACTURA;
DELIMITER |
CREATE trigger disminuir_existencia BEFORE INSERT ON DETALLE_DE_VENTA
FOR EACH ROW
BEGIN
DECLARE Existencia_Producto INTEGER;
SELECT PRODUCTO.Existencia INTO Existencia_Producto FROM PRODUCTO WHERE PRODUCTO.Codigo = NEW.Codigo;
IF Existencia_Producto>= NEW.Cantidad THEN
UPDATE PRODUCTO SET Existencia=Existencia-NEW.Cantidad WHERE PRODUCTO.Codigo = NEW.Codigo;
ELSE
SET NEW.Folio = NULL;
END IF;
END|
DELIMITER;
Pueden copiarlo a un archivo *.sql y pasarlo de la siguiente forma:
CODE:
CODE
UnderHouse sql # mysql -p < disparador.sql
Lo que hace es:
1) Extrae la existencia del producto que se trata de vender y se le asigna a la variable Existencia_Producto.
2) Verifica si la cantidad que se quiere vender es menor o igual a la existencia disponile (IF).
3) Si la venta es posible, se actualiza el valor de la existencia del producto que se quiere vender y el registro se lleva a cabo correctamente.
4) Si la venta no es posible, se crea un error a propósito para impedir que el registro se lleve a cabo correctamente (nota: en sqlserver es posible usar ROLLBACK pero con mysql no encontré otra forma de detener el insert, si alguien lo sabe y desea compartirlo ps con un comentario basta).
Cuestiones a tomar en cuenta para crear un trigger:
QUOTE
También hay limitaciones sobre lo que puede aparecer dentro de la sentencia que el disparador ejecutará al activarse:
*
El disparador no puede referirse a tablas directamente por su nombre, incluyendo la misma tabla a la que está asociado. Sin embargo, se pueden emplear las palabras clave OLD y NEW. OLD se refiere a un registro existente que va a borrarse o que va a actualizarse antes de que esto ocurra. NEW se refiere a un registro nuevo que se insertará o a un registro modificado luego de que ocurre la modificación.
*
El disparador no puede invocar procedimientos almacenados utilizando la sentencia CALL. (Esto significa, por ejemplo, que no se puede utilizar un procedimiento almacenado para eludir la prohibición de referirse a tablas por su nombre).
*
El disparador no puede utilizar sentencias que inicien o finalicen una transacción, tal como START TRANSACTION, COMMIT, o ROLLBACK.
Veamos si funcionan realmente:
MySQL:
CODE
/*
Valores iniciales
*/
mysql> SELECT * FROM DETALLE_DE_VENTA;
+--------------+--------+----------+--------+
| Folio | Codigo | Cantidad | Precio |
+--------------+--------+----------+--------+
| 200716100001 | 1 | 5 | 600 |
| 200716100001 | 2 | 10 | 600 |
| 200716100001 | 3 | 1 | 600 |
+--------------+--------+----------+--------+ 3 rows in SET (0.00 sec)
+--------+------------------+--------+------------+ 4 rows in SET (0.00 sec)
Eso es todo , como ejercicio pueden agregar que si la venta no se ingresa correctamente en la tabla DETALLE_DE_VENTA proceda a eliminar el registro de dicha venta en la tabla VENTA.
Group: Hackerss Member
Posts: 1
Joined: 3-November 08
Member No.: 6,399
Te agradezco mucho este post. He estado buscando info acerca de los triggers en mySQL pero he encontrado muy poca. Veremos con este tuto que se mira muy claro y explicativo.