lOMoARcPSD|13086934 Data Base System Report Database Systems (Danmarks Tekniske Universitet) StuDocu is not sponsored or endorsed by any college or university Downloaded by Andro Kranjcevic (andro.kranjcevic@gmail.com) lOMoARcPSD|13086934 Technical University of Denmark Handball Database Mandatory Group Project Course: 02170 - Database Systems Spring semester 2018 Author(s): Sebastian Fischer s164158@student.dtu.dk Mathias Jensen s164159@student.dtu.dk Frederik Andersen s164146@student.dtu.dk Frederik Kirkegaard s165509@student.dtu.dk TA: William With Hartmann Group: 3 18 April 2018 Downloaded by Andro Kranjcevic (andro.kranjcevic@gmail.com) lOMoARcPSD|13086934 Table of Contents Statement of Requirements 1 Conceptual Design 2 Logical Design 3 Normalization 4 Implementation 5 Database instance 7 SQL Data Queries 9 SQL Table Insert . Update Delete . Modifications 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 SQL Programming Functions . . . . . Procedures . . . . Transactions . . . Trigger . . . . . . . Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 11 12 12 14 15 Appendix 16 Appendix A: E-R Diagram . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 Appendix B: Logical Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 Downloaded by Andro Kranjcevic (andro.kranjcevic@gmail.com) lOMoARcPSD|13086934 Handball database Group Project 02170 18 April 2018 Statement of Requirements In our project for the mandatory project in the course 02170 Database Systems, we have chosen to create a database which reflects a real life handball league, in our case, the danish 888 league. The league is organized in several parts, namely the clubs. The clubs each have a club name, ID, the year which they were founded, the city that they represent, and which division they currently compete in. Furthermore, each club have several players assigned to their team, who all have ID’s, first names, last names, birthdays, salaries and their country of origin. The players can get injured, and in our database we can see which injury they have/had based on whether it is currently active or not. Each club can also have several coaches where each coach also has an ID, first name, last name, birthday, country of origin, a salary and which club they are currently employed at. Furthermore, for each "match/game" that is played, it is listed how many goals, 2-minute suspensions, yellow cards, red cards and saves are made/given. We have expanded this into accounting for which two clubs are playing each other and who is away/home, as well as their respective goals and the date of the game. Moreover, the players can also be transferred between clubs and from these transfers we can see which club is buying the player as well as the date and the price of the transfer. Finally, we have the division ID and its name. As in real life, many clubs are assigned to the same division, generally clubs are not assigned to several divisions, which we also assumed. In regards to who could use such a database, it is imaginable that it could be used for keeping track/statistics of the various leagues, and using it on various handball websites and/or betting sites in order to calculate odds of future games. 1/17 Downloaded by Andro Kranjcevic (andro.kranjcevic@gmail.com) lOMoARcPSD|13086934 Handball database Group Project 02170 18 April 2018 Conceptual Design We have created a Entity-Relationship diagram for the domain of our database, as can be seen in the figure below: Figure 1: Entity-Relationship diagram for the domain of the handball database The same figure, rotated, can be seen more clearly in appendix A. It can be seen in every entity set that the entity attributes are all simple (atomic) attributes. An example of the many-to-many cardinality (no arrowheads) can be seen between the entity set "Injury" and "Player", where the "PlayerInjury" is given the relationship attributes Active and Date. This is a many-to-many relationship since many players can have various different injuries, and it wouldn’t make sense to state e.g. that one player only could have one injury. We can also see that the participation is partial on both sides, which means that a player can have zero to several injuries, and that a specific injury can have zero to several players. A one-to-many (arrowhead) example can be seen between "Player" and "Club". This is because a club can be associated with many players via "Plays_for". However, a player can be associated with at most one club via "Plays_for", which makes sense since in real life no player is assigned to several clubs. Put shortly, one club employs many players. It is again partial participation on both sides, where the same logic applies as described earlier. "Club_divisions" defines relationships between the clubs and division. It has a many-to-one cardinality where the arrowhead is towards division. This is because many clubs are usually assigned to the same division, however, a club cannot exist in several divisions. We assume that a club can exist in the database without being present in a division, hence the lack of total participation. In general, all the entity sets and their attributes makes sense in regards to what one can expect to find in a real life handball league/division. The only actual "surprise" is the addition of the injuries. In the E-R diagram, we can also see that there are no weak entity sets since we have chosen to assign some form of ID in every set, which means that they can all be identified by their own individual attributes. It should be noted that in the textbook adapted UML notation 2/17 Downloaded by Andro Kranjcevic (andro.kranjcevic@gmail.com) lOMoARcPSD|13086934 Handball database Group Project 02170 18 April 2018 they simply underline the primary keys of the entities, however, we thought that adding a "PK" to indicate the primary key would make it more intuitive. Logical Design Our logical design can be seen on the relation schema on the figure below. Figure 2: Database schema diagram of the logical design This figure can also be seen in appendix B in a larger version. Since all of our attributes in our E-R diagram are already atomic (simple attributes), no further adaption of the attributes themselves were necessary. We will now look at the relationship between Player and Injury. Since this is a many-to-many relationship set and we have some relationship attributes; Active and Date, we need to create a whole new table, PlayerInjury. This needs to inherit the primary keys of Player and Injury; PlayerID and InjuryID, which then becomes foreign keys. These two combined will be the primary key of the new table PlayerInjury, which also contains the relationship attributes; Active and Date. The notation for the Player, Injury and PlayerInjury tables are as follows. Player(PlayerID, Firstname, Lastname, Birthday, Country, Salary, ClubID) foreign key (ClubID) references Club(ClubID). PlayerInjury(PlayerID,InjuryID,Active,Date)foreign key (PlayerID) references Player(PlayerID)foreign key (InjuryID)references Injury(InjuryID) Injury(InjuryID, Diagnosis) Between Player and Transfer we have a one-to-many relationship, since one player can be transferred several times. We add the primary key, PlayerID, to Transfer. Now PlayerID becomes a foreign key in Transfer. Now we have the relation schema for the Transfer table, since the relation schema for Player did not change. 3/17 Downloaded by Andro Kranjcevic (andro.kranjcevic@gmail.com) lOMoARcPSD|13086934 Handball database Group Project 02170 18 April 2018 Transfer(TransferID, PlayerID, BuyingClubID, SellingClubID, Date, Price) foreign key (PlayerID) references Player(PlayerID), foreign key (BuyingClubID) references Club(ClubID) , foreign key (SellingClubID) references Club(ClubID). Now, the case between Club and Game looks a bit special on the E-R diagram, but when converting it is quite simple. We just chose to treat it as two cases of one-to-many relationships, and applied the same steps as above, namely putting the primary keys from the "one" side into the "many" side. Club(ClubID, ClubName, FoundingYear, City, DivisionID) foreign key (DivisionID) references Division(DivisionID) Game(GameID, HomeClubGoals, AwayClubGoals, Date, HomeClubID, AwayClubID) foreign key (HomeClubID) references Club(ClubID) , foreign key (AwayClubID) references Club(ClubID) We have chosen not to do any more examples as we have done an example for each type of relationship in our E-R diagram. Normalization In order for the relation schemas and from our logical design to be in third normal form (3NF), it is required that they are already in 2NF and 1NF. For a table to be a relation in first normal form (1NF) all attributes must be atomic (simple), meaning not being multivalued or composite. Furthermore, we clearly see that each of them can be uniquely identified by the key. All attributes have values of the same type i.e. integers, strings, etc. We can also see that each column have unique attribute names. Finally, it is clear that order of the rows and the columns have no significance at all. All of these requirements are already fulfilled. In order for our relations to be in second normal form, they need to fulfill the following requirements. The table should already be in 1NF and all of the attributes must depend on the whole primary key of the table, which can be expressed more formally: K → A ∧ k1¬ → A | k1 ( K 3NF has additional requirements; the table must already be in 2NF and each attribute must depend directly on the entire primary key and not transitively i.e. via other attributes. K → A ∧ ¬(K → B → A) All of our tables are in atlest 3NF since all our attributes are atomic, uniquely identifiable by the primary key, of the same type, have unique names, not affected by order of rows or columns and dependant only on the entire primary key. This can be seen from the player relation schema. Player(PlayerID, Firstname, Lastname, Birthday, Country, Salary, ClubID) foreign key (ClubID) references Club(ClubID). From this it is seen that PlayerID is the primary key which all of the the attributes depend on directly. 4/17 Downloaded by Andro Kranjcevic (andro.kranjcevic@gmail.com) lOMoARcPSD|13086934 Handball database Group Project 02170 18 April 2018 Implementation We have created a MySQL database with tables and views implementing our logical design. We will go through a short example of using, creating a database, where in we create a table from our logical design. The rest can be found in the code appendix. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 DROP DATABASE IF EXISTS HandballDivision ; CREATE DATABASE HandballDivision ; USE HandballDivision ; DROP TABLE IF EXISTS Player ; CREATE TABLE Player ( PlayerId VARCHAR (5) , Firstname VarChar (20) , Lastname VarChar (20) , Birthday Date , Country VARCHAR (20) , Salary VARCHAR (10) , ClubID VARCHAR (4) , PRIMARY KEY ( PlayerID ) , FOREIGN KEY ( ClubID ) REFERENCES Club ( ClubID ) ON DELETE SET NULL ); Here we can see the implementation of the table "Player", where we have specified the relevant data types, primarily varchar and date. We have also specified the primary key, foreign key and references according to our relation schemas and logical design. Finally we have "ON DELETE SET NULL" which dictates that if a specific ClubID is deleted, then all the places where it is present, it will be replaced with "NULL". Similarly in other tables this has also been implemented, however, in some cases we also use "CASCADE". Some places we have also used decimal as datatype in order to do arithmetic calculations with them. We have also created several views. We have created the view: 1 2 3 4 CREATE VIEW TotalPlayerGoals as SELECT PlayerID , Firstname , Lastname , Sum ( NoOfGoals ) AS Goals FROM Player NATURAL JOIN PlayerResult Group By PlayerID ; The output is as follows: Figure 3 Here we want to show all the players in the divisions and their total number of goals this current season. The idea with Group By is that we get all the playerIDs, whereas if we had omitted the group by statement, we would have only gotten one player, and all of the goals in that table. Here we also use the aggregation function Sum, which is self-explanatory. 5/17 Downloaded by Andro Kranjcevic (andro.kranjcevic@gmail.com) lOMoARcPSD|13086934 Handball database Group Project 02170 18 April 2018 We have created another view as well, which we will explain: 1 2 3 4 5 6 7 8 9 10 11 12 CREATE VIEW ClubStatus as ( SELECT ClubID , ClubName as Clubname , SUM ( CASE WHEN ( ClubID = HomeClubID AND HomeClubGoals > AwayClubGoals ) OR ( ClubID = AwayClubID AND AwayClubGoals > HomeClubGoals ) THEN 2 WHEN ( ClubID = HomeClubID OR ClubID = AwayClubID ) AND ( HomeClubGoals = AwayClubGoals ) THEN 1 ELSE 0 END ) AS TotalPoints , COUNT ( CASE WHEN ( ClubID = HomeClubID AND HomeClubGoals > AwayClubGoals ) OR ( ClubID = AwayClubID AND AwayClubGoals > HomeClubGoals ) THEN 1 END ) as Wins , COUNT ( CASE WHEN ( ClubID = HomeClubID OR ClubID = AwayClubID ) AND ( HomeClubGoals = AwayClubGoals ) THEN 1 END ) as draws , COUNT ( CASE WHEN ( ClubID = HomeClubID AND HomeClubGoals < AwayClubGoals ) OR ( ClubID = AwayClubID AND AwayClubGoals < HomeClubGoals ) THEN 1 END ) as Losses , DivisionID FROM Game , Club GROUP BY ClubID ); The view above returns the table showing statistics of the clubs in all divisions. It works by looking at which club is the away club and which one is the homeclub, and then using cases we look at who won and allocating 2 points for a win, 1 point for draw and 0 points for losses. It also lists the wins, losses and draws and which division the club is in. Below is an example of the view being shown. Figure 4 6/17 Downloaded by Andro Kranjcevic (andro.kranjcevic@gmail.com) lOMoARcPSD|13086934 Handball database Group Project 02170 18 April 2018 Database instance In order to populate our tables we used INSERT commands like this one: INSERT INTO X (A_1, A_2, ..., A_n) VALUES (Val_1a, Val_2a, ..., Val_na), (Val_1b, Val_2b, ..., Val_nb); Where X is the table, A is an attribute and Val_na is an value for one of the attributes. A working example from our database: 1 2 3 4 5 INSERT INTO Club ( ClubID , ClubName , FoundingYear , City , DivisionID ) VALUES ( ' 1001 ', ' GOG ' , 1973 , ' Svendborg ', ' 001 ') , ( ' 1002 ', ' KIF ' , 1970 , ' Kolding ', ' 001 ') , ( ' 2001 ', ' Ringsted ', 1990 , ' Ringsted ', ' 002 ') , ( ' 2002 ', ' Ajax ␣Kø benhavn ', 1982 , 'Kø benhavn ' , ' 002 '); We now show the outputs from all of the tables in our database. This is done by using SELECT queries. Each of the queries was on the following form: "SELECT * FROM X", with X being the name of each of our tables. The figure can be seen on the next page: 7/17 Downloaded by Andro Kranjcevic (andro.kranjcevic@gmail.com) lOMoARcPSD|13086934 Handball database 18 April 2018 Group Project 02170 (b) Output from Division (c) Output from PlayerInjury (a) Output from Injury (d) Output from Club (e) Output from Coach (f) Output from Game (g) Output from PlayerResult (h) Output from Transfer (i) Output from Player Figure 5: Outputs from different select queries 8/17 Downloaded by Andro Kranjcevic (andro.kranjcevic@gmail.com) lOMoARcPSD|13086934 Handball database Group Project 02170 18 April 2018 SQL Data Queries In this section we will show some typical SQL select statements that could be interesting to look at in our database. Firstly; 1 2 3 SELECT ClubID , ClubName , Avg ( Salary ) As AvgSalary FROM Club NATURAL JOIN Player Group By ClubID Order By AvgSalary DESC ; This select statements gets the average club salary for clubs across all divisions. The table is constructed using natural join between the club table and the player table. It’s sorted by average salary in a descending order, i.e. the highest average paying club will be in the first row and so on. Below is an example of what it looks like when you run the statement. Figure 6: Average player salary for each club. Another statement could be to see how many total red cards, yellow cards and 2 minute suspensions each player have received throughout the season. 1 2 3 SELECT PlayerID , Sum ( TwoMinSusp ) as TotTwoMinSusp , Sum ( YellowCards ) AS TotYellowCards , Sum ( RedCards ) AS TotRedCards FROM PlayerResult GROUP BY PlayerID ; And an example showing the output. Figure 7: Total cards and suspensions. Finding all currently injured players, meaning players with an active injury can simply be done as shown below. 1 SELECT * FROM PlayerInjury WHERE Active = ' Yes '; And the output of the above statement is shown below. Figure 8: Players currently injured. 9/17 Downloaded by Andro Kranjcevic (andro.kranjcevic@gmail.com) lOMoARcPSD|13086934 Handball database Group Project 02170 18 April 2018 SQL Table Modifications Insert With a handball database there are a lot of times where it would be common to make an insert statement. In the danish handball league, which the database is modelled after, there are always new players joining the clubs, players getting injured, transfers being made and matches being played. These are all things that would require an insert statement in the database. To give an example we’ll show an example where several transfers have been made: 1 2 3 4 INSERT INTO Transfer ( TransferID , PlayerID , BuyingClubID , SellingClubID , TransferDate , Price ) VALUES ( ' 40000 ' , 19821 , ' 1002 ', ' 1001 ', ' 2018 -04 -16 ', 450000) , ( ' 40001 ' , 19821 , ' 2001 ', ' 1002 ' , ' 2018 -05 -16 ' , 450000) , ( ' 40002 ' , 11920 , ' 2002 ', ' 1002 ', ' 2018 -05 -16 ', 450000) ; Insertion of the above statement into the empty table Transfer. Figure 9: Table post insertion. Update During the season certain players might have earned themselves a raise. In this update statement we increase every player that has scored more than 20 goals gets a raise of 5%. This is done with the following SQL statement. Note that this statement makes use of the view TotalPlayerGoals which we showed earlier in the report. 1 2 UPDATE Player SET Player . Salary = Player . Salary *(1.05) WHERE Player . PlayerID IN ( SELECT PlayerID From TotalPlayerGoals WHERE Goals > 20) ; Below is a picture shown of the output, in this case the players Geroas Bew and Den McGhie got an increase in salary. Figure 10: Table of post update in salary. 10/17 Downloaded by Andro Kranjcevic (andro.kranjcevic@gmail.com) lOMoARcPSD|13086934 Handball database Group Project 02170 18 April 2018 Delete At last there are of course also times where we would have to delete rows in the database. It could for instance be a player retiring from the sport and then we would of course have to delete him from our database. In case we wanted to delete the player Den McGhie who has the player id 12548, we could do the following. 1 DELETE FROM Player WHERE PlayerID = 12548; We would the get the following input when looking at the player table. Figure 11: Table post deletion of PlayerID 12548. Since our tables like PlayerInjury and PlayerResults are constructed with an "ON DELETE CASCADE" they will of course also be removed from those, so there will essentially be no trace left of the retired player. SQL Programming Functions We’ve made a function to see which club a player previously played at, this is done by checking the transfer table and taking the transfer of the given player with the most recent date. The function is called PreviousClub and takes the parameter PlayerID and returns a clubID. 1 2 3 4 5 6 DELIMITER // CREATE FUNCTION PreviousClub ( vPlayerID VARCHAR (5) ) RETURNS VARCHAR (20) BEGIN Return ( SELECT SellingClubID FROM transfer WHERE PlayerID = vPlayerID AND TransferDate = ( SELECT MAX ( TransferDate ) FROM Transfer WHERE PlayerID = vPlayerID )); 7 8 9 END ; // DELIMITER ; An example of the function where we want to see which club the player with the PlayerID 19821 most recently played in. 11/17 Downloaded by Andro Kranjcevic (andro.kranjcevic@gmail.com) lOMoARcPSD|13086934 Handball database Group Project 02170 18 April 2018 Figure 12: SELECT PreviousClub(19821) Procedures We have made a procedure which decides whether a given club is the home team or away team for a given match. It then continues to add a given number of goals to the clubs tally for the given match, which gives the possibility to update the goal stats of a match. This procedure is used in an trigger, which we’ll show later. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 DELIMITER // CREATE PROCEDURE HomeOrAway ( IN vClubID VARCHAR (5) , IN vMatchID VARCHAR (5) , IN vNoOfGoals DECIMAL (4 ,0) ) BEGIN IF ( vClubID = ( SELECT HomeClubID FROM Game WHERE MatchID = NEW . MatchID )) THEN UPDATE Game SET Game . HomeClubGoals = Game . HomeClubGoals + vNoOfGoals WHERE Game . MatchID = vMatchID ; ELSE UPDATE Game SET Game . AwayClubGoals = Game . AwayClubGoals + vNoOfGoals WHERE Game . MatchID = vMatchID ; END IF ; END ; // DELIMITER ; Here is an example where we call the procedure, and a picture of the specific game in the Game table before and after. Figure 13: The game before update of goals. Figure 14: Call of the procedure Figure 15: The game after update of goals Transactions Once a year in handball the best teams gets moved up in a division above, and the worst in a division below. For this change we use a transaction so that we can ensure that all the team 12/17 Downloaded by Andro Kranjcevic (andro.kranjcevic@gmail.com) lOMoARcPSD|13086934 Handball database Group Project 02170 18 April 2018 that has to be moved, is moved and that the Game table is deleted, since we only keep track of this seasons games. The procedure that uses the transaction is shown below. 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 DELIMITER // CREATE PROCEDURE MoveTeamsProc () BEGIN DECLARE OldRowsCount001 , OldRowsCount002 , NewRowsCount001 , NewRowsCount002 INT DEFAULT 0; DROP TEMPORARY TABLE IF EXISTS Temp002 ; DROP TEMPORARY TABLE IF EXISTS Temp001 ; CREATE TEMPORARY TABLE IF NOT EXISTS Temp002 AS ( SELECT * FROM ClubStatus WHERE DivisionID = " 002 " ORDER BY TotalPoints DESC LIMIT 1) ; CREATE TEMPORARY TABLE IF NOT EXISTS Temp001 AS ( SELECT * FROM ClubStatus WHERE DivisionID = " 001 " ORDER BY TotalPoints LIMIT 1) ; START TRANSACTION ; SET OldRowsCount001 = ( SELECT Count ( ClubID ) FROM ClubStatus WHERE DivisionID = " 001 "); SET OldRowsCount002 = ( SELECT Count ( ClubID ) FROM ClubStatus WHERE DivisionID = " 002 "); UPDATE Club SET DivisionID = " 001 " WHERE Club . ClubID IN ( SELECT ClubID FROM Temp002 ); SET NewRowsCount001 = ( SELECT Count ( ClubID ) FROM ClubStatus WHERE DivisionID = " 001 "); UPDATE Club SET DivisionID = " 002 " WHERE ClubID IN ( SELECT ClubID FROM Temp001 ); SET NewRowsCount002 = ( SELECT Count ( ClubID ) FROM ClubStatus WHERE DivisionID = " 002 "); DELETE FROM Game ; IF ( OldRowsCount001 = NewRowsCount001 -1) AND ( OldRowsCount002 = NewRowsCount002 ) AND (( SELECT Count (*) FROM Game ) =0) THEN COMMIT ; ELSE ROLLBACK ; END IF ; END ; // DELIMITER ; Here is an example of the Game table at the Club table after the procedure is called. Figure 16: Game table after transaction We use this transaction in a timer which we’ll show later. 13/17 Downloaded by Andro Kranjcevic (andro.kranjcevic@gmail.com) lOMoARcPSD|13086934 Handball database Group Project 02170 18 April 2018 Figure 17: Club table after transaction Trigger We have a couple of triggers, first of all we have one after a transfer has been inserted, which updates the players club. We also has, as mentioned above, one "UpdateGame" that uses the procedure "HomeOrAway". This trigger is used before we insert a row in PlayerResult. We then start by checking the matchID in the row we want to insert is legit, meaning it exists in the Game table. If that is not the case, we throw an error. 1 2 3 4 5 6 7 8 9 10 11 DELIMITER // CREATE TRIGGER UpdateGame BEFORE INSERT ON PlayerResult FOR EACH ROW IF NOT EXISTS ( SELECT * FROM GAME WHERE Game . MatchID = NEW . MatchID ) THEN SIGNAL SQLSTATE ' HY000 ' SET MYSQL_ERRNO = 1525 , MESSAGE_TEXT = ' This ␣ MatchID ␣ does ␣ not ␣ exist ␣ in ␣ Game . ' ; ELSE CALL HomeOrAway (( SELECT ClubID FROM Player WHERE PlayerID = NEW . PlayerID ) , NEW . MatchID , NEW . NoOfGoals ); END IF ; // DELIMITER ; We show this trigger by trying to insert a row in PlayerResult: Figure 18: Insertion in PlayerResult Figure 19: Game table after trigger 14/17 Downloaded by Andro Kranjcevic (andro.kranjcevic@gmail.com) lOMoARcPSD|13086934 Handball database Group Project 02170 18 April 2018 Events As stated above, we use an event to call the procedure which starts a new season, once a year. The event is as follows: 1 2 3 4 5 6 7 8 9 DELIMITER // CREATE EVENT NewSeason ON SCHEDULE EVERY 2 MINUTE STARTS ' 2018 -06 -01 ␣ 00:00:00 ' DO BEGIN CALL MoveTeamsProc () ; END ; // DELIMITER ; Since the event call would get the same result as in the transaction section, we will not be showing an example of this. 15/17 Downloaded by Andro Kranjcevic (andro.kranjcevic@gmail.com) lOMoARcPSD|13086934 Handball database Group Project 02170 Appendix Appendix A: E-R Diagram 16/17 Downloaded by Andro Kranjcevic (andro.kranjcevic@gmail.com) 18 April 2018 lOMoARcPSD|13086934 Handball database Group Project 02170 Appendix B: Logical Design 17/17 Downloaded by Andro Kranjcevic (andro.kranjcevic@gmail.com) 18 April 2018