Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Para poder crear y ejecutar una máquina virtual, es necesario un software especial encargado de llevar a
cabo la simulación. Actualmente, las herramientas más utilizadas para la creación y gestión de máquinas
virtuales son Virtual Box y VMware .
La herramienta VMware dispone de una versión gratuita con las características y funciones necesarias
para un usuario particular, tales como la creación de una máquina virtual, y una versión de pago
orientada a empresas que añade funciones y características más avanzadas tales como la posibilidad
de virtualizar sistemas operativos y gestionarlos a través de la red como si se tratase de una nube.
Por otro lado, Virtual Box es una herramienta de código abierto, totalmente gratuita y disponible para
cualquier sistema operativo, propiedad de Oracle. No ofrece las mismas características avanzadas
orientadas hacia las empresas de VMware, pero sí dispone de todas las funciones necesarias para crear y
ejecutar máquinas virtuales. E incluso dispone de algunas funcionalidades propias como la capacidad de
ejecutar varias máquinas virtuales a la vez.
Con respecto a la eficiencia y rendimiento, VMware presenta un rendimiento mejor que Virtual Box en
el uso de la memoria y de la CPU. Sin embargo, con respecto al rendimiento del disco duro ambas
herramientas son similares.
Durante esta unidad, se os enseña cómo descargar e instalar la versión 5.1.22. Sin embargo, es
aconsejable que os descarguéis la última versión disponible. En las explicaciones siguientes se utilizará
la versión para Windows —para el resto de sistemas operativos el proceso es similar—. En la página de
descargas, se pulsa sobre el enlace correspondiente al sistema operativo sobre el que se quiere instalar
—en este caso sobre Windows hosts— y comienza la descarga. Como no se que versión de MacOS
tienes, te lo pongo primero para las versiónes hasta el SIERRA, y después para del SIERRA para
adelante.
Una vez que se ha bajado el archivo ejecutable, se pulsa sobre el instalador para que comience la
ejecución del asistente.
Se da doble click cobre el archivo *.dmg
Una vez descargado Lubuntu, se va a realizar la creación de la máquina virtual. Para ello, se abre
Virtual Box pulsando sobre el icono que habrá en el escritorio, o bien en la lista de programas, o bien
sobre el archivo VirtualBox.exe que se encuentra en la carpeta de instalación C:\Program
Files\Oracle\VirtualBox. En la interface principal de Virtual Box, se pulsa sobre el icono “Nueva” para
crear una nueva máquina virtual. Como resultado, se abre el asistente.
En la siguiente ventana, se verifica que se ha seleccionado la opción de “Crear disco virtual ahora” y
se pulsa sobre “Crear”.
En la siguiente ventana, se elige el tipo de archivo que se desea utilizar para el disco duro virtual. Se
puede dejar la recomendación que indica el asistente y se pulsa sobre “Next”.
Al pulsar sobre “Crear”, aparece la ventana de Virtual Box actualizada con la máquina que se ha
configurado.
La máquina virtual aún no se ha creado, lo que se ha hecho es configurar las características de la
máquina. Antes de crear la máquina es necesario configurar algunas más, lo cual se realiza
seleccionando la máquina y pulsando sobre el enlace “Configuración” que genera la ventana mostrada.
En esta ventana, se pulsa sobre el icono “Almacenamiento” y aparece la pestaña que se muestra
En esta pestaña, se pulsa en el icono “CD” del cuadro “Árbol de almacenamiento” del “Controlador:
IDE” que aparece vacío.
En el cuadro “Atributos”, se pulsa sobre el icono del “CD” y aparece una lista desplegable. Se
selecciona “Seleccione archivo de disco óptico virtual…”
Aparece un navegador de archivos y se selecciona el archivo de “Lubuntu” que se ha descargado
previamente.
A continuación, se pulsa sobre “OK” para volver a la interface principal de Virtual Box en la que se
puede observar que se ha actualizado el cuadro almacenamiento (figura 1.26.).
Ahora, se va a crear el sistema virtualizado. Desde la pantalla principal, se pulsa sobre el icono de
“Iniciar” para que se cargue el sistema. Aparecerán diferentes mensajes y pantallas de instalación. Son
mensajes similares a los que se mostrarían si se estuviera instalando realmente el sistema operativo.
Estos mensajes solo aparecerán la primera vez que se cargue el sistema virtualizado, no lo harán en las
restantes ocasiones.
Se selecciona “Instalar Lubuntu”.
Se selecciona el idioma.
Se seleccionan paquetes de software adicional para su instalación.
Y el tipo de instalación.
Se pulsa sobre “Continuar” en la pantalla que aparece a continuación.
Se configura el usuario .
Se realiza la instalación de Lubuntu.
La próxima vez que se quiera ejecutar el sistema virtual bastará con seleccionar la máquina virtual y
pulsar sobre “Iniciar” en la pantalla principal de Virtual Box.
• OSBoxes, http://www.osboxes.org/
• VirtualBoxes, https://virtualboxes.org/
Para ilustrar cómo cargar una máquina virtual, es posible descargar una de una distribución de
Lubuntu desde el siguiente enlace:
SourceForge, https://sourceforge.net/projects/virtualimages/files/Lubuntu/
Una vez descargada, se importa en Virtual Box. Para ello, se selecciona en el menú la opción:
“Archivos”> “Importar Servicio Virtualizado” y se selecciona la máquina virtual que se ha descargado.
A continuación, se selecciona la máquina virtual que se quiere importar.
Una vez importada la máquina virtual, debería aparecer en la parte de la izquierda de la pantalla una
nueva máquina virtual de nombre Lubuntu13-4.
Se pulsa sobre Lubuntu 13-4 y se selecciona la opción de “Configuración”.
A continuación, se selecciona en “Sistema” la opción “Placa Base” para fijar la cantidad de memoria
de la máquina virtual. Dependiendo de la memoria RAM que tenga el ordenador que se está usando, se
puede aumentar o disminuir el valor. 512 Mb deberían ser suficientes, pero se recomiendan 1024 Mb
para que esta funcione con fluidez.
Se selecciona la opción “Pantalla” y, en esta pestaña, se ajusta la cantidad de memoria para la tarjeta
gráfica: 32 Mb deberían ser suficientes.
Para ilustrar los contenidos de esta sección, se va utilizar una distribución de Linux denominada
Lubuntu que se caracteriza por exigir pocos recursos hardware para su ejecución. Linux dispone de una
aplicación denominada intérprete de comandos o Shell de comandos que permite interactuar al usuario
con el sistema operativo mediante la ejecución de comandos o sentencias.
Hay diferentes tipos de intérpretes que se diferencian en la sintaxis de los comandos y en la forma de
interaccionar con el usuario. Para acceder al intérprete de comandos, se pulsa sobre Ctrl+Alt+T o bien
se pulsa en un icono que aparece en la parte inferior izquierda, dentro de la barra de herramientas
inferior del escritorio de Lubuntu.
Algunas características generales son:
El terminal muestra en pantalla un indicador de línea de órdenes esperando que el usuario
introduzca una. El indicador finaliza con un carácter $ en el caso de usuarios normales y con #
en el caso del superusuario.
Al comienzo de la línea de órdenes aparece el usuario de la forma usuario@nombre: ~$ (figura
1.61.)
Cuando se escribe un comando para que se ejecute, hay que pulsar la tecla “Enter”.
Los comandos hay que teclearlos exactamente. En este sentido, las letras mayúsculas y
minúsculas se consideran caracteres diferentes.
El terminal siempre está dentro de una carpeta específica y puede navegar hasta otras carpetas
y gestionar los archivos. Siempre se abre desde la carpeta personal del usuario.
Comandos principales
Cambio de directorio
El comando borra uno o más directorios del sistema siempre que estos subdirectorios estén vacíos. La
sintaxis es rmdir subdir1 donde subdir es el nombre del directorio que se va a eliminar .
La sintaxis del comando es cp file1 file2 donde file1 y file2 indican el nombre de un archivo o la ruta
al mismo. Su ejecución hace una copia de file1 y lo llama file2. Si file2 no existía, lo crea con los
mismos atributos de file1 y en caso de existir su contenido es sustituido por el de file1. El archivo file2
estará en el mismo directorio que file1.
También se puede usar como cp file1 file2 namedir que hace copias de file1 y file2 en el directorio
namedir.
La sintaxis es mv file1 file2 y realiza la misma función que cp, pero eliminando el archivo original.
Desde la visión del usuario, se cambia el nombre a file1 por file2.
Si los nombres que aparecen son de directorios, entonces el comando mv namedir1 namedir2 cambia
el nombre del subdirectorio namedir1 por namedir2.
mv file1 file2 namedir traslada uno o más archivos (file1, file2, etc.) al directorio namedir
conservando el nombre.
El comando rm elimina uno o más archivos de un directorio en el cual tengamos permiso de escritura.
La sintaxis es rm file1 file2. En el comando, se pueden utilizar los caracteres de sustitución * y ?
Si se usa la opción -i, se pide confirmación para borrar cada archivo de la lista especificada: rm -i
file1 file2.
Un mismo archivo puede estar repetido con más de un nombre. También es posible tener un mismo
archivo con varios nombres distintos y poder acceder a él desde más de un directorio. Esto último se
denomina enlaces múltiples a un archivo y la forma de crearlo es mediante el comando ln: ln file1
file2.
De esta forma el archivo file1 tiene dos nombres: file1 y file2. Además, este comando advierte
previamente si el nombre file2 está ocupado y en este caso no se ejecuta. En el siguiente ejemplo se crea
un enlace al archivo Ejemplo.abw.
Los archivos enlazados a otro se borran como los archivos normales, de manera que si se borra el
archivo original permanece su contenido en los archivos enlazados.
Mediante el comando file se puede obtener información acerca de un archivo: file fich
En Linux, los archivos tienen asociados permisos que indican las operaciones que le está permitido
realizar a un usuario sobre los mismos. Los permisos de cada archivo se pueden ver con el
comando ls -l. Para cambiar los permisos de un archivo se emplea el comando chmod [quien] oper,
permiso, files donde:
Quien:
Indica a quién afecta el permiso que se desea cambiar. Es una combinación de las letras u para el
usuario, g para el grupo del usuario, o para los otros usuarios, y a para todos los anteriores. Si no se
indica nada, se supone a.
Oper:
Indica si el permiso se da usando un + o se quita usando un -.
Permiso:
Indica el permiso que se quiere dar o quitar. Es una combinación de las
letras: r (leer), w (escribir), x (ejecutar). Estos permisos son diferentes cuando se aplican a
directorios: r da la posibilidad de ver el contenido del directorio con el comando ls; el permiso w da la
posibilidad de crear y borrar archivos en ese directorio; el permiso x autoriza a buscar y utilizar un
archivo concreto.
Files:
Nombres de los archivos o directorios cuyos modos de acceso se quieren cambiar.
En el siguiente ejemplo, se cambian los permisos al archivo Ejemplo.abw
Solo lo puede emplear el actual propietario de los mismos. Los nombres de propietario se encuentran
almacenados en el archivo /etc/passwd
El comando chgrp se emplea para cambiar el grupo al que pertenece un archivo: chgrp newgroup
file1 file2... Los grupos de usuarios están almacenados en el archivo /etc/group.
El comando cat filename permite visualizar el contenido de uno o más archivos de forma no
formateada y también permite copiar uno o más archivos como apéndice de otro ya existente:
cat filename: saca por pantalla el contenido del archivo filename.
cat file1 file2…: saca por pantalla, secuencialmente y según el orden especificado, el
contenido de los archivos indicados.
cat file1 file2 >file3: El contenido de los archivos file1 y file2 es almacenado en file3.
cat file1 file2 >>file3: el contenido de file1 y file2 es añadido al final de file3.
cat >file1: Acepta lo que se introduce por el teclado y lo almacena en file1 (se crea file1). Para
terminar, se emplea <ctrl>d
Alternativamente, se puede usar el editor vi. El editor puede encontrarse en dos estados o modos:
En el modo de comandos, vi está esperando alguna orden (por tanto, interpreta lo que se
escribe como órdenes).
En el modo de edición, vi está esperando que se escriba el texto del fichero (por tanto,
interpreta lo escrito como texto).
Cuando se entra en vi, está en modo de comandos. Para pasar al modo de edición, se puede pulsar i
(insertar), a (añadir), o (añadir una línea). Para pasar al modo de comandos, se puede pulsar Escape o
Suprimir.
Algunos comandos de vi son:
i insertar antes del cursor
a añadir detrás del cursor
o añadir una línea en blanco
x borrar un carácter
j borrar el final de línea (une dos líneas)
dd borra la línea completa
u deshacer la última edición
:q salir
:q! salir sin guardar
:w guardar
:wq guardar y salir
:set nu muestra números de línea
:set nonu oculta números de línea
Los comandos more y less permiten visualizar un archivo pantalla a pantalla. El número de líneas por
pantalla es de 23 de texto más una última línea de mensajes, donde aparecerá la palabra more. Cuando
se pulsa la barra espaciadora se visualizará la siguiente pantalla. Para salir de este comando se
pulsa <ctrl>d o q. La sintaxis es more file.
El comando less permite el desplazamiento a lo largo del texto empleando las teclas de cursores
pudiendo ir hacia arriba o abajo de un archivo. La sintaxis es less file.
El comando grep 'conjuntocaracteres' file1 file2 file3 busca una palabra, clave o frase en un
conjunto de directorios, indicando en cuáles de ellos la ha encontrado. Busca archivo por archivo, por
turno, imprimiendo aquellas líneas que contienen el conjunto de caracteres buscado. Si el conjunto de
caracteres está compuesto por dos o más palabras separadas por un espacio, se escribe entre apóstrofes '.
El comando lpr nombre_archivo imprime por defecto el archivo indicado. Si se usa sin argumentos
imprime el texto que se introduzca a continuación en la impresora.
El comando tar -cvf nombre_archivo.tar archivo1 archivo2… agrupa varios archivos en uno solo
archivo tar. Con gzip archivo se comprime archivo (que es borrado) y se crea un archivo con nombre
archivo.gz.
Se pueden realizar las operaciones inversas, de manera que se pueden extraer los archivos mediante tar -
xpvf nombre_archivo.tar archivo1… y descomprimir un archivo mediante gzip -d archivo.gz.
Dado que suele emplearse tar y gzip de forma consecutiva obteniéndose archivos con extensión tar.gz o
tgz, entonces tar incluye la opción z para extraer archivos con esta extensión tar -zxf archivo.tar.gz.
Los comandos tienen una entrada estándar (número 0) y dos salidas estándar (número 1 para la salida
normal y número 2 para la salida con errores). Por defecto, la entrada y la salida estándar de un
comando es la terminal, a no ser que el comando especifique los nombres de archivos que hagan de
entrada y de salida, como por ejemplo el comando cp file1 file2.
Sin embargo, se puede redirigir la salida de un comando usando los operadores:
(>) redirige la salida estándar hacia el archivo indicado y en caso de no existir se crea.
(<) redirige la entrada estándar desde un determinado archivo.
(>>) redirige la salida estándar hacia otro archivo, pero añadiendo dicha salida al final de ese
archivo, sin sobrescribir el contenido original.
Por ejemplo:
date >>archivo el archivo archivo contendrá información sobre todas las veces que se ha
entrado en el sistema.
cat file1 file2 >file3 añade al archivo file2 al final de file1 y al conjunto lo llama file3.
cat file2 >>file1 realiza la misma operación que el anterior, pero al resultado lo llama file1.
Una tubería (|) permite comunicar la salida estándar de un comando con la entrada estándar de otro.
Por ejemplo, ls | mail juan envía a juan una lista de los archivos del sistema. Con el operador de tubería
se pueden empalmar tantos comandos como se desee.
Permite redirigir la salida de un comando a un determinado archivo y que también se bifurque hacia
la terminal. Para ello se usa el operador tee,como por ejemplo ls | tee file, que muestra la salida por el
terminal y además la envía al archivo file. En este ejemplo, si se quiere que la salida se añada al final de
file, se usaría la opción -a: ls | tee -a file.
Los mensajes de error se dirigen a la salida número 2, que normalmente es también la terminal. En
algunos casos puede interesar redirigir estos mensajes a otra salida como, por ejemplo, cuando se
ejecuta un programa en segundo plano.
Creación de scripts
Un guión o script es un archivo de texto que contiene comandos de la Shell que se interpretarán cuando
se ejecute el script.
Se caracterizan por:
Pueden tener cualquier nombre.
El archivo debe tener permiso de ejecución.
Para ejecutarlo se debe indicar el nombre del intérprete y el nombre del guión.
Las instrucciones del guión se procesan por orden, una por línea, de manera que los saltos de
línea se interpretan como un “INTRO”.
Las órdenes podrían aparecer en una misma línea separadas por punto y coma.
Los guiones pueden tener una línea inicial que indica el tipo de intérprete que se quiere utilizar para
ejecutar los comandos.
Por ejemplo #!/bin/bash indica que debe usarse el intérprete Bourne-Again Shell.
Asimismo, un guión puede contener comentarios que se marcan con el carácter # al inicio del texto
del comentario.
Variables y parámetros
Para definir una variable se usa la estructura variable=valor donde variable es el nombre de la misma.
Hay que tener en cuenta lo siguiente:
1.No puede haber un espacio entre el nombre de la variable, el signo = y el valor.
2.Si se desea que el valor contenga espacios, es necesario utilizar comillas.
3.Para recuperar el valor de una variable hay que anteponerle a su nombre el carácter $. Por
ejemplo, para visualizar el valor de una variable echo $variable.
En el siguiente ejemplo, se define la variable Prueba=”ls -l” y a continuación se invoca con $Prueba
Para eliminar una variable, se usa el comando unset. Por ejemplo:
Existen algunas variables definidas en la Shell. En la siguiente tabla se muestran las principales
variables.
La orden shift mueve todos los parámetros una posición a la izquierda, esto hace que el contenido del
parámetro $1 desaparezca y sea reemplazado por el contenido de $2, $2, que es reemplazado por $3, etc.
Además, existen algunas variables especiales tales como $# que contienen el número de parámetros que
ha recibido el script, y $* o $@ contienen todos los parámetros recibidos.
$var o ${var}
${var=val}
Valor de var si está definida, si no val y el valor de var pasa a ser val.
${var?message}
Devuelve $var si está definida y si no, imprime el mensaje en el terminal del Shell. Si el mensaje está
vacío imprime uno estándar.
${val+var}
Devuelve $val, si está var definida, si no, nada.
El siguiente ejemplo muestra cómo podemos usar una variable, asignándole un valor en caso de que
no esté definida.
Arrays
Un array es una colección de elementos del mismo tipo, dotados de un nombre, y que se almacenan
en posiciones contiguas de memoria.
No hay un tamaño límite para un array y la asignación de valores se puede hacer de forma alterna.
Estructuras de control
Indica que determinadas órdenes solo se ejecuten cuando se cumplan unas condiciones concretas.
Para ello, se utilizan las estructuras if o case.
Estructura IF
if [expresión]
then
órdenes a ejecutar si se cumple la condición
elif [expresión]
then
órdenes a ejecutar si se cumple la condición
else
órdenes a ejecutar en caso contrario
fi
Por ejemplo:
if grep -q set prueba.bash
then
echo encontrada la palabra clave set
else
echo no encontrada la palabra clave set
fi
Estructura case
case $var in
v1) … #Acción a realizar si var toma el valor v1
;;
v2|v3) …#Acción a realizar si var toma el valor v2 o v3
;;
*) …# Caso por defecto
;;
Esac
Por ejemplo:
case $var in
1) echo La variable var es un uno
;;
2) echo La variable var es un dos
;;
*) echo La variable var no es ni un uno ni un dos
;;
esac
BUCLES
Permite ejecutar bloques de órdenes de forma iterativa dependiendo de una condición. Para ello se
utilizan las estructuras if o case.
WHILE
until [ expresión ]
# Mientras la expresión sea falsa ...
do ...
done
FOR
for var in lista#Por cada valor en la estructura lista se ejecuta una iteración.
do
órdenes a ejecutar
done
Por ejemplo:
for i in 10 30 70
do
echo Mi número favorito es $i
done
Break y continue
Una orden interna del Shell es una orden que el intérprete implementa y que ejecuta sin llamar a
programas externos.
Echo
Envía una cadena a la salida estándar.
Read
Lee una cadena de la entrada estándar.
La orden read puede leer diferentes variables a la vez. También se puede combinar el uso de read con
echo para mostrar un prompt que indique qué es lo que se está pidiendo.
Hay una serie de caracteres especiales para usar en echo y que permiten posicionar el cursor en un
sitio determinado:
_ nb: retrocede una posición (sin borrar)
_ nf: alimentación de página
_ nn: salto de línea
_ nt: tabulador
Para que echo reconozca estos caracteres es necesario utilizar la opción .-e. y utilizar comillas dobles:
$ echo -e "Hola \t ¿cómo estás?"
hola como estás
True y false
Devuelven 0 y 1 siempre, respectivamente. El valor 0 se corresponde con true y cualquier valor
distinto de 0 con false.
La orden test
Test es una orden que permite evaluar si una expresión es verdadera o falsa. Se usan en la estructura
if/then/else/ para determinar qué parte del script se va a ejecutar.
La sintaxis de test puede ser una de las dos que se muestran a continuación:
test expresión
[ expresión ]
Algunos operadores que pueden aparecer en las condiciones a evaluar:
Operadores para números
-eq Igual a
-ne Distinto de
-n cadena
o
Verdad si la longitud de cadena no es cero
cadena
cadena1 == cadena2 Verdad si las cadenas son iguales. Se puede emplear = en vez de ==
Operadores lógicos
-o OR
-a AND
! NOT
Paréntesis
\(
izquierdo
\) Paréntesis derecho
Funciones
Declaración
Por ejemplo:
Ejemplo 3. Guión que borra con confirmación todos los archivos indicados como argumentos en la
línea de comandos.
#!/bin/bash
while test "$1" != ""
do
rm -i $1
shift
done
Ejemplo 4. Guión que evalúa la extensión de un archivo. Si esta se corresponde con .txt., copia el
archivo al directorio ~/copias. Si es otra la extensión presenta un mensaje.
case $1 in
*.txt)
cp $1 ~/copias/$1
;;
*)
echo "$1 extensión desconocida"
;;
Esac
Ejemplo 5. Guión que pone el atributo de ejecutable a los archivos pasados como argumento.
for fich in $@
do
if test -f $fich
then
chmod u+x $fich
fi
done
Ejemplo 6. Guión que lee dos números del teclado e imprime su suma.
#!/bin/bash
echo "Introduzca un número \n"
read numero1
echo "Introduzca otro número \n"
read numero2
let respuesta=$numero1+$numero2
echo "$numero1 + $numero2 = $respuesta \n"
Caso práctico
Se pide crear un script que muestre el siguiente menú:
Ver directorio actual...........[1]
Copiar archivos.................[2]
Editar archivos.................[3]
Imprimir archivo................[4]
Salir del menú..................[5]"
Donde:
Si elige la primera opción, se mostrarán los archivos del directorio actual.
Si elige la segunda opción, se le pedirá el nombre del archivo que se quiere copiar y el nombre
del archivo donde se quiere copiar.
Si elige la tercera opción, se le pedirá el nombre del archivo que se desea editar y se abrirá el
editor vi para editarlo.
Si elige la cuarta opción, se le pedirá el nombre del archivo que se desea imprimir y se
imprimirá el mismo.
Si elige la quinta opción, se saldrá del script.
SOLUCION
while true
do
clear
echo "
Ver directorio actual...........[1]
Copiar ficheros.................[2]
Editar ficheros.................[3]
Imprimir fichero................[4]
Salir del menú..................[5]"
read i
case $i in
1) ls -l|more; read z
;;
2) echo "Introduzca [desde] [hasta]"
read x y
cp $x $y
read x
;;
3) echo "¿Nombre de fichero a editar?"
read x;
vi $x
;;
4) echo "¿Nombre de fichero a imprimir?"
read x
lpr $x
;;
5) clear; break
;;
esac
done
El lenguaje Python y el entorno Jupyter
Notebook
El lenguaje de programación Python
Python es un lenguaje de programación de alto nivel creado por Guido van Rossum. Se desarrolla como
un proyecto de código libre, de manera que existe una comunidad de desarrolladores que mantienen el
lenguaje, gestionan las versiones del mismo y crean librerías para aumentar su funcionalidad.
Algunas de sus características son:
Es un lenguaje interpretado, por lo que no se debe compilar el código antes de su ejecución.
Es multiparadigma. En este sentido, permite varios estilos de programación: imperativo,
orientado a objetos y funcional.
Es multiplataforma. Python es un lenguaje disponible en los principales Sistemas Operativos
(Windows, Linux y Mac).
Posee un tipado dinámico. El tipo de los datos es inferido en tiempo de ejecución, de manera
que no es necesario declarar el tipo de sus variables y permite conversiones dinámicas de los
tipos de los datos.
En comparación con otros lenguajes de programación, Python es un lenguaje simple, fácil de leer y
escribir y simple de depurar. Por estas razones es fácil de aprender, de manera que la curva de
aprendizaje es corta.
Asimismo, Python cuenta con una gran cantidad de librerías, tipos de datos y funciones incorporadas en
el propio lenguaje, lo que le dota de una gran capacidad de procesamiento. En particular, es
ampliamente utilizado en el ámbito del análisis de datos y, en general, en tareas de procesamiento de
ciencias e ingeniería.
El entorno Jupyter notebook
Se trata de un entorno de edición y ejecución visual que permite integrar trozos de códigos con
contenidos multimedia o textuales que ayudan a documentar y facilitar la comprensión de los programas
realizados. Los documentos generados se visualizan con un navegador (Explorer, Chrome, Firefox...) y
pueden incluir cualquier elemento accesible a una página web, además de permitir la ejecución de
código escrito en el lenguaje de programación Python.
Jupyter contiene todas las herramientas científicas estándar de Python que permiten realizar tareas
propias en el contexto del análisis de datos: importación y exportación, manipulación y transformación,
visualización, etc.
Para instalarlo, lo mejor es el entorno Anaconda, el cual incluye un conjunto de herramientas de
desarrollo para Python, entre las que se encuentra el Jupyter Notebook. Anaconda se puede descargar
desde la página web de Anaconda.1 En la zona de descargas, aparecen dos versiones. Se debe bajar la
versión 3.x .
Título del notebook. Cada notebook tiene un título asociado. Por defecto, aparece con el
nombre Untitled. Para modificarlo, basta pulsar sobre Untitled y aparece una ventana en la que
se puede modificar el nombre.
Menús y Barra de herramientas. En la parte superior de la interface del notebook, aparece un
conjunto de menús con diferentes opciones para gestionar los archivos, para editar, visionar, etc.
Iconos de acceso rápido. Iconos que permiten realizar las acciones más comunes sobre los
elementos del notebook.
Celdas. La unidad de edición de un notebook son las celdas. Cada celda contiene código
Python o la información que documenta dicho código. En este sentido, un notebook es una
secuencia de celdas. Las celdas pueden ser de diferentes tipos según el contenido que almacenan:
Markdown: permite escribir texto formateado con el objetivo de documentar. Se usa el
lenguaje de marcas Markdown.
Raw NBConvert: son celdas que permiten escribir fragmentos de código sin que sean
ejecutados.
Heading: permite embeber código html.
Code: sirven para escribir código Python ejecutable. Están marcadas por la palabra In
[n] y están numeradas. El resultado de la ejecución de cada celda se muestra en el
campo Out[n], también numerado.
Todas las celdas son susceptibles de ser ejecutadas. La ejecución de una celda de código Python
ejecutará el código escrito en la celda y producirá una salida. La ejecución de celdas de tipo Markdown
dará formato al texto. Para ejecutar una celda, hay que colocarse en la celda y, posteriormente, pulsar el
botón cuyo icono es un triángulo mirando a la derecha
.
De igual forma para interrumpir la ejecución, se pulsa sobre el cuadrado. Para crear celdas nuevas, se
pulsa sobre el botón con el icono del signo +.
El flujo normal de edición de una celda consiste en:
Elegir el tipo de celda. Por defecto, son de tipo Code. Dependiendo del tipo de celda elegido,
Jupyter lo interpretará de diferente manera.
Una vez introducido el código o texto en la celda, se debe ejecutar. Para ello, se pulsa sobre el
icono en forma de flecha.
A continuación, se genera una nueva celda para editar.
Por ejemplo, si se quiere crear una celda que contenga la función: def multiplica(a,b): return a*b y
después invocarla con los valores 3 y 4, se haría como se muestra en la figura 2.10.
Elementos básicos de Python
Variables
Por ejemplo:
Una sentencia
de asignación
crea variables nuevas y las asocia a valores.
Es necesario llamar la atención sobre el hecho de que, antes de poder actualizar una variable, se debe
inicializar mediante una asignación. A continuación, se puede actualizar la variable aumentándola
(incrementar) o disminuyendo (decrementar).
Palabras reservadas
Los operadores son símbolos especiales que representan cálculos, como la suma o la multiplicación. Los
valores a los cuales se aplican esos operadores reciben el nombre de operandos. Los principales
operadores sobre los tipos int y float son:
i+j suma
i-j resta
i*j multiplicación
i/j división de dos números. Si son enteros, el resultado es un entero, y si son reales, el
resultado es un real
i//j cociente de la división entera
i%j resto de la división entera
i**j que representa i elevado a la potencia j
i==j que representa i igual que j
i!=j que representa i distinto que j
i>j que representa i mayor que j, y de forma similar: >=, <, <=
Se pueden usar los operadores con las cadenas.
Pero existen algunas particularidades cuando se usan los operadores sobre las cadenas.
Por ejemplo:
Expresiones
Un valor, por sí mismo, se considera una expresión y también lo es una variable.
Las expresiones tienen un tipo. Así, por ejemplo, 6 + 7 es una expresión que representa un
entero. Cuando en una expresión aparece más de un operador, el orden de evaluación depende de
las reglas de precedencia. Para los operadores matemáticos, Python sigue las convenciones
matemáticas:
El orden de los operadores es: paréntesis, exponenciales, multiplicación/división,
suma/resta.
Cuando existe la misma precedencia, se evalúa de izquierda a derecha.
Comentarios
En Python comienzan con el símbolo #, de forma que todo lo que va desde # hasta el final de la línea es
ignorado y no afecta al programa.
En el ejemplo anterior, el comentario aparece como una línea completa, pero también pueden ponerse
comentarios al final de una línea.
Entrada de información
Python proporciona una función llamada input que recibe la entrada desde el teclado, de forma que
cuando se llama el programa se detiene y espera a que el usuario escriba algo. Cuando el usuario pulsa
“Intro”, el programa continúa y la función devuelve como una cadena aquello que el usuario escribió.
Antes de recibir
cualquier dato
desde el usuario, es mejor escribir un mensaje explicando qué debe introducir. Se puede pasar una
cadena a input, que será mostrada al usuario antes de que el programa se detenga para recibir su entrada.
La secuencia \n al final del mensaje representa un newline, que es un carácter especial que provoca un
salto de línea. Por eso, la entrada del usuario aparece debajo del mensaje. Si se espera que el usuario
escriba un entero, puedes intentar convertir el valor de retorno a int usando la función int (), pero si el
usuario escribe algo que no sea una cadena de dígitos, obtiene un error.
Expresiones booleanas
Una expresión booleana es aquella que puede ser verdadera (True) o falsa (False). True y False son
valores especiales que pertenecen al tipo bool (booleano).
Los ejemplos siguientes usan el operador ==, que compara dos operandos y devuelve True si son iguales
y False en caso contrario.
Los principales operadores booleanos son:
x == y # x es igual que y.
x != y # x es distinto de y.
x > y # x es mayor que y.
x < y # x es menor que y.
x >= y # x es mayor o igual que y.
x <= y # x es menor o igual que y.
x is y # x es lo mismo que y.
x is not y # x no es lo mismo que y.
not representa la negación.
and cierto si las dos expresiones que relaciona son ciertas y falso en caso contrario.
or falso si las dos expresiones que relaciona son falsas y cierto en caso contrario.
Por ejemplo:
x >0 and x <10 es verdadero solo cuando x es mayor que 0 y menor que 10.
n%2 == 0 or n%3 == 0 es verdadero si el número es divisible por 2 o por 3.
not (x>y) es verdadero si x es menor o igual que y.
Hay que tener en cuenta que cualquier número distinto de cero se interpreta como “verdadero”.
Estructuras de control
Condicionales
Las expresiones condicionales facilitan la codificación de estructuras que bifurcan la ejecución del
código en varias ramas o caminos de ejecución. Existen varias formas.
If simple
Tiene la estructura:
if expresión booleana:
ejecutar código
Ahora bien, es preciso observar que:
La expresión booleana después de la sentencia if recibe el nombre de condición. La sentencia
if se finaliza con un carácter de dos puntos (:) y la/s línea/s que van detrás de la sentencia if van
indentadas. Este código se denomina bloque.
Si la condición lógica es verdadera, la sentencia indentada será ejecutada. Si la condición es
falsa, la sentencia indentada será omitida.
No hay límite en el número de sentencias que pueden aparecer en el cuerpo, pero debe haber al
menos una. A veces puede resultar útil tener un cuerpo sin sentencias, usándose en este caso la
sentencia pass, que no hace nada.
Bucles
Proceso:
Se inicializan una o más variables antes de que el bucle comience.
Se realiza alguna operación con cada elemento en el cuerpo del bucle, posiblemente cambiando
las variables dentro de ese cuerpo.
Se revisan las variables resultantes cuando el bucle se completa.
Existen varias formas:
WHILE
El primer tipo de bucle es el while. El cuerpo del bucle debe cambiar el valor de una o más variables, de
modo que la condición pueda en algún momento evaluarse como falsa y el bucle termine. La variable
que cambia cada vez que el bucle se ejecuta y controla cuándo termina este, recibe el nombre de
variable de iteración. Si no hay variable de iteración, el bucle se repetirá para siempre, resultando así un
bucle infinito. Cada vez que se ejecuta el cuerpo del bucle se dice que se realiza una iteración. Tiene la
siguiente estructura:
En este ejemplo, el bucle nunca se ejecuta cuando x=0 y nunca terminará si empieza con x<0.
Es preciso observar que, a veces, no se sabe si hay que terminar un bucle hasta que se ha recorrido la
mitad del cuerpo del mismo. En ese caso, se puede crear un bucle infinito a propósito y usar la sentencia
break para salir explícitamente cuando se haya alcanzado la condición de salida.
Algunas veces, estando dentro de un bucle se necesita terminar con la iteración actual y saltar a la
siguiente de forma inmediata. En ese caso se puede utilizar la sentencia continue para pasar a la
siguiente iteración sin terminar la ejecución del cuerpo del bucle para la actual.
FOR
El siguiente tipo de bucle es el for. Se repite a través de un conjunto conocido de elementos, de modo
que ejecuta tantas iteraciones como elementos hay en el conjunto. Es útil utilizar la función range para
crear una secuencia. Range puede tomar uno o dos valores:
Si toma dos valores, genera todos los enteros desde la primera entrada hasta la segunda
entrada-1. Por ejemplo: range (2, 5) = (2, 3, 4).
Y si toma un solo parámetro, entonces range(x) = range(0,x).
Tiene la siguiente estructura:
for variable in secuencia:
código
Estructuras de datos
Tuplas
Una tupla es una secuencia de valores de cualquier tipo indexada por enteros. Las tuplas son inmutables
—tienen una longitud fija y no pueden cambiarse sus elementos— y son comparables. Sintácticamente,
una tupla es una lista de valores separados por comas y encerradas entre paréntesis.
Para crear una tupla con un único elemento, es necesario incluir una coma al final.
Otra forma de construir una tupla es usar la función interna tuple que crea una tupla vacía si se invoca
sin argumentos, y si se le proporciona como argumento una secuencia (cadena, lista o tulpa) genera una
tupla con los elementos de la secuencia.
No se pueden modificar los elementos de una tupla, pero se puede reemplazar una tupla por otra.
Se comienza comparando el primer elemento de cada secuencia. Si es igual en ambas, pasa al siguiente
elemento, y así sucesivamente, hasta que encuentra uno que es diferente. A partir de ese momento, los
elementos siguientes ya no son tenidos en cuenta.
Listas
Una lista es una secuencia de valores de cualquier tipo que reciben el nombre de elementos.
Creación
El método más simple para crear una lista es encerrar los elementos entre corchetes.
Asignación
La asignación de valores a una lista no retorna nada, sin embargo, si se usa el nombre de la lista, es
posible ver el contenido de la variable.
Listas vacías
Una lista que no contiene elementos recibe el nombre de lista vacía —se crea con unos corchetes vacíos
[]—.
Acceso a elementos
Para acceder a los elementos de una lista, se usa el operador corchete que contiene una expresión que
especifica el índice —los índices comienzan por 0—. Los índices de una lista se caracterizan por:
Cualquier expresión entera puede ser utilizada como índice.
Si se intenta leer o escribir un elemento que no existe, se obtiene un IndexError.
Si un índice tiene un valor negativo, se cuenta hacia atrás desde el final de la lista.
Listas mutables
Las listas son mutables, puesto que su estructura puede ser cambiada después de ser creadas.
Tipo de elementos
Los elementos en una lista no tienen por qué ser todos del mismo tipo.
Anidación
Cuando una lista está dentro de otra, se dice que está anidada. En una lista anidada, cada lista interna
solo cuenta como un único elemento.
Soporta indexación con números negativos que permite seleccionar por el final de la lista.
6.2.1. Operadores y
Operadores y funciones
El operador in se puede usar para recorrer los elementos de una lista usando un bucle for, como por
ejemplo:
El operador (slice) cuya sintaxis es [inicio:final:salto] permite seleccionar secciones de una lista:
La función range () crea una secuencia de valores a partir del dado como parámetro. Es útil para los
bucles de tipo for. Por ejemplo:
Para ver el contenido generado por range (), se debe usar el constructor list.
append añade un nuevo elemento al final de una lista.
extend toma una lista como argumento y añade al final de la actual todos sus elementos.
El método pop elimina un elemento de la lista referenciado en forma de índice. Devuelve el elemento
que ha sido eliminado. Si no se proporciona un índice, borra y devuelve el último elemento.
En Python dos listas son equivalentes si tienen los mismos elementos, pero no son idénticas. Sin
embargo, si dos listas son idénticas, también son equivalentes, es decir, la equivalencia no implica que
sean idénticas. Para comprobar si dos variables son idénticas, se puede usar el operador is.
Si a y b son idénticas significa que la lista tiene dos referencias o nombres diferentes. Así, los cambios
que se hagan usando cualquiera de los nombres afectan a la misma lista.
Una cadena es una secuencia de caracteres y una lista es una secuencia de valores, pero una lista de
caracteres no es lo mismo que una cadena. Para convertir desde una cadena a una lista de caracteres, se
puede usar la función list, que divide una cadena en letras individuales.
Una vez usado split, se puede utilizar el operador índice (corchetes) para buscar una palabra concreta en
la lista.
Se puede llamar a split con un argumento opcional denominado delimitador, que especifica qué
caracteres se deben usar como delimitadores de palabras.
Join es la inversa de split y toma una lista de cadenas y concatena sus elementos. Al ser un método de
cadena, debe invocarse sobre el delimitador y pasarle la lista como un parámetro.
Por ejemplo:
Listas por comprensión
Una lista por comprensión es una expresión compacta para definir listas, conjuntos y diccionarios en
Python. Se trata de definir cada uno de los elementos sin tener que nombrar cada uno de ellos. La forma
general es:
Diccionarios
Un diccionario es una colección no ordenada de pares clave-valor donde la clave y el valor son
objetos que pueden ser de (casi) cualquier tipo. La función dict () crea un diccionario nuevo sin
elementos.
Otra forma de crear un diccionario es mediante una secuencia de pares clave-valor separados por comas
y encerrados entre llaves.
El orden de los elementos en un diccionario es impredecible, pero eso no es importante, ya que se usan
las claves para buscar los valores correspondientes. En este sentido, si la clave especificada no está en el
diccionario se obtiene una excepción.
Algunos métodos:
El método len()
El método in()
El método values()
Para ver si algo aparece como valor en un diccionario, se puede usar el método values, que devuelve los
valores como una lista, y después usar el operador in sobre esa lista.
El método get ()
Toma una clave y un valor por defecto. Si la clave aparece en el diccionario get, devuelve el valor
correspondiente. En caso contrario, devuelve el valor por defecto.
El método keys()
Devuelve una lista de tuplas, cada una de las cuales es una pareja clave-valor sin ningún orden definido.
Funciones
Una función es una secuencia de sentencias que realizan una operación y que reciben un nombre. Sus
principales características son:
Para crear una función se utiliza la palabra reservada def. A continuación, aparece el nombre de la
función, entre paréntesis los parámetros, y finaliza con :. Esta línea se denomina cabecera de la función.
Después de los : aparece el código que se ejecuta cuando se llama a la función. Este trozo de código, se
denomina cuerpo de la función y debe estar indentado. El cuerpo puede contener cualquier número de
sentencias. Para devolver el valor se usa la palabra reservada return.
Definición y llamada
Las reglas para los nombres de las funciones son los mismos que para las variables: se pueden usar
letras, números y algunos signos de puntuación, pero el primer carácter no puede ser un número. No se
puede usar una palabra clave como nombre de una función y se debería evitar también tener una
variable y una función con el mismo nombre. Las funciones con paréntesis vacíos después del nombre
indican que esta función no toma ningún argumento.
La sintaxis para llamar a una función definida consiste en indicar el nombre de la función junto a una
expresión entre paréntesis denominados argumentos de la función. El argumento es un valor o variable
que se pasa a la función como parámetro de entrada.
Algunas características
La definición de una función debe ser ejecutada antes de que la función se llame por primera vez, y no
generan ninguna salida. Sin embargo, las sentencias dentro de cada función son ejecutadas solamente
cuando se llama a esa función.
En las funciones no se especifica el tipo de parámetro ni lo que se retorna.
Las definiciones de funciones no alteran el flujo de la ejecución de un programa debido a que
las sentencias dentro de una función no son ejecutadas. Sin embargo, una llamada a una función
es como un desvío en el flujo de la ejecución. En vez de pasar a la siguiente sentencia, el flujo
salta al cuerpo de la función, ejecuta todas las sentencias que hay allí y después vuelve al punto
donde lo dejó.
Las funciones que disponen de argumentos son asignadas a variables llamadas parámetros. Se
puede usar cualquier tipo de expresión como argumento, la cual será evaluada antes de que la
función sea llamada. El nombre de la variable que se pasa como argumento no tiene nada que
ver con el nombre del parámetro, de manera que dentro de la función recibirá el nombre del
parámetro.
Cuando se definen los argumentos de una función, estos pueden tener valores por defecto.
Una vez que se ha definido una función puede usarse dentro de otra, facilitando de esta manera la
descomposición de un problema, y resolverlo mediante una combinación de llamadas a funciones
Aquellas que producen resultados, con los que se querrá hacer algo, como asignárselo a una variable.
Aquellas que realizan alguna acción, pero no devuelven un valor y, sin embargo, pueden mostrar algo
por pantalla. Si se asigna el resultado a una variable, se obtiene el valor None.
Funciones internas de Python
Python proporciona un número importante de funciones internas que pueden ser usadas sin necesidad de
tener que definirlas previamente:
Las funciones max y min dan respectivamente el valor mayor y menor de una lista.
La función len devuelve cuantos elementos hay en su argumento. Si el argumento es una
cadena devuelve el número de caracteres que hay en la cadena.
Funciones que permiten convertir valores de un tipo a otro: int(), float(), y str().
En Python el paso de argumentos a una función se hace por referencia, de manera que las
modificaciones que se hagan sobre los argumentos se mantienen después de la llamada y ejecución de la
función.
Importación de módulos
Python dispone de una amplia variedad de módulos o librerías. Los módulos son programas que amplían
las funciones y clases de Python para realizar tareas específicas. Los módulos tienen extensión py.
Para poder utilizarlas, hay que importarlas previamente, lo cual se puede hacer de varias formas:
De esta manera para utilizar un elemento hay que usar el nombre del módulo seguido de un punto (.) y
el nombre del elemento que se desee obtener.
Para conocer las operaciones disponibles de un módulo, se puede usar el comando dir.
Mediante la estructura from nombre_modulo import lista_elementos, los elementos importados se usan
directamente por su nombre.
Importar y definir un alias.
Importar todo el módulo mediante la palabra reservada import y definir un alias mediante la palabra
reservada as, de manera que para usar un elemento hay que utilizar el nombre del módulo seguido de un
punto (.) y el nombre del elemento que se desee obtener.
Gestión de archivos
Apertura
Para abrir un archivo en Python se usará la función open, que recibe el nombre del archivo a abrir. Por
defecto, si no se indica nada, el archivo se abre en modo lectura.
La función open abrirá el archivo con el nombre indicado. Si no tiene éxito, se lanzará una excepción. Si
se ha podido abrir el archivo correctamente, la variable asignada a la apertura permitirá manipularlo.
Lectura
La operación más sencilla que se debe realizar sobre un archivo es leer su contenido. Para procesarlo
línea por línea, es posible hacerlo de la siguiente forma:
Además, usando la función readlines es posible recuperar de una sola vez todo el contenido del archivo
estructurado en forma de líneas.
En este caso, la variable líneas tendrá una lista de cadenas con todas las líneas del archivo. Téngase en
cuenta que es posible eliminar los saltos de línea
Si se quiere abrir un archivo en modo escritura, hay que indicar una w como segundo parámetro de la
función open. En caso de que no exista el archivo se crea y, si existe, se pierde la información que
hubiera.
Cierre
Al terminar de trabajar con un archivo, se debe cerrar, ya que lo que se haya escrito no se guardará
realmente hasta no cerrar el archivo. Para ello, se usa close.
También es posible abrir un archivo en modo escritura posicionándose al final del mismo. Para ello, se
usa la opción a con la función open. En este caso se crea el archivo si no existe, pero en caso de que
exista se posiciona al final, manteniendo el contenido original.
Caso práctico
Considera un sistema de cifrado en el que se sustituye cada letra en el texto original por otra que se
encuentra un número fijo de posiciones más adelante en el alfabeto. Por ejemplo, si el desplazamiento es
3 posiciones y se considera la letra A, entonces sería sustituida por la letra D, que se encuentra situada 3
lugares a la derecha de la A. Se considera que el alfabeto es circular por lo que a continuación de la Z
comienza la letra A. Solo se codifican las letras, el resto de símbolos se mantienen.
Una vez cifrado el texto, si este contiene más de una palabra, se reordenan las palabras cifradas,
moviendo cada palabra m posiciones hacia la derecha. Así, la palabra que ocupa la posición 1 se mueve
a la posición m+1, y así sucesivamente —la palabra que ocupa la posición n se moverá a la posición
m—.
Se pide implementar un programa en Python que solicite al usuario que introduzca por teclado un texto
a codificar, dos números que representan el desplazamiento de letras y el desplazamiento de las palabras
codificadas. Como resultado, el programa mostrará por pantalla el mensaje codificado. Se deben hacer
las comprobaciones necesarias sobre la entrada, es decir, es una cadena y 2 números.
def cifrar(texto,desp,desp2):
muestra = ""
texto = convertir(texto,desp2)
palabras = texto.split(' ')
copia = palabras[:]
indices = []
for i in range(0,len(palabras)):
indices.append((i + int(desp)) % len(palabras))
copia[indices[i]] = palabras[i]
for j in range(0,len(copia)):
muestra += "".join(copia[j])+" "
print ("\nTexto cifrado: "+ muestra)
def convertir(text,desp2):
resul = ""
for car in text:
if car.isalpha():
if car.islower():
resul += chr((ord(car) - 97 + int(desp2)) % 26 + 97)
if car.isupper():
resul += chr((ord(car) - 65 + int(desp2)) % 26 + 65)
else:
resul += car
return resul
if __name__ == "__main__":
texto = input("Texo a cifrar: ")
desp2 = input("Desplazamiento letra: ")
desp = input("Desplazamiento palabra: ")
if desp.isdigit() and desp2.isdigit():
cifrar(texto,desp,desp2)
else:
print ("El desplazamiento ha de ser un digito")
Fundamentos de bases de datos relacionales
Introducción
En las últimas décadas, el mecanismo más utilizado para almacenar la información en los sistemas
informáticos ha sido las bases de datos relacionales. Ofrecen un modelo estable, con variedad de
herramientas de desarrollo y altos niveles de seguridad. Sin embargo, se podría decir que el elemento
clave del éxito de este modelo ha sido que dispone de un lenguaje estándar para poder realizar consultas
( SQL). Actualmente muchas fuentes de información se encuentran almacenadas en bases de datos
relacionales.
Por otro lado, dentro del fenómeno Big Data, han surgido nuevos modelos de persistencia de datos
denominados genéricamente como bases de datos NoSQL que, aunque no siguen el modelo relacional ,
sí guardan algunas similitudes en cuanto a sus lenguajes de consulta y conceptos usados. Es por ello
que el conocimiento de las bases de datos relacionales y de SQL facilita la comprensión y aprendizaje
de estos nuevos modelos.
En esta unidad se estudiará, en primer lugar, el modelo relacional que constituye el fundamento teórico
en el que se asientan las bases de datos relacionales. A continuación, se introducirán los elementos
principales del lenguaje SQL que permiten a un usuario gestionar una base de datos relacional . También
se presentará SQLiteStudio , una aplicación que implementa el lenguaje SQLite —una implementación
de SQL ligera muy utilizada en ámbitos como la telefonía móvil— y se mostrará cómo usarla desde
Python.
El modelo relacional
El modelo relacional es un mecanismo de representación de la información que se basa en el concepto
de relación . Formalmente una relación se constituye por dos elementos:
Un dominio representa un conjunto de valores de un tipo de datos que son atómicos —no pueden
descomponerse más—; por ejemplo: el dominio de los enteros, los reales…
En algunas ocasiones, pueden existir instancias en las que algunos atributos no tomen un valor concreto
y se representan con un valor especial denominado valor nulo. El valor nulo representa un valor
desconocido. En el ejemplo anterior, si se hubiera considerado el atributo “teléfono”, podría darse el
caso de algún empleado que no tenga teléfono y se consignaría el valor nulo.
Atomicidad. Los valores de los atributos deben ser atómicos, es decir, no se pueden descomponer más.
Unicidad de las tuplas. No pueden existir 2 tuplas con los mismos valores, dado que las
instancias son un conjunto. En un conjunto solo hay elementos únicos, no repetidos.
Tuplas sin orden. Las tuplas no están ordenadas debido a su definición como un conjunto. En
un conjunto no existe un orden entre sus elementos.
Atributos sin orden. En los atributos de una relación no hay un orden definido, pues se trata de
un conjunto. En un conjunto no existe un orden entre sus elementos.
Se denomina grado de una relación al número de atributos que pertenecen a su esquema y cardinalidad
al número de tuplas definidas en la relación. En el ejemplo anterior, el grado de la relación es 5 y su
cardinalidad 4. (5 atributos y 4 tuplas).
Un atributo es el nombre que recibe un dominio en el contexto de una relación. Por ejemplo, el atributo
nombre de una persona correspondería a una cadena o conjunto de caracteres.
En algunas ocasiones, pueden existir instancias en las que algunos atributos no tomen un valor concreto
y se representan con un valor especial denominado valor nulo. El valor nulo representa un valor
desconocido. En el ejemplo anterior, si se hubiera considerado el atributo “teléfono”, podría darse el
caso de algún empleado que no tenga teléfono y se consignaría el valor nulo.
Algunas características sobre las relaciones y sus tuplas son:
Atomicidad. Los valores de los atributos deben ser atómicos, es decir, no se pueden descomponer más.
Unicidad de las tuplas. No pueden existir 2 tuplas con los mismos valores, dado que las
instancias son un conjunto. En un conjunto solo hay elementos únicos, no repetidos.
Tuplas sin orden. Las tuplas no están ordenadas debido a su definición como un conjunto. En
un conjunto no existe un orden entre sus elementos.
Atributos sin orden. En los atributos de una relación no hay un orden definido, pues se trata de
un conjunto. En un conjunto no existe un orden entre sus elementos.
Se denomina grado de una relación al número de atributos que pertenecen a su esquema y cardinalidad
al número de tuplas definidas en la relación. En el ejemplo anterior, el grado de la relación es 5 y su
cardinalidad 4. (5 atributos y 4 tuplas).
Finalmente, una instancia de una relación consiste en una tupla de valores concretos del dominio de
datos asociado a los atributos de la relación. Por ejemplo, “Juan” es una cadena y representa un valor
concreto para el atributo “Nombre”.
Por ejemplo, si se considera representar la información acerca de los empleados de una empresa
mediante el modelo relacional, las instancias de la relación son tuplas de valores concretos para los
atributos de la relación:
(“Juan”, “Rodríguez Rojo”, 34, “4559999F”,30000)
(“Pedro”, “Sánchez Sánchez”, 54, “5444545E”,”45000”)
(“Isabel”, “Leyva Azul”, 36, “6667733R”,”35000”)
(“Jaime”, “García Redondo”, 39, “3456344T”,”39000”)
En algunas ocasiones, pueden existir instancias en las que algunos atributos no tomen un valor concreto
y se representan con un valor especial denominado valor nulo. El valor nulo representa un valor
desconocido. En el ejemplo anterior, si se hubiera considerado el atributo “teléfono”, podría darse el
caso de algún empleado que no tenga teléfono y se consignaría el valor nulo.
Algunas características sobre las relaciones y sus tuplas son:
Atomicidad. Los valores de los atributos deben ser atómicos, es decir, no se pueden descomponer más.
Unicidad de las tuplas. No pueden existir 2 tuplas con los mismos valores, dado que las
instancias son un conjunto. En un conjunto solo hay elementos únicos, no repetidos.
Tuplas sin orden. Las tuplas no están ordenadas debido a su definición como un conjunto. En
un conjunto no existe un orden entre sus elementos.
Atributos sin orden. En los atributos de una relación no hay un orden definido, pues se trata de
un conjunto. En un conjunto no existe un orden entre sus elementos.
Se denomina grado de una relación al número de atributos que pertenecen a su esquema y cardinalidad
al número de tuplas definidas en la relación. En el ejemplo anterior, el grado de la relación es 5 y su
cardinalidad 4. (5 atributos y 4 tuplas).
Una superclave de una relación es un subconjunto de los atributos del esquema tal que no puede haber
dos tuplas de la relación que tengan la misma combinación de valores para los atributos del subconjunto.
Así, una superclave permite identificar las tuplas de una relación.
Toda relación tiene al menos una superclave formada por todos los atributos de su esquema —se debe al
hecho de que una relación no puede tener tuplas repetidas—.
En el ejemplo anterior serían superclaves: {Nombre, Apellidos, Edad, DNI,Sueldo}, {DNI, Nombre,
Apellidos}, {DNI}
Importante:
En general, en un contexto real, es necesario gestionar más de una relación y entre las relaciones
consideradas existen vínculos o conexiones. Para modelizar estos vínculos, el modelo relacional dispone
de las claves foráneas.
Una clave foránea de una relación permite establecer conexiones entre las tuplas de varias relaciones.
En este sentido, una clave foránea está formada por el conjunto de atributos de una relación que
referencia la clave primaria de otra relación —o incluso de la misma relación—. Dado que las claves
foráneas establecen una conexión con la clave primaria que referencian, los valores de una clave foránea
deben estar presentes en la clave primaria correspondiente, o bien deben ser valores nulos.
Por ejemplo, considérense las relaciones EMPLEADOS y DESPACHOS que permiten modelizar la
información acerca de un empleado de una empresa y sobre el despacho en el que se encuentran los
empleados. Para la primera relación se han considerado los atributos: DNI, Nombre, Apellidos, DNIJefe,
PlantaDespacho, NumDespacho y para la segunda relación se consideran los atributos: Planta, Número,
Plazas. En la relación EMPLEADOS, la clave primaria podría ser {DNI} y en la relación DESPACHOS
la clave primaria podría ser {Planta, Numero}.
El conjunto de atributos {PlantaDespacho, NumDespacho} de la relación EMPLEADOS constituye una
clave foránea que se refiere a la clave primaria de la relación DESPACHOS y que indica para cada
empleado el despacho donde trabaja.
El atributo DNIJefe de la relación EMPLEADOS es una clave foránea que se refiere a la clave
primaria de la misma relación que indica, para cada empleado, quién es su jefe.
El número de atributos de una clave foránea y de la clave primaria a la que referencia deben
ser iguales.
Debe ser posible establecer una correspondencia entre los atributos de una clave foránea y los
atributos de la clave primaria a la que referencia.
Los dominios de los atributos de la clave foránea deben coincidir con los dominios de los
atributos de la clave primaria a la que referencian. En el ejemplo anterior, la clave foránea
{PlantaDespacho, NumDespacho} y la clave primaria {Planta, Número} cumplen estas
propiedades.
Un atributo de una relación podría formar parte tanto de la clave primaria como de una clave
foránea de la relación.
Operaciones en el modelo relacional
Las operaciones del modelo relacional deben permitir manipular la información representada en las
relaciones. En este sentido se definen dos tipos de operaciones:
Actualización. Permite modificar la información representada en una relación. Pueden ser de
tres tipos:
Inserción para añadir nuevas tuplas a una relación.
Borrado para eliminar tuplas de una relación.
Modificación para alterar los valores de una tupla de la relación.
Consulta. Permite recuperar la información representada en las relaciones y que se encuentra
almacenada en las tuplas.
Para implementar estas operaciones se han definidos lenguajes relacionales.
Integridad en el modelo relacional
Para mantener la integridad y la consistencia de la información que se representa en una relación se
define un conjunto de reglas de integridad:
Unicidad de la clave primaria
Establece que toda clave primaria de una relación no debe tener valores repetidos. Se debe garantizar el
cumplimiento de esta regla en todas las inserciones y modificaciones que afecten a atributos que
pertenezcan a la clave primaria de la relación.
Entidad de la clave primaria
Establece que los atributos de la clave primaria de una relación no pueden tener valores nulos. Se debe
garantizar el cumplimiento de esta regla en todas las inserciones y modificaciones que afecten a
atributos que pertenezcan a la clave primaria de la relación.
Integridad referencial
Establece que todos los valores que toma una clave foránea deben ser nulos o valores que existen en la
clave primaria que referencia.
Operaciones
Se debe tener en cuenta en las siguientes operaciones:
Inserciones en una relación que tenga una clave foránea.
Modificaciones que afecten a atributos que pertenezcan a la clave foránea de una relación.
Borrados en relaciones referenciadas por otras relaciones.
Modificaciones que afecten a atributos que pertenezcan a la clave primaria de una relación
referenciada por otras relaciones.
Políticas de actuación
Existen dos políticas de actuación para mantener la integridad referencial cuando se realiza alguna de las
operaciones anteriormente señaladas:
Rechazar cualquier operación que provoque el incumplimiento de alguna de las reglas
anteriores.
Llevar a cabo la operación y realizar posteriormente aquellas acciones necesarias para que las
relaciones mantengan la integridad. Es posible aplicarlo:
Cuando se borra una tupla que tiene una clave primaria referenciada.
Cuando se modifican los valores de los atributos de la clave primaria de una tupla que
es referenciada.
Para los casos anteriores existen 3 políticas de actuación:
Restricción. Consiste en no aceptar la operación de actualización siempre que afecte a una
clave primaria referenciada por una clave foránea.
Actualización en cascada. Se permite la operación de actualización y se lleva las mismas
operaciones sobre las tuplas que las referencian en otras relaciones.
Anulación. Se permite la operación de actualización y se ponen valores nulos a los atributos de
la clave foránea de las tuplas que la referencian.
Integridad del dominio
Establece que todos los valores no nulos para un determinado atributo deben ser del dominio declarado
para dicho atributo y que los operadores que se pueden aplicar sobre los valores dependen del dominio
de estos valores..
El lenguaje SQL
Las bases de datos relacionales se basan en el modelo relacional para almacenar y estructurar la
información. SQL es un lenguaje relacional que permite manipular bases de datos relacionales.
SQL es un lenguaje estándar ANSI/ISO de definición, manipulación y control de bases de datos
relacionales. Se caracteriza por:
Es un lenguaje declarativo basado en el álgebra relacional.
Está soportado por la mayoría de los sistemas relacionales comerciales.
Se puede utilizar de manera interactiva o embebido en un programa.
En el modelo relacional se estructura la información en base a los conceptos:
Relación.
Atributos.
Tuplas.
En SQL se consideran conceptos similares, pero con una nomenclatura diferente:
Tablas.
Columnas.
Filas.
A continuación, se van a estudiar los elementos principales de lenguaje SQL.
Una columna fecha_nacimiento podría ser del tipo DATE y tomar el valor ‘1978-12-25’.
Una columna inicio_pelicula podría ser del tipo TIME y tomar el valor ‘17:15:00.000000’.
Una columna entrada_clase podría ser de tipo TIMESTAMP y tomar el valor ‘1998-7-8 9:30:05’.
La opción def_defecto permite especificar valores por omisión mediante la sentencia DEFAULT
(literal|función|NULL) donde:
Si se elige la opción NULL, indica que la columna debe admitir valores nulos.
Si se elige la opción literal, señala que la columna tomará el valor indicado por el literal.
Si se elige la opción función, se indicará alguna de las funciones siguientes.
Función Descripción
Restricciones de columna
Restricción Descripción
PRIMARY KEY La columna no puede tener valores repetidos ni nulos. Es la clave primaria
REFERENCES tabla
La columna es la clave foránea de la columna de la tabla especificada
[(columna)]
A las restricciones se les puede poner un nombre de la siguiente manera, por ejemplo:
[CONSTRAINT nombre_restricción] CHECK (condiciones).
Cuando se han definido las columnas de una tabla, a continuación, se pueden especificar restricciones
sobre toda la tabla, que siempre se deberán cumplir:
Restricciones de tabla
Restricción Descripción
A las restricciones se les puede poner un nombre de la siguiente manera, por ejemplo:
[CONSTRAINT nombre_restricción] CHECK (condiciones).
e) Ejemplos de creación de tablas
Create table sucursal
(nombre_sucursal VARCHAR2(15) CONSTRAINT suc_PK PRIMARY KEY,
ciudad CHAR(20) NOT NULL CONSTRAINT cl_UK UNIQUE,
activos NUMBER(12,2) default 0);
f) Claves foráneas
Cuando se define una clave foránea, se pueden especificar las políticas de borrado y modificación de
filas que tiene una clave primaria referenciada por claves foráneas de la siguiente forma:
Donde:
NO ACTION indica no realizar ninguna acción: un intento de borrar o actualizar un valor de
clave primaria no será permitido si en la tabla referenciada hay un valor de clave foránea
relacionado.
CASCADE representa la actualización en cascada. Borra o actualiza el registro en la tabla
referenciada y automáticamente borra o actualiza los registros coincidentes en la tabla actual.
SET NULL borra o actualiza el registro en la tabla referenciada y establece en NULL la/s
columna/s de clave foránea en la tabla actual.
SET DEFAULT indica que se ponga el valor especificado por defecto.
Por ejemplo:
Create table cuenta
(numero_cuenta CHAR (20) PRIMARY KEY,
nombre_sucursal char(15)
CONSTRAINT ct_FK REFERENCES sucursal on delete set null,
saldo NUMBER(12,2) default 100,
CONSTRAINT imp_minimo CHECK(saldo >=100))
Donde:
acción_modificar_columna puede ser:
{ADD [COLUMN] columna def_columna |
ALTER [COLUMN] columna {SET def_defecto|DROP DEFAULT}|
DROP [COLUMN ] columna {RESTRICT|CASCADE}}
acción_modif_restricción_tabla puede ser:
{ADD restricción|DROP CONSTRAINT restricción {RESTRICT|CASCADE}}
Así pues, las acciones de modificación que pueden realizarse sobre una tabla son:
Desactivar restricciones.
alter table R disable CONSTRAINT nombre [CASCADE]
Activar restricciones
alter table R enable CONSTRAINT nombre
Índices
Los índices permiten que las bases de datos aceleren las operaciones de consulta y ordenación sobre los
campos a los que el índice hace referencia.
La mayoría de los índices se crean de manera implícita, como consecuencia de las restricciones
PRIMARY KEY y UNIQUE.
Se pueden crear explícitamente para aquellos campos sobre los cuales se realizarán búsquedas e
instrucciones de ordenación frecuente., se muestra un ejemplo.
CREATE [unique] INDEX NombreIndice ON NombreTabla(col1,...,colk);
Consultas y recuperación de información en SQL
Consultas sobre una sola tabla
Para hacer consultas sobre una tabla, se utiliza la sentencia SELECT:
SELECT nombre_columna_a_seleccionar [[AS] col_renombrada]
[,nombre_columna_a_seleccionar [[AS] col_renombrada]...] FROM tabla_a_consultar [[AS]
tabla_renombrada];
Obsérvese que la palabra clave AS permite renombrar las columnas que se quieren seleccionar o las
tablas que se quieren consultar. Esta palabra es opcional y muchas veces se sustituye por un espacio en
blanco.
Por ejemplo, si se quieren seleccionar las columnas código, nombre, dirección y ciudad de la tabla
clientes, se usaría la sentencia:
SELECT codigo_cli, nombre_cli, direccion, ciudad FROM clientes;
Sin embargo, si se quieren recuperar todas las columnas de la tabla se usa el símbolo *, en vez de listar
todas las columnas:
SELECT * FROM clientes;
Si se quieren seleccionar qué filas han de ser recuperadas, hay que utilizar en la consulta SELECT la
palabra reservada WHERE:
SELECT [DISTINCT|ALL] nombre_columnas_a_seleccionar FROM tabla_a_consultar
[WHERE condiciones];
Téngase en cuenta que:
La cláusula WHERE permite recuperar solo aquellas filas que cumplen la condición
especificada.
La cláusula DISTINCT permite ordenar que nos muestre las filas resultantes sin repeticiones.
La opción por defecto es ALL, que indica que muestre todas las filas.
Para construir las condiciones de la cláusula WHERE, es necesario usar operadores de
comparación o lógicos: < (menor), > (mayor), = (igual), <= (menor o igual), >= (mayor o igual),
<> (distinto), AND (conjunción de condiciones), OR (disyunción de condiciones), NOT
(negación).
Por ejemplo, si se quieren recuperar los diferentes sueldos de la tabla empleados:
SELECT DISTINCT sueldo FROM empleados;
Y si se quieren recuperar los empleados de la tabla empleados, cuyo sueldo es mayor de 1000 euros:
SELECT * FROM empleados WHERE sueldo> 1000;
Una subconsulta es una consulta incluida dentro de otra consulta, que aparecerá como parte de una
cláusula WHERE o HAVING —se verá más adelante—.
Por ejemplo, se quiere obtener los proyectos de la tabla proyectos que se corresponden con un cliente
que tiene como NIF el número “444555-E”:
SELECT * FROM proyectos WHERE codigo_cliente = (SELECT código_cli FROM clientes WHERE
nif=“444555-E”)
En la condición que aparece en la clausula WHERE, se puede utilizar un conjunto de predicados
predefinidos para construir las condiciones:
BETWEEN
Comprueba si un valor coincide con los elementos de una lista (IN) o no coincide (NOT IN):
SELECT nombre_columnas_a_seleccionar FROM tabla_a_consultar WHERE columna [NO
T] IN (valor1, ..., valorN);
Por ejemplo, se quieren recuperar todos los clientes que viven en Madrid y Zaragoza:
SELECT * FROM clientes WHERE ciudad IN (‘Madrid’, ‘Zaragoza’);
LIKE
×
Por ejemplo, si se quiere insertar en una tabla clientes que tiene las columnas :nif, nombre_cli,
codigo_cli, telefono, direccion, ciudad, se podría hacer de dos formas:
INSERT INTO clientes VALUES (10, ‘Mercadona’, ‘122233444-C’, ‘Gran vida 8’, ‘Madrid’,
DEFAULT);
O bien:
INSERT INTO clientes(nif, nombre_cli, codigo_cli, telefono, direccion, ciudad) VALUES (‘122233444-
C’, ‘Mercadona’, 10, DEFAULT, ‘Gran vida 8’, ‘Madrid’);
Insertar un préstamo en la relación Préstamo:
INSERT INTO Prestamo VALUES (‘Navacerrada’, ‘Pepe Pérez’, 125.000)
También es posible obtener los datos mediante una consulta SELECT que actúe como proveedor de
datos:
INSERT INTO Prestamo SELECT * FROM Nuevos_Prestamos
Borrados
Para borrar valores de algunas filas de una tabla, se usa la sentencia DELETE:
DELETE FROM nombre_tabla [WHERE condiciones];
Hay que tener en cuenta que si no se utiliza la cláusula WHERE se borrarán todas las filas de la tabla, en
cambio, si se utiliza WHERE, solo se borrarán aquellas filas que cumplan las condiciones especificadas.
Por ejemplo, si se quieren borrar todas las filas de la tabla proyectos se usaría la sentencia:
DELETE FROM proyectos;
Sin embargo, si solo se quieren borrar las filas de la tabla en las que el valor de la columna cliente vale
12, entonces se usaría la sentencia:
DELETE FROM proyectos WHERE codigo_cliente = 12;
Por ejemplo, para borrar todos los clientes que tengan un préstamo no registrado en la relación Préstamo:
DELETE FROM Clientes WHERE Clientes.NumPrestamo NOT IN(SELECT NumPrestamo FROM
Prestamo)
Modificacion
Para modificar los valores de algunas filas de una tabla se usa la sentencia UPDATE:
UPDATE nombre_tabla SET columna = {expresión|DEFAULT|NULL} [, columna =
{expr|DEFAULT|NULL} ...] WHERE condiciones;
La cláusula SET indica qué columna modificar y los valores que puede recibir, y la cláusula WHERE
especifica qué filas deben actualizarse.
Por ejemplo, si se quiere inicializar el sueldo de todos los empleados del proyecto 2 en 500 euros:
UPDATE empleados SET sueldo = 500 WHERE num_proyec = 2;
La parte WHERE es opcional y, si no se especifica, se actualizarán todas las tuplas de la tabla.
UPDATE Prestamo SET importe=200.000 WHERE NumPrestamo=‘P-170’
La cláusula WHERE admite consultas anidadas. Por ejemplo “Modificar todos los prestamos cuya
sucursal ha sido cerrada a la sucursal ‘Centro’”
UPDATE Prestamo SET sucursal= ‘Centro’ WHERE sucursal IN (SELECT sucursal FROM
Sucursales_Cerradas)
Operaciones sobre tablas
Las funciones de agregación son funciones que permiten realizar operaciones sobre los datos de una
columna. Algunas funciones se muestran en la figura 3.7.
En general, las funciones de agregación se aplican a una columna, excepto COUNT, que se aplica a
todas las columnas de las tablas seleccionadas. Se indica como COUNT (*).
Sin embargo, si se especifica COUNT (distinct columna), solo contará los valores no nulos ni repetidos,
y si se especifica COUNT (columna), solo contaría los valores no nulos.
Por ejemplo, si se quiere contar el número de clientes de la tabla clientes cuya ciudad es Madrid:
SELECT COUNT(*) AS numero_clie FROM clientesWHERE ciudad = ‘Madrid’;
Al realizar una consulta, las filas se pueden agrupar de la siguiente manera:
SELECT nombre_columnas_a seleccionar FROM tabla_a_consultar [WHERE condiciones] GROUP
BY columnas_según_las_cuales_se_quiere_agrupar
[HAVING condiciones_por_grupos] [ORDER BY columna_ordenación [DESC] [, columna [DESC]...]];
Donde:
La cláusula GROUP BY permite agrupar las filas según las columnas indicadas, excepto
aquellas afectadas por funciones de agregación.
La cláusula HAVING especifica las condiciones para recuperar grupos de filas.
Por ejemplo, si se quiere conocer el importe total de los proyectos agrupados por clientes:
SELECT código_cliente, SUM(precio) AS importe FROM clientes GROUP BY codigo_cliente;
Y si solo queremos aquellos clientes con un importe facturado mayor de 10000 euros:
SELECT código_cliente FROM clientes GROUP BY codigo_cliente HAVING SUM(precio)>10000
Una vista es una tabla ficticia —no existen como un conjunto de valores almacenados en la base de
datos— que se construye a partir de una consulta a una tabla real. Para definir una vista se usa la
siguiente sintaxis:
CREATE VIEW nombre_vista [(lista_columnas)] AS (consulta) [WITH CHECK OPTION];
A continuación de donde se indica el nombre de la vista, se pueden especificar los nombres de las
columnas de la vista, se define la consulta que construirá la vista, tras lo que se puede añadir la cláusula
“with check option” para evitar inserciones o actualizaciones excepto en los registros en que la cláusula
WHERE de la consulta se evalúe como true.
Para borrar una vista se utiliza la sentencia DROP VIEW:
Si se quiere crear una vista que indique para cada cliente el número de pedidos que tiene encargado, se definiría
la vista:
SQLitestudio
Para poner en práctica SQL, se va a utilizar SQLiteStudio: un sistema de gestión de bases de datos
relacionales que puede descargarse en:
Descarga:
https://sqlitestudio.pl/index.rvt?act=download
La descarga del enlace anterior es un fichero ejecutable . Da igual si es para un SO Linux, Mac o windows,
no necesita instalacion y es independiente del mismo.
Para ilustrar algunas de las funcionalidades de SQLiteStudio, se va a considerar una base de datos para
gestionar una empresa de arquitectura que tiene sedes en Madrid, Zaragoza y Granada. La información
que se desea almacenar es:
Información a mostrar
Sobre los empleados: código de empleado, nombre y apellido, sueldo, nombre de la ciudad y de su departamento
y el número de proyecto al que están asignados.
Sobre cada departamento: nombre, ciudad donde se encuentran y teléfono. Un departamento con el
mismo nombre puede estar en ciudades diferentes y, en una misma ciudad, puede haber departamentos
con nombres diferentes.
Sobre los proyectos: código, nombre, precio, fecha de inicio, fecha prevista de finalización, fecha real
de finalización y el código de cliente.
Sobre los clientes: código de cliente, el nombre, el NIF, la dirección, la ciudad y el teléfono.
En primer lugar, hay que crear la base de datos que contendrá las tablas que almacenarán la información:
Creación de tablas
Se van a crear las diferentes tablas. Para crear una tabla se puede usar un formulario gráfico o bien el
editor de SQL. Para ilustrar el uso de SQL, se va a utilizar el editor donde habrá que introducir las
sentencias en la sintaxis de SQL.
Se crea una tabla clientes para almacenar la información sobre los mismos. Para ello se introduce la
siguiente sentencia en el editor
Tabla departamentos
CREATE TABLE departamentos
(nombre_dep CHAR(20),
ciudad_dep CHAR(20),
telefono INTEGER DEFAULT NULL,
PRIMARY KEY (nombre_dep, ciudad_dep));
Tabla proyectos
CREATE TABLE proyectos
(codigo_proyec INTEGER,nombre_proyec CHAR(20),
precio REAL, fecha_inicio DATE, fecha_prev_fin DATE,
fecha_fin DATE DEFAULT NULL,codigo_cliente INTEGER,
PRIMARY KEY (codigo_proyec),
CHECK (fecha_inicio < fecha_prev_fin),
CHECK (fecha_inicio < fecha_fin),
FOREIGN KEY ( codigo_cliente ) REFERENCES clientes ( codigo_cli));
Tabla empleados
CREATE TABLE empleados
(codigo_empl INTEGER,nombre_empl CHAR (20),
apellido_empl CHAR(20),sueldo REAL CHECK (sueldo > 7000),
nombre_dep CHAR(20),ciudad_dep CHAR(20),
num_proyec INTEGER,PRIMARY KEY (codigo_empl),
FOREIGN KEY (nombre_dep, ciudad_dep) REFERENCES
departamentos (nombre_dep, ciudad_dep),
FOREIGN KEY (num_proyec) REFERENCES proyectos (codigo_proyec) );
Hay que tener en cuenta que, al crear una tabla, las restricciones se pueden definir a nivel de columna o
bien a nivel de tabla. Así, en el caso de que la restricción haga referencia a una sola columna, se puede
optar por una opción u otra. Sin embargo, si hace referencia a más de una columna, es necesario definir
la restricción a nivel de tabla.
Creación de una vista
A continuación, se va a crear una vista utilizando las tablas proyectos y clientes (figura 3.24.). Para ello,
se usa el editor de SQL de la misma forma que en el caso de la creación de tablas.
CREATE VIEW proyectos_por_cliente AS
SELECT c.codigo_cli, COUNT(*)
FROM proyectos p, clientes c
WHERE p.codigo_cliente = c.codigo_cli
GROUP BY c.codigo_cli;
Otras pruebas
Por último, se puede probar lo siguiente:
- Eliminar la vista proyectos_por_cliente usando la sentencia: DROP VIEW proyectos_por_cliente.
- Eliminar la tabla clientes usando la sentencia: DROP TABLE clientes.
- Añadir una nueva columna denominada “país” de tipo CHAR(20) a la tabla clientes: ALTER TABLE
clientes ADD COLUMN paises CHAR(20)-
Caso práctico
Considérese una base de datos para gestionar las solicitudes de acceso de estudiantes a los institutos. La
información que se desea almacenar es:
Sobre los institutos: nombre, área de la ciudad donde se encuentra y número máximo de plazas.
Sobre los estudiantes: identificador de estudiante, nombre, puntos que tiene para acceder y un
valor de corrección.
Sobre las solicitudes: identificador de estudiante, nombre del instituto, vía solicitada y decisión
sobre la solicitud.
Tablas
Tabla Institutos
Tabla Estudiantes
Tabla Solicitudes
Deben hacerse las siguientes consultas:
1.Obtener los nombres y notas de los estudiantes, así como el resultado de su solicitud, de
manera que tengan un valor de corrección menor que 1000 y hayan solicitado la vía de
“Tecnología” en el “Instituto Ramiro de Maeztu”.
2.Obtener la información sobre todas las solicitudes: ID y nombre del estudiante, nombre del
instituto, puntos y plazas, ordenadas de forma decreciente por los puntos y en orden creciente de
plazas.
3.Obtener todas las solicitudes a vías denominadas como “Ciencias” o “Ciencias Sociales”.
4.Obtener los estudiantes cuya puntuación ponderada cambia en más de un punto respecto a la
puntuación original.
5.Borrar a todos los estudiantes que solicitaron más de 2 vías diferentes.
6.Obtener las vías en las que la puntuación máxima de las solicitudes está por debajo de la media.
7.Obtener los nombres de los estudiantes y las vías que han solicitado.
8.Obtener el nombre de los estudiantes y la puntuación con valor de ponderación menor de 1000
que hayan solicitado la vía de “Tecnología” en el “Instituto San Isidro”.
SOLUCIONES
insert into Solicitudes values (123, 'Instituto Ramiro de Maeztu', 'Ciencias Sociales', 'No');
insert into Solicitudes values (123, 'Instituto San Isidro', 'Tecnologia', 'Si');
insert into Solicitudes values (123, 'Instituto Torres Quevedo', 'Ciencias Sociales', 'Si');
insert into Solicitudes values (234, 'Instituto San Isidro', 'Ciencias', 'No');
insert into Solicitudes values (345, 'Instituto Arturo Soria', 'Tecnologia', 'Si');
insert into Solicitudes values (345, 'Instituto Torres Quevedo', 'Tecnologia', 'No');
insert into Solicitudes values (345, 'Instituto Torres Quevedo', 'Ciencias', 'Si');
insert into Solicitudes values (345, 'Instituto Torres Quevedo', 'Ciencias Sociales', 'No');
insert into Solicitudes values (678, 'Instituto Ramiro de Maeztu', 'Ciencias Sociales', 'Si');
insert into Solicitudes values (987, 'Instituto Ramiro de Maeztu', 'Tecnologia', 'Si');
insert into Solicitudes values (987, 'Instituto San Isidro', 'Tecnologia', 'Si');
insert into Solicitudes values (876, 'Instituto Ramiro de Maeztu', 'Tecnologia', 'No');
insert into Solicitudes values (876, 'Instituto Arturo Soria', 'Ciencias', 'Si');
insert into Solicitudes values (876, 'Instituto Arturo Soria', 'Ciencias Sociales', 'No');
insert into Solicitudes values (765, 'Instituto Ramiro de Maeztu', 'Ciencias Sociales', 'Si');
insert into Solicitudes values (765, 'Instituto Torres Quevedo', 'Ciencias Sociales', 'No');
insert into Solicitudes values (765, 'Instituto Torres Quevedo', 'Ciencias', 'Si');
insert into Solicitudes values (543, 'Instituto Arturo Soria', 'Tecnologia', 'No');
Consultas
La resolución de las consultas se haría de la siguiente forma: