https://xkcd.com/327/
Acceso a datos con PDO
Conectar al servidor:
$server = "localhost";
$user = "root";
$password = "";
$db = "sakila";
try {
$conn = new PDO("mysql:host=$server;dbname=$db;charset=UTF8", $user, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (Exception $e) {
echo "Connection failed: " . $e->getMessage();
}
Ejecutar una consulta de acción (también funcionaría con query):
$sql = "update category set name='$nombre' where category_id=$category_id";
if ($conn->exec($sql) === true) {...}
Recorrer los registros:
$sql = "select * from category ";
$resul = $conn->query($sql);
if ($resul->rowCount()>0) {
while ($row = $resul->fetch()) {
...
}
}
Obtener todos los registros de una sola vez:
$sql = "select * from category "; $resul = $conn->query($sql); $rows=$resul->fetchAll()
Insertar y obtener el último id:
$sql = "insert into category (name) values ('" . addslashes($nombre) . "')";
if ($conn->query($sql) == true) {
$last_id = $conn->lastInsertId();
echo "Insertada categoría $nombre con id " . $last_id;
} else {
echo "Error " . $conn->error;
}
Enlazar resultados con variables:
$row = $conn->query('SELECT first_name,last_name from actor');
$row->bindColumn('first_name', $nombre);
$row->bindColumn(2, $apellido);
while ($row->fetch()) {
print "$nombre $apellido.
\n";
}
Preparar sentencias y luego pasar valores:
$st = $conn->prepare('INSERT INTO actor (first_name,last_name) VALUES (?,?)');
$st->execute(array('Vito','Corleone'));
$st->execute(array('Juan','Perez'));
$st = $conn->prepare('select * from actor where actor_id>?');
$st->execute(array(50));
print_r($st->fetchAll());
Pasar valores con nombre:
$st = $conn->prepare('select * from actor where first_name like :first_name');
$st->execute(array(':first_name'=>'%z%'));
Enlazar parámetros con variables:
$actores=['juan'=>'perez','ana'=>'pi','rosa'=>'buj'];
$st = $conn->prepare('insert into actor (first_name,last_name) values(:first_name,:last_name)');
$st->bindParam(':first_name', $first_name);
$st->bindparam(':last_name', $last_name);
foreach($actores as $first_name=>$last_name){
$st->execute();
}
Número de filas (Ojo, no funciona en todas las bases de datos):
$resul->rowCount()
Ejecutar con arrays:
$sentencia = $conn->prepare("INSERT INTO actor( first_name,last_name) VALUES (?,?)");
$sentencia->execute(array('asd','dsa'));
$sentencia = $conn->prepare("INSERT INTO actor( first_name,last_name) VALUES (:f,:l)");
$sentencia->execute(array('f'=>'asd','l'=>'dsa'));
Enlace manual php:
http://php.net/manual/es/pdo.prepared-statements.php
Un ejemplo:
<body>
<form action="#">
País:
<input type="text" name="pais">
<input type="submit">
</form>
<?php
$server = "localhost";
$user = "root";
$password = "";
$db = "sakila";
try {
$conn = new PDO("mysql:host=$server;dbname=$db;charset=UTF8", $user, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
//Para insertar, recupero el pais de GET y si hay país lo inserto
$pais = filter_input(INPUT_GET, "pais", FILTER_SANITIZE_MAGIC_QUOTES);
if (!empty($pais)) {
$sql = "insert into country (country) values('$pais')";
if ($conn->exec($sql) > 0) {
echo "Registro insertado<br/>";
}
}
$sql = "select * from country ORDER BY COUNTRY_ID DESC";
$q = $conn->query($sql);
while ($row = $q->fetch()) {
echo $row['country_id'] . "-" . $row['country'] . "<br>";
}
} catch (Exception $e) {
echo "Connection failed: " . $e->getMessage();
}
?>
</body>
Examen BD 2019
Ejemplo de procedimientos almacenados
Parámetros entrada y salida:
CREATE PROCEDURE `test`(in id int, out p_actor varchar(100))
BEGIN
select concat_ws(' ',first_name,last_name) into p_actor from actor where actor_id=id;
END
call test(2, @actor);
CREATE DEFINER=`root`@`localhost` PROCEDURE `suma`(in a int, in b int, out suma int)
BEGIN
set suma=a+b;
END
call suma(8,9,@res);
Alta de registros con comprobación incluída:
CREATE DEFINER=`root`@`localhost` PROCEDURE `alta_actor`(in nombre varchar(100), in apellido varchar(100))
BEGIN
declare c int;
select count(*) into c from actor where first_name=nombre and last_name=apellido;
if c=0 and length(nombre)>1 and length(apellido)>1 then
insert into actor (first_name, last_name) values (nombre, apellido);
end if;
END
call alta_actor ('juan','pa');
call alta_actor ('juan','pa'); --No funcionará por repetido
call alta_actor ('juan','p'); -- no funcionará por longitud
Ejemplo de cursor:
CREATE PROCEDURE `cursor_ejemplo`(out total int) BEGIN DECLARE final int DEFAULT 0; declare nombre varchar(100); DECLARE mi_cursor CURSOR FOR SELECT first_name FROM actor; DECLARE CONTINUE HANDLER FOR NOT FOUND SET final = 1; set total=0; OPEN mi_cursor; while final=0 do fetch mi_cursor into nombre; if nombre like '%z%' then set total=total+1; end if; end while; CLOSE mi_cursor; END call cursor_ejemplo(@t);
Procedimientos almacenados
Ejemplos de procedimientos almacenados
CREATE DEFINER=`root`@`localhost` PROCEDURE film_in_stock (IN p_film_id INT, IN p_store_id INT, OUT p_film_count INT) READS SQL DATA BEGIN SELECT inventory_id FROM inventory WHERE film_id = p_film_id AND store_id = p_store_id AND inventory_in_stock(inventory_id); SELECT FOUND_ROWS() INTO p_film_count; END
call film_in_stock(123,1,@w); select @w
CREATE DEFINER=`root`@`localhost` PROCEDURE `actores_por_categoria` (in p_categoria varchar(50)) BEGIN select distinct concat(first_name,' ',last_name) actor from actor join film_actor using (actor_id) join film using (film_id) join film_category using (film_id) join category c using (category_id) where c.name=p_categoria order by actor; END
call actores_por_categoria('Animation')
Ejercicios vistas
Crear una vista que nos muestre el pais, la ciudad, la dirección y el nombre de los clientes. La podemos llamar clientes_direccion
Con esa vista creada será muy fácil mostrar los clientes de Argentina o Italia
Crear una vista que nos relacione la película con sus pagos. Que nos muestre el id de la película, el title, y todos los datos de payment.
Con esa vista sería muy fácil ver el total de pagos por película.
Creando vistas en mysql
Categorías, películas y actores:
create view pelistotal as select category_id, category.name nombrecategoria, film_id,title,actor_id, first_name,last_name from category join film_category using (category_id) join film using (film_id) join film_actor using (film_id) join actor using (actor_id)
La usamos como una tabla normal:
select name,count(actor_id) total from pelistotal group by category_id
select * from actor where actor_id not in ( SELECT actor_id FROM pelistotal where name='action');
Como hacer una consulta del tipo actores que no han trabajado en películas de acción si usar subconsultas. Primero creamos la vista en positivo:
create view actores_accion as select actor_id,first_name,last_name from category join film_category using (category_id) join film using (film_id) join film_actor using (film_id) join actor using (actor_id) where name='action'
Y después hacemos un left join y buscamos los nulos:
SELECT * FROM actor left join actores_accion using(actor_id) where actores_accion.first_name is null
Ejemplos Create view
create view peliculas_pais as select country, count(rental_id) total from country join city using (country_id) join address using(city_id) join customer using(address_id) join rental using(customer_id) group by country_id
CREATE VIEW peliculas_categoria AS select name, count(film_id) total from category join film_category using (category_id) group by category_id
El formato JPG explicado y listo para enredar
Ejercicios repaso mysql
Encontrar los clientes que hayan gastado más de 100 dólares
Mostrar los diez actores que han trabajado en más películas
Buscar las películas que se hayan alquilado más de 20 veces
Clientes de España o Argentina
Películas para niños (children) o familiares (Family)
Actores que no hayan trabajado en películas para niños o familiares
Actores que hayan trabajado en películas que no se hayan alquilado nunca
