1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
/* Ejercicio 29: Realizar un procedimiento que teniendo en cuenta el procedimiento transac6 del apartado 6.10.5 de los materiales implemente otro procedimiento similar pero utilizando la estrategia optimista, que asume que es muy poco probable que el valor de una fila que se acaba de leer con intención de modificarla un tiempo más tarde cambie antes de poder hacerlo; en ese caso como mínimo habrá que asegurarse de que la fila no ha sido modificada después de haber sido leída y si así ha sido entonces la transacción no debe llevarse a cabo aun pudiéndose realizar (ROLLBACK). */ delimiter $$ drop procedure if exists 1x29 $$ create procedure 1x29( p_id int, p_alumno varchar(30) ) begin declare textoError tinytext; declare todoOk boolean default true; declare v_alumno varchar(30); declare v_antes_id int; declare v_antes_alumno varchar(30); declare continue handler for sqlexception begin set textoError = "Sql Exception"; set todoOk = false; end; -- Se hace una copia del contenido antes de la transaccion: select id, alumno into v_antes_id, v_antes_alumno from alumnos where id = p_id; START TRANSACTION; -- select sleep(20); -- Se hace la actualizacion si los datos son los mismos que los obtenidos anteriormente: if (select true from alumnos where id = v_antes_id and alumno = v_antes_alumno) then update alumnos set id = p_id, alumno = p_alumno where id = v_antes_id and alumno = v_antes_alumno; else set textoError = "Los datos no eran los mismos, no se ha realizo la modificacion."; set todoOk = false; end if; if todoOk then commit; else select textoError; rollback; end if; end $$ delimiter ; -- call 1x29( 2, 'Pedro'); |
1×28: Cursor de actualización
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
/* Ejercicio 28: “Representación gráfica de los salarios de los empleados”. Realizar un procedimiento que utilice un cursor de actualización para rellenar la columna estrellas de la tabla empleados con un asterisco por cada 100 unidades de salario. Antes de realizar el ejercicio añade la columna estrellas a la tabla empleados (ALTER TABLE empleados ADD COLUMN estrellas VARCHAR(10)). Incluir los dos manejadores de error del ejercicio anterior. Ejemplo de funcionamiento: +-------+---------+-----------+ | NUMEM | SALARIO | ESTRELLAS | +-------+---------+-----------+ | 110 | 400 | **** | | 120 | 350 | *** | | 130 | 290 | ** | | 150 | 440 | **** | | 160 | 310 | *** | | 180 | 480 | **** | | 190 | 420 | **** | | 210 | 440 | **** | | 240 | 280 | ** | | 250 | 450 | **** | | 260 | 900 | ********* | | 270 | 380 | *** | ... ... */ -- alter table empleados add stars varchar(5); -- Añade una columna -- alter table empleados change stars estrellas varchar(5); -- Modifica el nombre de una columna -- alter table empleados modify estrellas varchar(10); -- Cambia el tipo de una columna. delimiter $$ drop procedure if exists 1x28 $$ create procedure 1x28() begin declare finCursor boolean default false; declare todoOk boolean default true; declare textoError tinytext; declare v_numem integer; declare c_empleados cursor for select numem from empleados for update; declare continue handler for not found set finCursor = true; declare continue handler for sqlexception begin set todoOk = false; set textoError = "Sql Exception"; end; START TRANSACTION; open c_empleados; fetch c_empleados into v_numem; while finCursor = false do update empleados set estrellas = lpad('', salario div 100, '*') where numem = v_numem; -- Lpad nos ahorra tener que hacer una iteracion solo para concatenar estrellas. fetch c_empleados into v_numem; end while; close c_empleados; if todoOk then commit; else select textoError; rollback; end if; end $$ delimiter ; -- call 1x28; -- select numem, salario, estrellas from empleados; |
1×27: Transacción for update
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
/* Ejercicio 27: Realizar un procedimiento que actualice el salario de los empleados, con una cantidad por hijo que se pase al procedimiento, para aquellos trabajadores que su comisión es nula. Durante el proceso de actualización debe garantizarse que ningún otro usuario pueda cambiar los datos que están siendo modificados. Utilizar un manejador de tipo SQLEXCEPTION (que incluya la operación ROLLBACK) para tratar cualquier situación de error distinta de la excepción NOT FOUND que también deberá manejarse. Al final del proceso, confirmar la transacción si la ejecución ha sido correcta. Ejemplo de funcionamiento. Antes de llamar al procedimiento de actualización: +-------+---------+----------+-------+ | numem | salario | comision | numhi | +-------+---------+----------+-------+ | 110 | 310 | NULL | 3 | | 120 | 350 | 110 | 1 | | 130 | 290 | 110 | 2 | | 150 | 440 | NULL | 0 | | 160 | 310 | 110 | 2 | | 180 | 480 | 50 | 2 | | 190 | 300 | NULL | 4 | … …. Después de ejecutar CALL EJERCICIO3_1(30); +-------+---------+----------+-------+ | numem | salario | comision | numhi | +-------+---------+----------+-------+ | 110 | 400 | NULL | 3 | | 120 | 350 | 110 | 1 | | 130 | 290 | 110 | 2 | | 150 | 440 | NULL | 0 | | 160 | 310 | 110 | 2 | | 180 | 480 | 50 | 2 | | 190 | 420 | NULL | 4 | ... ... */ delimiter $$ drop procedure if exists 1x27 $$ create procedure 1x27(prima int) begin declare v_numem integer; declare finCursor boolean default false; declare c_cursor cursor for select numem from empleados where comision is null and numhi > 0 for update; declare continue handler for not found set finCursor = true; declare exit handler for sqlexception begin rollback; select "Ocurrio un error"; end; START TRANSACTION; open c_cursor; fetch c_cursor into v_numem; while finCursor = false do update empleados set salario = salario + (prima * numhi) where numem = v_numem; fetch c_cursor into v_numem; end while; close c_cursor; commit; end $$ delimiter ; -- select numem, salario, comision, numhi from empleados; -- call 1x27(30); -- select numem, salario, comision, numhi from empleados; |
Dropquest 2012 – 1GB extra para tu Dropbox
Se esta celebrando por segunda vez consecutiva el concurso Dropquest 2012. Todos aquellos que respondan todos los acertijos correctamente se llevaran 1 GB extra para Dropbox, los más rápidos podrán conseguir premios aun mejores.
Algunos de los acertijos:
Traducción de themes de WordPress
Ahora no sucede tanto pero hace un tiempo la gran mayoría de themes que podíamos encontrar para WordPress no estaban preparados para ser traducidos a nuestro idioma nativo. Esto hace que para traducirlos tengamos que buscar cada palabra a traducir entre todos los ficheros .php y traducirla. Además, según como de bien estuviesen hechos los estilos del theme, al cambiar el texto a traducir si es demasiado grande podemos tener el problema de que se deformase la página o no entrase correctamente en la caja/div en la que se debería de mostrar.
Por otro lado cambiar el texto en los propios ficheros es un poco chapucero ya que hay alternativas mejores. Y la alternativa es preparar el theme para poder traducirlo mediante ficheros .mo
Leer más1×26: Triggers para auditar
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
/* Ejercicio 26: Realizar tres triggers "ejercicio26a", "ejercicio26b", y "ejercicio26c" que realicen una auditoria similar a la que realiza el trigger2 del apartado 9.3 de los materiales, pero para la tabla centros: El trigger ejercicio26a auditará las operaciones de inserción. El trigger ejercicio26b auditará las operaciones de modificación. El trigger ejercicio26c auditará las operaciones de borrado. Antes de realizar el ejercicio necesitarás tener creada la tabla: create table audita ( mensaje varchar(200) ) engine = innodb; */ -- Trigger A: Audita las operaciones de inserción. delimiter $$ create trigger t_aud_insercion after insert on centros for each row begin insert into audita values ( concat ( 'Inserccion realizada por ', user(), ' el dia ', now(), '. Valores insertados: "', new.numce, '", "', new.nomce, '" y "', new.seas, '"' ) ); end $$ delimiter ; -- Trigger B: Audita las operaciones de modificación. delimiter $$ create trigger t_aud_modificacion after update on centros for each row begin insert into audita values ( concat ( 'Actualizacion realizada por ', user(), ' el dia ', now(), '. Anteriores valores: "', old.numce, '", "', old.nomce, '" y "', old.seas, '"', '. Nuevos valores: "', new.numce, '", "', new.nomce, '" y "', new.seas, '"' ) ); end $$ delimiter ; -- Trigger C: Audita las operaciones de borrado. delimiter $$ create trigger t_aud_borrado after delete on centros for each row begin insert into audita values ( concat ( 'Fila borrada por ', user(), ' el dia ', now(), '. Valores borrados: "', old.numce, '", "', old.nomce, '" y "', old.seas, '"' ) ); end $$ delimiter ; |
1×25: Uso de Triggers con insert, update y delete
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
/* Ejercicio 25: Realizar dos triggers que completen la funcionalidad del trigger1 del apartado 9.3 de los materiales, mantener sincronizada la tabla alumnos_replica, pero para las operaciones de modificación (trigger ejercicio25a) y borrado (trigger ejercicio25b). */ /* Un trigger es un programa almacenado que no se ejecuta por voluntad del usuario, si no que se ejecuta solo de forma automática cuando se realizan modificaciones con las sentencias: insert, update y delete. Podemos elegir cuando se ha de ejecutar el trigger, si antes (before) de realizar la acción o después (after). El trigger solo funciona bajo la tabla que especifiquemos y cada tabla como máximo podrá tener 6 trigger, 2 por cada sentencia. Notas de interes: Muestra los triggers: show triggers; Borra un trigger: drop trigger t_copia; */ -- Primero se copia una tabla para hacer las pruebas: create table alumnos_replica (select * from alumnos); -- Triger 1: Se encarga de sincronizar las nuevas filas insertadas: delimiter $$ create trigger t_copia before insert on alumnos for each row begin -- Disponemos de "new" para obtener el nuevo valor en insert y update -- y de "old" para obtener el valor anterior en update y delete. insert into alumnos_replica values (new.id, new.alumno); end $$ delimiter; -- Triger A: Mantiene las filas actualizadas: delimiter $$ create trigger t_modifica before update on alumnos for each row begin update alumnos_replica set id = new.id, alumno = new.alumno where id = old.id; end $$ delimiter ; -- Triger B: Borra las filas delimiter $$ create trigger t_borra before delete on alumnos for each row begin delete from alumnos_replica where id = old.id; end $$ delimiter ; |