Está en la página 1de 30

Bases de datos distribuidas.

Diseño BD de sede

CLIENTE DFE

CUENTA DFE

MOVIMIENTO

IOV.

CLIENTE(SUJETO)
cedula,nombre, direccion, telefono

CUENTA(GT1)
numero, fecha_apertura

MOVIMIENTO(GT1.1)
numero_movimiento, valor, fecha, tipo sede

Tablas

CLIENTE

cedula,nombre, direccion, telefono


PKS

CUENTA

cedula,numero_cuenta, fecha_apertura
PKS PKGT1

MOVIMIENTO
numero_cuenta, numero_movimiento, valor, fecha, tipo sede
PKGT1 PKGT1.1

MER
VALO NUMERO_MOVIMIE
TIPO
R NTO

SEDE MOVIMIEN
TO
FECH NUMERO_CUEN
A TA

NUMERO_CUEN FECHA_APERTUR
TA A

CUENTA
CEDUL
A

CEDUL DIRECCIO
A N

CLIENT
E
NOMB TELEFON
RE O

MR

MOVIMIENTO
NUMERO_MOVIMIENTO
pkNUMERO_CUENTA
fkVALORFECHATIPOSEDE

CUENTA
NUMERO_CUENTA
pkCEDULA
fkFECHA_APERTURA
CLIENTE
CEDULA
pkNOMBREDIRECCIONT
ELEFONO

TABLA FORANEA
MOVIMIENTO_TF
numero_cuenta, numero_movimiento, valor, fecha, tipo sede

BANCO PRINCIPAL

SALDO_CUENTA
cedula,numero_cuenta, saldo

AUDITORIA
fecha_movimiento, numero_movimiento id_auditoria

El modelo de la aplicación es el siguiente:

BANCO_BOGOTA BANCO_PRINCIPAL BANCO_CALI

CLIENTE SALDO_CUENTA CLIENTE

CUENTA CUENTA

MOVIMIENTO MOVIMIENTO

MOVIMIENTO_TF AUDITORIA MOVIMIENTO_TF

Procedimiento
Cuando se realiza la inserción de una cuenta asociada a un cliente en cualquiera de las sedes
del banco, Bogotá o Cali se dispara el siguiente procedimiento almacenado que permite que se
cree en la sede principal el registro en la tabla saldo cuenta.

Creando cliente en el banco_bogota


Se ejecuta el siguiente trigger de la cuenta para crear el registro en la tabla de la sede principal

BANCO BOGOTÁ

-- Trigger DDL Statements


DELIMITER $$
USE `BANCO_BOGOTA`$$

CREATE
DEFINER=`root`@`localhost`
TRIGGER `BANCO_BOGOTA`.`CREATE_CUENTA_PP`
BEFORE INSERT ON `BANCO_BOGOTA`.`CUENTA`
FOR EACH ROW
BEGIN
INSERT INTO BANCO_PRINCIPAL.SALDO_CUENTA VALUES (NEW.CEDULA,NEW.NUMERO_CUENTA,0);
END$$

El resultado es el siguiente

Creamos otro cliente en la ciudad de cali


Creamos una cuenta asociada al cliente

Al crearse este registro se ejecuta el siguiente trigger que crea el registro de saldo_cuenta en la
sede principal

BANCO CALI
-- Trigger DDL Statements
DELIMITER $$

USE `BANCO_CALI`$$

CREATE
DEFINER=`root`@`localhost`
TRIGGER `BANCO_CALI`.`CREATE_CUENTA_PP`
BEFORE INSERT ON `BANCO_CALI`.`CUENTA`
FOR EACH ROW
BEGIN
INSERT INTO BANCO_PRINCIPAL.SALDO_CUENTA VALUES (NEW.CEDULA,NEW.NUMERO_CUENTA,0);
END$$

A continuación al realizar un movimiento en la cuenta local desde la sede de bogotá se debe


tener actualizado el saldo de la cuenta en la sede principal.
Al realizarse la operación se ejecuta el siguiente trigger que actualiza el saldo en la sede
principal.

BANCO BOGOTÁ

-- Trigger DDL Statements


DELIMITER $$

USE `BANCO_BOGOTA`$$

CREATE
DEFINER=`root`@`localhost`
TRIGGER `BANCO_BOGOTA`.`CREATE_MOVIMIENTO_PP`
BEFORE INSERT ON `BANCO_BOGOTA`.`MOVIMIENTO`
FOR EACH ROW
BEGIN
DECLARE EXISTE INT;
DECLARE VALOR_SALDO DOUBLE;
DECLARE MSG VARCHAR(255);

SET EXISTE = (SELECT COUNT(NUMERO_CUENTA) FROM BANCO_PRINCIPAL.SALDO_CUENTA WHERE


NUMERO_CUENTA = NEW.NUMERO_CUENTA);
IF(EXISTE = 0) THEN
SET MSG = CONCAT('CUENTA NO EXISTE. NUMERO DE CUENTA: ',CAST(NEW.NUMERO_CUENTA AS
CHAR));
signal sqlstate '45000' set message_text = MSG;
END IF;

IF (NEW.TIPO='DEBITO') THEN
UPDATE BANCO_PRINCIPAL.SALDO_CUENTA SET SALDO=SALDO+NEW.VALOR WHERE
NUMERO_CUENTA = NEW.NUMERO_CUENTA;
END IF;
IF (NEW.TIPO='CREDITO') THEN
/*CREDITO*/
SET VALOR_SALDO = (SELECT SALDO FROM BANCO_PRINCIPAL.SALDO_CUENTA WHERE
NUMERO_CUENTA = NEW.NUMERO_CUENTA);
IF(NEW.VALOR>VALOR_SALDO) THEN
SET MSG = CONCAT('SALDO NO DISPONIBLE. SALDO ACTUAL: ',CAST(VALOR_SALDO AS
CHAR));
signal sqlstate '45000' set message_text = MSG;
END IF;
UPDATE BANCO_PRINCIPAL.SALDO_CUENTA SET SALDO=SALDO-NEW.VALOR WHERE
NUMERO_CUENTA = NEW.NUMERO_CUENTA;
END IF;

END$$

Lo que permite que el saldo quede actualizado.

Realizamos ahora la prueba en el banco de cali esta vez primero realizamos una transacción
tipo crédito lo que nos visualiza el mensaje del trigger
Luego creamos un movimiento válido

Esto ejecuta el trigger en la tabla de movimientos de cali que se muestra a continuación

BANCO CALI
-- Trigger DDL Statements
DELIMITER $$

USE `BANCO_CALI`$$

CREATE
DEFINER=`root`@`localhost`
TRIGGER `BANCO_CALI`.`CREATE_MOVIMIENTO_PP`
BEFORE INSERT ON `BANCO_CALI`.`MOVIMIENTO`
FOR EACH ROW
BEGIN
DECLARE EXISTE INT;
DECLARE VALOR_SALDO DOUBLE;
DECLARE MSG VARCHAR(255);

SET EXISTE = (SELECT COUNT(NUMERO_CUENTA) FROM BANCO_PRINCIPAL.SALDO_CUENTA WHERE


NUMERO_CUENTA = NEW.NUMERO_CUENTA);
IF(EXISTE = 0) THEN
SET MSG = CONCAT('CUENTA NO EXISTE. NUMERO DE CUENTA: ',CAST(NEW.NUMERO_CUENTA AS
CHAR));
signal sqlstate '45000' set message_text = MSG;
END IF;

IF (NEW.TIPO='DEBITO') THEN
UPDATE BANCO_PRINCIPAL.SALDO_CUENTA SET SALDO=SALDO+NEW.VALOR WHERE
NUMERO_CUENTA = NEW.NUMERO_CUENTA;
END IF;
IF (NEW.TIPO='CREDITO') THEN
/*CREDITO*/
SET VALOR_SALDO = (SELECT SALDO FROM BANCO_PRINCIPAL.SALDO_CUENTA WHERE
NUMERO_CUENTA = NEW.NUMERO_CUENTA);
IF(NEW.VALOR>VALOR_SALDO) THEN
SET MSG = CONCAT('SALDO NO DISPONIBLE. SALDO ACTUAL: ',CAST(VALOR_SALDO AS
CHAR));
signal sqlstate '45000' set message_text = MSG;
END IF;
UPDATE BANCO_PRINCIPAL.SALDO_CUENTA SET SALDO=SALDO-NEW.VALOR WHERE
NUMERO_CUENTA = NEW.NUMERO_CUENTA;
END IF;
END$$

Lo que permite tener el saldo actualizado en la sede principal tambien


A continuación realizamos un movimiento en la sede de cali desde la aplicación de la sede de
bogotá

Se ejecuta el siguiente trigger que actualiza el saldo de la cuenta en la tabla principal pero esta
vez el movimiento queda registrado en la tabla de transacciones foráneas
-- Trigger DDL Statements
DELIMITER $$

USE `BANCO_BOGOTA`$$

CREATE
DEFINER=`root`@`localhost`
TRIGGER `BANCO_BOGOTA`.`CREATE_MOVIMIENTO_TF_PP`
BEFORE INSERT ON `BANCO_BOGOTA`.`MOVIMIENTO_TF`
FOR EACH ROW
BEGIN
DECLARE EXISTE INT;
DECLARE VALOR_SALDO DOUBLE;
DECLARE MSG VARCHAR(255);

SET EXISTE = (SELECT COUNT(NUMERO_CUENTA) FROM BANCO_PRINCIPAL.SALDO_CUENTA WHERE


NUMERO_CUENTA = NEW.NUMERO_CUENTA);
IF(EXISTE = 0) THEN
SET MSG = CONCAT('CUENTA NO EXISTE. NUMERO DE CUENTA: ',CAST(NEW.NUMERO_CUENTA AS
CHAR));
signal sqlstate '45000' set message_text = MSG;
END IF;

IF (NEW.TIPO='DEBITO') THEN
UPDATE BANCO_PRINCIPAL.SALDO_CUENTA SET SALDO=SALDO+NEW.VALOR WHERE
NUMERO_CUENTA = NEW.NUMERO_CUENTA;
ELSE
/*CREDITO*/
SET VALOR_SALDO = (SELECT SALDO FROM BANCO_PRINCIPAL.SALDO_CUENTA WHERE
NUMERO_CUENTA = NEW.NUMERO_CUENTA);
IF(NEW.VALOR>VALOR_SALDO) THEN
SET MSG = CONCAT('SALDO NO DISPONIBLE. SALDO ACTUAL: ',CAST(VALOR_SALDO AS
CHAR));
signal sqlstate '45000' set message_text = MSG;
END IF;
UPDATE BANCO_PRINCIPAL.SALDO_CUENTA SET SALDO=SALDO-NEW.VALOR WHERE
NUMERO_CUENTA = NEW.NUMERO_CUENTA;
END IF;
END$$

El saldo queda de igual manera actualizado al realizar la transacción


Ahora realizamos una transacción en el banco de bogotá desde la aplicacion del banco de cali.

Se ejecuta el siguiente trigger que actualiza el saldo de la cuenta en la tabla principal pero esta
vez el movimiento queda registrado en la tabla de transacciones foráneas
-- Trigger DDL Statements
DELIMITER $$

USE `BANCO_CALI`$$

CREATE
DEFINER=`root`@`localhost`
TRIGGER `BANCO_CALI`.`CREATE_MOVIMIENTO_TF_PP`
BEFORE INSERT ON `BANCO_CALI`.`MOVIMIENTO_TF`
FOR EACH ROW
BEGIN
DECLARE EXISTE INT;
DECLARE VALOR_SALDO DOUBLE;
DECLARE MSG VARCHAR(255);

SET EXISTE = (SELECT COUNT(NUMERO_CUENTA) FROM BANCO_PRINCIPAL.SALDO_CUENTA WHERE


NUMERO_CUENTA = NEW.NUMERO_CUENTA);
IF(EXISTE = 0) THEN
SET MSG = CONCAT('CUENTA NO EXISTE. NUMERO DE CUENTA: ',CAST(NEW.NUMERO_CUENTA AS
CHAR));
signal sqlstate '45000' set message_text = MSG;
END IF;

IF (NEW.TIPO='DEBITO') THEN
UPDATE BANCO_PRINCIPAL.SALDO_CUENTA SET SALDO=SALDO+NEW.VALOR WHERE
NUMERO_CUENTA = NEW.NUMERO_CUENTA;
ELSE
/*CREDITO*/
SET VALOR_SALDO = (SELECT SALDO FROM BANCO_PRINCIPAL.SALDO_CUENTA WHERE
NUMERO_CUENTA = NEW.NUMERO_CUENTA);
IF(NEW.VALOR>VALOR_SALDO) THEN
SET MSG = CONCAT('SALDO NO DISPONIBLE. SALDO ACTUAL: ',CAST(VALOR_SALDO AS
CHAR));
signal sqlstate '45000' set message_text = MSG;
END IF;
UPDATE BANCO_PRINCIPAL.SALDO_CUENTA SET SALDO=SALDO-NEW.VALOR WHERE
NUMERO_CUENTA = NEW.NUMERO_CUENTA;
END IF;
END$$

El saldo queda de igual manera actualizado al realizar la transacción


Por último se realiza el llamado del programa que actualiza los valores de las transacciones
foráneas de una sede a la otra

package edu.udistrital.bancoprincipal.util;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;

import javax.ejb.Stateless;

@Stateless
public class DataBaseHelper {

public DataBaseHelper() {
}

static public void sincronizeBogotaCali(){


try {
Connection bogota = Conexion.getInstance().conectarBogota();
Connection cali = Conexion.getInstance().conectarCali();
Connection principal = Conexion.getInstance().conectar();

Statement st = bogota.createStatement();
ResultSet rsBogota = st.executeQuery("SELECT
NUMERO_MOVIMIENTO,NUMERO_CUENTA,VALOR,FECHA,TIPO,SEDE FROM BANCO_BOGOTA.MOVIMIENTO_TF;");

while(rsBogota != null && rsBogota.next()){


int numero_movimiento = rsBogota.getInt(1);
int numero_cuenta = rsBogota.getInt(2);
double valor = rsBogota.getDouble(3);
Date fecha = rsBogota.getDate(4);
String tipo = rsBogota.getString(5);
String sede = rsBogota.getString(6);
PreparedStatement stCali = cali.prepareStatement("INSERT INTO
BANCO_CALI.MOVIMIENTO(NUMERO_CUENTA,VALOR,FECHA,TIPO,SEDE) VALUES (?,?,?,?,?);");
stCali.setInt(1, numero_cuenta);
stCali.setDouble(2, valor);
stCali.setDate(3, fecha);
stCali.setString(4, "AUD-"+tipo);
stCali.setString(5, sede);
boolean ok = stCali.execute();

int numero_mov = 0;
stCali = cali.prepareStatement("select LAST_INSERT_ID() from
BANCO_CALI.MOVIMIENTO;");
ResultSet rsInsert = stCali.executeQuery();
if(rsInsert != null && rsInsert.next()){
numero_mov = rsInsert.getInt(1);
}

PreparedStatement stPrin = principal.prepareStatement("INSERT INTO


BANCO_PRINCIPAL.AUDITORIA (NUMERO_MOVIMIENTO,FECHA_MOVIMIENTO,SEDE) VALUES (?,?,?);");
stPrin.setInt(1, numero_mov);
stPrin.setDate(2, fecha);
stPrin.setDouble(3, valor);

boolean oka = stPrin.execute();


stCali.close();
}

st = bogota.createStatement();
st.executeUpdate("DELETE FROM MOVIMIENTO_TF");
st.close();

} catch (Exception e) {
e.printStackTrace();
}finally{
try {
Conexion.getInstance().desconectar();
Conexion.getInstance().desconectarBogota();
Conexion.getInstance().desconectarCali();
} catch (DataException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

static public void sincronizeCaliBogota(){


try {
Connection bogota = Conexion.getInstance().conectarBogota();
Connection cali = Conexion.getInstance().conectarCali();
Connection principal = Conexion.getInstance().conectar();

Statement st = cali.createStatement();
ResultSet rsCali = st.executeQuery("SELECT
NUMERO_MOVIMIENTO,NUMERO_CUENTA,VALOR,FECHA,TIPO,SEDE FROM BANCO_CALI.MOVIMIENTO_TF;");

while(rsCali != null && rsCali.next()){


int numero_movimiento = rsCali.getInt(1);
int numero_cuenta = rsCali.getInt(2);
double valor = rsCali.getDouble(3);
Date fecha = rsCali.getDate(4);
String tipo = rsCali.getString(5);
String sede = rsCali.getString(6);
PreparedStatement stBogota = cali.prepareStatement("INSERT INTO
BANCO_BOGOTA.MOVIMIENTO(NUMERO_CUENTA,VALOR,FECHA,TIPO,SEDE) VALUES (?,?,?,?,?);");
stBogota.setInt(1, numero_cuenta);
stBogota.setDouble(2, valor);
stBogota.setDate(3, fecha);
stBogota.setString(4, "AUD-"+tipo);
stBogota.setString(5, sede);
boolean ok = stBogota.execute();

int numero_mov = 0;
stBogota = cali.prepareStatement("select LAST_INSERT_ID() from
BANCO_BOGOTA.MOVIMIENTO;");
ResultSet rsInsert = stBogota.executeQuery();
if(rsInsert != null && rsInsert.next()){
numero_mov = rsInsert.getInt(1);
}

PreparedStatement stPrin = principal.prepareStatement("INSERT INTO


BANCO_PRINCIPAL.AUDITORIA (NUMERO_MOVIMIENTO,FECHA_MOVIMIENTO,SEDE) VALUES (?,?,?);");
stPrin.setInt(1, numero_mov);
stPrin.setDate(2, fecha);
stPrin.setDouble(3, valor);

boolean oka = stPrin.execute();


stBogota.close();
}

st = cali.createStatement();
st.executeUpdate("DELETE FROM MOVIMIENTO_TF");
st.close();

} catch (Exception e) {
e.printStackTrace();
}finally{
try {
Conexion.getInstance().desconectar();
Conexion.getInstance().desconectarBogota();
Conexion.getInstance().desconectarCali();
} catch (DataException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

/**
* @param args
*/
public static void main(String[] args) {
sincronizeBogotaCali();
sincronizeCaliBogota();

Como resultado este programa busca las transacciones y las genera en la sede
correspondiente dejando un log de auditoría en la tabla de la sede principal.

revisamos los movimientos de la sede de bogotá y vemos que se encuentran los dos en las
tablas de movimientos locales

De igual forma en la sede de cali podemos ver los dos movimientos como movimientos locales
uno marcado como tipo de auditoría.
En la auditoría quedan las transacciones que se generaron.
Video aplicación:

http://www.youtube.com/watch?v=KDCjB2j0dVg
Data Ware House

DFE

Usuario CompraIntern
et

VistaVideo
DFE

IOV:

Usuario
cedula nombre dirección telefono

Compra Internet:
numero_compra valor producto cantidad fecha_compra

VistaVideo
id_vista nombre_video id_categoria duración fecha_vista

TABLAS

USUARIO
cedula nombre correo telefono
pk

COMPRA_INTERNET
numero_compra cedula valor producto cantidad fecha_compra
pkgt1 pks

VISTA_VIDEO
id_vista cedula nombre_video id_categoria duración fecha_vista
pkgt2 pks fkd

CATEGORIA
id_categoria descripcion
pke

MER gt1
product
valor numero_compra
o

cantida
d COMPRA_INTERNE
T
CEDULA
fecha_compr
a CEDULA CORREO

USUARIO

NOMBR
TELEFONO
E

MER gt2
id_vista

nombre_video

CEDULA

VISTA_VIDEO CEDULA

CORREO

duración

fecha_vista
USUARIO

NOMBRE TELEFONO

id_categoria
CATEGORIA

id_categoria
descripcion

MR
COMPRA_INTERNET
numero_compra pkCEDULA
fkvalor productocantidadfecha_compra

VISTA_VIDEO
id_vista pkCEDULA
fknombre_videoid_categoria
fkduraciónfecha_vista

USUARIO
CEDULA
pkNOMBRECORREOTELEFO
NO

CATEGORIA
id_categoria
pkdescripcion

Reportes necesarios:

Datos de usuarios que ven videos musicales y compran artículos relacionados con las palabra:
guitarra, cuerda, batería, bajo, amplifica.

Lista de productos que los usuarios compran y las categorías de videos que visualizan durante
los meses de Noviembre y Diciembre.

Fechas en que los usuarios ven vídeos de la categoría de bricolaje y los valores de la compras
fueron mayores a 50.000 en esas fechas

Tabla de hechos:
Para realizar los reportes que se solicitan es necesario tener en la tabla de hechos los
siguientes campos de las tablas.

De tabla usuario:
cedula,nombre, correo, telefono
De tabla compra_internet:
producto, fecha_compra, valor
De tabla vista_video:
fecha_vista
De tabla categoria:
descripcion

La tabla de hechos resultante será la siguiente:

TABLA_HECHOS
cedula
nombre
correo
telefono
producto
valor
fecha_compra
fecha_visita
des_categoria

TABLA_HECHOS

cedulanombrecorreotelefonoprodu
ctovalorfecha_comprafecha_visita
des_categoria

A continuación se busca como llenar la tabla de hechos para realizar los estudias del cruce de
la información necesarios para suplir las necesidades del negocio.

ETL PARA LLENAR TABLA DE HECHOS:

SELECT
dataWarehouse.usuario.cedula,
dataWarehouse.usuario.nombre,
dataWarehouse.usuario.correo,
dataWarehouse.usuario.telefono,
dataWarehouse.compra_internet.producto,
dataWarehouse.compra_internet.valor,
dataWarehouse.compra_internet.fecha_compra,
dataWarehouse.vista_video.fecha_vista,
dataWarehouse.categoria.descripcion as des_categoria
FROM
dataWarehouse.usuario,
dataWarehouse.compra_internet,
dataWarehouse.vista_video,
dataWarehouse.categoria
WHERE
dataWarehouse.usuario.cedula = dataWarehouse.compra_internet.cedula
and dataWarehouse.usuario.cedula = dataWarehouse.vista_video.cedula
and dataWarehouse.vista_video.id_categoria = dataWarehouse.categoria.id_categoria;

Consultas para vistas de cubos que reportes

● Datos de usuarios que ven videos musicales y compran artículos relacionados con las
palabra: guitarra, cuerda, batería, bajo, amplifica.

SELECT
dataWarehouse.tabla_hechos.cedula,
dataWarehouse.tabla_hechos.nombre,
dataWarehouse.tabla_hechos.correo,
dataWarehouse.tabla_hechos.telefono
FROM dataWarehouse.tabla_hechos
WHERE dataWarehouse.tabla_hechos.des_categoria = 'MUSICA'
AND (dataWarehouse.tabla_hechos.producto like '%GUITARRA%'
OR dataWarehouse.tabla_hechos.producto like '%CUERDA%'
OR dataWarehouse.tabla_hechos.producto like '%BATERIA%'
OR dataWarehouse.tabla_hechos.producto like '%BAJO%'
OR dataWarehouse.tabla_hechos.producto like '%AMPLIFICA%')
GROUP BY cedula,nombre,correo,telefono;

● Lista de productos que los usuarios compran y las categorías de videos que visualizan
durante los meses de Noviembre y Diciembre.

SELECT
dataWarehouse.tabla_hechos.producto,dataWarehouse.tabla_hechos.des_categoria
FROM dataWarehouse.tabla_hechos
WHERE dataWarehouse.tabla_hechos.fecha_compra between '2012-11-01' and'2012-12-31'
GROUP BY producto,des_categoria order by producto;
● Fechas en que los usuarios ven vídeos de la categoría de bricolaje y los valores de la
compras fueron mayores a 50.000 en esas fechas

SELECT
dataWarehouse.tabla_hechos.fecha_vista,
dataWarehouse.tabla_hechos.fecha_compra
FROM
dataWarehouse.tabla_hechos
WHERE
dataWarehouse.tabla_hechos.valor>50000
and dataWarehouse.tabla_hechos.des_categoria = 'BRICOLAJE';
Video aplicación:

http://www.youtube.com/watch?v=ieB7jSDurbo

También podría gustarte