Está en la página 1de 22

Administración de Bases de Datos

Procedimientos almacenados y triggers.

Fecha de actualización: 05 de mayo de 2021


(actualización Docente unidad de software y TIC)
2

Contenido
1 Ideograma ............................................................................................................................................. 3
2. Automatización de tareas: Procedimientos Almacenados y Triggers............................................... 4
2.1 Definición ............................................................................................................................................. 4
2.2 Sintaxis de los procedimientos almacenados ................................................................................... 5
2.3 Sentencia IF ............................................................................................................................................. 9
2.4 Sentencia CASE...................................................................................................................................... 13
2.5 Sentencia LOOP..................................................................................................................................... 14
2.6 Sentencia REPEAT ................................................................................................................................. 15
2.7 Sentencia WHILE ................................................................................................................................... 15
2.8 ALTER PROCEDURE y ALTER FUNCTION ................................................................................................. 15
3. Disparadores Triggers....................................................................................................................... 16
3.1 Creación de un Trigger ..................................................................................................................... 16
3.2 Eliminación de Triggers – DROP TRIGGER .......................................................................................... 18
3.3 Utilización de disparadores Triggers .................................................................................................. 18
5 Actividades ..................................................................................................................................... 19
5.1 Taller 2 .................................................................................................................................................. 20
Bibliografía .................................................................................................................................................. 21
3

1 ideograma

Introducción a los DBMS

Procedimientos
almacenados

Procedimientos
almacenados y
triggers

Triggers

Optimización
4

2. Automatización de tareas: Procedimientos Almacenados y Triggers

En el siguiente módulo se realizará una profundización en los conceptos relacionados


con los procedimientos almacenados y triggers como herramientas de automatización de
las labores de gestión de la base de datos y se revisarán casos prácticos para
implementar este tipo de herramientas para la adecuada gestión de los DBMS.

2.1 Definición

Los procedimientos almacenados son de gran utilidad para realizar labores de gestión
de las bases de datos, permitiendo programar actividades periódicas, facilitando labores
para el adecuado manejo de los datos, realizar actividades de mantenimiento y
prevención, revisión de políticas de seguridad, entre otras.

Automatizar es una de las labores clave para realizar una buena administración de los
Sistemas gestores de Bases de Datos. En general los DBMS más importantes tanto
libres como comerciales, cuentan con herramientas para automatizar tareas y en general
hacen uso de rutinas entre las que se cuentan procedimientos almacenados, funciones,
disparadores o triggers, así como con Interfaces de programación de aplicaciones – API,
de diferentes lenguajes de programación orientados a la web tal como Python, PHP, o
PERL.

En MySQL las funciones y los procedimientos almacenados son relativamente nuevos y


han sido incorporados desde la versión 5.0. Un procedimiento almacenado es un
conjunto de comandos SQL que pueden almacenarse en el servidor. Una vez que se
encuentra en el servidor, los clientes pueden acceder a los procedimientos almacenados
y hacer uso de ellos, lo que permite un ahorro en cuanto al desarrollo de código en las
aplicaciones, eficiencia en la ejecución, reducción de errores, entre otros.
5

Algunos de los usos más destacados de los procedimientos almacenados son los
siguientes:

a. Aplicaciones multiplataforma: Cuando múltiples aplicaciones cliente


escritas en distintos lenguajes y desde distintas plataformas, necesitan
acceder a operaciones similares en la base de datos.
b. Seguridad: Las organizaciones pueden utilizar procedimientos
almacenados para todas las operaciones comunes, asignando perfiles de
usuarios y restricciones de uso. Esto proporciona un entorno seguro y
consistente, evitando por ejemplo que los usuarios tengan acceso directo
a las tablas de la base de datos.

Los procedimientos almacenados pueden mejorar el rendimiento debido a que utilizan


un flujo mejor de información entre el servidor y el cliente. Esto por otro lado aumenta la
carga del servidor de base de datos ya que la mayoría del trabajo se realiza en la parte
del servidor y no en el cliente.

2.2 Sintaxis de los procedimientos almacenados

Los procedimientos almacenados se pueden escribir ya sea desde un editor de texto


normal como notepad, hasta en los editores gráficos de MySQL como Workbench. En el
siguiente capítulo analizaremos la sintaxis de los procedimientos almacenados tomando
como base el manual de referencia de MySQL, específicamente el caitulo 19 que habla
de procedimientos almacenados.

Los procedimientos almacenados son creados con los comandos CREATE


PROCEDURE y CREATE FUNCTION y se invocan usando el comando CALL. Desde la
versión 5.0.1 de MySQL los procedimientos están asociados a la base de datos
específica en la cual se ejecutaran, es por esto que hay que tener en cuenta que si se
borra una base de datos los procedimientos almacenados asociados a esta se borraran
6

también.

A continuación, se muestra la sintaxis general de CREATE PROCEDURE Y CREATE


FUNCTION
CREATE PROCEDURE sp_name ([parameter[,...]])
[characteristic ...] routine_body
CREATE FUNCTION sp_name ([parameter[,...]])
RETURNS type
[characteristic ...] routine_body
parameter:
[ IN | OUT | INOUT ] param_name type
type:
Any valid MySQL data type
characteristic:
LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
| COMMENT 'string'
routine_body:
procedimientos almacenados o comandos SQL válidos
Manual de referencia de MYSQL 5.0
Donde:
sp_name: es el nombre de la rutina almacenada. Por defecto, la rutina se asocia
con la base de datos actual. Para asignarlo a una base de datos diferente se debe
establecer el nombre de la misma de la siguiente forma: db_name.sp_name. La lista
de parámetros entre paréntesis debe estar siempre presente. Si no hay
parámetros, se debe usar una lista de parámetros vacía ()
parameter: son los parámetros utilizados, se caracterizan por un tipo y un nombre.
El tipo puede ser de entrada (IN), salida (OUT) o de entrada y salida (INOUT). Por
defecto los tipos son de carácter IN, así que para definir un tipo diferente hay que
hacerlo explícito.
routine_body: Es el cuerpo de la rutina y generalmente se encuentra elaborado en
sentencias SQL
deterministic: hace referencia a si siempre produce el mismo resultado
Contains SQL | no SQL: especifica si contiene o no sentencias SQL.
7

reads SQL Data | Modifies SQL Data: indica si modifica o no los datos.
SQL Security: determina si debe ejecutarse con permisos del creador (definer) o del
que invoca (invoker).

Los corchetes indican parámetros opcionales, y las palabras en mayúscula son


reservadas del lenguaje SQL.
Con esta sintaxis de comandos se puede crear un procedimiento almacenado, es
necesario tener el permiso CREATE ROUTINE, y los permisos ALTER ROUTINE y
EXECUTE se asignan automáticamente al creador del procedimiento.

El siguiente es un ejemplo de un procedimiento almacenado que use un parámetro OUT.


El ejemplo usa el cliente mysql y el comando delimiter para cambiar el delimitador del
comando de “;” a “//” mientras se define el procedimiento. Esto permite pasar el
delimitador “;” usado en el cuerpo del procedimiento a través del servidor en lugar de ser
interpretado por mysql. Los ejemplos los realizaremos sobre la base de datos test que
viene por defecto en la instalación de MySQL
delimiter //
DROP PROCEDURE IF EXISTS test.procedimientosimple//
CREATE PROCEDURE test.procedimientosimple (OUT parametro INT)
BEGIN
SELECT COUNT(*) INTO parametro FROM tablaPrueba;
END //
delimiter ;

En este caso se utiliza la sentencia DROP PROCEDURE con el fin de borrar si existe
alguna instancia del procedimiento antes de realizar la creación. Para realizar el llamado
del procedimiento creado utilizamos el siguiente comando

CALL test.procedimientosimple(@a);
8

A diferencia de los procedimientos las funciones retornan un resultado, El siguiente es


un ejemplo de función que toma un parámetro, realiza una operación con una función
SQL, y retorna el resultado:

delimiter //
DROP FUNCTION IF EXISTS test.holaMundo//
CREATE FUNCTION test.holaMundo (palabra CHAR(20)) RETURNS CHAR(50)
RETURN CONCAT('Hola, ',palabra,'!');
//
delimiter ;

El llamado de la función dará el siguiente resultado:


SELECT test.holaMundo('Mundo');
+-------------------------+
| test.holaMundo('Mundo') |
+-------------------------+
| Hola, Mundo! |
+-------------------------+

Para comprobar que la función se encuentra almacenado en la base de datos test se


puede consultar con el comando SHOW CREATE FUNCTION test.holaMundo que
mostrará la información guardada en la base de datos de la función.

El siguiente ejemplo muestra el uso de otras clausulas como LANGUAGE que se utiliza
para indicar el lenguaje en el que se ejecutará el procedimiento, y NOT DETERMINISTIC
que indica que el procedimiento no siempre retorna el mismo valor, así mismo la cláusula
COMMENT que permite documentar los procedimientos creados:

delimiter //
DROP PROCEDURE IF EXISTS test.fecha//
CREATE PROCEDURE test.fecha()
LANGUAGE SQL
9

NOT DETERMINISTIC
COMMENT 'Procedimiento para saber la fecha y un número aleatorio'
SELECT CURRENT_DATE, RAND() //

En este ejemplo obtenemos la fecha actual y un número aleatorio, que no tienen un


resultado determinado, por lo tanto es NOT DETERMINISTIC.

En los procedimientos almacenados podemos contar con sentencias más elaboradas y


para esto contamos con sentencias IF, CASE, LOOP, WHILE, ITERATE, y LEAVE
implementadas, que pueden contener un comando simple, o un bloque de comandos
usando el comando compuesto BEGIN ... END. Así mismo se pueden anidar estas
sentencias, es decir, tener contenidas unas dentro de otras. Para tener en cuenta los
ciclos FOR no están soportados.

2.3 Sentencia IF

IF search_condition THEN statement_list


[ELSEIF search_condition THEN statement_list] ...
[ELSE statement_list]
END IF
Manual de referencia de MYSQL 5.0
10
La sentencia IF realiza una validación condicional básica. Si search_condition se
valida como verdadera, el comando SQL correspondiente se ejecuta. Si no se ejecuta el
comando listado en la cláusula ELSE. statement_list puede consistir en varios
comandos SQL.

A continuación, podemos un ejemplo que ilustra lo anterior.

delimiter //
DROP FUNCTION IF EXISTS test.estado//
CREATE FUNCTION test.estado(in_estado char(1))
RETURNS VARCHAR (20)
COMMENT 'Procedimiento para establecer el estado dado un parámetro
ingresado'

BEGIN
DECLARE estado VARCHAR (20);
IF in_estado = 'P' THEN
SET estado = 'Pendiente';
ELSEIF in_estado = 'C' THEN
SET estado = 'Cancelado';
ELSEIF in_estado = 'A' THEN
SET estado = 'Activo';
END IF;
RETURN (estado);
END; //
delimiter ;

La anterior función puede ser llamada con una sentencia SELECT con lo cual se obtendrá
el siguiente resultado:
SELECT test.estado('C');
+--------------------------+
| test.estado('C') |
+--------------------------+
| Cancelado |
+--------------------------+
El siguiente ejemplo realizaremos una serie de funciones con el fin de llamarlas desde
otras funciones utilizando clausulas IF. Empezamos con la función espar con la cual
11
definiremos si un número dado es par o no.
delimiter //
DROP FUNCTION IF EXISTS test.espar//
CREATE FUNCTION test.espar ( numero INT)
RETURNS INT
BEGIN
DECLARE par INT;
IF MOD(numero, 2)=0 THEN
SET par = TRUE;
ELSE SET par= FALSE;
END IF;
RETURN (par);
END; //
12

La función anterior devuelve el valor 1 (TRUE) si es par o 0 (FALSE) en caso de ser


impar, dado un número que se le pase como parámetro. La función utiliza el comando
MOD que permite calcular el módulo en base 2 permitiendo saber si el número ingresado
es par o no.
A continuación, realizaremos un procedimiento que llamará a la función
espar:

delimiter //
DROP PROCEDURE IF EXISTS test.paroimpar //
CREATE PROCEDURE test.paroimpar (in numero INT)
BEGIN
IF (espar(numero)) THEN
SELECT CONCAT("El número: ", numero, "es par");
ELSE SELECT CONCAT("El número: ", numero, " es impar");
END IF;
END; //
delimiter ;

Este procedimiento puede ser llamado por la siguiente sentencia, en donde se le pasa
como parámetro un número, como se muestra a continuación:

CALL test.paroimpar(1234);

+----------------------------------------+
| CONCAT("El número: ", numero, "es par")|
+----------------------------------------+
| El número: 1234 es par |
+----------------------------------------+

Este es un ejemplo sencillo de cómo las funciones pueden reducir la complejidad del
código, al encapsular sentencias que pueden ser reutilizadas según las necesidades del
desarrollador, permitiendo también que el código sea mucho más legible.
13

2.4 Sentencia CASE


CASE case_value
WHEN when_value THEN statement_list
[WHEN when_value THEN statement_list] ...
[ELSE statement_list]
END CASE
Ó
CASE
WHEN search_condition THEN statement_list
[WHEN search_condition THEN statement_list] ...
[ELSE statement_list]
END CASE
Manual de referencia de MYSQL 5.0

El comando CASE evalúa casos, si una condición dada es verdadera el comando SQL
correspondiente se ejecuta. Si no coincide ninguna condición se ejecutarán los
comandos SQL que se encuentren en la cláusula ELSE. A continuación un ejemplo que
muestra el uso de CASE
delimiter //
DROP PROCEDURE IF EXISTS test.notas//
CREATE PROCEDURE test.notas (in numero FLOAT)
BEGIN
CASE
WHEN numero<3 THEN
SELECT CONCAT("Perdió: ", numero);
WHEN 3 <= numero && numero < 4 THEN
SELECT CONCAT("Aprobó: ", numero);
ELSE
SELECT CONCAT("Sobresaliente: ", numero);
END CASE;
END; //
14

El ejemplo anterior recibe un número con la nota de un estudiante y define si perdió,


aprobó o tuvo una nota destacada.

2.5 Sentencia LOOP


[begin_label:] LOOP
statement_list
END LOOP [end_label]
Manual de referencia de MYSQL 5.0

La sentencia LOOP realiza un ciclo que permite la ejecución repetida de comandos SQL,
que se repiten hasta que finaliza el ciclo, usualmente con un comando LEAVE.
Para el ejemplo crearemos una tabla de prueba en la Base de Datos test con el siguiente
comando
CREATE TABLE test.prueba (id INT)

Sobre esta tabla ejecutaremos el siguiente procedimiento con el fin de insertar


secuencialmente elementos como se muestra a continuación:
delimiter //
DROP PROCEDURE IF EXISTS test.ciclo//
CREATE PROCEDURE test.ciclo (in numero INT)
BEGIN
DECLARE contador INT;
SET contador = 0;
ciclo_insertar: LOOP
INSERT INTO test.prueba VALUES (contador);
SET contador = contador +1;
IF contador > numero THEN
LEAVE ciclo_insertar;
END IF;
END LOOP;
END; //
15

Este procedimiento insertará valores desde cero hasta el número que se pase como
parámetro.

2.6 Sentencia REPEAT

[begin_label:] REPEAT
statement_list
UNTIL search_condition
END REPEAT [end_label]

La sentencia REPEAT permite ejecutar los comandos SQL hasta que la condición
search_condition se cumpla

CREATE PROCEDURE test.ciclo_repeat()


BEGIN
SET @x = 10;
SET @numero= 20;
REPEAT SET @x = @x + 1;
INSERT INTO test.prueba VALUES (@x);
UNTIL @x > @numero
END REPEAT;
END//

El procedimiento anterior insertará los número del 11 al 20 en la tabla prueba de la base


de datos test.

2.7 Sentencia WHILE


[begin_label:] WHILE search_condition DO
statement_list
END WHILE [end_label]
15

Los comandos que se encuentren dentro de una sentencia WHILE se repetiran mientras
la condición search_condition sea cierta. Para el siguiente ejemplo utilizaremos la tabla
prueba2 en la base de datos test, creada bajo el siguiente script

CREATE TABLE test.prueba2 (id INT, par VARCHAR(20));

El procedimiento insertará un identificador secuencial en la columna id y un 1 o un 0


dependiendo si es par o impar según la función creada anteriormente espar.
delimiter //
DROP PROCEDURE IF EXISTS test.ciclo_while//
CREATE PROCEDURE test.ciclo_while()
BEGIN
SET @x = 0;
SET @numero= 10;
WHILE @x <= @numero DO
INSERT INTO test.prueba2 VALUES (@x, espar(@x));
SET @x = @x+1;
END WHILE;
END//
delimiter ;

Un comando WHILE no necesita etiquetarse necesariamente, como se muestra en el


ejemplo.

2.8 ALTER PROCEDURE y ALTER FUNCTION

Para modificar un procedimiento o función almacenada se pueden utilizar los comandos


ALTER PROCEDURE y ALTER FUNCTION, hay que tener en cuenta que se deben tener
permisos de ALTER ROUTINE. La sintaxis es la siguiente:

ALTER {PROCEDURE | FUNCTION} sp_name [characteristic ...]


16

characteristic: { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES


SQL DATA } | SQL SECURITY { DEFINER | INVOKER } | COMMENT 'string'
Manual de referencia de MYSQL 5.0

3. Disparadores Triggers

Un disparador o trigger es un objeto dentro de una base de datos que se asocia con una
tabla y se activa cuando ocurre un evento en particular dentro de la tabla. Es un tipo
especial de procedimiento almacenado y tiene una gran utilidad ya que permite mantener
por ejemplo la integridad de los datos, desarrollar rutinas para el mantenimiento, entre
otras. La siguiente es la sintaxis para la creación de un trigger:

3.1 Creación de un Trigger

CREATE TRIGGER nombre_disp momento_disp evento_disp


ON nombre_tabla FOR EACH ROW sentencia_disp

Según el manual de referencia de MySQL 5.0 estas son las referencias a tener en cuenta
para la ejecución de la sentencia:
▪ nombre_disp: Nombre del trigger puede esr BEFORE para indicar que el
disparador se ejecutará antes o AFTER para indicar que se ejecutará después de la
sentencia que lo activa.
▪ momento_disp: es el momento en que el disparador entra en acción. Puede ser
BEFORE (antes) o AFTER (después), para indicar que el disparador se ejecute
antes o después que la sentencia que lo activa.
▪ evento_disp: indica la clase de sentencia que activa al disparador. Puede ser
INSERT, UPDATE, o DELETE. Por ejemplo, un disparador BEFORE para
sentencias INSERT podría utilizarse para validar los valores a inserta.
17

▪ sentencia_disp: es la sentencia que se ejecuta cuando se activa el disparador.


Si se desean ejecutar múltiples sentencias, deben colocarse entre BEGIN ... END,
el constructor de sentencias compuestas.

Hay que tener en cuenta que no puede haber dos disparadores en una misma tabla que
correspondan al mismo momento. Por ejemplo, no se pueden tener dos disparadores
BEFORE UPDATE. Pero sí es posible tener los disparadores BEFORE UPDATE y
BEFORE INSERT o BEFORE UPDATE y AFTER UPDATE.

Para mostrar el uso de los triggers realizaremos un ejemplo que muestre en la práctica
cómo funcionan. Realizaremos la inserción en una tabla y crearemos un disparador para
para sentencias INSERT dentro de la tabla que inserte si la inserción fue realizada
correctamente en otra tabla. El script sería de la siguiente forma:

CREATE TABLE test.prueba1(a1 INT);


CREATE TABLE test.prueba2(a2 VARCHAR (100));

DELIMITER //
CREATE TRIGGER test.trigger1 AFTER INSERT ON test.prueba1
FOR EACH ROW BEGIN
INSERT INTO prueba2 SET a2 = CONCAT("Se insertó correctamente el
valor ", NEW.a1, " en la tabla prueba1");
END
//
DELIMITER ;

Para verificar que el disparador realizaremos inserciones en la tabla prueba1, y


posteriormente una consulta en la tabla prueba2, con el fin de verificar que se encuentren
el mismo número de registros de la siguiente manera:

insert into test.prueba1 VALUES (1), (2), (3);


18

select * from test.prueba2;

a2
Se insertó correctamente el valor 1 en la tabla prueba1
Se insertó correctamente el valor 2 en la tabla prueba1
Se insertó correctamente el valor 3 en la tabla prueba1

3.2 Eliminación de Triggers – DROP TRIGGER

DROP TRIGGER [nombre_esquema.]nombre_disp

La sentencia DROP TRIGGER necesita que se posea el privilegio SUPER. Para eliminar
el Trigger creado para el ejemplo anterior el comando que se necesita es el siguiente:

Drop trigger test.trigger1;

Para verificar que la sentencia se ejecutó de manera correcta se pueden realizar


inserciones en la tabla prueba1 y verificar que no se realicen inserciones automáticas en
la tabla prueba2.

3.3 Utilización de disparadores Triggers

Como los triggers están asociados con una tabla en particular, no se pueden tener
múltiples triggers con el mismo nombre en la misma tabla. Para una mejor compatibilidad
con desarrollos futuros, se debe intentar emplear nombres de disparadores que no se
repitan dentro de la base de datos, ya que pueden generar problemas.
Adicionalmente al requisito de nombres únicos de disparador en cada tabla, hay otras
limitaciones como que un trigger no puede invocar procedimientos almacenados
utilizando la sentencia CALL, o que no se pueden utilizar sentencias que inicien o
19

finalicen una transacción, tal como START TRANSACTION, COMMIT, o ROLLBACK.


Dentro de los usos más destacados de los triggers se pueden nombrar las siguientes:

▪ Control de sesiones de usuario: Con los triggers se puede realizar un


control para el registro de actividades de los usuarios del sistema.
▪ Reportes y estadísticas: se puede realizar registro de operaciones
en la base de datos
▪ Registro y auditoría: Se pueden crear Tiggers para examinar
actividades puntuales sobre las bases de datos, por ejemplo cuando
se realizan operaciones como borrado y actualización, con el fin de
auditar actividades clave del negocio.

5 Actividades

Creación de Procedimientos Almacenados y funciones


Taller 1.
Sobre la base de datos test crear un procedimiento para mostrar el año actual.
Crear una función que permita concatenar dos palabras pasadas por parámetro
en mayúscula.
Crear una función para obtener el valor de la hipotenusa según dos lados pasados
por parámetro.
Crear un procedimiento que devuelva el mayor de tres números pasados como
parámetro.
Crear un procedimiento que permita devolver la sumatoria de los primeros n
números enteros dependiendo un número n pasado como parámetro.
Crear una función para saber si un número es primo.
Con la función anterior crear un procedimiento que permita almacenar en la tabla
primos (id, número) de la base de datos test los números primos entre 1 y un
número pasado como parámetro.
20

5.1 Taller 2
Elaborar un script que permita la creación en la base de datos las tablas
blog(id_blog, fecha, autor, titulo, contenido) y notificación(id, id_blog, fecha,
notificación). Realizar un procedimiento almacenado tal que una vez se inserte
una nueva entrada en la tabla blog, registre en la tabla notificación que se ha
ingresado a nueva entrada.
Crear un trigger que elimine el registro correspondiente a la tabla blog una vez se
borre el registro de la tabla notificación.
21
Bibliografía
• Martínez López, F. J. y Gallegos Ruiz, A. (2017). Programación de bases de datos
relacionales. RA-MA Editorial. https://elibro-
net.proxy.umb.edu.co/es/lc/biblioumb/titulos/106525 (Recuperado Base de Datos new
elibro)
• Arenal Laza, C. (2020). Sistemas de información y bases de datos en consumo. UF1755.
Editorial Tutor Formación. https://elibro-
net.proxy.umb.edu.co/es/lc/biblioumb/titulos/125939 (Recuperado Base de Datos new
elibro)
• Pulido Romero, E. Escobar Domínguez, Ó. y Núñez Pérez, J. Á. (2019). Base de datos. Grupo
Editorial Patria. https://elibro-net.proxy.umb.edu.co/es/lc/biblioumb/titulos/121283
(Recuperado Base de Datos new elibro)
• A review of different approaches in natural language interfaces to databases. (2017).
(Recuperado Base de Datos IEEE Xplore)
• Kumar, K., & Azad, S. K. (2017). Relational Database Normalization under Tabular
Approach: A Design Methodology. International Journal Of Advanced Research In
Computer Science, 8(5), 2160-2164. (Recuperado Base de Datos EBSCO)
• Capacho, P. J. R., & Nieto, B. W. (2017). Diseño de base de datos. (Recuperado eBook
Collection - (EBSCOhost)
• Somenzi, D. M. (2017). Database Normalization and a Case Study. (Recuperado Base de
Datos EBSCO)
• Database normalization design pattern. (2017). (Recuperado Base de Datos IEEE Xplore)
• Sudhindaran, D. S. (2017). Generating a Normalized Database Using Class Normalization.
(2017). United States, North America: UNF
• Sarasa, A. (2016). Introducción a las bases de datos NoSQL usando MongoDB. Editorial UOC.
https://elibro-net.proxy.umb.edu.co/es/lc/biblioumb/titulos/58524 (Recuperado Base de
Datos new elibro)

También podría gustarte