DAM - DAW - MP 0484 Bases de Dades - NF5
Pràctica 6 – Cursors
En aquesta pràctica, aplicareu els vostres coneixements sobre l’ús de cursors per processar una sèrie de files d'una taula i omplir una altra taula amb els resultats.
Per fer aquests exercicis cal tenir les següents taules creades:
CREATE OR REPLACE TABLE EMPLEATS AS SELECT * FROM empresa.EMPLOYEES;
CREATE OR REPLACE TABLE TOP_DOGS(salary DECIMAL(8,2));
Canvieu el delimitador per a treballar millor (si ho feu des de la shell)
DELIMITER //
Es recomana, per possibles errades, treballar amb una transacció
START TRANSACTION //
SAVEPOINT P1 //
i així, en qualsevol moment poder desfer el que s’ha fet
ROLLBACK TO P1 //
-
Creeu un bloc anònim que determini els millors empleats pel que fa al seu sou.
-
Declareu una variable
@n, per indicar les n persones amb millor salari de taulaEMPLEATS. Per veure els cinc empleats millor retribuïts, assignaremSET @n=5. -
Enregistreu, a la taula
TOP_DOGS, els salaris dels n primers empleats de la taulaEMPLEATS, sense duplicats en els sous. Si dos empleats cobren el mateix sou, es guarda una sola vegada. -
Proveu com es comportaria en els casos extrems, com ara
@n = 0o n més gran que el nombre d'empleats a la taulaEMPLEATS(SET @n=30). Cal buidar la taulaTOP_DOGSdesprés de cada prova o abans de començar a omplir-la.TRUNCATE TABLE TOP_DOGS; -
Els cinc salaris més alts de la taula
EMPLEATS(n=5) són:+----------+ | salary | +----------+ | 24000.00 | | 17000.00 | | 13000.00 | | 12000.00 | | 11000.00 | +----------+
Possible solució amb
FOR-- -- Exercici 1 - FOR -- DELIMITER // SET @n = 5 // BEGIN NOT ATOMIC DECLARE v_q INT DEFAULT 0; TRUNCATE TABLE TOP_DOGS; iteracio: FOR r_sous IN (SELECT DISTINCT SALARY FROM EMPLEATS ORDER BY SALARY DESC) DO SET v_q = v_q + 1; IF v_q >= @n THEN LEAVE iteracio; END IF; INSERT INTO TOP_DOGS VALUES(r_sous.salary); END FOR; END // SELECT * FROM TOP_DOGS //Possible solució amb
LOOPiCURSOR-- -- Exercici 1 - CURSOR -- DELIMITER // SET @n = 5 // BEGIN NOT ATOMIC DECLARE v_fi BOOLEAN DEFAULT FALSE; DECLARE v_q INT DEFAULT 0; DECLARE c1 CURSOR FOR SELECT DISTINCT SALARY FROM EMPLEATS ORDER BY SALARY DESC; BEGIN DECLARE r_c1 ROW TYPE OF c1; DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET v_fi = TRUE; TRUNCATE TABLE TOP_DOGS; OPEN c1; FETCH c1 INTO r_c1; l_iteracio: LOOP IF v_fi THEN LEAVE l_iteracio; END IF; INSERT INTO TOP_DOGS VALUES(r_C1.salary); SET v_q = v_q + 1; IF v_q >= @n THEN LEAVE L_iteracio; END IF; FETCH c1 INTO r_c1; END LOOP; CLOSE c1; END; END // SELECT * FROM TOP_DOGS //-
Creeu un bloc de codi anònim que faci el següent:
-
Declareu una variable d’usuari per emmagatzemar l'ID del departament (
@dep_id). -
Escriviu un bloc anònim, per recuperar el
last_name,salaryimanager_iddels empleats que treballen en aquest departament. -
Si el sou de l'empleat (
salary) és inferior a 5.000 i si l'identificador del gerent (manager_id) és101o124, mostreu el missatge:<<last_name>> tindrà un augment.En cas contrari, mostreu el missatge
<<lastname>> no tindrà augment. -
Proveu el bloc de codi en els casos següents:
10,20,50,80SET @dep_id = 10 // Whalen tindrà un augment SET @dep_id = 20 // Hartstein no tindrà un augment Fay no tindrà un augment SET @dep_id = 50 // Mourgos no tindrà un augment Rajs tindrà un augment Davies tindrà un augment Matos tindrà un augment Vargas tindrà un augment SET @dep_id = 80 // Zlotkey no tindrà un augment Abel no tindrà un augment Taylor no tindrà un augment
Possible solució amb
FOR-- -- Exercici 2 - FOR -- DELIMITER // SET @dep_id = 80 // BEGIN NOT ATOMIC FOR r_c1 IN (SELECT last_name, salary, manager_id FROM EMPLEATS WHERE department_id = @dep_id) DO IF r_c1.salary < 5000 AND r_c1.manager_id IN (101, 124) THEN SELECT CONCAT_WS(' ', r_c1.last_name, 'tindrà un augment'); ELSE SELECT CONCAT_WS(' ', r_c1.last_name, 'no tindrà un augment'); END IF; END FOR; END //Possible solució amb
LOOPiCURSOR-- -- Exercici 2 - CURSOR -- DELIMITER // SET @dep_id = 10 // BEGIN NOT ATOMIC DECLARE v_fi BOOLEAN DEFAULT FALSE; DECLARE c1 CURSOR FOR SELECT last_name, salary, manager_id FROM EMPLEATS WHERE department_id = @dep_id; BEGIN DECLARE r_c1 ROW TYPE OF c1; DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET v_fi = TRUE; OPEN c1; FETCH c1 INTO r_c1; l_iteracio: LOOP IF v_fi THEN LEAVE l_iteracio; END IF; IF r_c1.salary < 5000 AND r_c1.manager_id IN (101, 124) THEN SELECT CONCAT_WS(' ', r_c1.last_name, 'tindrà un augment'); ELSE SELECT CONCAT_WS(' ', r_c1.last_name, 'no tindrà un augment'); END IF; FETCH c1 INTO r_c1; END LOOP; CLOSE c1; END; END // -