You are on page 1of 10

Task 06

Exercise 1

In every stage, each maillot can be worn by only one cyclist. Therefore we need to create a trigger before
inserting on the Wear table to check that situation. An error must be thrown showing an error message
when trying to insert more than one cyclist with the same maillot on one stage. For example, on stage 1,
Miguel Indurain is wearing the yellow maillot, so, nobody else can wear it. An error must be shown if you
try to insert another rider with the yellow maillot on this stage. But there is no problem if you try to insert
some cyclist wearing the 'violet stars' maillot on the stage 5.

Show how you check the trigger.

DELIMITER //

CREATE TRIGGER tr_wear_check

BEFORE INSERT ON `Wear`

FOR EACH ROW

BEGIN

DECLARE count_wear INT;

SET count_wear = (SELECT COUNT(*) FROM Wear WHERE stage = NEW.stage AND maillot =
NEW.maillot);

IF count_wear > 0 THEN

SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Error: This maillot is already being worn by another
cyclist in this stage';

END IF;

END;
Exercise 2

We want to keep track every time a team changes its director. For this reason, we will create a table to
save the former directors. The table has the following structure:

id_team: tinyint, time_stamp: datetime, director: varchar(50),

At the time_stamp field we will register the current time (when the row is inserted). Use as primary key
the combination of id_team and time_stamp.

Create a trigger (every time an update is done on Team table ) to fill this table. Take into account that it
doesn't matter if the team name is changed, we only need to know when the 'director' field is changed.

Show how you check the trigger.

CREATE TABLE FormerDirectors (

id_team TINYINT,

time_stamp DATETIME,

director VARCHAR(50),

PRIMARY KEY (id_team, time_stamp)

);

—---

DELIMITER //

CREATE TRIGGER `update_director`

AFTER UPDATE ON `Team`

FOR EACH ROW

BEGIN

IF (OLD.director <> NEW.director) THEN

INSERT INTO `FormerDirectors` (id_team, time_stamp, director)

VALUES (OLD.id_team, NOW(), OLD.director);

END IF;

END;
Exercise 3

A rider cannot stay on database without a team if he has won a stage, or if he has won a pass or he has
worn a maillot. We want to check that the team field of riders cannot be updated to null in none of
previous situations. Give a customized error in every case. Example of customized errors:

In order to get different errors for each case, we need to create different triggers for each possibility:

1. Trigger to prevent updating a rider's team to null if they have won a stage:

DELIMITER //

CREATE TRIGGER `prevent_null_team_stage` BEFORE UPDATE ON `StageWinners`

FOR EACH ROW

BEGIN

IF NEW.id_team IS NULL AND OLD.id_team IS NOT NULL THEN

SIGNAL SQLSTATE '45000'

SET MESSAGE_TEXT = 'Cannot set rider team to NULL. Rider has won a stage.';

END IF;

END;

2. Trigger to prevent updating a rider's team to null if they have won a pass:

DELIMITER //

CREATE TRIGGER `prevent_null_team_pass` BEFORE UPDATE ON `PassWinners`

FOR EACH ROW

BEGIN

IF NEW.id_team IS NULL AND OLD.id_team IS NOT NULL THEN

SIGNAL SQLSTATE '45000'

SET MESSAGE_TEXT = 'Cannot set rider team to NULL. Rider has won a pass.';

END IF;

END;
3. Trigger to prevent updating a rider's team to null if they have worn a maillot:

DELIMITER //

CREATE TRIGGER `prevent_null_team_wear` BEFORE UPDATE ON `Wear`

FOR EACH ROW

BEGIN

IF NEW.id_team IS NULL AND OLD.id_team IS NOT NULL THEN

SIGNAL SQLSTATE '45000'

SET MESSAGE_TEXT = 'Cannot set rider team to NULL. Rider has worn a maillot.';

END IF;

END;
Exercise 4

Create a procedure to remove a team. For avoiding to get an error about foreign key constraints fails,
previously we must transfer its riders to other team. So this procedure needs two parameters, one is the
team to delete and another is the team where the riders will be transfered. Use team identifiers as
parameters. Customize errors for any team identifier that doesn't exist.

DELIMITER $$

CREATE PROCEDURE remove_team(IN team_to_delete TINYINT, IN team_to_transfer TINYINT)

BEGIN

DECLARE no_team_riders INT;

DECLARE team_to_transfer_riders INT;

-- Check if both teams exist

SELECT COUNT(*) INTO no_team_riders FROM Rider WHERE team_id = team_to_delete;

IF no_team_riders = 0 THEN

SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Error: Team to delete does not exist.';

END IF;

SELECT COUNT(*) INTO team_to_transfer_riders FROM Rider WHERE team_id = team_to_transfer;

IF team_to_transfer_riders = 0 THEN

SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Error: Team to transfer riders does not exist.';

END IF;

-- Transfer riders to the team to transfer

UPDATE Rider SET team_id = team_to_transfer WHERE team_id = team_to_delete;

-- Delete the team

DELETE FROM Team WHERE id_team = team_to_delete;

END $$

DELIMITER ;
Exercise 5

Create a procedure with two parameters. The first one represents the name of a country. The procedure
must show all the cyclists (and their dorsal between brackets) from this country and return the result
through an output parameter (the second one).

Execution example:

DELIMITER //

CREATE PROCEDURE CC (

IN CountryName VARCHAR(50),

OUT OutputMessage VARCHAR(5000)

BEGIN

DECLARE CyclistList VARCHAR(5000);

SELECT GROUP_CONCAT(CONCAT(`name`, ' (', dorsal, ')') SEPARATOR ', ') INTO CyclistList

FROM Rider

WHERE country = CountryName;

IF (CyclistList IS NOT NULL) THEN

SET OutputMessage = CONCAT('List of cyclists from ', CountryName, ': ', CyclistList);

ELSE

SET OutputMessage = CONCAT('No cyclists found from ', CountryName);

END IF;
END;

—-- To call this procedure:

CALL CC('ESP', @OutputMessage);

SELECT @OutputMessage;

Exercise 6

Create a function that takes rider id as a parameter and shows information about his awards, that is the
number of stages and mountain passes he has won. This information must be shown as an string.

Example execution:
DELIMITER $$

CREATE FUNCTION `rider_awards`(rider_id INT) RETURNS VARCHAR(255)

DETERMINISTIC

BEGIN

DECLARE stage_count INT;

DECLARE pass_count INT;

DECLARE rider_name VARCHAR(255);

DECLARE rider_dorsal VARCHAR(255);

DECLARE rider_age INT;

SELECT COUNT(*) INTO stage_count FROM Stage WHERE winner = rider_id;

SELECT COUNT(*) INTO pass_count FROM Pass WHERE winner = rider_id;

SELECT `name`, dorsal, age INTO rider_name, rider_dorsal, rider_age FROM Rider WHERE dorsal =
rider_id;

RETURN CONCAT(rider_dorsal, ' - ', rider_name, ' (', rider_age, ' years old) has won ', stage_count, ' stages
and ', pass_count, ' passes.');

END$$

DELIMITER ;

—---

In order to check results we must run the following query:

SELECT rider_awards(1);

We will get his dorsal, name, age and wins.

You might also like