! ! PHP Introducción a las Bases de Datos Área de Ingeniería Telemática Dpto. Automática y Computación http://www.tlm.unavarra.es/ Almacenando información ‣ Ficheros?? ‣ DBMS (DataBase Managemente System) ‣ Masivo (TB) ‣ Persistente ‣ Seguro ‣ Multi-usuario (acceso concurrente) ‣ Conveniente (data independence y lenguaje de petición) ‣ Eficiente (queries/s) ‣ Fiable (99.9% uptime) ! ‣ Genérico y accesible desde diferentes lenguajes Modelo relacional ‣ Usado en todos los sistemas de DB actuales ‣ Modelo muy simple ‣ Peticiones en lenguaje de alto nivel SQL : Structured Query Language ‣ Implementaciones muy eficientes No confundir ‣ SQL: Structured Query Language ! ‣ Gestores de bases de datos (DBMS) ‣ MySQL <<< usaremos este ‣ PostgreSQL ‣ Oracle ‣ Sqlite ‣ ... El modelo ‣ Una base de datos es un conjunto de tablas o relaciones ‣ Tablas/Relaciones ‣ Esquema estudios { NIA, Carrera, CredSuperados } personas { NIA, Nombre, Lugar, Foto } personas estudios NIA Nombre Lugar Foto NIA Carrera CredSuperados 51242 Juan Madrid f1223.png 51242 Informatica 40 61623 Ane Pamplona f2662.png 61623 Fisica 42 11112 Bob New York f4233.png 11112 null 50 23212 Juan Madrid null 23212 Historia 0 77172 Cristina Barcelona f2111.png 77172 Informatica 30 ... ... El modelo ‣ La base de datos es un conjunto de relaciones (o tablas) ‣ La relación tiene un conjunto de atributos con nombre (columnas) ‣ Cada tupla (o fila) es tiene un valor para cada atributo ‣ Cada atributo tiene un tipo (o dominio) personas estudios NIA Nombre Lugar Foto NIA Carrera CredSuperados 51242 Juan Madrid f1223.png 51242 Informatica 40 61623 Ane Pamplona f2662.png 61623 Fisica 42 11112 Bob New York f4233.png 11112 null 50 23212 Juan Madrid null 23212 Historia 0 77172 Cristina Barcelona f2111.png 77172 Informatica 30 ... ... El modelo ‣ Los atributos que llamamos key (clave) no pueden tener dos filas con el mismo valor ‣ Hay atributos que pueden tener un valor indefinido: NULL ‣ Hay atributos que pueden incrementarse automáticamente cada vez que insertamos una fila personas estudios NIA Nombre Lugar Foto NIA Carrera CredSuperados 51242 Juan Madrid f1223.png 51242 Informatica 40 61623 Ane Pamplona f2662.png 61623 Fisica 42 11112 Bob New York f4233.png 11112 null 50 23212 Juan Madrid null 23212 Historia 0 77172 Cristina Barcelona f2111.png 77172 Informatica 30 ... ... Creando tablas ‣ Lenguaje SQL CREATE TABLE Personas ( NIA, Nombre, Lugar, Foto ) CREATE TABLE Estudios ( NIA, Carrera, CredSuperados )! Con tipos CREATE TABLE Personas ( ! NIA integer,! Nombre varchar(20), ! Lugar varchar(50),! Foto varchar(50)! );! CREATE TABLE Estudios (! NIA integer, Carrera varchar(50), CredSuperados integer! );! INSERT INTO Personas (NIA,Nombre,Lugar,Foto) ! VALUES (11112,"Bob","New York","f4233.png");! INSERT INTO Estudios (NIA,Carrera,CredSuperados) ! VALUES (77172,"Informatica",30); Usando un DBMS ‣ Servidor de bases de datos ‣ Usando el comando mysql ! ! $ mysql -u mikel -p ! ! ! ‣ Con mysql a un host remoto $ mysql -u mikel -p ! Enter password: ! Welcome to the MySQL monitor. …! mysql> use mikel;! Database changed! mysql> show tables;! +-----------------+! | Tables_in_mikel |! +-----------------+! | Estudios |! | prueba |! +-----------------+! 2 rows in set (0.00 sec)! Commands end with ; or \ ! mysql> select * from prueba;! +------------+-------+-------+! | nombre | nia | foto |! +------------+-------+-------+! | Alice | 22212 | s.png |! | Caschar | 50045 | |! +------------+-------+-------+! 2 rows in set (0.00 sec) ! ! $ mysql -u mikel -p -h 10.1.1.36 -P 3307 ! ‣ Usando un gestor como PHPMyAdmin ‣ Demo Obteniendo información ‣ Create Read Update Delete ‣ Orden SELECT SELECT campos FROM tabla [ WHERE condiciones ] mysql> SELECT * FROM Personas;! +-------+----------+-----------+-----------+! | NIA | Nombre | Lugar | Foto |! +-------+----------+-----------+-----------+! | 51242 | Juan | Madrid | f1223.png |! | 61623 | Ane | Pamplona | f2662.png |! | 11112 | Bob | New York | f4233.png |! | 23212 | Juan | Madrid | NULL |! | 77172 | Cristina | Barcelona | f2111.png |! +-------+----------+-----------+-----------+! 5 rows in set (0.08 sec)! mysql> SELECT NIA,Nombre FROM Personas;! +-------+----------+! | NIA | Nombre |! +-------+----------+! | 51242 | Juan |! | 61623 | Ane |! | 11112 | Bob |! | 23212 | Juan |! Obteniendo información ‣ Incluyendo condiciones sobre los campos SELECT campos FROM tabla WHERE condiciones mysql> SELECT * FROM Estudios WHERE Carrera="informatica";! +-------+-------------+---------------+! | NIA | Carrera | CredSuperados |! +-------+-------------+---------------+! | 51242 | Informatica | 40 |! | 77172 | Informatica | 30 |! +-------+-------------+---------------+! 2 rows in set (0.00 sec)! ! mysql> SELECT * FROM Estudios! -> WHERE Carrera="Informatica" and CredSuperados>30;! +-------+-------------+---------------+! | NIA | Carrera | CredSuperados |! +-------+-------------+---------------+! | 51242 | Informatica | 40 |! +-------+-------------+---------------+! 1 row in set (0.00 sec)! ! SELECT avanzado... ‣ Usando varias tablas para obtener un resultado ! ! ! ! ! mysql> SELECT NIA,Nombre,CredSuperados ! -> FROM Personas natural join Estudios! -> WHERE carrera="Informatica" and credsuperados>30;! +-------+--------+---------------+! | NIA | Nombre | CredSuperados |! +-------+--------+---------------+! | 51242 | Juan | 40 |! +-------+--------+---------------+! 1 row in set (0.00 sec)! ‣ Ordenando los resultados mysql> SELECT * FROM Estudios ORDER BY CredSuperados DESC;! +-------+-------------+---------------+! | NIA | Carrera | CredSuperados |! +-------+-------------+---------------+! | 11112 | NULL | 50 |! | 61623 | Fisica | 42 |! | 51242 | Informatica | 40 |! | 77172 | Informatica | 30 |! | 23212 | Historia | 0 |! +-------+-------------+---------------+! 5 rows in set (0.00 sec)! Modificando ‣ Insertar INSERT INTO tabla (campos) VALUES (valores); ! mysql> INSERT INTO Personas (NIA,Nombre,Lugar) VALUES (11112,"Mikel","Pamplona") ERROR 1062 (23000): Duplicate entry '11112' for key 'PRIMARY'! mysql> INSERT INTO Personas (NIA,Nombre,Lugar) VALUES (32111,"Mikel","Pamplona") ! Query OK, 1 row affected (0.00 sec)! ! ! ‣ Borrar entradas DELETE FROM tabla WHERE condiciones; mysql> DELETE FROM Personas WHERE Foto IS NULL;! ! Query OK, 2 rows affected (0.01 sec)! !! ‣ Borrar tablas mysql> TRUNCATE TABLE Estudios;! Query OK, 0 rows affected (0.05 sec)! Borra el contenido mysql> DROP TABLE Estudios;! Query OK, 0 rows affected (0.01 sec)! Borra la tabla Modificando ‣ UPDATE tabla SET valoresnuevos WHERE condiciones; mysql> UPDATE Personas SET Foto="f5512.png" WHERE NIA=23212;! Query OK, 1 row affected (0.02 sec)! Rows matched: 1 Changed: 1 Warnings: 0! ! mysql> SELECT * FROM Personas;! +-------+----------+-----------+-----------+! | NIA | Nombre | Lugar | Foto |! +-------+----------+-----------+-----------+! | 51242 | Juan | Madrid | f1223.png |! | 61623 | Ane | Pamplona | f2662.png |! | 11112 | Bob | New York | f4233.png |! | 23212 | Juan | Madrid | f5512.png |! | 77172 | Cristina | Barcelona | f2111.png |! +-------+----------+-----------+-----------+! 5 rows in set (0.00 sec)! En resumen ‣ Bases de datos relacionales ‣ Gestores de bases de datos (DBMS) ‣ Lenguaje de peticiones a bases de datos (SQL) ‣ Operaciones básicas ‣ SELECT ‣ Crear tablas ‣ INSERT, DELETE, UPDATE ! ‣ Atributos especiales ‣ Primary keys ‣ Campos con autoincremento Tipos de datos ‣ Tipos de datos numericos INTEGER o INT... FLOAT, REAL ... ‣ Fecha y hora DATETIME, DATE, TIME, TIMESTAMP ‣ Cadenas CHAR(n) cadena de texto de n caracteres VARCHAR(n) cadena de texto de hasta n caracteres BINARY(n) cadena de n bytes VARBINARY(n) cadena de hasta n bytes Tipos de datos ‣ Objetos de gran tamaño (como contenido de ficheros...) ‣ Se almacenan aparte y no con el resto de la fila. VARCHAR es mas rapido si el tamaño es razonable... BLOB/TEXT es mas comodo para objetos arbitrariamente grandes ‣ Tipos TINYBLOB / TINYTEXT (max256B) BLOB / TEXT (max 65kB) MEDIUMBLOB / MEDIUMTEXT (max 16MB) LONGBLOB / LONGTEXT (max 4GB) Tipos de datos ‣ ENUM( valores ) un valor entre varios un conjuntos de valores ‣ SET( valores ) Maximo 64 valores posibles ! CREATE TABLE persona ( ! nombre VARCHAR(50), ! rol ENUM( 'admin' , 'teacher' , 'student' ), ) ! CREATE TABLE persona ( ! nombre VARCHAR(50), ! rol SET( 'admin' , 'teacher' , 'student' ), ) Mas información sobre SQL ‣ http://dev.mysql.com/ ‣ http://dev.mysql.com/doc/refman/5.5/en/index.html Demo ‣ Ejemplos: SELECT con condiciones describe alumnos; select * from alumnos ; select nia, nombre, apellidos from alumnos; select nia, nombre, apellidos from alumnos order by nia; select nia, nombre, apellidos from alumnos limit 10; select nia, nombre, apellidos from alumnos limit 0,5; select nia, nombre, apellidos from alumnos limit 5,5; select nia, nombre, apellidos from alumnos where nia<65000; select nia, nombre, apellidos from alumnos where nombre like 'M%'; select nia, nombre, apellidos from alumnos where nombre like 'Mi%'; select nia, nombre, apellidos from alumnos where nombre like '% %'; select count(*) from alumnos where nombre like '% %'; select nia, nombre, apellidos from alumnos order by rand(); select nia, nombre, apellidos from alumnos order by rand() limit 3; ! ! BD Combinando tablas Área de Ingeniería Telemática Dpto. Automática y Computación http://www.tlm.unavarra.es/ BD ‣ Usando varias tablas ‣ Ejemplo: !mysql> select * from asignaturas;! +-------+--------+----------+--------------------+---------------+! | gradonalumnos |! !| aid | nombre | nalumnos | gradonombre +-------+--------+----------+--------------------+---------------+! | 20209 | RC | 20 | Informatica | 300 |! !| 10312 | SWS | 50 | Telecomunicaciones | 400 |! | 10314 | SWC | 53 | Telecomunicaciones | 400 |! 70 | Telecomunicaciones | 400 |! !| 10203 | ARSS | | 20206 | AR | 30 | Informatica | 300 |! +-------+--------+----------+--------------------+---------------+! ! ! ! ! mysql> select * from asignaturas;! +-------+------------+--------------+------+! | aid | asignatura | matriculados | gid |! +-------+------------+--------------+------+! | 20209 | RC | 20 | 2 |! | 20206 | AR | 30 | 2 |! | 10312 | SWS | 50 | 1 |! | 10314 | SWC | 53 | 1 |! | 10203 | ARSS | 70 | 1 |! +-------+------------+--------------+------+! !! ‣ ¿Cual tiene más sentido? mysql> select * from grados;! +-----+--------------------+----------+! | gid | grado | nalumnos |! +-----+--------------------+----------+! | 2 | Informatica | 300 |! | 1 | Telecomunicaciones | 400 |! | 3 | Fisica | 42 |! +-----+--------------------+----------+! Obteniendo información de varias tablas ‣ JOIN para unir tablas ! ! ! ! ! ! ! ! ! mysql> SELECT * FROM grados JOIN asignaturas;! +-----+--------------------+----------+-------+------------+--------------+------+! | gid | grado | nalumnos | aid | asignatura | matriculados | gid |! +-----+--------------------+----------+-------+------------+--------------+------+! | 2 | Informatica | 300 | 20209 | RC | 20 | 2 |! | 1 | Telecomunicaciones | 400 | 20209 | RC | 20 | 2 |! | 3 | Fisica | 42 | 20209 | RC | 20 | 2 |! | 2 | Informatica | 300 | 20206 | AR | 30 | 2 |! | 1 | Telecomunicaciones | 400 | 20206 | AR | 30 | 2 |! | 3 | Fisica | 42 | 20206 | AR | 30 | 2 |! | 2 | Informatica | 300 | 10312 | SWS | 50 | 1 |! | 1 | Telecomunicaciones | 400 | 10312 | SWS | 50 | 1 |! | 3 | Fisica | 42 | 10312 | SWS | 50 | 1 |! | 2 | Informatica | 300 | 10314 | SWC | 53 | 1 |! | 1 | Telecomunicaciones | 400 | 10314 | SWC | 53 | 1 |! | 3 | Fisica | 42 | 10314 | SWC | 53 | 1 |! | 2 | Informatica | 300 | 10203 | ARSS | 70 | 1 |! | 1 | Telecomunicaciones | 400 | 10203 | ARSS | 70 | 1 |! | 3 | Fisica | 42 | 10203 | ARSS | 70 | 1 |! +-----+--------------------+----------+-------+------------+--------------+------+! ! ‣ Producto cartesiano todas las combinaciones Aplicando condiciones al JOIN ‣ table1 JOIN table2 ON table1.campo = table2.campo ! mysql> select * from grados join asignaturas on grados.gid = asignaturas.gid;! +-----+--------------------+----------+-------+------------+--------------+------+! | gid | grado | nalumnos | aid | asignatura | matriculados | gid |! ! +-----+--------------------+----------+-------+------------+--------------+------+! | 2 | Informatica | 300 | 20209 | RC | 20 | 2 |! |! 2 | Informatica | 300 | 20206 | AR | 30 | 2 |! | 1 | Telecomunicaciones | 400 | 10312 | SWS | 50 | 1 |! | 1 | Telecomunicaciones | 400 | 10314 | SWC | 53 | 1 |! |! 1 | Telecomunicaciones | 400 | 10203 | ARSS | 70 | 1 |! +-----+--------------------+----------+-------+------------+--------------+------+! ! ‣ table1 JOIN table2 USING(campo) mysql> select * from grados join asignaturas using(gid);! +-----+--------------------+----------+-------+------------+--------------+! | gid | grado | nalumnos | aid | asignatura | matriculados |! +-----+--------------------+----------+-------+------------+--------------+! | 2 | Informatica | 300 | 20209 | RC | 20 |! | 2 | Informatica | 300 | 20206 | AR | 30 |! | 1 | Telecomunicaciones | 400 | 10312 | SWS | 50 |! | 1 | Telecomunicaciones | 400 | 10314 | SWC | 53 |! | 1 | Telecomunicaciones | 400 | 10203 | ARSS | 70 |! +-----+--------------------+----------+-------+------------+--------------+! ! Natural JOIN ‣ JOIN con todos los campos que se llamen igual ! mysql> select * from grados natural join asignaturas;! +-----+--------------------+----------+-------+------------+--------------+! ! | grado | gid | nalumnos | aid | asignatura | matriculados |! +-----+--------------------+----------+-------+------------+--------------+! | ! 2 | Informatica | 300 | 20209 | RC | 20 |! | 2 | Informatica | 300 | 20206 | AR | 30 |! | ! 1 | Telecomunicaciones | 400 | 10312 | SWS | 50 |! | 1 | Telecomunicaciones | 400 | 10314 | SWC | 53 |! | ! 1 | Telecomunicaciones | 400 | 10203 | ARSS | 70 |! +-----+--------------------+----------+-------+------------+--------------+! ! ‣ Cuidado, podría haber campos que se llamen igual pero no nos interese identificar (si matriculados se llamara nalumnos por ejemplo) Implicit JOIN ‣ Se puede escribir también.... mysql> select *! -> from grados, asignaturas! -> where grados.gid = asignaturas.gid AND matriculados > 40;! +-----+--------------------+----------+-------+------------+--------------+------+! | gid | grado | nalumnos | aid | asignatura | matriculados | gid |! +-----+--------------------+----------+-------+------------+--------------+------+! | 1 | Telecomunicaciones | 400 | 10312 | SWS | 50 | 1 |! | 1 | Telecomunicaciones | 400 | 10314 | SWC | 53 | 1 |! | 1 | Telecomunicaciones | 400 | 10203 | ARSS | 70 | 1 |! +-----+--------------------+----------+-------+------------+--------------+------+! ! Mas avanzados... ‣ Se pueden añadir condiciones mysql> select *! -> from grados join asignaturas! -> on grados.gid = asignaturas.gid! -> where matriculados > 40 ;! +-----+--------------------+----------+-------+------------+--------------+------+! | gid | grado | nalumnos | aid | asignatura | matriculados | gid |! +-----+--------------------+----------+-------+------------+--------------+------+! | 1 | Telecomunicaciones | 400 | 10312 | SWS | 50 | 1 |! | 1 | Telecomunicaciones | 400 | 10314 | SWC | 53 | 1 |! | 1 | Telecomunicaciones | 400 | 10203 | ARSS | 70 | 1 |! +-----+--------------------+----------+-------+------------+--------------+------+! Mas avanzados... ‣ LEFT y RIGHT OUTER JOINs mysql> SELECT * FROM grados LEFT OUTER JOIN asignaturas USING (gid);! +-----+--------------------+----------+-------+--------+----------+! | gid | nombre | nalumnos | aid | nombre | nalumnos |! +-----+--------------------+----------+-------+--------+----------+! | 2 | Informatica | 300 | 20209 | RC | 20 |! | 2 | Informatica | 300 | 20206 | AR | 30 |! | 1 | Telecomunicaciones | 400 | 10312 | SWS | 50 |! | 1 | Telecomunicaciones | 400 | 10314 | SWC | 53 |! | 1 | Telecomunicaciones | 400 | 10203 | ARSS | 70 |! | 3 | Fisica | 42 | NULL | NULL | NULL |! +-----+--------------------+----------+-------+--------+----------+! Para que vale esto? ‣ Normalmente no todo está en una tabla usuarios ( userid, nombre, pass, foto ) SELECT userid, nombre, pass, foto FROM usuarios WHERE userid=X ! mensajes ( userid, tiempo, mensaje ) Si quiero imprimir los mensajes con formato nombre > mensaje SELECT userid, tiempo, mensaje FROM mensajes ... ! SELECT nombre, tiempo, mensaje FROM usuarios JOIN mensajes USING (userid) WHERE ...