Implementación de Bases de Datos Activas y Triggers SQL: Ejercicios Resueltos
Clasificado en Informática
Escrito el en español con un tamaño de 12,87 KB
Base de Datos II
Resoluciones (Modelo) de Ejercicios Prácticos
Base de Datos Activas – Práctico 1
1) Creación de Tabla Empleados y Dominio Personalizado
A continuación, se presenta la definición de la tabla Empleados con sus respectivos atributos y restricciones:
CREATE TABLE Empleados
(
DNI CHAR(8) NOT NULL PRIMARY KEY,
Legajo CHAR(6) UNIQUE,
Ape_Nom VARCHAR2(50),
Cargo NUMBER CHECK(Cargo BETWEEN 50 AND 120),
Sueldo DEC(8,2) CHECK(Sueldo <= 30000)
);
Alternativa: Crear un tipo de datos de usuario a partir de un tipo de dato estándar; luego, lo podemos referenciar, por ejemplo, al definir una tabla.
CREATE DOMAIN Documento INT(8) CHECK(Documento > 0);
Se modificaría la definición de la tabla Empleados para el atributo DNI, que haría referencia al tipo de dato Documento creado previamente:
DNI Documento PRIMARY KEY,
Implementación de un Trigger para controlar la actualización del sueldo:
CREATE TRIGGER Control_Sueldo
BEFORE UPDATE OF Sueldo ON Empleados -- Cuando se actualiza el atributo Sueldo de la tabla Empleados
FOR EACH ROW -- Se activa este disparador, controlando que el Sueldo no se
BEGIN -- incremente en más del 20% del valor del Sueldo anterior
IF :new.Sueldo > (:old.Sueldo * 1.20) THEN
-- Sentencia que cancela la actualización (ej. RAISE_APPLICATION_ERROR('Error', 'Aumento de sueldo excede el 20%'));
END IF;
END;
Una forma de incorporar comentarios en las sentencias SQL es mediante el uso de --
o /* */
:
-- Esto es un comentario de una línea
Y otra manera es:
/*
Comentario
en varias
líneas
*/
2) Definición de Tabla Seguros con Claves Foráneas y Restricciones
Definición de la tabla Seguros, incluyendo claves foráneas y restricciones de valores:
CREATE TABLE Seguros
(
Nro_Poliza CHAR(8) NOT NULL PRIMARY KEY,
DNI CHAR(6) REFERENCES Clientes(DNI),
Marca CHAR(7) CHECK(Marca IN ('Ford', 'Renault', 'Fiat', 'Peugeot', 'VW')),
Modelo CHAR(4) DEFAULT '2015',
Patente CHAR(10),
Nro_Motor VARCHAR2(30),
Imp_Pagar DEC(10,2) NOT NULL,
FOREIGN KEY(Marca, Modelo) REFERENCES Vehiculos(Marca, Modelo)
);
3) Gestión de Pedidos con Triggers de Control de Stock
Definición de la tabla Pedidos con sus atributos y un trigger para controlar el stock:
CREATE TABLE Pedidos
(
Nro_Orden CHAR(6) NOT NULL UNIQUE,
Fecha_Pedido DATE DEFAULT CURRENT_DATE,
CUIT CHAR(11) NOT NULL,
CUIT_Proveedor CHAR(11) NOT NULL, -- Se agrega este atributo
REFERENCES Clientes(CUIT),
PRIMARY KEY(CUIT, Nro_Orden),
Nro_Producto NUMBER,
Tipo_Pedido CHAR(1) CHECK(Tipo_Pedido IN ('M', 'C', 'G', 'H', 'N')),
Cant_Pedida INT CHECK(Cant_Pedida > 0)
);
Trigger para controlar la cantidad pedida en relación con el stock disponible:
CREATE TRIGGER Control_Pedido
BEFORE INSERT ON Pedidos
FOR EACH ROW
BEGIN
/* La condición evalúa que la nueva cantidad pedida no sea mayor al valor del stock actual
del producto que se rescata de la tabla Stock_Productos */
IF :new.Cant_Pedida > (SELECT Stock_Actual FROM Stock_Productos
WHERE Producto = :new.Nro_Producto) THEN
-- Sentencia que cancela la inserción (ej. RAISE_APPLICATION_ERROR('Error', 'Cantidad pedida superior al stock disponible'));
ELSE
UPDATE Stock_Productos
SET Stock_Actual = Stock_Actual - :new.Cant_Pedida
WHERE Producto = :new.Nro_Producto;
END IF;
END;
4) Adición de Restricciones a la Tabla Pedidos
Estas restricciones se agregarían a las sentencias del ejercicio 3), al definir la tabla Pedidos:
CONSTRAINT ClaveProducto FOREIGN KEY (Nro_Producto, Tipo_Pedido) REFERENCES Productos(Id_Producto, Id_Tipo),
CONSTRAINT CantidadPermitida CHECK(Cant_Pedida BETWEEN 10 AND 2000);
Para añadir una restricción a una tabla existente:
ALTER TABLE Pedidos WITH NO CHECK ADD
CONSTRAINT ControlCuit CHECK (CUIT <> CUIT_Proveedor);
5) Creación de Tablas Clientes y Facturas con Trigger de Cálculo
Definición de un Dominio para el código de cliente:
CREATE DOMAIN CodigoCliente INT(7) CHECK (CodigoCliente > 0);
Definición de la tabla Clientes:
CREATE TABLE Clientes
(
Cod_Cliente CodigoCliente PRIMARY KEY,
Nombre VARCHAR2(40) NOT NULL,
Direccion VARCHAR2(35) NOT NULL,
Cod_Postal CHAR(5),
FOREIGN KEY (Cod_Postal) REFERENCES CodPostales(CP),
Importe_Base DEC(8,2)
);
Definición de la tabla Facturas:
CREATE TABLE Facturas
(
Nro_Factura CHAR(8) NOT NULL PRIMARY KEY,
Fecha_Fact DATE,
Cliente_Factura CodigoCliente,
FOREIGN KEY(Cliente_Factura) REFERENCES Clientes(Cod_Cliente),
Tipo_Descuento INT(2) CHECK(Tipo_Descuento BETWEEN 5 AND 20),
IVA INT(2) CHECK((IVA = 15) OR (IVA = 21)),
Importe DEC(10,2) NOT NULL
);
Trigger para calcular el importe de la factura:
CREATE TRIGGER Calcular_Importe
BEFORE UPDATE OF Importe_Base ON Clientes
FOR EACH ROW
DECLARE
Resultado DEC(10,2); -- Variable auxiliar declarada dentro del trigger
BEGIN
-- Descontamos del importe base el respectivo importe de acuerdo al valor de descuento
Resultado := :new.Importe_Base - ((:new.Tipo_Descuento * :new.Importe_Base) / 100);
/* Al importe obtenido en el paso anterior, que almacenamos en el campo auxiliar ‘Resultado’,
debemos incrementar dicho valor de acuerdo al porcentaje del IVA a aplicar */
Resultado := Resultado + ((:new.IVA * Resultado) / 100);
UPDATE Facturas
SET Importe = Resultado
WHERE Cliente_Factura = :new.Cod_Cliente;
END;
6) Registro y Eliminación de Empleados Dados de Baja
Definición de la tabla Empleado_Baja para registrar empleados eliminados:
CREATE TABLE Empleado_Baja
(
DNI CHAR(8),
Legajo CHAR(6),
Cargo NUMBER,
Usuario VARCHAR2(15),
Fecha DATE
);
Trigger para registrar empleados eliminados:
CREATE TRIGGER Empleado_Eliminado -- Se registran en una tabla aquellos empleados dados de
AFTER DELETE ON Empleados -- baja
FOR EACH ROW
BEGIN
INSERT INTO Empleados_Baja VALUES (:old.DNI, :old.Legajo, :old.Cargo, USER, SYSDATE);
END;
Trigger para eliminar el usuario asociado a un empleado dado de baja:
CREATE TRIGGER Baja_Usuario -- Eliminamos el usuario del empleado, con el cual accedía al sistema
AFTER DELETE ON Empleados -- de gestión de la empresa a la cual pertenecía
FOR EACH ROW
BEGIN
DELETE FROM Usuarios WHERE Usuarios.DNI = :old.DNI;
END;
7) Modificación y Desactivación de Triggers
Para reemplazar un trigger existente (por ejemplo, cambiando la condición de eliminación):
REPLACE TRIGGER Baja_Usuario
AFTER DELETE ON Empleados
FOR EACH ROW
BEGIN
DELETE FROM Usuarios WHERE Usuarios.Legajo = :old.Legajo;
END;
Para deshabilitar un trigger específico:
ALTER TRIGGER Calcular_Importe DISABLE;
Para deshabilitar todos los triggers de una tabla:
ALTER TABLE Consumos DISABLE ALL TRIGGERS;
8) Adición de Columnas y Trigger de Recargo en Facturas
Dependerá del manejador de base de datos que usemos, ya que permite distintos formatos para agregar columnas a una tabla.
Opción 1: Añadir columnas individualmente
ALTER TABLE Facturas ADD Fecha_Vto DATE;
ALTER TABLE Facturas ADD Fecha_Pago DATE;
ALTER TABLE Facturas ADD Intereses INT NULL;
Opción 2: Añadir múltiples columnas en una sola sentencia
ALTER TABLE Facturas ADD Fecha_Vto DATE, Fecha_Pago DATE, Intereses INT NULL;
Trigger para aplicar un recargo en facturas si la fecha de pago excede la fecha de vencimiento:
CREATE TRIGGER Recargo_Factura
AFTER UPDATE OF Fecha_Pago ON Facturas
FOR EACH ROW
BEGIN
IF :new.Fecha_Pago > :new.Fecha_Vto THEN
UPDATE Facturas
SET Intereses = 1
WHERE Cliente_Factura = :new.Cod_Cliente;
END IF;
END;
Comentarios Generales sobre Triggers
En los triggers, podemos hacer referencia a los valores que insertamos o actualizamos anteponiendo al nombre de cada atributo :new.
; y para hacer referencia a los valores de una fila que vamos a eliminar, anteponemos :old.
. Ejemplos:
:new.Cantidad_Pedida
- Cantidad pedida de un cierto producto:old.DNI
- DNI del empleado eliminado de la respectiva tabla
Recuerden que estas resoluciones pueden sufrir cambios de acuerdo a otra forma de plantearlos que cada uno desee incorporar, pero siempre llegando a soluciones válidas para los ítems requeridos.