Todos Los Apuntes PDF
Todos Los Apuntes PDF
Dashito
Facultad de Informática
Universidad Complutense de Madrid
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
2
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Índice general
2. Normalización 59
2.1. ¿Qué es la normalización? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
2.2. Redundancias y anomalı́as . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
2.3. Conceptos necesarios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
2.3.1. Notación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
2.3.2. Dependencias funcionales . . . . . . . . . . . . . . . . . . . . . . . . . 61
2.4. Formas normales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
2.4.1. Primera forma normal . . . . . . . . . . . . . . . . . . . . . . . . . . 63
2.4.2. Segunda forma normal . . . . . . . . . . . . . . . . . . . . . . . . . . 65
2.4.3. Tercera forma normal . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
2.4.4. Forma normal de Boyce-Codd (FNBC) . . . . . . . . . . . . . . . . . 67
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Ampliación de Bases de Datos
Banco de apuntes de la
II Modelos alternativos de bases de datos 75
3. XML 77
3.1. Modelo semiestructurado de bases de datos . . . . . . . . . . . . . . . . . . . 77
3.1.1. Lenguaje XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
3.1.2. Bases de datos con XML . . . . . . . . . . . . . . . . . . . . . . . . . 79
3.2. Lenguaje XML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
3.3. Documentos bien formados . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
3.3.1. Document Type Definition . . . . . . . . . . . . . . . . . . . . . . . . 82
3.4. Lenguajes para bases de datos de XML . . . . . . . . . . . . . . . . . . . . . 88
3.4.1. XPath . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
3.4.2. XQuery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
3.4.3. SGBD eXist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
3.4.4. xQuery tester . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
4. MongoDB 99
4.1. Conceptos básicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
4.1.1. ¿Qué es MongoDB? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
4.1.2. Documentos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
4.1.3. Tipos de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
4.1.4. Colecciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
4.2. Inserción y borrado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
4.3. Consultas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
4.3.1. Consultas sobre documentos embebidos . . . . . . . . . . . . . . . . . 115
4.3.2. Lı́mites, saltos y ordenaciones . . . . . . . . . . . . . . . . . . . . . . 117
4.4. Actualizaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
4.5. Indexación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
4.6. MapReduce . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
4.7. MongoDB y PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
5. Datalog 137
5.1. Bases de datos deductivas . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
5.2. Datalog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
5.3. El lenguaje Datalog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
5.3.1. Hechos y objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
5.3.2. Ajustes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
5.3.3. Reglas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
5.3.4. Reglas automáticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
5.3.5. Mecanismo de cómputo de Datalog . . . . . . . . . . . . . . . . . . . 145
5.3.6. Programando con Datalog . . . . . . . . . . . . . . . . . . . . . . . . 145
5.3.7. Reglas recursivas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
5.4. Datalog avanzado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
5.4.1. Reuniones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
5.4.2. Agrupaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
5.4.3. Funciones de agregación . . . . . . . . . . . . . . . . . . . . . . . . . 152
5.4.4. Aritmética . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
5.4.5. Negación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
5.5. Más allá de Datalog: Prolog . . . . . . . . . . . . . . . . . . . . . . . . . . . 156
5.5.1. ¿Qué es la programación declarativa? . . . . . . . . . . . . . . . . . . 156
5.5.2. Prolog: listas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
6
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Parte I
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Capı́tulo 1
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 1.1: Ventana principal de XAMPP
Existen clientes que permiten crear los esquemas relacionales de una base de datos a
través de una interfaz gráfica.
1.1.1. XAMPP
Se especifica el nombre de la base de datos.
10
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 1.2: Creando una base de datos con XAMPP
Los SGBD permiten definir permisos sobre el tipo de operaciones que pueden realizar
los usuarios.
Si un usuario intenta realizar una operación para la que no tiene permiso, el SGBD la
rechazará.
11
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 1.3: Contenido de la base de datos libreria
Existe un usuario especial (administrador) que tiene acceso total a las bases de datos
almacenadas y puede asignar permisos a los demás usuarios.
12
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 1.4: Definiendo la estructura de una tabla categoria
Gestión de permisos:
13
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 1.5: Definiendo relaciones entre tablas categoria
◦ Ejemplo:
REVOKE ALL PRIVILEGES ON ∗ FROM Manuel
• Transferencia de privilegios:
◦ La cláusula GRANT permite conceder al usuario afectado la capacidad de poder
conceder el privilegio correspondiente a otros usuarios de la base de datos.
14
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 1.6: Definiendo relaciones entre tablas categoria
15
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 1.7: Contenido de la tabla categoria
Esta tecnologı́a permite realizar páginas web dinámicas. Su contenido puede ser com-
pletado en el momento de la llamada a la página gracias a cierta información. Por
ejemplo: la información extraı́da de un formulario o de una base de datos.
16
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 1.8: Modo consola de XAMPP categoria
<!DOCTYPE>
<html>
<head>
< t i t l e >Mi p r i m e r a p á g i n a PHP</ t i t l e >
</head>
<body>
<p>
<?php echo ” B i e n v e n i d o a l mundo de PHP! ” ; ?>
</p>
</body>
</html>
17
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 1.9: Gestión de usuarios categoria
18
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
<p>
B i e n v e n i d o a l mundo de PHP!
</p>
</body>
</html>
Delimitadores PHP
Delimitadores de los scripts de PHP:
Opción 1:
< s c r i p t l a n g u a g e=”PHP”>
...
</ s c r i p t >
Opción 2:
<?php . . . ?>
Bloques PHP
Dentro de un bloque PHP (entre dos delimitadores) puede haber:
Una sola instrucción:
<?php echo ” Hola mundo ! ” ?>
19
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Comentarios PHP
Escritura en la página: echo y print.
<?php
// De una s o l a lı́ n e a
# Otro de una s o l a lı́ n e a
/∗ Y e s t e e s un c o m e n t a r i o de m ú l t i p l e s lı́ n e a s ∗/
?>
Tipos básicos:
• boolean
• integer
• float
• string
Tipos compuestos:
• array
• Object
20
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Cadenas de caracteres (string)
Pueden ser de cualquier longitud.
Para utilizar comillas simples o dobles en una expresión como parte del texto es nece-
sario especificarlas como \’ o \”:
<?php
echo ”Don \ ’ t l e t me down” ;
?>
?>
La primera posición es la 0.
21
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Operadores para cadenas
Concatenación: operador . (punto):
<?php
$nombre = ” Pablo ” ;
$ a p e l l i d o = ” Fernández ” ;
echo $nombre . ” ” . $ a p e l l i d o ; // Pablo Fernández
?>
Arrays
Los arrays en PHP son mapas con orden, es decir, son pares de parejas clave-valor.
Claves: pueden ser integer o string. Pueden estar ambos tipos en un mismo array:
<?php
$num = 1 2 ;
$ m a t r i z = a r r a y ( ” f o o ” => ” bar ” , 12 => t r u e ) ;
echo $ m a t r i z [ ” f o o ” ] ; // bar
echo $ m a t r i z [ 1 2 ] ; // 1
}
?>
22
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Para PHP las matrices son arrays de arrays.
Ejemplo:
<?php
$ c i u d a d e s = a r r a y ( ’ESPAÑA ’=> a r r a y ( ’ Madrid ’ , ’ B a r c e l o n a ’ , ’
Zaragoza ’ ) ,
’FRANCIA ’=> a r r a y ( ’ P a rı́ s ’ , ’ Nantes ’ ) ) ;
echo $ c i u d a d e s [ ’ESPAÑA ’ ] [ 0 ] ;
echo $ c i u d a d e s [ ’FRANCIA ’ ] [ 1 ] ;
?>
Constantes
Las constantes son sensibles a mayúsculas y minúsculas.
Definición:
<?php
d e f i n e ( ”CONSTANTE” , ” Hola amigo ! ” ) ;
echo CONSTANTE; // muestra ” Hola amigo ! ”
?>
23
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
El alcance de una costante definida es el script donde se encuentra.
Existen muchas constantes predefinidas.
Operadores
Son similares a los de C++:
+ - * / % ++ -- .(para las cadenas)
= += -= *= /= .=
== != < <= >=
! && ||
=== (igualdad y tipos idénticos)
!== (desigualdad o tipos distintos)
Instrucciones de control
También son similares a las de C++
if(condición){...} else {...} o if(condicion){...} elseif(condicion) {...}
switch(expresión){
case valor1: ...; break;
case valor2: ...; break;
...
default: ...
}
Nota: existe una sintaxis ligeramente distinta si queremos intercalar código HTML: <?php
if (condición)?>
código HTML
<?php endif; ?>
while(condición){
...
}
do
...
while(condición)
for(inicialización; condición; incremento) {
...
}
Al igual que en el caso anterior, la sintaxis de los bucles puede variar ligeramente si se
intercala código HTML.
24
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Procesamiento de colecciones
Procesamiento de los elementos de un array:
foreach(array as $valor)...
Se itera para cada elemento del array, asignando el valor a $valor (y la clave a $key en
el segundo caso).
<?php
$ m a t r i z = a r r a y ( ” a ” , ”b” , ” c ” , ”d” , ” e ” ) ;
fo reac h ( $matriz as $val ) {
echo ” $ v a l ” ;
};
f o r e a c h ( $ m a t r i z a s $key => $ v a l ) {
echo ” $key : $ v a l ” ;
}
?>
Funciones
Una función se define a partir de nombre y de sus sus parámetros:
Sintaxis:
function nombre($par1 [=valor1], $par2 [=valor2], ... , $parN [=valorN])
{ ...}
...
}
Se pueden omitir argumentos por el final, usándose entonces los valores por defecto.
Algunos ejemplos:
<?php
// Algunas d e c l a r a c i o n e s :
function hola () {
echo ” ¡ H o l a ! ” ;
}
f u n c t i o n producto ( $valor1 , $valor2 ) {
return $valor1 ∗ $valor2
}
25
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
// Algunas l l a m a d a s :
hola () ;
p r o d u ct o ( 3 , 7 ) ;
?>
26
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
1.3.2. Formularios
Introducción
En HTML existen dos métodos principales para interactuar con el usuario:
• Los vı́nculos.
• Los formularios.
Los vı́nculos
Los vı́nculos pueden enviar información a la página que se llama.
Sintaxis: Nombre-url?variable-1=valor-1&...&variable-n=valor-n.
Ejemplo:
pagina1.php:
<?php $nombre=Pepe ’ ; ?>
...
<body>
...
<a h r e f =”p a g i n a 2 . php? nombre=<?php echo $nombre ; ?”>Pagina 2 >/a>
...
</body>
Si pagina2.php es:
27
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
...
<body>
...
<?php echo ” Página 2 − Hola $nombre ; ?>
...
</body>
”Página 2 - Hola”
28
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
// d e l idioma ( c l a v e de l a m a t r i z ) y e l nombre d e l idioma .
$idiomas disponibles = array (
’E ’ => ’ Espa ñol ’ ,
’F ’ => ’ F r a n cé s ’ ,
’ I ’ => ’ I t a l i a n o ’ ) ;
// Código d e l idioma d e l u s u a r i o .
$idioma = ’E ’ ;
?>
29
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
<!DOCTYPE html>
<head><t i t l e >Generar una l i s t a de o p c i o n e s de s e l e c c i ó n m ú l t i p l e </ t i t l e
></head>
<body>
<div>
<?php
// F r u t a s para m o st ra r en l a l i s t a , con l a forma
// de una m a t r i z a s o c i a t i v a que da e l c ó d i g o
// de l a f r u t a ( c l a v e de l a m a t r i z ) y e l nombre de l a f r u t a .
$frutas del mercado = array (
’A ’ => ’ A l b a r i c o q u e s ’ ,
’C ’ => ’ C e r e z a s ’ ,
’F ’ => ’ F r e s a s ’ ,
’P ’ => ’ M e l o c o t o n e s ’ ,
’ ? ’ => ’No s a b e ’ ) ;
// F r u t a s p r e f e r i d a s d e l u s u a r i o , con l a forma
// de una m a t r i z que da e l c ó d i g o de l a s f r u t a s c o r r e s p o n d i e n t e s .
$ f r u t a s p r e f e r i d a s = a r r a y ( ’A ’ , ’F ’ ) ;
// A d v e r t e n c i a : veremos más a d e l a n t e cómo r e c u p e r a r
// e s t a i n f o r m a c i ó n en una b a s e de d a t o s .
?>
30
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
// para l a i n d i c a c i ó n de s e l e c c i ó n y l a v a r i a b l e $nombre
// para e l t e x t o mostrado en l a l i s t a .
echo ”<o p t i o n v a l u e =\” $ c ó d i g o \” $ s e l e c c i ó n >$nombre</o p t i o n >” ;
}
?>
</ s e l e c t >
</form>
</body>
</html>
Procesamiento de formularios
Existen tres formas para procesar la información de un formulario con scripts de PHP:
El formulario en HTML puro (sin ningún elemento dinámico) se relaciona con el script
de PHP a través del atributo action.
Ninguna de estas formas es mejor que las demás. La elección de una u otra depende
de cada caso.
Cuestión: ¿cómo podemos tener acceso a los datos enviados cuando submitimos la
información de un formulario.
También están disponibles en la variable superglobal $ REQUEST que agrupa a las an-
teriores.
31
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
<form a c t i o n=” p r o c e s o . php” method=” p o s t ”>
<div>
Nombre : <i n p u t type=” t e x t ” name=”nombre” v a l u e=” ” />
<i n p u t type=” submit ” name=” a c e p t a r ” v a l u e=” Aceptar ” />
</div>
</form>
</body>
</html>
32
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Otra posibilidad para acceder a la información de un formulario consiste en importar
en variables PHP la información.
Un ejemplo:
<form a c t i o n=” p r o c e s a r . php” method=”POST”><div>
A p e l l i d o : <i n p u t type=” t e x t ” name=” e n t r a d a [ ] ”>
Nombre:< i n p u t type=” t e x t name=” e n t r a d a [ ] ”>
<i n p u t type=” submit ” name=” a c e p t a r ” v a l u e=” Aceptar ”>
</form>
La aparición de entrada[] como valor de name produce una única variable entrada
con formato de matriz (array). El primer elemento tiene la clave 0.
33
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Es posible utilizar una notación de tipo matriz indicando el nombre de clave de
entrada[].
Un ejemplo:
<form a c t i o n=” p r o c e s a r . php” method=”POST”><div>
A p e l l i d o : <i n p u t type=” t e x t ” name=” e n t r a d a [ a p e l l i d o ] ”>
Nombre:< i n p u t type=” t e x t name=” e n t r a d a [ nombre ] ”>
<i n p u t type=” submit ” name=” a c e p t a r ” v a l u e=” Aceptar ”>
</form>
34
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Acceso a la información de las casillas de verificación
35
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Validación de datos
Limpieza de los espacios innecesarios:
Dato obligatorio:
Ejemplo:
$nombre=t r i m ( $ POST [ ’ nombre ’ ] ) ;
i f ( s t r l e n ( $nombre ) >25){
// P r o c e s a r r e s p u e s t a
}
Con las funciones eregi y ereg se puede controlar el formato de una cadena de carac-
teres.
Ejemplo:
• Una cadena de caracteres debe comenzar por una letra, seguida de letras (y ca-
racteres: ,#,*,$ ). Debe de tener una longitud mı́nima de 4:
36
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
$ c o n t r a s e ñ a=t r i m ( $ POST [ ’ c o n t r a s e ñ a ’ ] ) ;
i f ( ! e r e g i ( ’ ˆ [ a−z ] [ a−z0 −9 #∗$ ] { 3 , } ’ , $ c o n t r a s e ñ a ) ) {
// P r o c e s a r c o n t r a s e ñ a i n v á l i d a
}
Tomemos, por ejemplo, el formato de fecha: DD/MM/AAAA. Por lo tanto, son inváli-
das: 01/01/99 y 32/01/1999.
^: marca de comienzo.
Existen tres métodos similares para saber si una fecha con formato correcto es válida.
37
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
i f ( ! c h e c k d a t e ( $dma [ 1 ] , $dma [ 0 ] , $dma [ 2 ] ) ) {
// P r o c e s a r f e c h a i n v á l i d a
}
38
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
<br />
<i n p u t type=” t e x t ” name=” e m a i l ” v a l u e=”<?php echo $ e m a i l ?>” />
<br />
<i n p u t type=” submit ” v a l u e=” Enviar ” />
</form>
Comentarios:
filter var($valor, FILTER VALIDATE INT, $opciones) es un filtro que permite va-
lidar si una variable contiene un valor numérico. Opcionalmente (como en este caso)
se puede indicar unos valores máximos y mı́nimos permitidos.
39
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
La función validarEntero funcionarı́a también si no pasamos un intervalo de máximos
y mı́nimos ya que $opciones tiene un valor por defecto.
filter var($valor, FILTER VALIDATE EMAIL): es un filtro (predefinido) que permite
validar si una variable contiene una dirección de correo electrónico válida.
Declaramos un otra página validado.php auxiliar para indicar que todo ha ido bien:
<!DOCTYPE>
<html>
<head>
< t i t l e > F o r m u l a r i o </ t i t l e >
<meta http−e q u i v=” Content−Type” c o n t e n t=” t e x t / html ; c h a r s e t=u t f
−8” />
</head>
<body>
<s t r o n g > Sus d a t o s han s i d o e n v i a d o s c o r r e c t a m e n t e </s t r o n g >
</body>
</html>
La función isset determina si una variable está definida (tiene contenido) o no. Juntándolo
todo:
<?php
// Importamos e l a r c h i v o con l a s v a l i d a c i o n e s .
r e q u i r e o n c e ’ v a l i d a c i o n e s . php ’ ;
// Guarda l o s v a l o r e s de l o s campos en v a r i a b l e s , s i e m p r e y cuando s e
haya e n v i a d o e l f o r m u l a r i o , s i n o s e gu a r d ar á n u l l .
$nombre = i s s e t ( $ POST [ ’ nombre ’ ] ) ? $ POST [ ’ nombre ’ ] : n u l l ;
$edad = i s s e t ( $ POST [ ’ edad ’ ] ) ? $ POST [ ’ edad ’ ] : n u l l ;
$ e m a i l = i s s e t ( $ POST [ ’ e m a i l ’ ] ) ? $ POST [ ’ e m a i l ’ ] : n u l l ;
// Este a r r a y g u a r d a r á l o s e r r o r e s de v a l i d a c i ó n que s u r j a n .
$ e r r o r e s = array () ;
// Pregunta s i e s t á l l e g a n d o una p e t i c i ó n por POST, l o que s i g n i f i c a que
e l u s u a r i o e n v i ó e l f o r m u l a r i o .
i f ($ SERVER [ ’REQUEST METHOD ’ ] == ’POST ’ ) {
// V a l i d a que e l campo nombre no e s t é v a cı́ o .
i f ( ! v a l i d a R e q u e r i d o ( $nombre ) ) {
$ e r r o r e s [ ] = ’ El campo nombre e s i n c o r r e c t o . ’ ;
}
// V a l i d a l a edad con un rango de 3 a 130 a ños .
$opciones edad = array (
’ o p t i o n s ’ => a r r a y (
// D e f i n i m o s e l rango de edad e n t r e 3 a 1 3 0 .
’ min range ’ => 3 ,
’ max range ’ => 130
40
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
)
);
i f ( ! v a l i d a r E n t e r o ( $edad , $ o p c i o n e s e d a d ) ) {
$ e r r o r e s [ ] = ’ El campo edad e s i n c o r r e c t o . ’ ;
}
// V a l i d a que e l campo e m a i l s e a c o r r e c t o .
i f ( ! validaEmail ( $email ) ) {
$ e r r o r e s [ ] = ’ El campo e m a i l e s i n c o r r e c t o . ’ ;
}
// V e r i f i c a s i ha e n c o n t r a d o e r r o r e s y de no haber r e d i r i g e a l a
p á g i n a con
// e l mensaje de que pasó l a v a l i d a c i ó n .
i f (! $errores ){
h e a d e r ( ’ L o c a t i o n : v a l i d a d o . php ’ ) ;
exit ;
}
}
?>
<!DOCTYPE>
<html>
<head>
< t i t l e > F o r m u l a r i o </ t i t l e >
<meta http−e q u i v=” Content−Type” c o n t e n t=” t e x t / html ; c h a r s e t=u t f
−8” />
</head>
<body>
<?php i f ( $ e r r o r e s ) : ?>
<ul>
<?php f o r e a c h ( $ e r r o r e s a s $ e r r o r ) : ?>
< l i > <?php echo $ e r r o r ?> </ l i >
<?php e n d f o r e a c h ; ?>
</ul>
<?php e n d i f ; ?>
<form method=” p o s t ” a c t i o n=” i n d e x 2 . php”>
<l a b e l > Nombre </ l a b e l >
<br />
<i n p u t type=” t e x t ” name=”nombre” v a l u e=”<?php echo $nombre
?>” />
<br />
<l a b e l > Edad </ l a b e l >
41
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
<br />
<i n p u t type=” t e x t ” name=” edad ” s i z e=”3 ” v a l u e=”<?php echo
$edad ?>” />
<br />
<l a b e l > E−m a i l </ l a b e l >
<br />
<i n p u t type=” t e x t ” name=” e m a i l ” v a l u e=”<?php echo $ e m a i l ?>
” />
<br />
<i n p u t type=” submit ” v a l u e=” Enviar ” />
</form>
</body>
</html>
Comentarios:
Con una lista no ordenada (generada dinámicamente) se muestran los errores conteni-
dos en el array $errores.
• Catálogos de productos.
• Lista de clientes.
• Lista de transacciones realizadas, etc.
PHP permite una conexión a una gran número de sistemas de base de datos: MySQL,
ORACLE, Microsoft SQL Server, Informix, SQLite, etc.
PHP admite ODBC (Open DataBase Connectivity) y, por lo tanto, puede conectarse
a cualquier base de datos que soporte ODBC.
42
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• MySQL (prefijo mysql ).
• MySQLi (prefijo mysqli ).
Conexión/desconexión.
Consultas.
Actualizaciones.
1.4.2. Conexión
mysqli connect: permite establecer una conexión con una base de datos MySQL. Paráme-
tros:
usuario: nombre del usuario debe de utilizarse para establecer la conexión. Ejemplo:
root@localhost.
La función mysqli connect devuelve un objeto con un identificador mysqli o el valor FALSE
en caso de error. mysqli close: permite cerrar una conexión durante la ejecución de un
script. Parámetros:
La función mysqli close devuelve TRUE en caso de éxito y FALSE en caso de error. Ejemplo:
< t i t l e >Conexión y d e s c o n e x i ó n </ t i t l e >
<?php
// D e f i n i c i ó n de una peque ña f u n c i ó n que a b r e una c o n e x i ó n .
f u n c t i o n c o n e c t a r ( $host , $ u s u a r i o , $ c o n t r a s e n i a= ’ ’ ) {
$db = @ m y s q l i c o n n e c t ( $host , $ u s u a r i o , $ c o n t r a s e n i a ) ;
i f ( $db ) {
echo ’ Conexión r e a l i z a d a c o r r e c t a m e n t e .< br /> ’ ;
echo ’ I n f o r m a c i ó n s o b r e e l s e r v i d o r : ’ ,
m y s q l i g e t h o s t i n f o ( $db ) , ’<br /> ’ ;
43
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
echo ’ V e r s i ó n d e l s e r v i d o r : ’ ,
m y s q l i g e t s e r v e r i n f o ( $db ) , ’<br /> ’ ;
} else {
printf (
’ E r r o r %d : %s .< br /> ’ ,
mysqli connect errno () , mysqli connect error () ) ;
}
r e t u r n $db ;
}
// D e f i n i c i ó n de una peque ña f u n c i ó n que c i e r r a una c o n e x i ó n .
function desconectar ( $conexion ) {
i f ( $conexion ) {
$ok = @ m y s q l i c l o s e ( $ c o n e x i o n ) ;
i f ( $ok ) {
echo ’ Desco nex ión r e a l i z a d a c o r r e c t a m e n t e .< br /> ’ ;
} else {
echo ’ F a l l o en l a d e s c o n e x i ó n . <br /> ’ ;
}
} else {
echo ’ Conexión no a b i e r t a .< br /> ’ ;
}
}
// Primera prueba de c o n e x i ó n / d e s c o n e x i ó n .
echo ’<b>Primera prueba </b><br /> ’ ;
$db = c o n e c t a r ( ’ l o c a l h o s t ’ , ’ b l a s ’ , ’ web ’ ) ;
d e s c o n e c t a r ( $db ) ;
// Segunda prueba de c o n e x i ó n / d e s c o n e x i ó n .
echo ’<b>Segunda prueba </b><br /> ’ ;
$db = c o n e c t a r ( ’ xampp ’ , ’ d e s c o n o c i d o ’ , ’ d e s c o n o c i d o ’ ) ;
d e s c o n e c t a r ( $db ) ;
?>
Comentarios:
Utilizamos el carácter @ para no mostrar las alertas generadas por las funciones en caso
de error.
mysqli connect errno(): devuelve el número que corresponde a cada error (un cero
si no hay error).
mysqli connect error(): devuelve una cadena de caracteres con la descripción del
error (la cadena vacı́a si no hay error).
44
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
1.4.3. Selección de una base de datos
mysqli select db permite seleccionar (si no se ha hecho con mysqli connect) o mo-
dificar la base de datos seleccionada.
Parámetros:
La función mysqli select db devuelve TRUE en caso de éxito y FALSE en caso de error.
Y crear tablas:
<?php
$db = @ m y s q l i c o n n e c t ( ’ l o c a l h o s t ’ , ’ r o o t ’ , ’ ’ , ’mydb ’ ) ;
i f ( $db ) {
echo ’ Conexión r e a l i z a d a c o r r e c t a m e n t e .< br /> ’ ;
echo ’ I n f o r m a c i ó n s o b r e e l s e r v i d o r : ’ ,
m y s q l i g e t h o s t i n f o ( $db ) , ’<br /> ’ ;
echo ’ V e r s i ó n d e l s e r v i d o r : ’ ,
45
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
m y s q l i g e t s e r v e r i n f o ( $db ) , ’<br /> ’ ;
} else {
printf (
’ E r r o r %d : %s .< br /> ’ ,
mysqli connect errno () , mysqli connect error () ) ;
};
// s q l t o c r e a t e t a b l e
$ s q l = ”CREATE TABLE c a t e g o r i a s (
i d INT ( 6 ) UNSIGNED AUTO INCREMENT PRIMARY KEY,
c a t e g o r i a VARCHAR( 3 0 ) NOT NULL
)” ;
i f ( m y s q l i q u e r y ( $db , $ s q l ) ) {
echo ” Table c a t e g o r i a s c r e a t e d s u c c e s s f u l l y ” ;
} else {
echo ” E r r o r c r e a t i n g t a b l e : ” . m y s q l i e r r o r ( $db ) ;
}
@ m y s q l i c l o s e ( $db ) ;
?>
1.4.4. Consultas
mysqli query permite realizar una consulta en una base de datos. Parámetros:
mysqli query devuelve un identificador (de tipo mysqli result) en caso de éxito y el valor
FALSE en caso contrario.
Con la función mysqli num rows podemos conocer el número de filas del resultado.
La ejecución de una consulta devuelve un resultado que puede ser leı́do por las siguien-
tes funciones:
Básicamente, estas funciones hacen lo mismo: leen una fila del resultado y avanzan el
puntero a la siguiente fila.
46
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Diferencia de formatos entre estas funciones:
mysqli fetch assoc: devuelve una matriz asociativa cuya clave es el nombre de la
columna.
mysqli fetch row: devuelve una matriz con enteros como ı́ndices.
Sintaxis:
matriz mysqli fetch array(objeto resultado, tipo)
matriz mysqli fetch assoc(objeto resultado)
objeto mysqli fetch object(objeto resultado)
matriz mysqli fetch row(objeto resultado)
donde:
resultado: es el identificador devuelto por mysqli query.
47
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
$ f i l a = mysqli fetch row ( $consulta ) ;
mostrar matriz ( $ f i l a , ’ mysql fetch row ’ ) ;
// Segundo f e t c h con m y s q l i f e t c h a s s o c .
$ f i l a = mysqli fetch assoc ( $consulta ) ;
mostrar matriz ( $ f i l a , ’ mysql fetch assoc ’ ) ;
Resultados:
mysqli fetch row:
0=1
1 = Recursos informáticos
2 = 22.44
mysqli fetch assoc:
id = 2
nombre = TechNote
precio siniva = 9.48
mysqli fetch array:
48
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
0=3
id = 3
1 = Prácticas Técnicas
nombre = Prácticas Técnicas
2 = 25.59
precio siniva = 25.59
$fila->id = 4
$fila->nombre = Pack Técnico
$fila->precio siniva = Pack Técnico
1.4.5. Actualizaciones
Actualizar datos supone ejecutar consultas INSERT, UPDATE o DELETE.
La función mysqli affected rows permite conocer el número de filas afectadas por la
última consulta INSERT, UPDATE o DELETE.
49
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
La función mysqli insert id devuelve el último valor generado para la columna con
el tipo AUTO INCREMENT por una consulta INSERT
Ejemplo:
<!DOCTYPE html>
<head><t i t l e >C o n su l ta no p r e p a r a d a : a c t u a l i z a c i ó n </ t i t l e ></head>
<body>
<?php
// D e f i n i c i ó n de una peque ña f u n c i ó n de v i s u a l i z a c i ó n de l a
lista
// de l a s c o l e c c i o n e s .
f u n c t i o n m o s t r a r c o l e c c i o n e s ( $db ) {
$ s q l = ’SELECT ∗ FROM c o l e c c i o n ’ ;
$ c o n s u l t a = m y s q l i q u e r y ( $db , $ s q l ) ;
echo ”<b>L i s t a de l a s c o l e c c i o n e s :</b><br />” ;
while ( $ f i l a = mysqli fetch assoc ( $consulta ) ) {
echo $ f i l a [ ’ i d ’ ] , ’ − ’ , $ f i l a [ ’ nombre ’ ] ,
’ − ’ , $ f i l a [ ’ p r e c i o s i n i v a ’ ] , ’<br /> ’ ;
}
}
// Conexión ( con s e l e c c i ó n de l a b a s e de d a t o s ) .
$db = m y s q l i c o n n e c t ( ’ l o c a l h o s t ’ , ’ eniweb ’ , ’ web ’ , ’ e n i ’ ) ;
i f ( ! $db ) {
e x i t ( ’ F a l l o en l a c o n e x i ó n . ’ ) ;
}
// V i s u a l i z a c i ó n de c o n t r o l .
m o s t r a r c o l e c c i o n e s ( $db ) ;
// C o n su l ta INSERT .
$ s q l = ”INSERT INTO c o l e c c i o n ( nombre , p r e c i o s i n i v a ) ” .
”VALUES( ’ Pack O f i m á t i c a ’ , 5 5 . 9 2 ) ” ;
$ c o n s u l t a = m y s q l i q u e r y ( $db , $ s q l ) ;
$ i d e n t i f i c a d o r = m y s q l i i n s e r t i d ( $db ) ;
echo ’ I d e n t i f i c a d o r de l a nueva c o l e c c i ó n = ’ ,
$ i d e n t i f i c a d o r , ’<br /> ’ ;
// C o n s ul ta UPDATE.
$ s q l = ”UPDATE c o l e c c i o n SET p r e c i o s i n i v a = p r e c i o s i n i v a ∗
1.05 ” .
”WHERE p r e c i o s i n i v a < 25 ” ;
$ c o n s u l t a = m y s q l i q u e r y ( $db , $ s q l ) ;
$número = m y s q l i a f f e c t e d r o w s ( $db ) ;
echo ” $número c o l e c c i ó n / c o l e c c i o n e s más.< br />” ;
// V i s u a l i z a c i ó n de c o n t r o l .
50
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
m o s t r a r c o l e c c i o n e s ( $db ) ;
?>
</body>
</html>
Inserción: Borrado:
<?php
$db = @ m y s q l i c o n n e c t ( ’ l o c a l h o s t ’ , ’ r o o t ’ , ’ ’ , ’mydb ’ ) ;
i f ( $db ) {
echo ’ Conexión r e a l i z a d a c o r r e c t a m e n t e .< br /> ’ ;
echo ’ I n f o r m a c i ó n s o b r e e l s e r v i d o r : ’ ,
m y s q l i g e t h o s t i n f o ( $db ) , ’<br /> ’ ;
echo ’ V e r s i ó n d e l s e r v i d o r : ’ ,
m y s q l i g e t s e r v e r i n f o ( $db ) , ’<br /> ’ ;
} else {
printf (
’ E r r o r %d : %s .< br /> ’ ,
mysqli connect errno () , mysqli connect error () ) ;
};
// s q l t o d e l e t e a r e c o r d
$ s q l = ”DELETE FROM l i b r o s WHERE i d=3” ;
i f ( m y s q l i q u e r y ( $db , $ s q l ) ) {
echo ” Record d e l e t e d s u c c e s s f u l l y ” ;
} else {
echo ” E r r o r d e l e t i n g r e c o r d : ” . m y s q l i e r r o r ( $db ) ;
}
@ m y s q l i c l o s e ( $db ) ;
?>
En cada ejecución de este tipo de consultas se utiliza el valor actual de las variables
PHP asociadas a los parámetros.
Su interés consiste en poder utilizar varias veces la misma consulta con valores dife-
rentes sin tener que analizar de nuevo la consulta. Mejora el rendimiento.
51
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Pasos a realizar para realizar una consulta preparada:
Vincular las variables PHP con los parámetros de la consulta (mysqli stmt bind param).
Vincular las variables PHP a las columnas del resultado (mysqli bind result).
booleano mysqli stmt bind param(objeto consulta, cadena tipos, mixto variables).
tipos es una cadena de caracteres donde indicamos los tipos de las variables a vincular.
Casos:
Ejemplo:
<!DOCTYPE html>
<head><t i t l e >C o n su l ta p r e p ar a d a : l e c t u r a </ t i t l e ></head>
<body>
<?php
// Conexión y s e l e c c i ó n de l a b a s e de d a t o s .
$db = m y s q l i c o n n e c t ( ’ l o c a l h o s t ’ , ’ eniweb ’ , ’ web ’ , ’ e n i ’ ) ;
i f ( ! $db ) {
e x i t ( ’ F a l l o en l a c o n e x i ó n . ’ ) ;
}
// P r e p a r a c i ó n de l a c o n s u l t a .
$ s q l = ’SELECT id , t i t u l o FROM l i b r o WHERE i d c o l e c c i o n = ? ’ ;
$ c o n s u l t a = m y s q l i p r e p a r e ( $db , $ s q l ) ;
// Enl ace de l o s p a r ám e tro s .
$ok = m y s q l i s t m t b i n d p a r a m ( $ c o n s u l t a , ’ i ’ , $ i d c o l e c c i o n ) ;
// E j e c u c i ó n de l a c o n s u l t a .
52
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
$id coleccion = 1;
$ok = m y s q l i s t m t e x e c u t e ( $ c o n s u l t a ) ;
// Enl ace de l a s columnas d e l r e s u l t a d o .
$ok = m y s q l i s t m t b i n d r e s u l t ( $ c o n s u l t a , $id , $ tı́ t u l o ) ;
// L e c t u r a d e l r e s u l t a d o .
echo ”<b>C o l e c c i ó n número $ i d c o l e c c i o n </b><br />” ;
while ( mysqli stmt fetch ( $consulta ) ) {
echo ” $ i d − $ tı́ t u l o <br />” ;
}
// Nueva e j e c u c i ó n y l e c t u r a d e l r e s u l t a d o
// ( no v a l e r e h a c e r l o s e n l a c e s ) .
$id coleccion = 3;
$ok = m y s q l i s t m t e x e c u t e ( $ c o n s u l t a ) ;
echo ”<b>C o l e c c i ó n número $ i d c o l e c c i o n </b><br />” ;
while ( mysqli stmt fetch ( $consulta ) ) {
echo ” $ i d − $ tı́ t u l o <br />” ;
}
// Des con exi ón .
$ok = m y s q l i c l o s e ( $db ) ;
?>
</body>
</html>
Vincular las variables PHP con los parámetros de la consulta (mysqli stmt bind param).
Conocer el valor del último identificador generado para una columna con el tipo
AUTO INCREMENT (mysqli stmt insert id).
Ejemplo:
53
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
<!DOCTYPE html>
<head><t i t l e >C o n s ul ta pr e p a r ad a : a c t u a l i z a c i ó n </ t i t l e ></head>
<body>
<?php
// Conexión y s e l e c c i ó n de l a b a s e de d a t o s .
$db = m y s q l i c o n n e c t ( ’ l o c a l h o s t ’ , ’ eniweb ’ , ’ web ’ , ’ e n i ’ ) ;
i f ( ! $db ) {
e x i t ( ’ F a l l o en l a c o n e x i ó n . ’ ) ;
}
// P r e p a r a c i ó n de l a c o n s u l t a .
$ s q l = ’UPDATE c o l e c c i o n SET g a s t o s s i n i v a = ? ’ .
’WHERE g a s t o s s i n i v a IS NULL ’ ;
$ c o n s u l t a = m y s q l i p r e p a r e ( $db , $ s q l ) ;
// E nlac e de l o s p a r á me tros .
$ok = m y s q l i s t m t b i n d p a r a m ( $ c o n s u l t a , ’ d ’ , $ g a s t o s s i n i v a ) ;
// E j e c u c i ó n de l a c o n s u l t a .
$gastos siniva = 1;
$ok = m y s q l i s t m t e x e c u t e ( $ c o n s u l t a ) ;
echo ’ Número de c o l e c c i o n e s m o d i f i c a d a s = ’ ,
m y s q l i s t m t a f f e c t e d r o w s ( $ c o n s u l t a ) , ’<br /> ’ ;
// P r e p a r a c i ó n de l a c o n s u l t a .
$ s q l = ’INSERT INTO c o l e c c i o n ( nombre ) VALUES( ? ) ’ ;
$ c o n s u l t a = m y s q l i p r e p a r e ( $db , $ s q l ) ;
// E nlac e de l o s p a r á me tros .
$ok = m y s q l i s t m t b i n d p a r a m ( $ c o n s u l t a , ’ s ’ , $nombre ) ;
// E j e c u c i ó n de l a c o n s u l t a .
$nombre = ’ S o l u c i o n e s I n f o r m á t i c a s ’ ;
$ok = m y s q l i s t m t e x e c u t e ( $ c o n s u l t a ) ;
echo ’ I d e n t i f i c a d o r de l a nueva c o l e c c i ó n = ’ ,
m y s q l i s t m t i n s e r t i d ( $ c o n s u l t a ) , ’<br /> ’ ;
// Descon exi ón .
$ok = m y s q l i c l o s e ( $db ) ;
?>
</body>
</html>
1.5. Sesiones
Introducción:
54
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
El protocolo HTTP es un protocolo ”sin estado”:
Para un sitio web interactivo es necesario identificar a un usuario que recorre las páginas
de su web (no pensar que son dos usuarios distintos) y, en general, conservar cierta
información del usuario de una página a otra.
Cualquier script relacionado con la gestión de sesiones tiene que invocar esta función
para tener acceso a las variables de sesión.
Si no se ha abierto todavı́a la sesión, está función intentará almacenar una cookie que
contenga el identificador de sesión en el sistema del usuario.
55
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Después de llamar a la función session start, los datos de la sesión puede manipularse
directamente en la matriz $ SESSION.
Para leer o modificar un valor de esta matriz solamente hay que acceder a él utilizando
su clave.
Para guardar un nuevo dato en la sesión, solo hay que almacenar este dato en esta
matriz con la clave que se quiera.
session id:
Invocada sin parámetro devuelve el valor del identificador de la sesión.
Esta función no elimina los datos de la sesión hasta que no finalice la ejecución del
script actual. Para eliminar inmediatamente la información se puede asignar una matriz
vacı́a a $ SESSION.
56
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
<!DOCTYPE html>
<head><t i t l e >S e s i ó n − Página 1</ t i t l e ></head>
<body>
<div><a h r e f=” pagina −2.php”>Página 2</a></div>
</body>
</html>
pagina-2.php
<?php
// Llamada a s e s s i o n s t a r t .
session start () ;
?>
<!DOCTYPE html>
<head><t i t l e >S e s i ó n − Página 2</ t i t l e ></head>
<body>
<div>
<?php
// Llamada a s e s s i o n s t a r t .
session start () ;
// V i s u a l i z a c i ó n .
echo ’ $ SESSION [ \ ’ nombre \ ’ ] = ’ ,
i s s e t ( $ SESSION [ ’ nombre ’ ] ) ?$ SESSION [ ’ nombre ’ ] : ’ ’ ,
’<br /> ’ ;
echo ’ $ SESSION [ \ ’ d a t o s \ ’ ] [ \ ’ a p e l l i d o \ ’ ] = ’ ,
i s s e t ( $ SESSION [ ’ d a t o s ’ ] [ ’ a p e l l i d o ’ ] ) ?
$ SESSION [ ’ d a t o s ’ ] [ ’ a p e l l i d o ’ ] : ’ ’ ,
’<br /> ’ ;
?>
</div>
</body>
</html>
57
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
58
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Capı́tulo 2
Normalización
• Redundancias de Datos.
• Anomalı́as de actualización.
• Filas incorrectas.
• Exceso de espacio ocupado.
• Un diseño relacional sin redundancias es menos vulnerable a inconsistencias y
anomalı́as de actualización.
59
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
2.2. Redundancias y anomalı́as
Consideremos las siguientes tablas:
Empleados
Id-empleado NombreE DirecciónE Puesto Salario Centro
123A Ana Almansa c/Argentales Profesor 20.000 Informática
456B Bernardo Botı́n c/Barcelona Administrativo 15.000 Matemáticas
789C Carlos Crespo c/Cruz Catedrático 30.000 CC.Empresariales
012D David Dı́az c/Daroca Ayudante 10.000 Informática
Centros
NombreC DirecciónC Teléfono
Informática Complutense 123
Matemáticas Complutense 456
CC.Empresariales Somosaguas 789
Empleados-Centros
Id-empleado NombreP DirecciónP Puesto Salario Centro DirecciónC Teléfono
123A Ana Almansa c/Argentales Profesor 20.000 Informática Complutense 123
456B Bernardo Botı́n c/Barcelona Administrativo 15.000 Matemáticas Complutense 456
789C Carlos Crespo c/Cruz Catedrático 30.000 CC.Empresariales Somosaguas 789
012D David Dı́az c/Daroca Ayudante 10.000 Informática Complutense 123
Anomalı́as de actualización:
• Anomalı́as de inserción:
◦ Cuando se inserta sin respetar la dependencia funcional. Ejemplo: añadir un
empleado a Informática con un teléfono distinto de 123.
◦ Cuando se inserta el consecuente de la dependencia funcional sin el antece-
dente. Ejemplo: no se puede dar de alta un centro sin dar de alta un empleado.
• Anomalı́as de modificación: en aquellos casos con información redundante modi-
ficar solamente algunas de sus apariciones. Ejemplo: para modificar el teléfono de
Informática es preciso modificar todas sus apariciones.
• Anomalı́as de eliminación: cuando se eliminan todas las filas redundantes de una
dependencia funcional. Ejemplo: si se eliminan todos los empleados de un centro
también se elimina el centro.
60
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
2.3. Conceptos necesarios
2.3.1. Notación
Necesitamos representar de forma adecuada tanto la estructura de la tabla como las filas
de ella. Seguiremos la siguiente notación:
r(A, B, C, D, ...)
Utilizamos la letra ρ para denotar el conjunto de todos los atributos de una relación r.
La notación t[β] representa la proyección de la tupla t sobre los atributos del conjunto
β.
Una instancia de r que satisface las restricciones impuestas es una instancia legal de
r.
61
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
¿Cómo se expresan formalmente estas restricciones?
1. Claves.
2. Dependencias funcionales.
Superclave:
Dependencia funcional
Una instancia de r(ρ) satisface la dependencia funcional α → β si para cada par de
tuplas t, t0 de la instancia se cumple:
62
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
La forma normal de una BD se refiere a la forma normal más exigente que satisfacen
todas sus tablas.
Las formas normales más habituales, por orden ascendente de exigencia de las propie-
dades deseadas, son:
Ejemplo:
Centros:
NombreC DirecciónC Teléfonos
Informática Complutense 123, 321, 213
Matemáticas Complutense 456
CC. Empresariales Somosaguas 789, 987
63
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Solución 1: Eliminar el atributo Teléfonos y crear una nueva relación que asocie
en cada fila un centro con un teléfono.
Centros:
NombreC DirecciónC
Informática Complutense
Matemáticas Complutense
CC. Empresariales Somosaguas
Teléfonos:
NombreC Teléfono
Informática 123
Informática 321
Informática 213
Matemáticas 456
CC. Empresariales 789
CC. Empresariales 987
Consecuencias:
◦ La clave de la 1a relación debe formar parte de clave de la 2a relación.
◦ Suceden anomalı́as cuando se borra un centro (en la tabla Centros) y olvida-
mos borrar los teléfonos asociados.
◦ La integridad referencial (FK) asegura evitar estas anomalı́as. El NombreC
de Teléfonos se hace FK con apunte a NombreC de Centros.
• Solución 2: ampliar la clave de la relación de manera que incluya al atributo
multivalorado.
NombreC DirecciónC Teléfono
Informática Complutense 123
Informática Complutense 321
Informática Complutense 213
Matemáticas Complutense 456
CC. Empresariales Somosaguas 789
CC. Empresariales Somosaguas 987
Consecuencias:
◦ Inconveniente: añade redundancia que provoca anomalı́as.
• Solución 3: si se conoce la cardinalidad máxima del atributo multivalorado se
pueden crear tantas columnas como la cardinalidad máxima
NombreC DirecciónC Teléfono1 Teléfono2 Teléfono3
Informática Complutense 123 321 213
Matemáticas Complutense 456 null null
CC. Empresariales Somosaguas 789 987 null
64
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Consecuencias:
◦ Inconveniente: uso de valores null.
• Consideremos la tabla:
Personal-proyectos
Id-empleado NúmeroP Horas NombreE NombreP
123A P-1 16 Ana Almansa Proyecto 1
012D P-1 8 David Dı́az Proyecto 1
012D P-2 4 David Dı́az Proyecto 2
NO está en 2a FN pero sı́ en 1a FN.
• Dependencias funcionales:
◦ (Id − empleado, N umeroP ) →DF 1 Horas
◦ Id − empleado →DF 2 N ombreE
◦ N umeroP →DF 3 N ombreP
• Problema: Todos los atributos no dependen de la PK completa. Alguno solo de
parte de ella (de algún atributo, no de todos).
• Existen anomalı́as de actualización causadas por DF2 y DF3. Como sus antede-
centes no son clave, puede haber varias filas con los mismos valores para estas
dependencias funcionales.
65
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
La 2FN evita este tipo de anomalı́as. Se basa en el concepto de Dependencia funcional
completa.
Un tabla está en 2FN si cada atributo que no forme parte de ninguna clave candidata
depende funcional y completamente de cada clave candidata.
Empleados-departamentos:
Id-empleado NombreE DirecciónE CódigoD NombreD DirectorD
123A Ana Almansa c/ Argentales DS Sistemas 999Z
012D David Dı́az c/ Daroca DS Sistemas 999Z
66
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
2. no son subconjunto de ninguna clave candidata y
3. se cumple que α → β y β → γ.
67
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Sea F un conjunto de DFs de una relación r(ρ). El cierre de F (escrito F ∗ ) es el
conjunto de DFs que están implicadas por F .
• Se puede obtener el cierre de cualquier conjunto F mediante los tres axiomas de
Armstrong:
◦ Reflexividad: Si β ⊆ α, entonces se cumple α → β.
◦ Aumentatividad: Si α → β entonces αγ → βγ para cualquier conjunto γ.
◦ Transitividad: Si α → β y β → γ, entonces α → γ.
• Estos tres axiomas son correctos y completos:
◦ Correctos: no dan lugar a DFs incorrectas.
◦ Completos: son suficientes para obtener F ∗ .
• Aunque las reglas de reflexividad, aumentatividad y transitividad son suficientes
para obtener F ∗ , suele ser útil la aplicación de otras reglas que se deducen de las
primeras:
◦ Union: Si α → β y α → γ, entonces α → βγ.
◦ Descomposición: Si α → βγ, entonces α → β y α → γ.
◦ Pseudotransitividad: Si α → β y γβ → δ, entonces αγ → δ.
• Ejemplo:
◦ Consideremos la tabla:
id nombre salario dpto edificio presupuesto
INF1 Laura Estévez álgebra 1600 FM 30000
INF2 Juan Herrero Sistmas inf. 1550 FM 25000
INF3 Javier Guzmán álgebra 1600 FM 30000
◦ Sea F = {(id → nombre, dpto), (id → salario), (dpto → edif icio), (dpto →
presupuesto)}
◦ Enumera algunas de las DFs que forman parte de F ∗ .
• Calculo de F ∗ :
◦ Existe un algoritmo para calcular F ∗ .
◦ Consiste en la aplicación exhaustiva de los tres axiomas de Armstrong.
◦ Este algoritmo no se utiliza en la práctica, ya que el conjunto F ∗ es demasiado
grande.
◦ Existe una manera de saber si una dependencia funcional α → β pertenece a
F ∗ sin tener que enumerar todo el conjunto F ∗ .
◦ La herramienta utilizada será el cierre de un conjunto de atributos.
• Cierre de un conjunto de atributos:
◦ Sea α ⊆ ρ un conjunto de atributos en r(ρ) y un conjunto F de dependencias
funcionales. El cierre de α (denotado α∗ ) bajo F es el conjunto de atributos
de r(ρ) que está funcionalmente determinado por α.
68
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
◦ Es decir, el mayor conjunto de atributos posible β tales que α → β ∈ F ∗
◦ Ejemplo: Sea F = {A → CE, C → D, CE → B} entonces A∗ = {A, C, E, D, B}
A→B
A→C
CG → H
CG → I
B→H
Calcula {AG∗ }
Ejemplo:
• Consideremos la relación:
id nombre salario dpto edificio presupuesto
INF1 Laura Estévez álgebra 1600 FM 30000
INF2 Juan Herrero Sistmas inf. 1550 FM 25000
INF3 Javier Guzmán álgebra 1600 FM 30000
• Dados: (id → nombre, dpto), id → salario, dpto → edif icio, dpto → presupuesto
• ¿Es id superclave?. id∗ = {id, nombre, dpto, salario, edif icio, presupuesto}. Por
tanto, id es superclave.
• ¿se deduce dpto → edif icio, salario, a partir de estas DFs?. dpto∗ = {dpto, edif icio, presupuesto}.
Como salario 6∈ dpto∗ , no se deduce.
69
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Un esquema de relación r(ρ) está en forma normal de Boyce-Codd con respecto a un
conjunto de dependencias funcionales F si y sólo si para todo α → β ∈ F ∗ se cumple
uno de los siguientes requisitos:
• α → β es una DF trivial.
• α es superclave de ρ.
Ejemplo:
Transformación a BCNF:
Ejemplo:
70
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 2.1: Test sobre BCNF
Transformación a BCNF:
Ejemplo:
• Sea (A, B, C, D, E)
• Volvemos al ejemplo anterior: F = {A → B, BC → D}
• Como estamos descomponiendo la relación inicial, sólo es necesario buscar depen-
dencias funcionales que no cumplan las condiciones de BCNF en F .
◦ En nuestro caso, A → B no cumple las condiciones.
• Para (A, B):
71
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
{A}∗ = {A, B} contiene todo {A, B} {B}∗ = {B} no contiene atributos de
{A, B} − {B}
{A, B}∗ = {A, B} contiene todo {A, B}
◦ Aplicamos el algoritmo de búsqueda de DFs que violen las condiciones de
BCNF en la tabla (A, B)
◦ Por tanto (A,B) está en BCNF. Eso ya lo sabı́amos, porque cualquier relación
con dos atributos está en BCNF.
• Para (A, C, D, E):
◦ Aplicamos el algoritmo de búsqueda de DFs que violen las condiciones de
BCNF.
{A}∗ = {A, B}
{C}∗ = {C}
{D}∗ = {D}
{E}∗ = {E}
{A, C}∗ = {A, C, B, D}
{A, D}∗ = {A, D, B}
{A, E}∗ = {A, E, B}
{C, D}∗ = {C, D}
{C, E}∗ = {C, E}
{D, E}∗ = {D, E}
{A, C, D}∗ = {A, C, D, B}
{A, C, E}∗ = {A, C, E, B, D}
{A, D, E}∗ = {A, D, E, B}
{C, D, E}∗ = {C, D, E}
{A, C, D, E}∗ = {A, C, D, E, B}
◦ Aplicamos el algoritmo de búsqueda de DFs que violen las condiciones de
BCNF: {A, C}∗ = {A, C, B, D}
◦ La DF que no cumple las condiciones de BCNF es: AC → D
• Comprobamos (A, C, D):
{A}∗ = {A, B}
{C}∗ = {C}
{D}∗ = {D}
{A, C}∗ = {A, C, B, D}
{A, D}∗ = {A, D, B}
{C, D}∗ = {C, D}
Está en BCNF.
72
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
{A}∗ = {A, B}
{C}∗ = {C}
{E}∗ = {E}
{A, C}∗ = {A, C, B, D}
{A, E}∗ = {A, E, B}
{C, E}∗ = {C, E}
{A, C, E}∗ = {A, C, E, B, D}
Está en BCNF.
73
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
74
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Parte II
75
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Capı́tulo 3
XML
77
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
3.1.1. Lenguaje XML
Es un lenguaje de marcado (markup).
Ventajas:
• Legibilidad.
• Representación jerárquica de la información.
• Numerosos intérpretes de XML disponibles.
Inconvenientes:
78
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
3.1.2. Bases de datos con XML
Una base de datos XML es un sistema que almacena datos XML de manera persistente.
Sistemas gestores de bases de datos XML nativos:
• BaseX (http://basex.org/)
• eXistdb (http://www.exist-db.org/)
• Sedna (http://sedna.org/)
Existe un lenguaje estándar para realizar consultas sobre las bases de datos XML:
XQuery.
79
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
<a p e l l i d o s >Martı́n Moreno</ a p e l l i d o s >
• Los nombres de las etiquetas son identificadores formados por letras, números y
caracteres de guión/subrayado. Deben comenzar por una letra.
• Un documento XML ha de contener un elemento raı́z que contenga a los demás.
• Si un elemento no tiene contenido (no contiene otras etiquetas), puede utilizarse
una sintaxis alternativa:
< t e l e f o n o t i p o =”c a s a ” num=”913102321”/ >
Atributos:
Entidades: sirven para representar caracteres que tienen un significado especial en XML
(forman parte de la sintaxis), tales como los sı́mbolos <, >. Comienzan por & y terminan
por ;
Entidad Sı́mbolo
& &
< <
> >
" ”
' ’
Secciones CDATA: Sirven para expresar contenido que contenga caracteres especiales
(<, >, etc.), sin necesidad de utilizar entidades. Están delimitadas por <![CDATA[ y
]]>. Ejemplo:
<c ó d i g o −f u e n t e > <![CDATA[
i f ( x > 0 && x <= 1 0 ) then p r i n t ( ” Hola ” )
]] > </ c ó d i g o −f u e n t e >
80
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Sin secciones CDATA:
<c ó d i g o −f u e n t e >
i f ( x &g t ; 0 && ; x &l t ;= 1 0 ) then
p r i n t ( ” Hola ” )
</c ó d i g o −f u e n t e >
81
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Document type definition (DTD).
• XML Schema.
• Relax NG (no es estándar W3C).
Un documento XML es válido con respecto a una DTD (o un Schema) si está bien
formado y su contenido se adecua a las restricciones impuestas por dicho DTD (o
Schema).
Componentes:
• Declaraciones <!ELEMENT>.
• Declaraciones <!ATTLIST>.
• Declaraciones <!ENTITY> (permiten especificar abreviaturas, no las usaremos).
Declaraciones ELEMENT:
Ejemplo:
<!ELEMENT d i r e c c i ó n ( c a l l e , número , c ó d i g o −p o s t a l , l o c a l i d a d )>
82
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Podemos utilizar el operador (|) para expresar distintas alternativas en el conte-
nido de un elemento:
<!ELEMENT nombre ( elem −1 | elem −2 | ... | elem−n)>
• Esta vez el elemento <nombre> debe incluir <elem-1>, o bien, <elem-2>, ..., o
bien, <elem-n>. Ejemplo:
<!ELEMENT p o s i c i ó n ( d i r e c c i ó n | c o o r d e n a d a s )>
o:
<p o s i c i ó n >
<c o o r d e n a d a s > . . . </c o o r d e n a d a s >
</ p o s i c i ó n >
permite:
<p o s i c i ó n >
<d i r e c c i ó n > . . . </ d i r e c c i ó n >
</ p o s i c i ó n >
<p o s i c i ó n >
<l a t i t u d > . . . </ l a t i t u d >
<l o n g i t u d > . . . </ l o n g i t u d >
</ p o s i c i ó n >
Para indicar que un elemento sólo puede contener texto en su interior, utilizamos
#PCDATA. Ejemplo:
<!ELEMENT c a l l e (#PCDATA)>
83
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Los operadores ?, *, + permiten expresar otras reglas de cardinalidad:
Operador Significado
? El elemento puede no aparecer o aparecer una sóla vez
+ El elemento puede aparecer una o más veces
* El elemento puede aparecer cero, una, o más veces
Ejemplo:
<!ELEMENT c o n t a c t o ( nombre , a p e l l i d o s , d i r e c c i ó n ? , t e l e f o n o ∗)>
permite:
<c o n t a c t o d n i =”51233412H”>
<nombre>David</nombre>
<a p e l l i d o s >Álvez Campos</ a p e l l i d o s >
<d i r e c c i ó n > . . . </ d i r e c c i ó n >
< t e l e f o n o t i p o =”c a s a ”>943102321</ t e l e f o n o >
< t e l e f o n o t i p o =”m o v i l ”>617702341</ t e l e f o n o >
</c o n t a c t o >
<c o n t a c t o d n i =”51233412H”>
<nombre>David</nombre>
<a p e l l i d o s >Álvez Campos</ a p e l l i d o s >
</c o n t a c t o >
Otro ejemplo:
<!ELEMENT body (#PCDATA | b | i ) ∗ >
Define una etiqueta <body> que puede contener en su interior texto intercalado con los
elementos <b> e <i>.
Más ejemplos:
<!ELEMENT p r o d u c t o EMPTY>
permite:
<p r o d u c t o i d =”e34 ” c a n t i d a d =”2”/>
<!ELEMENT d e s c r i p c i ó n ANY>
permite:
<d e s c r i p c i ó n >
<t i t u l o >D e s c r i p c i ó n d e l o b j e t o </ t i t u l o >
E s t e e s e l c o n t e n i d o de l a d e s c r i p c i ó n .
</ d e s c r i p c i ó n >
84
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Declaraciones ATTLIST:
donde:
◦ elemento indica la etiqueta en la que se adjunta el atributo.
◦ atributo es el nombre del atributo.
◦ tipo indica el conjunto de valores que puede tener el atributo.
◦ valor hace referencia al valor por defecto y a la obligatoriedad de incluir el
atributo.
• tipo puede ser uno de los siguientes:
◦ CDATA: Cadena de caracteres (Tipo por defecto).
◦ Lista de valores: Valores posibles para el atributo.
◦ ID: Identificador único. Dos elementos no pueden tener el mismo valor para
este atributo.
◦ IDREF : Referencia al identificador de un elemento.
◦ IDREFS : Lista de referencias a identificadores de otros elementos, separadas
por espacios.
• valor puede ser uno de los siguientes:
◦ ”Valor”: El atributo es opcional. Si no se indica, tomará el valor indicado.
◦ #FIXED ”Valor”: El atributo es obligatorio y ha de tener el valor indicado.
◦ #REQUIRED: El atributo es obligatorio.
◦ #IMPLIED: El atributo es opcional.
• Se pueden declarar varios atributos con el mismo nombre, siempre que pertenezcan
a elementos distintos.
• En los elementos que tienen tipos ID, IDREF, IDREFS, los identificadores tienen
que adecuarse a la sintaxis XML.
• En particular, han de comenzar por carácter alfabético.
• Ejemplos:
<!ATTLIST t e l e f o n o t i p o
( c a s a | t r a b a j o | m o v i l ) ” c a s a”>
< t e l e f o n o t i p o =”m o v i l”> . . . </ t e l e f o n o >
<!ATTLIST c o n t a c t o d n i CDATA #REQUIRED>
<c o n t a c t o d n i =”51233412H”>
...
</c o n t a c t o >
contactos.xml:
85
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
<?xml v e r s i o n =”1.0” e n c o d i n g=”UTF−8”?>
<agenda>
<c o n t a c t o d n i =”51233412H”>
<nombre>David</nombre>
<a p e l l i d o s >Álvez Campos</ a p e l l i d o s >
<d i r e c c i ó n >
<c a l l e >Paseo de Ondarreta </ c a l l e >
<numero>5</numero>
<c ó d i g o −p o s t a l >20018</ c ó d i g o −p o s t a l >
<l o c a l i d a d >San S e b a s t i á n </ l o c a l i d a d >
</ d i r e c c i ó n >
< t e l e f o n o t i p o =”c a s a ”>943102321</ t e l e f o n o >
< t e l e f o n o t i p o =”m o v i l ”>617702341</ t e l e f o n o >
</c o n t a c t o >
<c o n t a c t o d n i =”46821354T”>
<nombre>Vı́ c t o r </nombre>
<a p e l l i d o s >Martı́n Moreno</ a p e l l i d o s >
< t e l e f o n o t i p o =”c a s a ”>914621100</ t e l e f o n o >
</c o n t a c t o >
</agenda>
contactos.dtd:
<!ELEMENT agenda ( c o n t a c t o)+>
<!ELEMENT c o n t a c t o ( nombre , a p e l l i d o s , d i r e c c i ó n ? , t e l e f o n o ∗)>
<!ELEMENT nombre (#PCDATA)>
<!ELEMENT a p e l l i d o s (#PCDATA)>
<!ELEMENT d i r e c c i ó n ( c a l l e , numero , c ó d i g o −p o s t a l , l o c a l i d a d )>
<!ELEMENT c a l l e (#PCDATA)>
<!ELEMENT numero (#PCDATA)>
<!ELEMENT c ó d i g o −p o s t a l (#PCDATA)>
<!ELEMENT l o c a l i d a d (#PCDATA)>
<!ELEMENT t e l e f o n o (#PCDATA)>
<!ATTLIST t e l e f o n o t i p o ( c a s a | t r a b a j o | m o v i l ) #REQUIRED>
<!ATTLIST c o n t a c t o d n i CDATA #REQUIRED>
86
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
<!ELEMENT numero (#PCDATA)>
<!ELEMENT c ó d i g o −p o s t a l (#PCDATA)>
<!ELEMENT l o c a l i d a d (#PCDATA)>
<!ELEMENT t e l e f o n o (#PCDATA)>
<!ATTLIST t e l e f o n o t i p o ( c a s a | t r a b a j o | m o v i l ) #REQUIRED>
<!ATTLIST c o n t a c t o d n i CDATA #REQUIRED>
]>
<agenda>
<c o n t a c t o d n i =”51233412H”>
...
</c o n t a c t o >
<c o n t a c t o d n i =”46821354T”>
...
</c o n t a c t o >
</agenda>
87
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
</ l i s t a −compra>
</t i e n d a >
tienda.dtd:
<!ELEMENT t i e n d a ( a r t i c u l o ∗ , l i s t a −compra)>
<!ELEMENT a r t i c u l o ( nombre , c a n t i d a d , p r e c i o +)>
<!ELEMENT l i s t a −compra ( a r t i c u l o s , t o t a l )>
<!ELEMENT a r t i c u l o s ( p r o d u c t o )∗>
<!ELEMENT p r o d u c t o EMPTY>
<!ELEMENT nombre (#PCDATA)>
<!ELEMENT c a n t i d a d (#PCDATA)>
<!ELEMENT p r e c i o (#PCDATA)>
<!ELEMENT t o t a l (#PCDATA)>
<!ATTLIST a r t i c u l o i d ID #REQUIRED>
<!ATTLIST p r e c i o d i v i s a CDATA ”EUR”>
<!ATTLIST t o t a l d i v i s a CDATA ”EUR”>
<!ATTLIST p r o d u c t o i d IDREF #REQUIRED>
<!ATTLIST p r o d u c t o c a n t i d a d CDATA ”1”>
<!ATTLIST p r o d u c t o d e s c u e n t o CDATA ”0”>
Una expresión especifica una ruta (o rutas) donde se encuentra la información buscada.
Estos nodos son relativos a un documento XML determinado, que se obtiene mediante
la función doc, que recibe un nombre de archivo almacenado en la base de datos.
Sintaxis
Elementos sintácticos:
Expresión Significado
nodo Selecciona todos los nodos cuyo nombre es nodo
/ Selecciona nodos desde la raı́z
// Selecciona nodos
@ Selecciona atributos
* representa cualquier nodo
@* representa cualquier atributo
| permite sentencias compuestas (relacionadas por un AND)
Ejemplos:
• Consideremos un documento XML con las etiquetas: bookstore, book, title y price.
88
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• /bookstore: selecciona el elemento raı́z bookstore.
• bookstore/book: selecciona todos los elementos book hijos de bookstore.
• //book: selecciona todos los elementos book en cualquier parte del documento.
• bookstore//book: selecciona todos los elementos book descendientes de bookstore.
• //@lang: selecciona todos los atributos lang.
• /bookstore/book[last()]: selecciona el último elemento book hijo de bookstore.
• /bookstore/book[last()-1]: selecciona el penúltimo elemento book hijo de books-
tore.
• /bookstore/book[position()<3]: selecciona los dos primeros hijos de book hijo
de bookstore.
• //title[@lang]: selecciona todos los elementos title que tengan el atributo lang.
• //title[@lang=’en’]: selecciona todos los elementos title que tengan el atributo
lang y su valor sea en.
• /bookstore/book[price>35.00]: selecciona los hijos de book cuyo texto para
price sea mayor que 35.
• /bookstore/book[price>35.00]/title: selecciona title de los hijos de book cuyo
texto para price sea mayor que 35.
• /bookstore/*: todos los hijos de bookstore.
• //*: todos los elementos.
• //title[@*]: todos los elementos title que tengan un atributo (de cualquier ti-
po!!!).
• //book/title | //book/price: todos los tı́tulos y precios de cualquier elemento
book.
• //title | //price: todos los tı́tulos y precios.
• /bookstore/book/title |//price: todos los tı́tulos de cualquier elemento book
y todos los precios.
Ejemplos
Tomamos como referencia el siguiente documento XML:
<?xml v e r s i o n =”1.0” e n c o d i n g=”UTF−8”?>
<b o o k s t o r e >
<book c a t e g o r y =”COOKING”>
< t i t l e l a n g=”en”>Everyday I t a l i a n </ t i t l e >
<author>Giada De L a u r e n t i i s </author>
<year >2005</ year>
<p r i c e >30.00</ p r i c e >
</book>
89
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
<book c a t e g o r y =”CHILDREN”>
< t i t l e l a n g=”en”>Harry P o t t e r </ t i t l e >
<author>J K. Rowling </author>
<year >2005</ year>
<p r i c e >29.99</ p r i c e >
</book>
<book c a t e g o r y =”WEB”>
< t i t l e l a n g=”en”>XQuery Kick S t a r t </ t i t l e >
<author>James McGovern</author>
<author>Per Bothner </author>
<author>Kurt Cagle </author>
<author>James Linn </author>
<author>Vaidyanathan Nagarajan </author>
<year >2003</ year>
<p r i c e >49.99</ p r i c e >
</book>
<book c a t e g o r y =”WEB”>
< t i t l e l a n g=”en”>L e a r n i n g XML</ t i t l e >
<author>E r i k T . Ray</author>
<year >2003</ year>
<p r i c e >39.95</ p r i c e >
</book>
</b o o k s t o r e >
Ejemplos:
3.4.2. XQuery
Estándar del W3C que se apoya en XPath para realizar consultas más complejas en
bases de datos XML.
Es (o pretende ser) para XML lo que es SQL para bases datos relacionales.
90
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• For: selecciona una secuencia de nodos.
• Let: enlaza los elementos de esta secuencia a una variable.
• Where: filtra los elementos de la secuencia.
• Order by: ordena los elementos de la secuencia.
• Return: construye la respuesta.
Ejemplo:
f o r $x i n doc ( ” books . xml ” ) / b o o k s t o r e / book
where $x / p r i c e >30
o r d e r by $x / t i t l e
r e t u r n $x / t i t l e
Expresiones FLWOR
for:
f o r $b i n doc ( ” l i b r o s . xml ” ) / l i b r o s / l i b r o
r e t u r n $b / a u t o r e s / a u t o r
let: sirve para introducir definiciones auxiliares y hacer más legible el código. Ejemplo:
f o r $b i n doc ( ” l i b r o s . xml ” ) / l i b r o s / l i b r o
l e t $ t i t u l o := $b / t i t u l o
return $ t i t u l o
91
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
order by: ordena los resultados. Ejemplo:
f o r $b i n doc ( ” l i b r o s . xml ” ) / l i b r o s / l i b r o
l e t $ t i t u l o := $b / t i t u l o
o r d e r by $ t i t u l o
return $ t i t u l o
f o r $b i n doc ( ” l i b r o s . xml ” ) / l i b r o s / l i b r o
l e t $ t i t u l o := $b / t i t u l o d e s c e n d i n g
o r d e r by $ t i t u l o
return $ t i t u l o
Sintaxis:
Ejemplo:
f o r $b i n doc ( ” l i b r o s . xml ” ) / l i b r o s / l i b r o
where some $x i n $b // a u t o r
s a t i s f i e s $x / @id = ” a01 ”
r e t u r n $b
• $b: es un elemento.
• $b//autor: es un conjunto o secuencia.
Constructoras de elementos
Es posible integrar los resultados de una consulta en otros elementos XML.
Ejemplo:
92
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
f o r $b i n doc ( ” l i b r o s . xml ” ) / l i b r o s / l i b r o
r e t u r n <r e s u l t a d o >
{ $b / t i t u l o }
{ $b / p r e c i o }
</ r e s u l t a d o >
Más ejemplos:
f o r $b i n doc ( ” l i b r o s . xml ” ) / l i b r o s / l i b r o
l e t $numautores := count ( $b / a u t o r e s / a u t o r )
r e t u r n <r e s u l t a d o >
<t >{data ( $b / t i t u l o )}</ t>
<p>{data ( $b / p r e c i o )}</p>
<na>{$numautores}</na>
</ r e s u l t a d o >
f o r $b i n doc ( ” l i b r o s . xml ” ) / l i b r o s / l i b r o
l e t $numautores := count ( $b / a u t o r e s / a u t o r )
r e t u r n <r e s u l t a d o numautores=”{$numautores}”>
<t >{data ( $b / t i t u l o )}</ t>
<p>{data ( $b / p r e c i o )}</p>
</ r e s u l t a d o >
93
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
f o r $b i n doc ( ” l i b r o s . xml ” ) / l i b r o s / l i b r o
l e t $numautores := count ( $b / a u t o r e s / a u t o r )
where $numautores = 1
r e t u r n <r e s u l t a d o >
<t >{data ( $b / t i t u l o )}</ t>
<p>{data ( $b / p r e c i o )}</p>
</ r e s u l t a d o >
Consultas anidadas
Es posible anidar expresiones FLWOR en los resultados de una consulta.
Ejemplos:
f o r $b i n doc ( ” l i b r o s . xml ” ) / l i b r o s / l i b r o
r e t u r n <r e s u l t a d o >
<t >{data ( $b / t i t u l o )}</ t>
<p>{data ( $b / p r e c i o )}</p>
{ f o r $a i n $b // a u t o r
r e t u r n $a
}
</ r e s u l t a d o >
f o r $b i n doc ( ” l i b r o s . xml ” ) / l i b r o s / l i b r o
r e t u r n <r e s u l t a d o >
<t >{data ( $b / t i t u l o )}</ t>
<p>{data ( $b / p r e c i o )}</p>
{ f o r $a i n $b // a u t o r
l e t $ i n f o a u t o r := doc ( ” a u t o r e s . xml ” ) / / a u t o r [ @id = $a / @id ]
r e t u r n <a u t o r >{data ( $ i n f o a u t o r / nombre ) }
{ data ( $ i n f o a u t o r / a p e l l i d o s ) }
</a u t o r >
}
</ r e s u l t a d o >
XQuery y HTML
Es posible construir una página HTML con el resultado de una consulta XQuery. Ejemplo:
l e t $my−doc := doc ( ” books . xml ” )
return
<html>
94
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Función Descripción
count(seq) Devuelve el número de elementos de la secuencia dada
sum(seq) Devuelve la suma de los elementos de la secuencia dada
avg(seq) Devuelve la media de los elementos de seq
max(seq), min(seq) Devuelve el máximo/mı́nimo de los elementos de seq
distinct-values(seq) Elimina los duplicados de seq
contains(cadena,subcadena) Busca una subcadena de caracteres en una cadena
except Permite ”quitar” código XML
<head>
< t i t l e >C u rr e n t Rates </ t i t l e >
</head>
<body>
<ul >
{
f o r $x i n $my−doc / b o o k s t o r e / book
o r d e r by $x / t i t l e
r e t u r n < l i >{data ( $x / t i t l e ) } . Category : { data ( $x / @category )}</ l i >
}</ ul>
</body>
</html>
En los laboratorios:
95
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 3.1: Ventana principal de eXist-db
96
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 3.3: Adición de documentos en eXist-db
Los documentos XML se almacenan en carpetas que pueden ser anidadas. Similar a
un sistema de archivos.
97
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 3.5: Ventana de xQuery tester
98
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Capı́tulo 4
MongoDB
Está orientado a documentos de esquema libre: cada registro puede tener un esquema
de datos distinto. Los atributos no tienen que ser iguales en diferentes registros.
Cada registro o conjunto de datos se denomina documento, que pueden ser agrupados
en colecciones, (equivalente a las tablas de las bases de datos relacionales pero sin estar
sometidos a un esquema fijo).
99
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Servidor
Base de datos
Colección
Documentos
Campos
Estructura de la información en MongoDB.
Caracterı́sticas:
• Replicación:
◦ MongoDB, es más flexible que las bases de datos relacionales, y por ello menos
restrictivo, lo que puede presentar en ocasiones problemas de volatilidad.
◦ MongoDB manda los documentos escritos a un servidor maestro, que sincro-
nizado a otro u otros servidores mandará esta misma información replicada,
a estos ”esclavos”.
• Indexación: Cualquier campo en un documento de MongoDB puede ser indexa-
do. Es posible hacer ı́ndices secundarios. El concepto de ı́ndices en MongoDB es
similar al de datos relacionales.
• Escalabilidad horizontal:
◦ Capacidad de trabajar con varias máquinas de manera distribuida, almace-
nando en cada uno de los nodos cierta información que de una forma u otra
debe estar comunicada con el resto de nodos que forman nuestro sistema.
◦ Esto dota de mayor flexibilidad al sistema, ya que facilita la agregación de
equipos en función de las necesidades.
• Sharding:
◦ MongoDB utiliza el Sharding como método para dividir los datos a lo largo
de los múltiples servidores de nuestra solución.
◦ Las bases de datos relacionales también hacen tareas similares a ésta, si bien
de forma diferente.
◦ Tal vez el rasgo más destacable en MongoDB porque realiza estas tareas de
manera automática.
• Balanceo:
◦ El balanceador es un proceso de MongoDB para equilibrar los datos en nuestro
sistema.
◦ Mueve porciones de datos de un shard a otro, de manera automática.
100
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Algunos inconvenientes:
4.1.2. Documentos
Los documentos son la unidad básica de organización de la información en MongoDB,
y desempeñan el papel equivalente a una fila en las bases de datos relacionales.
Caracterı́sticas:
101
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Los pares clave-valor están ordenados en los documentos. Por ejemplo el docu-
mento {”x”:3,”y”:5} no es lo mismo que {”y”:5,”x”:3}.
• Los valores de un documento pueden ser de diferentes tipos.
102
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Los arrays pueden contener diferentes tipos de valores como por ejemplo
{”Cosas”:[”edad”,45]}(de hecho soporta cualquiera de los tipos de valores
soportados para los documentos, pudiéndose crear arrays anidados).
◦ Una propiedad importante en MongoDB es que es reconoce la estructura
de los arrays y permite navegar por el interior de los arrays para realizar
operaciones sobre sus contenidos como consultas o crear ı́ndices sobre sus
contenidos.
◦ En el ejemplo anterior se podrı́a crear una consulta para recuperar todos
aquellos documentos donde 3.14 es un elemento del array ”Cosas”, y si por
ejemplo esta fuera una consulta habitual entonces incluso se podrı́a crear un
ı́ndice sobre la clave ”Cosas” y mejorar el rendimiento de la consulta.
◦ Ası́ mismo MongoDB permite realizar actualizaciones que modifican los con-
tenidos de los arrays tales como cambiar un valor del array por otro.
• Documentos embebidos:
◦ Los documentos pueden ser usados como valores de una clave, y en este caso
se denominan ”documentos embebidos”. Se suelen usar para organizar los
datos de una manera lo más natural posible.
◦ Por ejemplo si se tiene un documento que representa a una persona y se quiere
almacenar su dirección podrı́a crearse anidando un documento ”dirección” al
documento asociado a una persona como por ejemplo:
{
” nombre ” : ” Juan ” ,
” d i r e c c i ó n ” : {
” c a l l e ” : ” Mayor , 3 ” ,
” c i u d a d ” : ” Madrid ” ,
” P a i s ” : ” España ”
}}
103
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
◦ El tipo ObjectID es el tipo por defecto para los valores asociados a la clave
” id”. Es un tipo de datos diseñado para ser usado en ambientes distribuidos
de manera que permita disponer de valores que sean únicos globalmente.
◦ Cada valor usa 12 bytes lo que permite representar una cadena de 24 dı́gitos
hexadecimales(2 digitos por cada byte). Si se crean múltiples valores del tipo
ObjectID sucesivamente sólo cambian unos pocos dı́gitos del final y una pareja
de dı́gitos de la mitad. Esto se debe a la forma en la que se crean los valores
del tipo ObjectIDs.
◦ Observaciones:
Los primeros 4 bytes son un marca de tiempo en segundos que combinados
con los siguientes 4 bytes proporciona unicidad a nivel de segundo y que
identifican de manera implı́cita cuando el documento fue creado.
Por otro lado, a causa de que la marca de tiempo aparece en primer lugar,
entonces los ObjectIDs se ordenan obligatoriamente en orden de inserción
lo que hace que la indexación sobre ObjectIDs sea eficiente.
Los siguientes 3 bytes son un identificador único de la máquina que lo
genera, lo que garantiza que diferentes máquinas no generan colisiones.
Para conseguir unicidad entre diferentes procesos que generan ObjectIDs
concurrentemente en una misma máquina se usan los siguientes 2 bytes
que son tomados del identificador del proceso que genera un ObjectID.
◦ Cuando un documento se va a insertar si no tiene un valor para la clave ” id”
entonces es generado automáticamente por MongoDB.
4.1.4. Colecciones
Una colección es un grupo de documentos, y desempeña el papel análogo a las tablas
en las bases de datos relacionales.
Las colecciones tienen esquemas dinámicos lo que significa que dentro de una colección
puede haber cualquier número de documentos con diferentes estructuras.
Por ejemplo en una misma colección podrı́an estar los siguientes documentos diferentes:
{”edad”:34},{”x”:”casa”} que tienen diferentes claves y diferentes tipos de valores.
Dado que cualquier documento se puede poner en cualquier colección y dado que no
es necesario disponer de esquemas distintos para los diferentes tipos de documentos,
entonces surge la pregunta de por qué se necesita usar más de una colección y tener
que separar los documentos mediante colecciones separadas:
104
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• En general, por eficiencia, es razonable crear un esquema y agrupar los tipos
relacionados de documentos juntos aunque MongoDB no lo imponga como obli-
gatorio.
Una colección se identifica por su nombre, el cual es una cadena con las siguientes
restricciones:
Una convención para organizar las colecciones consiste en definir subcolecciones usando
espacios de nombres separados por el carácter ”.”.
Por ejemplo una aplicación que contuviese un blog podrı́a tener una colección denomi-
nada blog.posts y otra colección denominada blog.autores con un propósito organizativo
y que sin embargo ni exista la colección blog y en caso de existir no exista una relación
entre la colección padre blog y las subcolecciones.
Las colecciones se agrupan en bases de datos, de manera que una única instancia
de MongoDB puede gestionar varias bases de datos cada una agrupando cero o más
colecciones.
• Cada base de datos tiene sus propios permisos y se almacena en ficheros del disco
separados.
• Una buena regla general consiste en almacenar todos los datos de una aplicación
en la misma base de datos.
• Las bases de datos separadas son útiles cuando se almacenan datos para aplica-
ciones o usuarios diferentes que usan el mismo servidor de MongoDB.
Las bases de datos se identifican mediante nombres que son cadenas con las siguientes
restricciones:
105
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• El nombre de una base de datos no puede contener ninguno de los siguientes
caracteres:
\,/,.,’’,*,<,>,:,|,?,$,espacio o \0(valor nulo)
• Los nombres de las bases de datos son sensitivos a mayúsculas y minúsculas
incluso sobre sistemas de archivos que no lo sean. Una regla práctica es usar
siempre nombres en minúscula.
• Los nombres están limitados a un máximo de 64 bytes.
Existen nombres que no pueden usarse para las bases de datos por estar reservados:
Mediante la concatenación del nombre de una base de datos con una colección de la
base de datos se consigue un cualificación entera del nombre de la colección denominado
espacio de nombres.
Observaciones:
106
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
> db . g e t C o l l e c t i o n ( ” v e r s i o n ” )
test . version
}
107
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
El método remove elimina todos los documentos de una colección, pero no elimina la
colección ni la metainformación acerca de la colección.
Una vez que se ha realizado el borrado no se puede dar revertir y se pierden todos los
documentos borrados.
A veces si se van a borrar todos los documentos es más rápido eliminar toda la colección
en vez los documentos. Para ello se usa el método drop:
db . prueba . drop ( )
4.3. Consultas
El método find se utiliza para realizar consultas en MongoDB, las cuales retornan un
subconjunto de documentos de una colección (desde ningún documento hasta todos los
documentos de la colección).
El primer argumento especifica las condiciones que deben cumplir los documentos que
se quieren recuperar.
Una condición de búsqueda vacı́a ({}) encaja con todos los documentos de la colección.
Si se quiere consulta un tipo simple entonces basta especificar el valor que se está
buscando.
Por ejemplo si se quiere encontrar todos los documentos dónde el valor de la edad es
27, entonces se añade como condición de búsqueda el par clave/valor {”edad”:27} a la
condición de búsqueda:
db . u s e r s . f i n d ( { ” edad ” : 2 7 } )
108
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Cuando se quieren usar múltiples condiciones juntas se añaden los pares clave/valor que
sean necesarias, las cuales serán interpretadas como ’’Condición1 AND Condición2
AND...AND Condición N’’.
Por ejemplo si se quieren recuperar todos los usuarios con 27 años y que se llamen
”Isabel” se realizarı́a la siguiente consulta:
db . u s e r s . f i n d ( { ” nombre ” : ” I s a b e l ” , ” edad ” : 2 7 } )
Por ejemplo si se tiene una colección de usuarios y solo se quiere recuperar el nombre
del usuario y el email entonces se podrı́a realizar la siguiente consulta:
db . u s e r s . f i n d ( { ” nombre ” : 1 , ” e m a i l ” : 1 } )
Por ejemplo se puede tener una colección que tenga documentos con diferentes claves
pero en todos ellos no se quiere recuperar la clave ”teléfono”, entonces se podrı́a realizar
la siguiente consulta:
db . u s e r s . f i n d ( { ” t e l e f o n o ” : 0 } )
Existe un método similar a find() que es findOne() que permite recuperar un único
documento cumpliendo las condiciones especificadas.
Operadores condicionales:
109
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Este tipo de consultas son muy útiles para realizar consultas sobre las fechas. Por
ejemplo para encontrar las personas que se registraron antes del 1 de Enero de
2007 se puede hacer de la siguiente manera:
> f e c h a = new Date ( ” 0 1 / 0 1 / 2 0 0 7 ” )
> db . u s u a r i o s . f i n d ( { ” r e g i s t r a d o s ” : {” $ l t ” : f e c h a } } )
• Una coincidencia exacta sobre la fecha es menos útil puesto que las fechas son
sólo almacenadas con precisión de milisegundos, y con frecuencia lo que se busca
es comparar un dı́a, semana o mes entero haciendo necesario una consulta sobre
rangos.
• También puede ser útil consultar los documentos en los que el valor de una clave
no es igual a cierto valor, para lo cual se usa el operador ”$ne” que representa ”no
igual”. Por ejemplo si se quieren recuperar los usuarios que no tienen por nombre
”Pablo”, se podrı́an consultar de la siguiente manera:
db . u s e r s . f i n d ( { ” username ” : {” $ne ” : ” j o e ” } } )
• Observar que el operador ”$ne” puede ser usado con cualquier tipo.
• ”$in” es más flexible y permite especificar criterios sobre diferentes tipos y valores.
• Por ejemplo supóngase una base de datos donde se pueden usar tanto nombres
de usuario como identificadores numéricos de usuario, entonces se podrı́a realizar
una consulta de la siguiente manera:
db . u s u a r i o s . f i n d ( { ” u s e r i d ” : {” $ i n ” : [ 1 2 3 4 5 , ” Pablo ” ] } )
• Si el operador ”$in” aparece con un array con un único valor, entonces se comporta
intentado hacer coincidir el valor. Por ejemplo {”dni” : {$in : [725]}} es equivalente
a {”dni” : 725}.
110
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• El operador opuesto a ”$in” es ”$nin”, el cual retorna documentos que no coinci-
den con ninguno de los criterios dados en el array de valores.
• Por ejemplo si se quieren recuperar todos los documentos de personas que tienen
un dni que no está autorizado se podrı́a hacer de la siguiente manera:
db . a u t o r i z a d o s . f i n d ( { ” d n i ” : {” $ n i n ” : [ 7 2 5 , 5 4 2 , 3 9 0 ] } } )
• ”$or” también puede contener otros condicionales. Por ejemplo si se quieren re-
cuperar los documentos de personas que tienen 30, 34 y 35 años o que no son
fumadores se podrı́a hacer de la siguiente manera:
db . p e r s o n a s . f i n d ( { ” $ o r ” : [ { ” edad ” : { ” $ i n ” : [ 3 0 , 3 4 , 3 5 ] } } , { ” fumador ” : f a l s e } ] } )
• El operador ”$or” siempre funciona pero siempre que se pueda es mejor usar ”$in”
dado que es más eficiente.
El ”$not”:
Observar que no existe el operador ”$eq” pero se puede simular con el operador ”$in”
con un único valor.
Observaciones:
• Se pueden expresar múltiples condiciones sobre una clave dada. Por ejemplo si se
quieren encontrar todos los usuarios que tienen una edad entre 20 y 30, se podrı́an
usar los operadores $gt y $lt sobre la clave ”edad” de la siguiente manera:
db . u s u a r i o s . f i n d ( { ” edad ” : {” $ l t ” : 3 0 , ” $ g t ” : 2 0 } } )
111
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
entonces la consulta:
db . comida . f i n d ( { ” f r u t a ” : ” p l a t a n o ” } )
El operador $all:
• Cuando se quieren encajar todos los valores de un array se puede usar el operador
$all.
• Por ejemplo si se tuviera la siguiente colección de documentos:
> db . comida . i n s e r t ( { ” i d ” : 1 , ” f r u t a ” : [ ” manzana ” , ” p l a t a n o ” , ” m e l o c o t o n ” ] } )
> db . comida . i n s e r t ( { ” i d ” : 2 , ” f r u t a ” : [ ” manzana ” , ” p e r a ” , ” n a r a n j a ” ] } )
> db . comida . i n s e r t ( { ” i d ” : 3 , ” f r u t a ” : [ ” c e r e z a ” , ” p l a t a n o ” , ”manzana ” ] } )
• Se podrı́a buscar todos los documentos que tienen a la vez ”manzana” y ”platano”
mediante una consulta de la forma:
db . comida . f i n d ( { f r u t a : { $ a l l : [ ” manzana ” , ” p l a t a n o ” ] } } )
es equivalente a:
{ fruta : ’ manzana ’ }
• Se puede realizar una consulta para buscar una coincidencia exacta usando el
array entero. Sin embargo, la coincidencia exacta no encajará un documento si
alguno de los elementos no se encuentran o sobran.
• Por ejemplo, la siguiente consulta recupera el primer documento:
db . comida . f i n d ( { ” f r u t a ” : [ ” manzana ” , ” p l a t a n o ” , ” m e l o c o t o n ” ] } )
112
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
db . comida . f i n d ( { ” f r u t a . 2 ” : ” m e l o c o t o n ” } )
• Observar que los ı́ndices empiezan a contar desde cero por lo que la consulta
anterior buscarı́a que el tercer elemento del array tome el valor de ”melocoton”.
El operador $size:
• Este operador permite consultar arrays de un tamaño dado. Por ejemplo, la si-
guiente consulta:
db . comida . f i n d ( { ” f r u t a ” : {” $ s i z e ” : 3 } } )
El operador $slice:
113
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Por ejemplo, si se tuviera el siguiente documento:
>db . b l o g . p o s t s . findOne ( )
{
” i d : ObjectId ( . . . ) ,
” t i t u l o : ”un buen p o s t ” ,
” contenido : ” . . . ” ,
” comentarios = [
{
” nombre ” : ” j u a n ” ,
” e m a i l ” : ” juan@ejemplo . com ” ,
” contenido ” : ” estupendo ”
},
{
” nombre ” : ” i s a b e l ” ,
” e m a i l ” : ” i s a b e l @ e j e m p l o . com ” ,
” contenido ” : ” excelente ”
}
]
}
>
• Se puede observar que se recupera además del comentario, también la clave ”ti-
tulo” y ”contenido” aunque no se haya especificado.
• A veces se desconoce el ı́ndice del elemento que se quiere recuperar. En estos casos
se puede utilizar el operador $.
• En el ejemplo anterior si se quiere recuperar el comentario que ha realizado ”juan”
se podrı́a hacer de la siguiente manera:
db . b l o g . p o s t s . f i n d ( { ” c o m e n t a r i o s . nombre ” : ” j u a n ” } , {” c o m e n t a r i o s . $ ” : 1 } )
114
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
{” x” : {” $ g t ” : 1 0 , ” $ l t ” : 20}}
deberı́a cumplirse a la vez que x es más grande que 10 y más pequeño que 20.
• Sin embargo, si en un documento x fuera un array entonces el documento encajarı́a
si existe un elemento de x que encaja con cada uno de los criterios que aparecen en
la consulta pero cada criterio puede encajar con un elemento diferente del array.
Ası́ por ejemplo si se tuvieran los siguientes documentos en una colección:
{” x” : 5}
{” x” : 15}
{” x” : 25}
{” x” : [5 , 25]}
Si se quieren encontrar todos los documentos donde x está entre 10 y 20, entonces
se podrı́a construir la siguiente consulta:
db . t e s t . f i n d ( { ” x” : {” $ g t ” : 1 0 , ” $ l t ” : 2 0 } } )
esperando que recuperase como resultado el documento {"x": 15} sin embargo
recupera dos documentos:
{” x” : 15}
{” x” : [ 5 , 2 5 ] }
La consulta sobre un documento embebido entero funciona de la misma forma que una
consulta normal.
115
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Sin embargo, una consulta sobre un subdocumento entero debe encajar exactamente
con el subdocumento. Por ejemplo si se añadiera un nuevo campo en el subdocumento
o se cambiara el orden de los campos entonces ya no coincidirı́an con la búsqueda.
Para consultar sobre claves especı́ficas de documentos embebidos se usa la notación ”.”
como por ejemplo:
db . prueba . f i n d ( { ” nombre . nombre ” : ” J a v i e r ” , ” nombre . a p e l l i d o ” : ” Sanz ” } )
Observar que en los documentos de consultas el uso de la notación dot tiene como
significado alcanzar el interior del documento embebido. Es por ello que no se permita
usar el caracter ”.” dentro de los documentos que se van a insertar(por ejemplo existen
problemas cuando se quieren almacenar URLS).
Por ejemplo supóngase que se están almacenando posts de un blog y se quieren recupe-
rar comentarios de Javier que fueron puntuados con al menos un 5, entonces se podrı́a
modelar el post de la siguiente manera:
>db . b l o g . p o s t s . findOne ( )
{
” i d : ObjectId ( . . . ) ,
” contenido : ” . . . ” ,
” comentarios = [
{
” autor ” : ” j a v i e r ” ,
” puntuacion ” : 3 ,
” comentario ” : ” bonito post ”
},
{
” a u t o r ” : ” maria ” ,
” puntuacion ” : 6 ,
” comentario ” : ” t e r r i b l e post ”
}
]
}
>
116
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
dado que los documentos embebidos deben encajar el documento entero y éste no
encaja con la clave ”comentario”.
dado que la condición del autor podrı́a encajar con un comentario diferente al comen-
tario que encajarı́a con la condición de la puntuación.
Ası́ esta consulta devolverı́a el documento anterior dado que encajarı́a autor ”Javier”
con el primer comentario y puntuación ”6” con el segundo comentario.
Para agrupar correctamente los criterios de búsqueda sin necesidad de especificar ca-
da clave se puede usar $elemMatch. Este operador permite especificar parcialmente
criterios para encajar con un único document embebido en un array. Ası́ la consulta
correcta serı́a:
db . b l o g . f i n d ( { ” c o m e n t a r i o s ” : { ” $elemMatch ” : { ” a u t o r ” : ” j a v i e r ” , ” p u n t u a c i o n ” : { ” $ g t e ” : 5 } } } } )
Por tanto, $elemMatch será til cuando exista más de una clave que se quiere encajar
en un documento embebido.
Para conseguir limitar los resultados se encadena la función limit() sobre la llamada
a find(). Por ejemplo, para retornar solo 3 resultados se harı́a de la siguiente manera:
db . c . f i n d ( ) . l i m i t ( 3 )
Si existen menos de 3 documentos que encajan con la consulta entonces solo se retornan
los documentos que encajan (limit solo establece un lı́mite superior pero no un lı́mite
inferior).
La función sort() toma un objeto formado por pares clave-valor donde las claves son
nombres de claves y los valores indican un sentido de la ordenación: 1(ascendente) o
-1(descendente). Cuando existen más de una clave, los resultados son ordenados en ese
orden.
117
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Por ejemplo, para ordenar los resultados en orden ascendente de ”nombre” y en orden
descendente de ”edad” se harı́a de la siguiente manera:
db . c . f i n d ( ) . s o r t ( { username : 1 , age : −1})
Cuando la persona hace click sobre la página siguiente para ver más resultados entonces
se puede añadir un skip() a la consulta de manera que se salten los primeros 50
resultados:
db . s t o c k . f i n d ( { ” d e s c ” : ” l i b r o s ” } ) . l i m i t ( 5 0 ) . s k i p ( 5 0 ) . s o r t ( { ” p r i c e ” : −1})
A veces se puede dar el caso de tener un clave con multiples tipos, de manera que si
se aplica la función sort() entonces se ordenarán de acuerdo a un orden predefinido.
Los valores del más pequeño al más grande son:
1. Minimum value
2. Null
3. Numbers: integers, floats, doubles
4. Strings
5. Objects/document
6. Array
7. Binary data
8. Object ID
9. Boolean
10. Date
11. Timestamp
12. Regular expression
13. Maximum value
4.4. Actualizaciones
Para modificar un documento almacenado se usa el método update que toma 2 paráme-
tros:
118
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Una condición de búsqueda que localiza el documento a actualizar.
• Un conjunto de cambios a realizar sobre el documento.
Las actualizaciones son atómicas de manera que si se quieren realizar dos a la vez, la
primera que llegue es la primera en realizarse y a continuación se hará la siguiente.
Y se quiere crear un campo ”relaciones” que englobe a los campos ”amigos” y ”enemi-
gos” como subdocumentos. Esta operación se puede llevar a cabo con un update:
> v a r j u a n=db . prueba . findOne ( { ” nombre ” : ” Juan ” } ) ;
> j u a n . r e l a c i o n e s = {” amigos ” : j u a n . amigos , ” e ne mig os ” : j u a n . e n em igo s } ;
{” amigos ” : 3 2 , ” en e mi g o s ” : 2 }
> j u a n . PrimerNombre=j u a n . nombre
Juan
> d e l e t e j u a n . amigos
true
> d e l e t e j u a n . en e m i g o s
true
> d e l e t e j u a n . nombre
true
> db . prueba . update ( { ” nombre ” : ” j u a n ” } , j u a n ) ;
W r i t e R e s u l t ( { ” nMachted ” : 1 , ” nUpersted ” : 0 , ” n M o d i f i e d ” : 1 } )
>db . prueba . findOne ( )
{
” i d ” : ObjectId ( ” . . . ” ) ,
” relaciones ”: {
” amigos ” : 3 2 ,
” e n e mi g o s ” : 2
},
” PrimerNombre ” : ” Juan ”
}
>
Reemplazamiento:
119
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
> j u a n=db . prueba . findOne ( { ” nombre ” : ” Juan ” , ” edad ” : 3 3 } )
{
” i d ” : ObjectId ( ” . . . 5 5 ” ) ,
” nombre ” : ” Juan ” ,
” edad ” : 33
}
> j u a n . edad++;
33
> db . prueba . update ( { ” nombre ” : ” j u a n ” } , j u a n ) ;
WriteResult ({
” nMachted ” : 0 ,
” nUpersted ” : 0 ,
” nModified ” : 0 ,
” w r i t e E r r o r : {}
” code ” : 1 6 8 3 7 ,
” errmsg ” : ”The i d f i e l d cannot be changed from { O b j e c t I d ( ” . . . 5 4 ” ) } t o O b j e c t I d ( ” . . . 5 5 ” ) }
}
})
• Se produce un error dado que el método update busca un documento que encaje
con la condición de búsqueda y el primero que encuentra es el referido al ”Juan”
que tiene 32 años. Intenta cambiar ese documento por el actualizado, y se encuen-
tra que si hace el cambio habrı́a dos documentos con el mismo id, y eso no es
posible(el id debe ser único).
• Para evitar estas situaciones lo mejor es usar el método update con el campo id
que es único. En el ejemplo anterior se podrı́a hacer la actualización si se hiciera
de la siguiente forma:
> db . prueba . update ( { ” i d ” : O b j e c t I d ( ” . . . 5 5 ” ) } , j u a n ) ;
W r i t e R e s u l t ( { ” nMachted ” : 1 , ” nUpersted ” : 0 , ” n M o d i f i e d ” : 1 } )
>
• Otra ventaja de usar el campo id es que el documento está indexado por este
campo.
Modificadores:
120
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
” i d ” : ObjectId ( ” . . . ” ) ,
”URL” : ”www. e j e m p l o . e s ” ,
” v i s i t a s ” : 34
}
>
• Cada vez que alguien visita una página se busca la página a partir de su URL y
se incrementa el campo de ”visitas” con el modificador $inc que incrementa el
campo dado en el valor descrito:
> db . prueba . update ( { ”URL” : ”www. e j e m p l o . e s ” } , { ” $ i n c ” : { ” v i s i t a s ” : 1 } } )
W r i t e R e s u l t ( { ” nMachted ” : 1 , ” nUpersted ” : 0 , ” n M o d i f i e d ” : 1 } )
> db . prueba . findOne ( )
{
” i d ” : ObjectId ( ” . . . ” ) ,
”URL” : ”www. e j e m p l o . e s ” ,
” v i s i t a s ” : 35
}
>
• Por ejemplo, se podrı́a añadir un nuevo campo para indicar el número de enlaces
de la página:
> db . prueba . update ( { ”URL” : ”www. e j e m p l o . e s ” } , { ” $ i n c ” : { ” e n l a c e s ” : 2 0 } } )
W r i t e R e s u l t ( { ” nMachted ” : 1 , ” nUpersted ” : 0 , ” n M o d i f i e d ” : 1 } )
> db . prueba . findOne ( )
{
” i d ” : ObjectId ( ” . . . ” ) ,
”URL” : ”www. e j e m p l o . e s ” ,
” v i s i t a s ” : 27 ,
” e n l a c e s ” : 20
}
>
121
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Cuando se usan operadores de modificación el valor del campo id no puede ser
cambiado (en cambio cuando se reemplaza un documento entero si es posible cam-
biar el campo id). Sin embargo los valores para cualquier otra clave incluyendo
claves indexadas únicas si pueden ser modificadas.
• Este operador solo puede ser usado con números enteros, enteros largos o double,
de manera que si se usa con otro tipo de valores (incluido los tipos que algu-
nos lenguajes tratan como números tales como booleanos, cadenas de números,
nulos,...) producirá un fallo.
$set y $set:
• Si el usuario desea añadir un campo sobre su libro favorito, se podrı́a hacer usando
el modificador $set:
> db . prueba . update ( { . . . { ” $ s e t : { ” l i b r o F a v o r i t o ” : ” Guerra y Paz ” } } )
Para añadir, modificar o eliminar claves se debe usar siempre los modificadores $. En
este sentido observar que si intentara hacer un cambio en las claves con un comando
como el siguiente:
122
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
db . prueba . update ( c r i t e r i o , {” edad ” : ” p aı́ s ” } )
tendrı́a como efecto reemplazar el documento que encaje con el criterio de búsqueda
por el documento ”edad”: ”paı́s”
{ ’ ’ edad ’ ’ : ’ ’ p aı́ s ’ ’ }
• Adición de elementos:
◦ El modificador $push añade elementos al final del array si existe o bien crea
uno nuevo si no existe.
◦ Por ejemplo, supóngase que se almacenan posts de un blog y se quiere añadir
una clave ”comentarios” que contenga un array de comentarios. Esto puede
hacerse usando el modificador $push que en el ejemplo crea una nueva clave
denominada ”comentarios”.
◦ Si se especifica un array con un único elemento, su comportamiento es similar
a un $push sin $each.
◦ También es posible limitar la longitud hasta la que puede crecer un array
usando el operador $lice junto al operador $push.
◦ Por último el operador $sort permite ordenar los elementos indicando el cam-
po de ordenación y el criterio en forma de 1(ascendente) o -1(descendente).
◦ Tanto $lice como $sort deben ir junto a un operador $each y no pueden
aparecer solos con un $push.
◦ $sort también puede ser usado para ordenar elementos que no son documen-
tos, en cuyo caso no hay que indicar ningún campo. En el siguiente ejemplo
se insertan dos elementos y se ordena el conjunto de manera ascendente.
• Los arrays se pueden tratar como un conjunto añadiendo valores solo si no estaban
ya. Para ello se usa el operador $ne junto al operador $push.
• Por ejemplo si se quiere añadir un autor a una lista de citas pero solo en el caso
de que no estuviera, entonces se podrı́a hacer de la siguiente manera:
db . a r t i c u l o s . update ( { ” a u t o r e s c i t a d o s ” : {” $ne ” : ” Pepe ” } } ,
{” $push ” : { ” a u t o r e s c i t a d o s ” : {” $ne ” : ” Pepe ” } } )
Borrado de elementos:
123
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Existen varias formas de eliminar elementos de un array dependiendo de la forma
en la que se quieran gestionar. Si se quiere gestionar como si fuera una pila o una
cola entonces se puede usar el operador $pop que permite eliminar elementos del
final del array(si toma el valor 1) o bien del principio del array (si toma el valor
-1):
• Otra forma alternativa de eliminar elementos es especificando un criterio en vez
de una posición en el array usando el operador $pull. El operador $pull eli-
mina todas las coincidencias que encuentre en los documento no solo la primera
coincidencia.
4.5. Indexación
Son una estructura de datos que mantiene información acerca de los valores de campos
especı́ficos en los documentos de una colección, y se utiliza para ordenar y clasificar
rápidamente los documentos de una colección.
De esta forma asegura una búsqueda y recuperación rápida de datos de los documentos.
Esencialmente se puede pensar que un ı́ndice es una consulta predefinida que fue eje-
cutada y los resultados de la misma se almacenan, de esta forma la consulta de in-
formación se hace rápida al no tener que recorrer la base de datos para recopilar esta
información.
Es por ello que generalmente es mejor añadir ı́ndices en las colecciones cuando el
número de lecturas es mayor que el número de escrituras, de hecho si hay más
escrituras que lecturas entonces los ı́ndices pueden ser contraproducentes.
Por otra parte, cuando se tienen ı́ndices de vez en cuando hay que borrar algunos
ı́ndices o reconstruirlos debido a varias razones:
124
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Aumento del tamaño de la base de datos.
• Espacio excesivo ocupado por los ı́ndices. Solo se pueden definir como máximo 40
ı́ndices por colección.
Ası́ por ejemplo si se ejecuta el comando indexes.find() permite ver los ı́ndices que
se han creado hasta el momento.
En general los ı́ndices se usan con las consultas (find, findOne) y en las ordenaciones.
Ası́ si se usa el comando sort() sobre una colección donde no existen ı́ndices sobre
los campos que aparecen especificados en la ordenación, entonces puede dar lugar a un
error si se excede el tamaño máximo del buffer interno de ordenación.
Listado de ı́ndices:
En el ejemplo se tiene una base de datos denominada blog que tiene dos coleccio-
nes: posts y autores.
• Aunque sobre las colecciones no se han definido ı́ndices por el usuario, sin embargo
si existen dos ı́ndices que se han creado de forma automática sobre los campos
id de cada colección.
• Los ı́ndices sobre el campo id son creados y borrados automáticamente por el
sistema cada vez que se crea o se borra una colección.
125
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Si no existe ningún ı́ndice adecuado, entonces se recorren todos los documentos de la
colección para encontrar los registros que satisfacen la consulta.
Creación de un ı́ndice simple:
• Para añadir nuevos ı́ndices a una colección se usa la función createIndex().
• Esta función primero chequea si ya se ha definido un ı́ndice con la misma especi-
ficación, en cuyo caso devuelve el ı́ndice, y en caso contrario lo crea.
• La función toma como parámetros el nombre de una clave de uno de los docu-
mentos que se usará para crear el ı́ndice, y un número que indica la dirección de
ordenación del ı́ndice: 1 almacena los ı́tems en orden ascendente y -1 almacena
los ı́tems en orden descendente.
• El comando asegura que el ı́ndice se creará para todos los valores de la clave
indicada para todos los documentos de la colección.
• Por ejemplo si se quiere crear un ı́ndice ascendente sobre el campo ”Etiquetas” se
harı́a de la siguiente manera:
> db . p o s t . c r e a t e I n d e x ( { ” E t i q u e t a s ” : 1 } )
{
” createdCollectionAutomatically ”: false ,
” numIndexesBefore ” : 1 ,
” n umI nde xesAft er ” : 2 ,
” ok ” : 1
}
>db . system . i n d e x e s . f i n d ( )
{” v ” : 1 , ” key ” : { ” i d ” : 1 } , ” name ” : ” i d ” , ” ns ” : ” b l o g . p o s t s ”}
{” v ” : 1 , ” key ” : { ” i d ” : 1 } , ” name ” : ” i d ” , ” ns ” : ” b l o g . a u t o r e s ”}
{” v ” : 1 , ” key ” : { ” E t i q u e t a s ” : } , ” name ” : ” E t i q u e t a s 1 ” , ” ns ” : ” b l o g . p o s t s ”}
>
126
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• De esta forma cada documento es enlazado a múltiples valores del ı́ndice.
• Observar que existe un operador especial para realizar consultas donde se selec-
cionan solos aquellos documentos que tienen todos los términos que se especifican.
• Ası́ por ejemplo en la base de datos blog, se tiene la colección posts con un campo
denominado ”Etiquetas” que representa las etiquetas que se le asocian a un post
determinado.
• En este sentido se podrı́a definir una consulta que recuperase todos los artı́culos
que tienen unas determinadas etiquetas como ”teléfono”, ”app”:
> db . p o s t . f i n d ( ) ( { ” E t i q u e t a s ” : { ” $ a l l ” : [ ” t e l e f o n o ” , ” app ” ] } } )
• Sin un ı́ndice multiclave sobre el campo ”Etiquetas”, se habrı́a tenido que consul-
tar cada documento de la colección para ver si existe un término, y en tal caso a
continuación chequear si ambos términos están presentes.
Creación de un ı́ndice compuesto:
• A primera vista parece que crear un ı́ndice separado para cada campo que aparece
en las consultas serı́a una buena idea para hacerlas más eficientes, sin embargo
los ı́ndices tienen un impacto significativo sobre la adición y eliminación de datos
de la base de datos puesto que es necesario actualizarlos cada vez que se realiza
una de estas operaciones.
• Los ı́ndices compuestos son una buena forma de mantener bajo el número de
ı́ndices que se tienen sobre una colección, permitiendo combinar múltiples campos
en un único ı́ndice.
• Es por ello que se deben usar este tipo de ı́ndices siempre que sea posible.
• Para crear un ı́ndice compuesto se especifican varias claves en vez de una.
• Existen dos tipos de ı́ndices compuestos: ı́ndices de subdocumentos e ı́ndices com-
puestos definidos por el usuario.
• Se han definido algunas reglas para usar los ı́ndices compuestos en consultas que
no usan todos los claves que componen el ı́ndice.
• La comprensión de estas reglas, permite construir un conjunto de ı́ndices com-
puesto que cubren todas las consultas que se desean realizar sobre una colección
sin tener un ı́ndice individual sobre cada elemento (evitando ası́ el impacto sobre
el rendimiento en las actualizaciones e inserciones).
• Un contexto donde puede que los ı́ndices compuestos no sean una buena elección
es cuando se usa el ı́ndice en una ordenación.
• En la ordenación no es bueno usar ı́ndices compuestos salvo que la lista de términos
y las direcciones de ordenación encajen exactamente con la estructura del ı́ndice.
• En estos casos, una elección mejor es usar ı́ndices simples individuales sobre cada
campo.
127
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Se puede crear un ı́ndice compuesto usando un subdocumento entero, de manera
que cada elemento del documento embebido se convierte en parte del ı́ndice.
• Por ejemplo supóngase que se tiene un subdocumento autor con el nombre y el
email en su interior, entonces se puede crear un ı́ndice compuesto con los términos
autor.nombre y autor.email.
• El único problema que existe con esta forma de crear ı́ndices compuestos es que
se pierde la posibilidad de configurar el orden de las claves en el ı́ndice puesto que
no se puede configurar la dirección de cada uno de ellos.
• Además observar que cuando se realizan consultas exactas sobre documentos em-
bebidos, el orden en que ocurren los campos debe encajar exactamente.
• Índices creados manualmente:
◦ Tal como se ha visto antes, cuando se usa un subdocumento como clave
del ı́ndice, entonces el orden de los elementos usados para construir el ı́ndice
multiclave encaja con el orden en el cual aparecen en la representación interna
del subdocumento.
◦ En muchos casos esto no da el suficiente control sobre el proceso de creación
de un ı́ndice.
◦ Para evitar esto y garantizar que la consulta usa un ı́ndice construido de
la forma deseada, se necesita asegurar que se usa la misma estructura del
subdocumento para crear el ı́ndice que la usada para realizar la consulta.
◦ Para ello se crea un ı́ndice compuesto nombrando explı́citamente todos los
campos por los que se desea combinar el ı́ndice, y el orden de combinación.
◦ Ası́ por ejemplo si se quiere crear un ı́ndice compuesto en el que los documen-
tos primero se ordena con respecto al campo ”Email” y a continuación para
cada valor del campo ”Email” se ordena con respecto al campo ”Nombre”:
> db . p o s t . f i n d ( ) ( { ” Autor ” : { ” Email ” : ” p e p i t o @ g m a i l . com ” , ” Nombre ” : ” P e p i t o ” } } )
128
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Opciones sobre ı́ndices:
◦ Para ello se especifican las opciones como parámetros de la función createIndex()
de la siguiente manera:
db . C o l e c c i o n . c r e a t e I n d e x ( ) ( { Campo : 1 } , { o p c i o n 1 : t r u e , o p c i o n 2 : t r u e , . . . } )
◦ Si se quiere crear un ı́ndice único para un campo donde se conoce que existe
valores duplicados, entonces se puede usar la opción dropdups, que elimina
los documentos que causan que falle la creación de un ı́ndice único.
◦ Se mantendrá el primer documento que se encuentre en la ordenación natural
de la colección y se eliminará cualquier otro documento que se encuentre y
viole la condición de creación del ı́ndice.
◦ En el siguiente ejemplo se crea un ı́ndice único sobre el campo ”titulo” de la
colección ”posts” y además se indica que se borren todos los documentos que
129
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
pudieran hacer fallar la creación del ı́ndice debido a la duplicidad de valores
del campo ”titulo”:
> db . p o s t . c r e a t e I n d e x ( { ” t i t u l o ” : 1 } , { ” u n i q u e ” : t r u e , ” dropdups ” : t r u e } )
{
” createdCollectionAutomatically ”: false ,
” numIndexesBefore ” : 1 ,
” numI ndexesAft er ” : 2 ,
” ok ” : 1
}
• Eliminación de ı́ndices:
◦ Se puede elegir entre eliminar un ı́ndice concreto de una colección usando la
función dropIndex(Especificación del ı́ndice):
◦ También es posible eliminar todos los ı́ndices de una colección usando la
función dropIndexes():
◦ Cuando se sospecha que un ı́ndice está dañado, entonces se puede forzar la
reindexación de la colección.
• Selección de ı́ndices:
◦ Cuando se quiere ejecutar una consulta, entonces el sistema crea un plan de
ejecución que es una lista de los pasos que debe ejecutar para llevar a cabo
la consulta.
◦ Cada consulta tiene múltiples planes que producirán el mismo resultado.
◦ Sin embargo cada plan puede tener elementos que son más costosos de ejecutar
que otros.
◦ Por ejemplo un recorrido de todas los registros de una colección es una ope-
ración costosa y cualquier plan que lo incorpore será lenta.
◦ Estos planes pueden incluir alternativamente listas de ı́ndices a usar para las
operaciones de consulta y ordenación.
◦ MongoBD usa un componente denominado ”analizador de consultas, el cual
toma una consulta y los objetivos de la misma, y produce un conjunto de
planes de ejecución.
◦ La función explain() lista tanto el plan que se usará para la consulta ası́
como los planes alternativos.
◦ Ası́ mismo existe otro componente denominado ”optimizador de consultas”
que tiene como función seleccionar qué plan de ejecución es el más adecuado
para una consulta particular.
◦ Este componente no usa un método basado en costes para seleccionar el plan
de ejecución, sino que ejecuta todos en paralelo y usa el que retorna los
resultados más rápidamente, finalizando el resto una vez el plan ganador
ejecuta la última lı́nea.
• El comando hint():
130
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
◦ Sin embargo puede haber casos en los que el optimizador no haga la mejor
elección.
◦ En estos casos es posibles forzar al optimizador de consultas a que use un
ı́ndice dado usando el operador hint().
◦ Por ejemplo supóngase que se tiene un ı́ndice sobre un subdocumento llamado
”Autor” que tiene como campos ”nombre” e ”email”:
> db . p o s t . c r e a t e I n d e x ( { ” Autor ” : 1 } )
{
” createdCollectionAutomatically ”: false ,
” numIndexesBefore ” : 1 ,
” numI ndexesAft er ” : 2 ,
” ok ” : 1
}
◦ También es posible usar hint() para forzar a que una consulta no use ı́ndices,
es decir que se use el escaneo de la colección de documentos como medio para
seleccionar los registros entonces se harı́a de la siguientes manera:
> db . p o s t . f i n d ( { ” Autor ” : { ” Nombre ” : ” Juan ” , ” Email ” : ” juan@gmail . com } } ) . h i n t ( { ” $ n a t u r a l ” : 1 } )
4.6. MapReduce
¿Qué es MapReduce?:
131
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 4.1: Esquema de MapReduce
>db . c o l l e c t i o n . mapReduce (
f u n c t i o n ( ) { emit ( key , v a l u e ) ; } , //map f u n c t i o n
f u n c t i o n ( key , v a l u e s ) { r e t u r n r e d u c e F u n c t i o n } , { // r e d u c e f u n c t i o n
out : c o l l e c t i o n ,
query : document ,
s o r t : document ,
l i m i t : number
}
)
Comentarios:
• map es una función javascript función que asigna un valor a una clave.
• reduce es una función javascript función que agrupa todos los documentos por su
clave. Algunos parámetros:
◦ out especifica la colección que almacena el resultado de la consulta map-
reduce.
◦ query especifica el criterio, opcional, para la selección de documentos.
◦ sort especifica el criterio, opcional, para la ordenación del resultado
◦ limit especifica el máximo número de elementos devuleltos.
Consideremos la siguiente estructura de documento que almacena usuarios. El docu-
mento almacena user id de un usuario y el estatus de ”post”.
132
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
{
” p o s t t e x t ” : ” t u t o r i a l s p o i n t i s an awesome w e b s i t e f o r t u t o r i a l s ” ,
” u s e r i d ” : ”mark ” ,
” status ”:” active ”
}
La función reduce relaciona todos los valores generados para una clave (en este caso
los suma todos).
Usamos una función mapReduce en nuestra colección de ”posts” para seleccionar todos
los ”posts” activos, agruparlos por user name y contar el número de ”posts” por cada
usuario:
>db . p o s t s . mapReduce (
f u n c t i o n ( ) { emit ( t h i s . u s e r i d , 1 ) ; } ,
f u n c t i o n ( key , v a l u e s ) {
v a r count = 0 ;
f o r ( v a r i = 0 ; i < v a l u e s . l e n g t h ; ++){
count += v a l u e s [ i ] ;
}
r e t u r n count } , {
query : { s t a t u s : ” a c t i v e ” } ,
out : ” p o s t t o t a l ”
}
)
La consulta da el siguiente resultado que indica que ambos usuarios tienen dos ”posts”
activos:
{ ” i d ” : ”tom ” , ” v a l u e ” : 2 }
{ ” i d ” : ”mark ” , ” v a l u e ” : 2 }
De forma similar, las consultas MapReduce se pueden utilizar para construir consultas
de agregación complejas. El uso de funciones Javascript functions hace que el uso de
MapReduce sea muy flexible.
133
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
// s e l e c t a d a t a b a s e
$db = $m−>mydb ;
echo ” Database mydb s e l e c t e d ” ;
?>
Insertando un documento:
<?php
// c o n n e c t t o mongodb
$m = new MongoClient ( ) ;
echo ” C o n n e c t i o n t o d a t a b a s e s u c c e s s f u l l y ” ;
// s e l e c t a d a t a b a s e
$db = $m−>mydb ;
echo ” Database mydb s e l e c t e d ” ;
$ c o l l e c t i o n = $db−>mycol ;
echo ” C o l l e c t i o n s e l e c t e d s u c c e s s f u l l y ” ;
$document = a r r a y (
” t i t l e ” => ”MongoDB” ,
” d e s c r i p t i o n ” => ” d a t a b a s e ” ,
” l i k e s ” => 1 0 0 ,
” u r l ” => ” h t t p : / /www. t u t o r i a l s p o i n t . com/mongodb / ” ,
”by ” , ” t u t o r i a l s p o i n t ”
);
$ c o l l e c t i o n −>i n s e r t ( $document ) ;
echo ”Document i n s e r t e d s u c c e s s f u l l y ” ;
?>
Actualizando un documento:
<?php
// c o n n e c t t o mongodb
134
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
$m = new MongoClient ( ) ;
echo ” C o n n e c t i o n t o d a t a b a s e s u c c e s s f u l l y ” ;
// s e l e c t a d a t a b a s e
$db = $m−>mydb ;
echo ” Database mydb s e l e c t e d ” ;
$ c o l l e c t i o n = $db−>mycol ;
echo ” C o l l e c t i o n s e l e c t e d s u c c s e s s f u l l y ” ;
// now update t h e document
$ c o l l e c t i o n −>update ( a r r a y ( ” t i t l e ”=>”MongoDB ” ) ,
a r r a y ( ’ $ s e t ’=> a r r a y ( ” t i t l e ”=>”MongoDB T u t o r i a l ” ) ) ) ;
echo ”Document updated s u c c e s s f u l l y ” ;
// now d i s p l a y t h e updated document
$ c u r s o r = $ c o l l e c t i o n −>f i n d ( ) ;
// i t e r a t e c u r s o r t o d i s p l a y t i t l e o f documents
echo ” Updated document ” ;
f o r e a c h ( $ c u r s o r a s $document ) {
echo $document [ ” t i t l e ” ] . ”\n ” ;
}
?>
135
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
136
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Capı́tulo 5
Datalog
5.2. Datalog
Datalog es un lenguaje utilizado para representar bases de datos deductivas y realizar
consultas sobre las mismas.
Se puede considerar como una versión restringida (y menos expresiva) que el lenguaje
de programación lógica Prolog.
137
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Existen muchas implementaciones:
• IRIS (http://iris-reasoner.org/)
• 4QL (http://4ql.org/)
• XSB (http://xsb.sourceforge.net/)
Sistema DES (Datalog Educational System):
• Desarrollado por Fernando Sáenz Perez (FdI - UCM), se distribuye bajo la licencia
GNU GPL 3.
• Disponible en http://www.fdi.ucm.es/profesor/fernan/des/
• Soporta tres lenguajes de consulta:
◦ Datalog.
◦ Álgebra relacional.
◦ SQL (con vistas recursivas).
• Es un sistema enfocado en la simplicidad y facilidad de uso, no en la eficiencia.
Comandos básicos del modo consola:
Comando Significado
/consult nombre fichero Carga un fichero (Datalog, RA, o SQL) en la base de datos
/assert hecho o regla Añade un hecho o regla a la base de datos.
/save ddb nombre fichero Exporta la base de datos actual a un fichero Datalog
/cd nombre dir Cambia el directorio actual.
/quit Abandona la consola DES
138
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Átomos:
Comentarios:
Valores null.
Ejemplo:
c u e n t a ( ’ J a v i e r ’ , ’ Herranz ’ , nomina , 1 2 0 0 0 ) .
c u e n t a ( ’ Ana ’ , ’ Martin ’ , a h o r r o , 2 1 5 0 0 ) .
c u e n t a ( ’ Gerardo ’ , ’ de l a I g l e s i a ’ , a h o r r o , 1 2 0 0 ) .
c u e n t a ( ’ Manuel ’ , ’ Moreno ’ , nomina , 5 0 0 0 ) .
c u e n t a ( ’ Lucia ’ , ’ Rodriguez ’ , a h o r r o , 5 0 0 0 ) .
c u e n t a ( ’ Raquel ’ , ’ V e l a s c o ’ , n u l l , 1 0 0 ) .
139
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Ejemplos:
Cuenta de las personas cuyo apellido es ’Moreno’:
DES> c u e n t a ( Nombre , ’ Moreno ’ , Tipo , S a l d o )
Este conjunto de hechos es lo análogo a una tabla cuenta en base de datos relacionales.
5.3.2. Ajustes
Una sustitución es una función que asocia a variables con constantes u otras variables.
Ejemplo:
θ = [X 7→ 2, Y 7→ pepe, Z 7→ V ]
La aplicación de θ a p se denota por θ(p). Ejemplo: θ(p(X, 13, Z)) = p(2, 13, V ).
Decimos que un átomo q se ajusta a p si existe una sustitución θ tal que θ(p) = q.
Ejemplo: p(lucia, 23, Z) se ajusta a p(X, 23, Y ).
El mecanismo de Datalog busca en la base de datos hechos (que pueden ser inferidos
a partir de otros) de tal forma que se ajusten al objetivo.
5.3.3. Reglas
La base de datos intensional contiene la información que se infiere de la ya existente
en la base de datos.
| {z } : − literal
Sintaxis de las reglas: atomo
| 1 , literal2 , . . . , literaln
{z }
cabeza cuerpo
140
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Si se satisface cada uno de los términos del cuerpo se considera que se satisface la
cabeza. O lo que es lo mismo:
| {z } : − literal
Dada la regla: atomo
| 1 , literal2 , . . . , literaln , si existe una sustitu-
{z }
cabeza cuerpo
ción θ de tal forma que θ(literal1 ), . . . , θ(literaln ) sean conocidos (o deduci-
bles) entonces se puede inferir θ(atomo).
Este es el mecanismo de inferencia de la información.
Ejemplo:
• En una BB.DD. de un banco podemos saber si un cliente es ”preferente” si sabe-
mos cuánto dinero tiene en el banco y le decimos al sistema el valor a partir del
cual ya se considera preferente.
• Base de datos extensional:
c u e n t a ( ’ Pepe ’ , ’ Lopez ’ , a h o r r o , 1 0 0 0 ) .
c u e n t a ( ’ Juan ’ , ’ Lopez ’ , a h o r r o , 5 0 0 ) .
c u e n t a ( ’ Lucas ’ , ’ Lopez ’ , a h o r r o , 4 0 0 0 ) .
c u e n t a ( ’ Antonio ’ , ’ Lopez ’ , a h o r r o , 5 0 0 0 ) .
c u e n t a ( ’ Manuel ’ , ’ Moreno ’ , nomina , 5 0 0 0 ) .
141
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
p :− a , b .
p :− a , c .
Para programar cualquier inferencia que podamos pensar es necesario que tenga cierta
forma.
Si cada cláusula tiene exactamente un literal positivo (un literal no negado) puede
transformarse en una regla.
Ejemplo:
Ejemplo:
142
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Decimos que dos clientes son ”amiguetes” si los saldos de su cuenta coinciden.
• Es decir, el cliente con nombre N1 y apellidos A1 es amiguete del cliente con
nombre N2 y apellidos A2 si existe un número S y sendos tipos T1 y T2, tales
que:
◦ La cuenta de N1, A1 tiene tipo T1 y saldo S.
◦ La cuenta de N2, A2 tiene tipo T2 y saldo S.
• Su expresión lógica es:
es equivalente a:
que es equivalente a:
% a m i g u e t e s ( Nombre1 , A p e l l i d o s 1 , Nombre2 , A p e l l i d o s 2 )
a m i g u e t e s (N1 , A1 , N2 , A2) :− c u e n t a (N1 , A1 , T1 , S ) , c u e n t a (N2 , A2 , T2 , S ) .
En el ejemplo anterior si hacemos una consulta podemos encontrar algo con el siguiente
aspecto:
DES> a m i g u e t e s (N1 , A1 , N2 , A2)
{
a m i g u e t e s ( ’ Ana ’ , ’ Martin ’ , ’ Ana ’ , ’ Martin ’ ) ,
a m i g u e t e s ( ’ Gerardo ’ , ’ de l a I g l e s i a ’ , ’ Gerardo ’ , ’ de l a I g l e s i a ’ ) ,
a m i g u e t e s ( ’ J a v i e r ’ , ’ Herranz ’ , ’ J a v i e r ’ , ’ Herranz ’ ) ,
a m i g u e t e s ( ’ Lucia ’ , ’ Rodriguez ’ , ’ Lucia ’ , ’ Rodriguez ’ ) ,
a m i g u e t e s ( ’ Lucia ’ , ’ Rodriguez ’ , ’ Manuel ’ , ’ Moreno ’ ) ,
a m i g u e t e s ( ’ Manuel ’ , ’ Moreno ’ , ’ Lucia ’ , ’ Rodriguez ’ ) ,
a m i g u e t e s ( ’ Manuel ’ , ’ Moreno ’ , ’ Manuel ’ , ’ Moreno ’ ) ,
a m i g u e t e s ( ’ Raquel ’ , ’ V e l a s c o ’ , ’ Raquel ’ , ’ V e l a s c o ’ )
}
Es posible sustituir estas variables (cuyo nombre es irrelevante) por variables anónimas.
143
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Las variables anónimas ajustan con cualquier elemento.
El código anterior queda con la siguiente forma:
% a m i g u e t e s ( Nombre1 , A p e l l i d o s 1 , Nombre2 , A p e l l i d o s 2 )
a m i g u e t e s (N1 , A1 , N2 , A2) :−
c u e n t a (N1 , A1 , , S) ,
c u e n t a (N2 , A2 , , S ) , N1 \= N2 .
a m i g u e t e s (N1 , A1 , N2 , A2) :−
c u e n t a (N1 , A1 , , S) ,
c u e n t a (N2 , A2 , , S ) , A1 \= A2 .
Este código es más claro. Permite centrar la atención en las variables relevantes.
El operador punto y coma permite expresar la disyunción entre dos literales. Esto
permite expresar las dos reglas en una:
% a m i g u e t e s ( Nombre1 , A p e l l i d o s 1 , Nombre2 , A p e l l i d o s 2 )
a m i g u e t e s (N1 , A1 , N2 , A2) :−
c u e n t a (N1 , A1 , , S) ,
c u e n t a (N2 , A2 , , S ) , (N1 \= N2 ; A1 \= A2 ) .
144
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
5.3.5. Mecanismo de cómputo de Datalog
Consideremos el siguiente código en Datalog:
edad ( pepe , 1 3 ) .
edad ( juan , 1 8 ) .
edad ( maria , 2 3 ) .
edad ( ana , 1 9 ) .
amigos ( pepe , j u a n ) .
amigos ( juan , ana ) .
amigos ( maria , j u a n ) .
a m i g o s a d u l t o s (X,Y): − amigos (X,Y) , edad (X,V) ,V>17 , edad (Y,W) ,W>17.
2. edad(pepe,X): el sistema busca ajustes que hagan al objetivo cierto. En este caso
θ = [X 7→ 13]. También podı́amos haber enviado el objetivo edad(X,13). En tal caso
θ = [X 7→ pepe].
3. edad(X,Y): el sistema busca ajustes que lo hagan cierto. Hay varios, por ejemplo:
θ = [X 7→ maria, Y 7→ 23].
5. amigos adultos(W,Z): serı́a similar con la diferencia de que se plantean más ajustes.
Hechos y reglas son funciones booleanas. Un hecho es una función booleana constante.
145
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Si se trata de propiedades no booleanas (existe más de un valor), utilizamos una
función lógica de dos argumentos (en el que el segundo argumento será el valor
de la propiedad). Por ejemplo: edad(juan,18).
• Si estamos representando representaciones entre objetos utilizaremos funciones
booleanas con dos argumentos (si la relación es booleana, o más si no lo es).
Es la caracterı́stica que hace que Datalog sea muy potente en términos de expresividad.
Árboles genealógicos
p r o g e n i t o r ( abraham , h e r b e r t ) .
p r o g e n i t o r ( abraham , homer ) .
p r o g e n i t o r ( mona , homer ) .
p r o g e n i t o r ( c l a n c y , marge ) .
p r o g e n i t o r ( j a c k i e , marge ) .
progenitor ( clancy , patty ) .
progenitor ( jackie , patty ) .
p r o g e n i t o r ( c l a n c y , selma ) .
p r o g e n i t o r ( j a c k i e , selma ) .
p r o g e n i t o r ( homer , b a r t ) .
p r o g e n i t o r ( marge , b a r t ) .
p r o g e n i t o r ( homer , l i s a ) .
p r o g e n i t o r ( marge , l i s a ) .
p r o g e n i t o r ( homer , maggie ) .
p r o g e n i t o r ( marge , maggie ) .
p r o g e n i t o r ( selma , l i n g ) .
146
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 5.1: Datalog y los Simpson
147
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Reglas sobre la paternidad:
◦ Semántica de padre(X,Y): X es padre de Y. Semántica de madre(X,Y): X es
madre de Y.
◦ En Datalog se expresa:
padre (X,Y) :− p r o g e n i t o r (X,Y) , hombre (X ) .
madre (X,Y) :− p r o g e n i t o r (X,Y) , mujer (X ) .
• Relaciones de hermandad:
◦ Semántica de hermanos(X,Y): X es hermano o hermana de Y.
◦ En Datalog se expresa:
hermanos (X,Y) :− p r o g e n i t o r ( Z ,X) , p r o g e n i t o r ( Z ,Y) , X \= Y.
• De modo similar podemos indicarle al sistema en qué consiste ser ”tı́a” y ”abuela”:
t i a (X,Y) :− mujer (X) , hermanos (X, Z ) , p r o g e n i t o r ( Z ,Y ) .
a b u e l a (X,Y) :− madre (X, Z ) , p r o g e n i t o r ( Z ,Y ) .
Regla recursiva:
• Otro ejemplo:
◦ Ser de la misma generación mg(X,Y).
◦ Se codifica:
mg(X,Y) :− hermanos (X,Y ) .
mg(X,Y) :− p r o g e n i t o r ( Z ,X) , p r o g e n i t o r (V,Y) , mg( Z ,V ) .
148
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
DES> mg(X,Y)
{
mg( ba r t , l i n g ) ,
mg( ba r t , l i s a ) ,
mg( ba r t , maggie ) ,
mg( h e r b e r t , homer ) ,
mg( homer , h e r b e r t ) ,
mg( l i n g , b a r t ) ,
...
}
Caminos en un grafo
Representar un grafo es muy sencillo con Datalog: simplemente hay que especificar las
aristas.
Ejemplo:
arista (a , b ).
a r i s t a (b , d ) .
a r i s t a (d , c ) .
a r i s t a (d , e ) .
arista (e , f ).
arista (f , c ).
arista (f ,g ).
arista (g , d ).
Codificado:
camino (X,Y) :− a r i s t a (X,Y ) .
camino (X,Y) :− a r i s t a (X, Z ) , camino ( Z ,Y ) .
149
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
ciclo ( f ) ,
ciclo (g)
}
• Natural join.
• Left outer join.
• Right outer join.
• Full outer join.
Reuniones internas
No existe ninguna función especial para representar reuniones internas.
Ejemplo:
% c l i e n t e ( Id , Nombre , A p e l l i d o s )
c l i e n t e ( 1 , ’ J a v i e r ’ , ’ Herranz ’ ) .
c l i e n t e ( 2 , ’ Ana ’ , ’ Martin ’ ) .
c l i e n t e ( 3 , ’ Gerardo ’ , ’ de l a I g l e s i a ’ ) .
c l i e n t e ( 4 , ’ Manuel ’ , ’ Moreno ’ ) .
c l i e n t e ( 5 , ’ Lucia ’ , ’ Rodriguez ’ ) .
c l i e n t e ( 6 , ’ Raquel ’ , ’ V e l a s c o ’ ) .
c l i e n t e ( 7 , ’ I g n a c i o ’ , ’ Martin ’ ) .
% c u e n t a ( Id , Tipo , Saldo , I d T i t u l a r )
c u e n t a ( 1 , nomina , 1 2 0 0 0 , 1 ) .
cuenta ( 2 , ahorro , 15000 , 1 ) .
c u e n t a ( 3 , nomina , 2 1 5 0 0 , 2 ) .
cuenta ( 4 , ahorro , 1200 , 3 ) .
c u e n t a ( 5 , nomina , 5 0 0 0 , 4 ) .
cuenta ( 6 , ahorro , 5000 , 5 ) .
cuenta (7 , null , 100 , 6 ) .
c u e n t a ( 8 , nomina , 1 5 0 0 , 6 ) .
150
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Un posible resultado:
% c u e n t a ( Id , Tipo , Saldo , I d T i t u l a r )
DES> c l i e n t e s c u e n t a s (N, A, T, S )
{
c l i e n t e s c u e n t a s ( ’ Ana ’ , ’ Martin ’ , nomina , 2 1 5 0 0 ) ,
c l i e n t e s c u e n t a s ( ’ Gerardo ’ , ’ de l a I g l e s i a ’ , a h o r r o , 1 2 0 0 ) ,
c l i e n t e s c u e n t a s ( ’ J a v i e r ’ , ’ Herranz ’ , a h o r r o , 1 5 0 0 0 ) ,
c l i e n t e s c u e n t a s ( ’ J a v i e r ’ , ’ Herranz ’ , nomina , 1 2 0 0 0 ) ,
c l i e n t e s c u e n t a s ( ’ Lucia ’ , ’ Rodriguez ’ , a h o r r o , 5 0 0 0 ) ,
c l i e n t e s c u e n t a s ( ’ Manuel ’ , ’ Moreno ’ , nomina , 5 0 0 0 ) ,
c l i e n t e s c u e n t a s ( ’ Raquel ’ , ’ V e l a s c o ’ , nomina , 1 5 0 0 ) ,
c l i e n t e s c u e n t a s ( ’ Raquel ’ , ’ V e l a s c o ’ , n u l l , 1 0 0 )
}
Las funciones is null e is not null permiten comprobar si un atributo es nulo (no
utilizar en comparaciones):
DES> c l i e n t e s c u e n t a s (N, A, T, S ) , i s n o t n u l l (T)
Info : Processing :
answer (N, A, T, S ) :−
c l i e n t e s c u e n t a s (N, A, T, S ) ,
i s n o t n u l l (T ) .
{
answer ( ’ Ana ’ , ’ Martin ’ , nomina , 2 1 5 0 0 ) ,
answer ( ’ Gerardo ’ , ’ de l a I g l e s i a ’ , a h o r r o , 1 2 0 0 ) ,
answer ( ’ J a v i e r ’ , ’ Herranz ’ , a h o r r o , 1 5 0 0 0 ) ,
answer ( ’ J a v i e r ’ , ’ Herranz ’ , nomina , 1 2 0 0 0 ) ,
answer ( ’ Lucia ’ , ’ Rodriguez ’ , a h o r r o , 5 0 0 0 ) ,
answer ( ’ Manuel ’ , ’ Moreno ’ , nomina , 5 0 0 0 ) ,
answer ( ’ Raquel ’ , ’ V e l a s c o ’ , nomina , 1 5 0 0 )
}
Reuniones externas
Reunión externa por la izquierda (left outer join): lj(RelIzqda, RelDcha, CondicionJoin)
Reunión externa por la derecha (right outer join): rj(RelIzqda, RelDcha, CondicionJoin)
Reunión externa completa (full outer outer join): fj(RelIzqda, RelDcha, CondicionJoin)
Ejemplo:
c l i e n t e s c u e n t a s l e f t (N, A, T, S ) :−
l j ( c l i e n t e ( Id , N, A) , c u e n t a ( , T, S , IdC ) , I d = IdC ) .
DES> c l i e n t e s c u e n t a s l e f t (N, A, T, S )
{
c l i e n t e s c u e n t a s l e f t ( ’ Ana ’ , ’ Martin ’ , nomina , 2 1 5 0 0 ) ,
c l i e n t e s c u e n t a s l e f t ( ’ Gerardo ’ , ’ de l a I g l e s i a ’ , a h o r r o , 1 2 0 0 ) ,
c l i e n t e s c u e n t a s l e f t ( ’ I g n a c i o ’ , ’ Martin ’ , n u l l , n u l l ) ,
c l i e n t e s c u e n t a s l e f t ( ’ J a v i e r ’ , ’ Herranz ’ , a h o r r o , 1 5 0 0 0 ) ,
c l i e n t e s c u e n t a s l e f t ( ’ J a v i e r ’ , ’ Herranz ’ , nomina , 1 2 0 0 0 ) ,
c l i e n t e s c u e n t a s l e f t ( ’ Lucia ’ , ’ Rodriguez ’ , a h o r r o , 5 0 0 0 ) ,
c l i e n t e s c u e n t a s l e f t ( ’ Manuel ’ , ’ Moreno ’ , nomina , 5 0 0 0 ) ,
c l i e n t e s c u e n t a s l e f t ( ’ Raquel ’ , ’ V e l a s c o ’ , nomina , 1 5 0 0 ) ,
c l i e n t e s c u e n t a s l e f t ( ’ Raquel ’ , ’ V e l a s c o ’ , n u l l , 1 0 0 )
}
151
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
5.4.2. Agrupaciones
Instrucción básica: group by(Rel, VarsGroup, CondsGroup)
Realiza un agrupamiento de los resultados de la relación Rel, reuniendo aquellos que
coincidan en las variables indicadas en VarsGroup. En CondsGroup podemos utilizar
funciones de agregación y ligar sus valores a variables externas.
VarsGroup es una lista [Var-1, ..., Var-n]
CondsGroup se compone de una o varias condiciones Var = Exp, donde Exp puede
contener funciones de agregación.
Ejemplo:
c l i e n t e s c u e n t a s l e f t ( Id , N, A, T, S ) :−
l j ( c l i e n t e ( Id , N, A) , c u e n t a ( , T, S , IdC ) , I d = IdC ) .
c l i e n t e s n u m c u e n t a s (N, A, NumCuentas ) :−
group by (
c l i e n t e s c u e n t a s l e f t ( Id , N, A, T, S ) ,
[ Id , N, A] ,
NumCuentas = count ( S )
).
152
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
DES> c l i e n t e s n u m c u e n t a s y s a l d o t o t a l (N, A, NumCuentas , S a l d o T o t a l )
{
c l i e n t e s n u m c u e n t a s y s a l d o t o t a l ( ’ Ana ’ , ’ Martin ’ , 1 , 2 1 5 0 0 ) ,
c l i e n t e s n u m c u e n t a s y s a l d o t o t a l ( ’ Gerardo ’ , ’ de l a I g l e s i a ’ , 1 , 1 2 0 0 ) ,
c l i e n t e s n u m c u e n t a s y s a l d o t o t a l ( ’ I g n a c i o ’ , ’ Martin ’ , 0 , n u l l ) ,
c l i e n t e s n u m c u e n t a s y s a l d o t o t a l ( ’ J a v i e r ’ , ’ Herranz ’ , 2 , 2 7 0 0 0 ) ,
c l i e n t e s n u m c u e n t a s y s a l d o t o t a l ( ’ Lucia ’ , ’ Rodriguez ’ , 1 , 5 0 0 0 ) ,
c l i e n t e s n u m c u e n t a s y s a l d o t o t a l ( ’ Manuel ’ , ’ Moreno ’ , 1 , 5 0 0 0 ) ,
c l i e n t e s n u m c u e n t a s y s a l d o t o t a l ( ’ Raquel ’ , ’ V e l a s c o ’ , 1 , 1 6 0 0 )
}
5.4.4. Aritmética
Pueden realizarse operaciones aritméticas mediante el operador is.
Sintaxis: X is Expresión
Ejemplo:
% a r t i c u l o ( Nombre , Cantidad , P r e c i o U n i d a d )
a r t i c u l o ( ’ Aceite ’ , 2 , 6 . 9 5 ) .
a r t i c u l o ( ’ Azúcar ’ , 1 , 1 . 2 0 ) .
a r t i c u l o ( ’ Leche ’ , 3 , 0 . 9 0 ) .
t o t a l a r t i c u l o ( Nombre , T o t a l ) :−
a r t i c u l o ( Nombre , Cantidad , P r e c i o U n i d a d ) ,
T o t a l i s Cantidad ∗ P r e c i o U n i d a d .
t o t a l c o m p r a ( Suma ) :−
g r o u p b y ( t o t a l a r t i c u l o ( , T o t a l ) , [ ] , Suma = sum ( T o t a l ) ) .
DES> t o t a l c o m p r a (T ) .
{
total compra (17.8)
}
153
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Los argumentos de las relaciones sólo pueden ser constantes o variables; nunca expre-
siones. El siguiente código es incorrecto:
t o t a l a r t i c u l o ( Nombre , Cantidad ∗ P r e c i o U n i d a d ) :−
a r t i c u l o ( Nombre , Cantidad , P r e c i o U n i d a d ) .
Las variables que aparezcan en las expresiones aritméticas han de estar ligadas a algún
valor. El siguiente código es incorrecto:
p (X, Z ) :− Z i s X+Y.
La Y no está ligada.
5.4.5. Negación
En Datalog se considera que una relación no se cumple si no se puede deducir de la ya
existente en la base de datos.
154
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
El operador not permite comprobar si una determinada relación no es cierta.
Ejemplo:
c l i e n t e s s i n c u e n t a a h o r r o (N, A) :−
c l i e n t e s c u e n t a s (N, A, , ),
not c l i e n t e s c u e n t a s (N, A, a h o r r o , ).
DES> c l i e n t e s s i n c u e n t a a h o r r o (N,A ) .
{
c l i e n t e s s i n c u e n t a a h o r r o ( ’ Ana ’ , ’ Martin ’ ) ,
c l i e n t e s s i n c u e n t a a h o r r o ( ’ Manuel ’ , ’ Moreno ’ ) ,
c l i e n t e s s i n c u e n t a a h o r r o ( ’ Raquel ’ , ’ V e l a s c o ’ )
}
Negación estratificada
La negación puede ser problemática cuando aparece en relaciones definidas recursiva-
mente.
Una definición de relación, que contenga una negación, se considera segura si no aparece
en un camino de cómputo recursivo.
Comprobación de la corrección:
Mediante el comando /pdg de DES se puede obtener una representación del grafo de
dependencias.
155
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
5.5. Más allá de Datalog: Prolog
5.5.1. ¿Qué es la programación declarativa?
La idea clave consiste en describir relaciones entre los datos sin concretar los algoritmos.
• Programación lógica.
• Programación funcional.
En la práctica:
156
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Estos estilos de programación enriquecen considerablemente las habilidades del
programador, aunque posteriormente utilice algún lenguaje imperativo.
• El diseño declarativo es normalmente más conciso, elegante, claro y fácil de man-
tener.
Descargable en http://www.swi-prolog.org/
Listas en Prolog:
Una lista es una secuencia ordenada de elementos que puede tener cualquier longitud.
Los elementos de una lista pueden ser cualquier término (constantes, variables, estruc-
turas) u otras listas.
157
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Lista Cabeza Cola
[a,b,c] a [b,c]
[a] a []
[] no tiene no tiene
[[a,b],c] [a,b] [c]
[a,[b,c]] a [[b,c]]
[a,[b,c],d] a [[b,c],d]
[a+b,c+d] a+b [c+d]
Nota: + es el operador concatenación.
Los siguientes ejemplos muestran funciones lógicas para saber si un elemento dado está
o no en una lista:
miembro (E , L) :− L=[X|Y] , X=E .
miembro (E , L) :− L=[X|Y] , miembro (E ,Y ) .
miembro (X , [ X|Y ] ) .
miembro (E , [ X|Y ] ) :− miembro (E ,Y ) .
miembro (X , [ X| ] ) .
miembro (X , [ |Y ] ) :− miembro (X,Y ) .
/∗ e s l i s t a ( L i s t a ) <− L i s t a e s una l i s t a ∗/
es lista ([]).
es lista ([ | ]).
/∗ c o n c a t e n a (A, B, C) <− c o n c a t e n a c i ó n de l a s l i s t a s A y B
dando l u g a r a l a l i s t a C ∗/
c o n c a t e n a (A, B, C) :− A= [ ] , C=B .
c o n c a t e n a (A, B, C) :− A=[X|D] , c o n c a t e n a (D, B, E) , C=[X| E ] .
o bien:
/∗ c o n c a t e n a ( L1 , L2 , L3 ) <− c o n c a t e n a c i ó n de l a s l i s t a s L1 y L2
dando l u g a r a l a l i s t a L3 ∗/
concatena ( [ ] , L , L ) .
c o n c a t e n a ( [ X| L1 ] , L2 , [ X| L3 ] ) :− c o n c a t e n a ( L1 , L2 , L3 ) .
158
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
/∗ i n v e r s a ( L i s t a , I n v e r ) <− I n v e r e s l a i n v e r s a de l a l i s t a L i s t a ∗/
inversa ( [ ] , [ ] ) .
i n v e r s a ( [ X|Y] , L) :− i n v e r s a (Y, Z ) ,
c o n c a t e n a ( Z , [ X] , L ) .
/∗ s u b c o n j u n t o ( L1 , L2 ) <− l a l i s t a L1 e s un s u b c o n j u n t o de l i s t a L2 ∗/
s u b c o n j u n t o ( [ X|Y] , Z ) :− miembro (X, Z ) ,
s u b c o n j u n t o (Y, Z ) .
subconjunto ( [ ] ,Y) .
/∗ p e r m u t a c i o n ( L1 , L2 ) <− l a l i s t a L2 e s una p e r m u t a c i ó n de l i s t a L1 ∗/
permutacion ( [ ] , [ ] ) .
p e r m u t a c i ó n ( [ X|Y] , Z ) :− p e r m u t a c i o n (Y, L ) ,
i n s e r t a r (X, L , Z ) .
Recursión:
qsort ( [ ] , [ ] ) .
q s o r t ( [ X| Xs ] , Zs ) :−
p a r t i t i o n (X, Xs , Ls , Gs ) ,
q s o r t ( Ls , L s S o r t ) ,
q s o r t ( Gs , GsSort ) ,
append ( LsSort , [X| GsSort ] , Zs ) .
?− q s o r t ( [ 6 , 1 , 4 , 9 , 2 ] , Xs ) .
Xs = [ 1 , 2 , 4 , 6 , 9 ] .
159
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 5.2: Secuencia de llamadas para el cómputo de la función nel
160
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Parte III
161
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Capı́tulo 6
6.1. Almacenamiento
En el nivel conceptual o lógico hemos las bases de datos en el modelo relacional como
conjuntos de tablas. En realidad, el modelo lógico de las bases de datos es el nivel
adecuado en el que se deben centrar los usuarios.
• Caché:
◦ Es la forma de almacenamiento más rápida y costosa. Por lo tanto, es pequeña.
◦ Su uso lo gestiona el hardware del sistema informático. No hay que preo-
cuparse sobre la gestión del almacenamiento caché del sistema de bases de
datos.
• Memoria principal: aunque la memoria principal puede contener muchos megabi-
tes de datos, suele ser demasiado pequeña (o demasiado cara) para guardar toda
la base de datos.
• Memoria flash:
◦ Memoria sólo de lectura programable y borrable eléctricamente.
◦ La memoria flash se diferencia de la memoria principal en que los datos pueden
sobrevivir a los fallos del suministro eléctrico.
163
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Almacenamiento en discos y cintas magnéticas.
• Almacenamiento óptico: CDs, DVDs.
6.1.1. RAID
Los requisitos de almacenamiento de datos de algunas aplicaciones (por ejemplo, debido
a las aplicaciones web: bases de datos y multimedia) crecen muy rápidamente.
Se necesita un gran número de discos para almacenar sus datos, incluso aunque las
capacidades de los discos hayan estado creciendo muy rápidamente.
164
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Un disco lógico consiste en dos discos fı́sicos y cada proceso de escritura se lleva
a cabo en ambos discos. Si uno de los discos falla se pueden leer los datos del
otro. Los datos sólo se perderán si falla el segundo disco antes de que se repare el
primero que falló.
Niveles de RAID:
165
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Nivel 2:
◦ Cada byte del sistema de memoria puede tener asociado un bit de paridad
que registra el número de bits que valen 1.
◦ Si, por error, se produce un error pequeño (el cambio de un bit) habrá una
discrepancia entre el bit de paridad guardado y el bit de paridad calculado.
◦ Garantiza la fiabilidad sin la necesidad de duplicar la información.
• Cada nivel adicional, hasta el nivel 6, supone un paso adicional para lograr fiabi-
lidad y velocidad.
6.2. Índices
Motivación:
La mayor parte de las consultas hacen referencia sólo a una pequeña parte de los
registros de un archivo. Por ejemplo, buscar por DNI (solamente habrá un registro!!!).
No es eficiente para el sistema tener que leer cada registro (búsqueda secuencial) y
comprobar que cumple las condiciones de la búsqueda.
Lo más adecuado serı́a que el sistema fuese capaz de localizar directamente estos regis-
tros. Para facilitar estas formas de acceso se diseñan estructuras adicionales (ı́ndices)
que se asocian con archivos.
Conceptos básicos:
Un ı́ndice para un archivo del sistema funciona como el ı́ndice de un libro: permite
encontrar la información si necesidad de leer todo el libro.
Existen varias técnicas de indexación. Ninguna es mejor de una forma absoluta. De-
pende de la aplicación especı́fica de la base de datos.
166
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Cada técnica debe ser valorada según los siguientes criterios:
• Tipos de acceso.
• Tiempo de acceso.
• Tiempo de inserción.
• Tiempo de borrado.
• Espacio adicional requerido.
Los atributos o conjunto de atributos usados para buscar en un archivo se llaman
claves de búsqueda. Hay que observar que esta definición de clave difiere de la usada
en clave primaria, clave candidata y superclave. Este doble significado de clave está
(por desgracia) muy extendido en la práctica.
Un ı́ndice es una estructura que permite la búsqueda eficiente de un registro a través
de un determinado campo.
Asocia los valores de un campo (claves de búsqueda) con la posición del registro co-
rrespondiente dentro de la base de datos.
Tipos:
• Índices ordenados: basados en el orden de los valores. Pueden implementarse me-
diante un árbol B + :
◦ Índices densos: el ı́ndice contiene una entrada por cada clave de búsqueda en
la tabla.
◦ Índices dispersos: el ı́ndice contiene entradas sólo para algunas claves de
búsqueda. Son una combinación de acceso directo con acceso secuencial.
• Índices hash: basados en una función que distribuye uniformemente los valores en
un conjunto de ”cajones”.
Índices en SQL:
• SQL crea automáticamente ı́ndices para las claves primarias de una relación.
• Es recomendable la creación de ı́ndices sobre otros campos si se van a realizar
búsquedas intensivas sobre los mismos.
• Instrucciones relacionadas:
◦ Creación de un nuevo ı́ndice: CREATE INDEX nombre indice ON tabla(columna);
◦ Borrado de un ı́ndice: DROP INDEX nombre indice;
Índices en MongoDB:
• Cuando se añade un documento a una colección MongoDB crea de forma au-
tomática un campo ( id) sobre el que construye un ı́ncide.
• MongoDB permite crear ı́ndices sobre cualquier clave.
167
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
6.2.1. Árboles B +
Caracterı́sticas generales:
Todos los caminos desde la raı́z hasta las hojas de un árbol son de la misma longitud.
El número de hijos para cada nodo oscila entre dn/2e y n hijos, donde n es un número
fijo para todo el árbol con la excepción de la raı́z del árbol.
Estructura de un árbol B +
En cada nodo interno se almacenan punteros y claves:
[P1 , K1 , P2 , K2 , . . . KN , PN +1 ]
La semántica de un nodo interno consiste en almacenar claves dentro del rango [K1 , KN ).
Además, en un nodo interno el puntero, Pi , que está entre las claves Ki y Ki+1 señala
a un nodo cuyas claves están entre estos valores: [Ki , Ki+1 ).
Nodos hoja:
• Al menos la mitad de las casillas, en concreto d(n − 1)/2e, deben contener claves.
• El puntero que hay a la izquierda de cada clave apunta al registro correspondiente
en la tabla.
• El puntero de más a la derecha apunta a la siguiente hoja del árbol (si existe).
Ejemplo: n = 3
[62, ∅, ∅]
[7, 15, 21] [24, 32, ∅] [39, 47, 59] [62, 70, ∅] [75, 78, ∅]
168
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Búsqueda en un árbol B +
Para buscar una determinada clave se recorre el árbol desde la raı́z hasta la hoja
correspondiente siguiendo un mecanismo similar al de la búsqueda en un árbol binario.
El enlazar los nodos hoja nos permite un procesamiento secuencial. Ejemplo: buscar
claves dentro de cierto rango.
• Nodos visitados: [62, ∅, ∅], [24, 39, ∅], [39, 47, 59].
• Nodos visitados: [62, ∅, ∅], [24, 39, ∅], [24, 32, ∅], [39, 47, 59], [62, 70, ∅].
Inserción en un árbol B +
Se desciende por el árbol hasta encontrar la posición del elemento a insertar (similar a
una consulta).
[7, 15, 21] [24, 28, 32] [39, 47, 59] [62, 70, ∅] [75, 78, ∅]
169
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
División de nodos hoja:
• Si el tamaño de nodo es n las hojas del árbol B + permiten almacenar hasta n-1
claves.
• Si se pretenden almacenar n claves en una hoja hemos de dividirla en dos:
◦ Las primeras dn/2e se quedan en la hoja existente.
◦ Las restantes pasan a una nueva hoja.
• En el nodo padre deberá insertarse una referencia a la nueva hoja creada. Esto
puede provocar una división en el nodo padre!!!.
Un poco de notación:
Ejemplo:
• Clave a insertar: 30
• Inserción en: [24, 28, 32]
• Nuevo nodo: [24, 28, 30, 32].
• Nodos que surgen de la división: [24, 28∅] y [30, 32, ∅].
• post(21) = 24.
• Los nodos [24, 28, ∅], [30, 32, ∅] y [39, 47, 59] se enlazan secuencialmente.
• Se añade la entrada con el nuevo nodo creado en el nodo padre.
• Si el tamaño de nodo es n, los nodos del árbol interno pueden contener n punteros
a hojas.
• Al insertar el elemento (n+1)-ésimo debemos dividir el nodo interno y repartir
los punteros:
◦ Los primeros dn/2e) se quedan en el nodo existente.
◦ Las restantes pasan a un nuevo nodo.
• Al repartir los punteros de un nodo interno existe una clave que no está rodeada
por dos punteros.
• Esta clave será eliminada del nodo dividido y será propagada hacia el nodo padre,
que la insertará en el lugar adecuado.
• Esto puede provocar una división en el nodo padre, que se tratará de la misma
manera.
170
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Eliminación en un árbol B +
Se busca la clave a eliminar y se borra de la hoja correspondiente.
Esto puede provocar que la hoja resultante tenga un número de entradas inferior al de
la capacidad mı́nima.
Si el resultado de fusionar las dos hojas diese lugar a un nodo demasiado grande, en
lugar de fusionar se realizará una redistribución de hijos desde la hoja anterior.
Las fusiones de nodos provocan la eliminación de entradas en el nodo padre, que puede
quedar por debajo de la capacidad mı́nima. Se repite el mismo proceso en el padre.
Una tabla hash se compone de varios ”cajones” (buckets) con un tamaño fijo numerados
desde 0 hasta n − 1.
Se basan en la utilización de una función hash, que transforma una clave de búsqueda
en un número de 0 a n − 1 que indica el cajón donde se buscará el valor deseado.
Tipos:
Una función hash debe distribuir las claves de búsqueda uniformemente entre los dis-
tintos cajones.
Hashing estático
Búsqueda:
• Buscamos la clave K.
• Calculamos m = h(K).
• Búsqueda en el cajón m-ésimo.
• Ejemplo:
171
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
◦ Función hash: h(x) = x mod 4
◦ Si K = 25, h(25) = 1.
◦ La función resto reparte uniformemente las posiciones de las claves.
• Eficiencia:
◦ Para una tabla hash con un cajón por valor de la función hash (o pocos), las
operaciones de lectura tienen una complejidad cercana a θ(1).
◦ En cambio, para una tabla hash con listas largas de cajones por cada valor
de la función hash, las operaciones de lectura tienen una complejidad cercana
a θ(n).
Inserción:
• Buscar el cajón que le corresponde a una clave e insertarlo ahı́ (si es posible).
• ¿Qué hacer si el cajón está lleno?. Existen dos alternativas:
◦ Encadenamiento: enlazar el cajón lleno con otro (inicialmente vacı́o) e insertar
en él la nueva clave.
◦ Open hashing: colocar la clave en otro cajón distinto.
Inconvenientes del Hashing estático:
• El número de cajones iniciales es difı́cil de determinar. Un número inadecuado da
lugar a complejidades lineales (ineficiencia).
• Comenzar con un número demasiado elevado de cajones deperdicia memoria.
Hashing extensible
Idea clave: tener una función hash adaptable al tamaño de los datos que maneja.
Consiste en la combinación de una función hash con el truncamiento de su valor ex-
presado en binario. En la práctica tendremos una función hash variable.
b representa el números de bits tomados. Valores tı́picos: b = 32, b = 64.
Ejemplo: si h(x) = x mod 4, entonces h(27) = 3 = |{z}
11 .
binario
Estructura:
1. Una tabla de cajones (a modo de ı́ndice) asociada a un valor de K.
2. K: número de bits necesarios para direccionar los cajones (valor de la función
hash truncada). Este valor puede cambiar a lo largo de tiempo.
3. Un conjunto de cajones (o lista de cajones) que almacenan la información. Cada
cajón (o lista de cajones) posse un valor J que representa el número de bits reales
para su direccionamiento. Comparado con K permite insertar eficazmente.
172
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Todas las claves de un cajón poseen los últimos J bits iguales.
Búsqueda:
Inserción:
173
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 6.1: Estado inicial
174
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 6.2: Inserción del registro ”Einstein”
175
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 6.4: Inserción del registro ”Katz”
176
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 6.6: Inserción del registro ”Kim”
177
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
178
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Capı́tulo 7
Transacciones y control de la
concurrencia
7.1. Transacciones
Una transacción es una unidad lógica (atómica, indivisible) de trabajo en una base de
datos.
Ejemplos:
El lenguaje contiene primitivas para leer desde la BBDD en disco a la memoria principal
y para escribir desde la memoria principal a la BBDD.
• READ A: Lee el elemento A desde la BBDD a una variable temporal que también
se llamará A.
179
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• WRITE A: Escribe el valor de la variable temporal A en el elemento correspondiente
de la base de datos.
• A = expresión: Asigna a la variable que contiene el valor del elemento A el valor
indicado por la expresión.
Los elementos leı́dos y escritos son globales a todas las transacciones. Las variables
temporales son locales a cada transacción.
Durabilidad (Durability): Una vez realizada una transacción, sus cambios son perma-
nentes en la base de datos.
Observaciones:
180
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 7.1: Transiciones posibles entre los estados de una transacción
Una transacción que termina con éxito pasa a un estado de confirmación (commit). La
propiedad de permanencia exige que se proporcionen los mecanismos necesarios para
que los cambios sean permanentes.
Los efectos de una transacción finalizada no se pueden deshacer, salvo que se haga otra
transacción que realice el efecto contrario.
Sin embargo, la concurrencia es una herramienta demasiado valiosa como para renun-
ciar a ella: aumenta la eficiencia.
Plan de transacciones:
181
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Un plan de transacciones es una elección concreta del orden en que se realizan las
operaciones de un conjunto de transacciones.
Debe contener todas las operaciones de todas las transacciones involucradas.
Se debe respetar el orden de las instrucciones de cada transacción individual.
Sin embargo, es posible entremezclar instrucciones provenientes de transacciones dis-
tintas.
Consideremos las siguientes transacciones:
T1 :
READ A
A = A − 10
WRITE A
T2 :
READ A
A = A ∗ 2
WRITE A
Tiempo Acción
1 T1:READ A
2 T1:A = A - 10
3 T1:WRITE A
4 T2:READ A
5 T2:A = A * 10
6 T2:WRITE A
Tiempo Acción
1 T2:READ A
2 T2:A = A * 2
3 T2:WRITE A
4 T1:READ A
5 T1:A = A - 10
6 T1:WRITE A
Tiempo Acción
1 T2:READ A
2 T2:A = A * 2
3 T1:READ A
4 T1:A = A - 10
5 T2:WRITE A
6 T1:WRITE A
182
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Planes serializables
Un plan de transacciones se realiza en serie cuando todas las instrucciones de cada
transacción individual se ejecutan consecutivamente.
Ejemplo:
• Basados en bloqueos.
• Basados en timestamps.
• Aislamiento de instantáneas (snapshot isolation).
183
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Si una transacción Ti quiere acceder al candado de un elemento A, pero éste está en
posesión de otra transacción Tj, la transacción Ti deberá esperar a que Tj libere el
candado.
La liberación del candado asociado a A se realiza mediante la instrucción UNLOCK A.
Ejemplo: Consideremos las siguientes transacciones:
T1 :
LOCK A
READ A
A = A − 10
WRITE A
UNLOCK A
T2 :
LOCK A
READ A
A = A + 20
WRITE A
UNLOCK A
T1 T2
LOCK A
READ A
A = A - 10
WRITE A
UNLOCK A
LOCK A
READ A
A = A + 20
WRITE A
UNLOCK A
T1 T2
LOCK A
READ A
LOCK A (T1 tenı́a el candado sobre A)
READ A
A = A + 20
WRITE A
UNLOCK A
A = A - 20
WRITE A
UNLOCK A
184
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Bloqueos y serializabilidad
Los bloqueos realizados en T1 y T2 sólo permiten dos planes de transacciones:
Un poco de notación:
T2 :
LOCK A
UNLOCK A
T1 T2
LOCK A
UNLOCK A
LOCK A
UNLOCK A
Test de serializabilidad:
185
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Si el grafo no contiene ciclos, el plan es serializable. Realizando un recorrido en
el orden indicado por las aristas obtendremos un plan en serie equivalente al
analizado.
T1 T2 T3
LOCK A
LOCK B
LOCK C
UNLOCK B
LOCK B
UNLOCK A
LOCK A
UNLOCK C
UNLOCK A
LOCK A
LOCK C
UNLOCK B
UNLOCK C
UNLOCK A
T1 T2 T3
LOCK A
UNLOCK A
LOCK A
UNLOCK A
LOCK B
UNLOCK B
LOCK B
UNLOCK B
186
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Si todas las transacciones se adhieren a este protocolo, cualquier plan de transac-
ciones que respete los bloqueos es serializable.
• Ejemplos:
T1 :
LOCK A
READ A
A := A − 10
WRITE A
LOCK B
READ B
B := B + 10
WRITE B
UNLOCK A
UNLOCK B
Respeta el bloqueo.
T2 :
LOCK A
READ A
A := A − 10
WRITE A
UNLOCK A
LOCK B
READ B
B := B + 10
WRITE B
UNLOCK B
No respeta el bloqueo.
T3 :
LOCK A
LOCK B
READ A
A := A − 10
WRITE A
READ B
B := B + 10
WRITE B
UNLOCK A
UNLOCK B
Respeta el bloqueo.
187
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
◦ RLOCK A Ejecutada por una transacción que sólo quiere leer el elemento A.
Evita que otra transacción acceda al elemento A para escribir en él, pero per-
mite que otras transacciones puedan adquirir el candado RLOCK A simultánea-
mente.
◦ WLOCK A Obtención de un candado con el fin de leer y/o escribir en el elemento
A.
◦ UNLOCK A Libera el candado obtenido, independientemente de su tipo.
Conversiones de bloqueo:
T2 :
RLOCK B
READ B
UNLOCK B
Plan válido:
T1 T1
RLOCK A
RLOCK B
RLOCK B
UNLOCK B
WLOCK B
UNLOCK B
UNLOCK A
Plan no válido:
188
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
T1 T1
RLOCK A
RLOCK B
RLOCK B
WLOCK B
UNRLOCK B
UNLOCK B
UNLOCK A
Test de serializabilidad:
189
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Sirve para garantizar la serializabilidad de las transacciones que se ajusten a este
protocolo.
• Fase de adquisición: La transacción puede adquirir candados (RLOCK, WLOCK),
pero no liberarlos. También puede realizar promoción de sus candados.
• Fase de liberación: La transacción puede liberar candados, pero no puede adquirir
nuevos candados. También puede degradar los candados que ya haya obtenido.
• Una forma muy utilizada de generar las instrucciones de bloqueo automáticamente
en función de las operaciones de lectura y escritura consiste en utilizar la siguiente
estrategia:
◦ Antes de cada instrucción READ X, generar una instrucción RLOCK X.
◦ Antes de cada instrucción WRITE X, generar una instrucción WLOCK X.
◦ Al final de cada transacción se liberan todos los candados obtenidos.
• El resultado obtenido mediante esta estrategia respeta el protocolo de bloqueo en
dos fases.
• Ejemplo:
T1 :
READ A
READ B
B = 2∗A + B
WRITE B
se transforma en:
T1 :
RLOCK A
READ A
RLOCK B
READ B
B := 2∗A + B
WLOCK B
WRITE B
UNLOCK B
UNLOCK A
Modos de bloqueo:
• Añadir dos modos de bloqueo distintos nos permite que el gestor de bloqueos
permita mayor concurrencia, pero preservando la serializabilidad.
• Esto se ha conseguido relajando las reglas de bloqueo con respecto a la versión
anterior (LOCK):
◦ El gestor de bloqueos concede bloqueo de lectura de X a una transacción, si
no existe otra transacción que haya bloqueado X para escritura previamente.
◦ El gestor de bloqueos concede bloqueo de escritura de X si no existe otra
transacción que haya bloqueado X, bien para lectura, o bien para escritura.
• Esto permite ser expresado mediante la siguiente tabla de compatibilidades:
190
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Bloqueo en manos de una transacción existente
Lectura Escritura
Bloqueo solicitado Lectura Sı́ No
Escritura No No
• Esta idea puede generalizarse a otros tipos de bloqueos.
• Para poder aplicar el test de serializabilidad hemos de disponer de la tabla de
compatibilidad.
• Para generar esta tabla utilizamos el siguiente criterio:
Si una transacción T1 quiere bloquear un elemento para la operación X
y otra transacción T2 ya ha bloqueado dicho elemento para la operación
Z, el candado se concederá si las operaciones X y Z conmutan.
• Ejemplo. Supongamos que añadimos un nuevo tipo de bloqueo: ILOCK X. La
transacción que adquiera el candado correspondiente podrá incrementar el valor
de X de manera atómica.
Lectura Escritura Incrementar
Lectura Sı́ No No
Escritura No No No
Incrementar No No Sı́
Test de serializabilidad:
• En el grafo de transacciones se coloca un arco cuando T1 adquiere el bloqueo X
antes de que T2 adquiera el bloqueo Z, y la celda correspondiente de la tabla de
compatibilidad contiene el valor NO.
Concurrencia y granularidad:
• En algunos contextos es necesario bloquear varios elementos a la vez. Por ejemplo:
◦ Una consulta puede necesitar acceso a todos los registros de una tabla.
◦ Una actualización puede afectar a un subconjunto de filas de una tabla.
• El bloqueo individual de cada uno de los elementos resulta ineficiente.
• Existen mecanismos para definir múltiples niveles de granularidad en los bloqueos.
Protocolo de bloqueo en árbol:
• Sea:
A
B C
D E
191
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• El bloqueo en un elemento conlleva el bloqueo de sus descendientes.
◦ T2 no podrá bloquear ni A ni B.
• Esto implica, que cada vez que se quiera bloquear un determinado elemento, se
ha de comprobar que sus descendientes no estén bloqueados por otra transacción
(ineficiente).
• Matriz de compatibilidad:
• Ejemplo. Sea:
B C
D E F G
192
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
T1 T2 T3
WARN A
WARN A
WARN A
WARN B
LOCK C
LOCK D
UNLOCK C
UNLOCK D
UNLOCK A
UNLOCK B
LOCK B
WARN C
LOCK F
UNLOCK A
UNLOCK B
UNLOCK F
UNLOCK C
UNLOCK A
El plan es serializable.
Problemas con bloqueos:
• Inanición:
◦ Una transacción espera permanentemente que se libere el candado sobre un
elemento que otras transacciones ocupan.
◦ Existen varias soluciones. Una de ellas es utilizar una estrategia first-come-
first-served para la concesión de bloqueos.
• Interbloqueo:
◦ T1 y T2 esperan indefinidamente a que la otra transacción libere el bloqueo
que obtiene sobre el recurso:
T1 :
LOCK A
LOCK B
UNLOCK A
UNLOCK B
T2 :
LOCK B
LOCK A
UNLOCK B
193
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
194
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Capı́tulo 8
Procesamiento de consultas y
optimización
8.1. Introducción
Conceptos generales:
Los primeros sistemas basados en el modelo relacional tenı́an un rendimiento muy bajo
en las consultas.
En un sistema relacional:
195
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
2. Ejecutar dich estrategia.
2. Optimización.
3. Generación de código.
4. Ejecución.
Validación semántica: verificar la validez de los nombres de las tablas, vistas, columnas,
etc.
Ejemplo:
SELECT nombre FROM Empleado E , T r a b a j a e n T WHERE E . n s s = T . n s s e AND T . nump=2 ;
196
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Figura 8.1: Operaciones del álgebra relacional
Observaciones:
Ejemplo:
SELECT e . f i r s t N a m e , e . lastName , e . h i r e D a t e , d . deptName
FROM Emp e , Dept d WHERE e . d e p t I d= d . d e p t I d
AND ( e . h i r e D a t e > ’01 −SEP−07 ’ AND d . deptName LIKE ’ IT ’ ) ;
./e.deptId=d.deptId
Emp Dept
8.2.2. Optimización
El optimizador de consultas combina varias técnicas. Destacan las siguientes:
197
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
• Optimización heurı́stica: ordenar las operaciones de la consulta para incrementar
la eficiencia de su ejecución.
• Estimación de costes:
◦ Estimar sistemáticamente el coste de cada estrategia de ejecución.
◦ Elegir la estrategia de menor coste estimada.
Lenguajes como SQL permiten expresar una misma consulta de varias formas. El ren-
dimiento no deberı́a depender de cómo sea expresada la consulta.
• Búsqueda lineal.
• Búsqueda binaria
• Empleo del ı́ndice primario o clave de dispersión.
• La información estadı́stica.
• Información sobre la interdependencia entre las operaciones de bajo nivel.
Ejecutar primero las selecciones más restrictivas (las que producen menor número de
filas).
Combinar un producto cartesiano con una selección en un join cuya condición sea la
de la selección.
198
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
8.2.4. Reglas de transformación de expresiones
Las siguientes reglas nos permiten equivalencias entre expresiones para elegir la más
eficiente:
2. Una secuencia de proyecciones se puede reducir a una sola si ésta última aparece en
todas las demás:
3. Una selección de una proyección puede transformarse en una proyección de una selec-
ción:
Es una buena idea hacer una selección antes que una proyección pues la selección reduce
el tamaño de entrada de la selección.
199
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
πp (R1 ./ R2) = πP −R1 R1 ./ (πP −R1 (R2))
200
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.
Índice de figuras
201
a64b0469ff35958ef4ab887a898bd50bdfbbe91a-1600742
Reservados todos los derechos. No se permite la explotación económica ni la transformación de esta obra. Queda permitida la impresión en su totalidad.