-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathScript 2 - Quering & Advanced SQL Programming.sql
265 lines (199 loc) · 8.81 KB
/
Script 2 - Quering & Advanced SQL Programming.sql
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
/* This is a script for querying the database, manipulating its data and using advanced programming in order to achieve different objectives */
USE Library;
####################################################################################
############################## QUERYING THE DATABASE ###############################
####################################################################################
###############################################################################
############################## SQL DATA QUERY 1 ###############################
###############################################################################
# This query shows all books and their authors.
SELECT GROUP_CONCAT(Author.AuthorID SEPARATOR ', ') AS AuthorIds,
GROUP_CONCAT(CONCAT(Author.FirstName,' ', Author.LastName) SEPARATOR ', ') AS AuthorNames,
Writes.BookID,
Book.Title BookTitle
FROM Writes
JOIN Author on Writes.AuthorID = Author.AuthorID
JOIN Book on Writes.BookID = Book.BookID
GROUP BY Writes.BookID;
###############################################################################
############################## SQL DATA QUERY 2 ###############################
###############################################################################
# This query shows the number of books the Library has from each author. Shows the author with the most books first, and so on.
SELECT Author.AuthorID,
CONCAT(Author.FirstName,' ', Author.LastName) AS FullName,
COUNT(*) AS NumberOfBooks
FROM Author
JOIN Writes ON Author.AuthorID = Writes.AuthorID
GROUP BY FullName
ORDER BY NumberOfBooks DESC;
###############################################################################
############################## SQL DATA QUERY 3 ###############################
###############################################################################
# This query gives an overview of all loans for each library user and the status of these.
SELECT LibraryUser.UserID,
CONCAT(LibraryUser.FirstName,' ', LibraryUser.LastName) AS FullName,
SUM(LoanedStatus LIKE 'LOANED') AS ActiveLoans,
SUM(LoanedStatus LIKE 'RETURNED') AS Returned,
SUM(LoanedStatus LIKE 'FINED') AS Fined,
COUNT(*) AS Total
FROM LibraryUser
JOIN Loans on LibraryUser.UserID = Loans.UserID
GROUP BY UserID;
#######################################################################################
############################## ADVANCED SQL PROGRAMMING ###############################
#######################################################################################
#######################################################################
############################## FUNCTION ###############################
#######################################################################
DROP FUNCTION IF EXISTS LoanedQuantity;
DELIMITER //
CREATE FUNCTION LoanedQuantity(vBookID INTEGER) RETURNS INTEGER
BEGIN
DECLARE LoanedQuantity INTEGER DEFAULT 0;
SELECT COUNT(*) INTO LoanedQuantity FROM Loans L
WHERE L.BookID = vBookID AND L.LoanedStatus != 'RETURNED' GROUP BY BookID;
RETURN LoanedQuantity;
END //
DELIMITER ;
# Testing the function:
SELECT Title, TotalQuantity, LoanedQuantity(BookID) AS LoanedQuantity
FROM Book;
########################################################################
############################## PROCEDURE ###############################
########################################################################
DROP PROCEDURE IF EXISTS LoanBook;
DELIMITER //
CREATE PROCEDURE LoanBook(IN vUserID INTEGER, IN vBookID INTEGER)
BEGIN
INSERT Loans(UserID, BookID, LoanedDate, UntilDate, ReturnedDate, LoanedStatus)
VALUES (vUserID, vBookID, NOW(), ADDDATE(CURDATE(), INTERVAL 30 DAY), NULL, 'LOANED');
END //
DELIMITER ;
# Testing the procedure:
# BEFORE:
SELECT B.Title, L.LoanedDate, L.UntilDate, L.LoanedStatus
FROM Book B
NATURAL JOIN Loans L
WHERE L.UserID = 4;
# CALLING THE PROCEDURE:
CALL LoanBook(4, 1);
# AFTER:
SELECT B.Title, L.LoanedDate, L.UntilDate, L.LoanedStatus
FROM Book B
NATURAL JOIN Loans L
WHERE L.UserID = 4;
#########################################################################################
############################## PROCEDURE WITH TRANSACTION ###############################
#########################################################################################
DROP PROCEDURE IF EXISTS CreateFines;
DELIMITER //
CREATE PROCEDURE CreateFines()
BEGIN
START TRANSACTION;
INSERT INTO Fine (UserID, Amount, IssuedDate, PaymentStatus)
SELECT UserID, 100.00, CURDATE(), 'NOT PAID' FROM Loans L
WHERE L.LoanedStatus = 'LOANED' AND DATEDIFF(L.UntilDate, CURDATE()) < 0;
UPDATE Loans L SET LoanedStatus = 'FINED'
WHERE L.LoanedStatus = 'LOANED' AND DATEDIFF(L.UntilDate, CURDATE()) < 0;
COMMIT;
END; //
DELIMITER ;
# Testing the procedure with transaction:
# BEFORE:
SELECT B.Title, L.LoanedDate, L.UntilDate, L.LoanedStatus
FROM Book B
NATURAL JOIN Loans L
WHERE L.UserID = 4;
SELECT * FROM Fine F WHERE F.UserID = 4;
# CREATE TEST CONDITIONS:
UPDATE Loans L SET L.LoanedDate = ADDDATE(CURDATE(), -40)
WHERE L.UserID = 4 AND L.BookID = 1;
UPDATE Loans L SET L.UntilDate = ADDDATE(CURDATE(), -10)
WHERE L.UserID = 4 AND L.BookID = 1;
# CALLING THE PROCEDURE:
CALL CreateFines();
# AFTER:
SELECT B.Title, L.LoanedDate, L.UntilDate, L.LoanedStatus
FROM Book B
NATURAL JOIN Loans L
WHERE L.UserID = 4;
SELECT * FROM Fine F WHERE F.UserID = 4;
######################################################################
############################## TRIGGER ###############################
######################################################################
DROP TRIGGER IF EXISTS Loans_Before_INSERT;
DELIMITER //
CREATE TRIGGER Loans_Before_INSERT
BEFORE INSERT ON Loans FOR EACH ROW
BEGIN
DECLARE LoanedQuantity, TotalQuantity, ActiveLoansOfBook INTEGER DEFAULT 0;
SELECT LoanedQuantity(NEW.BookID) INTO LoanedQuantity;
SELECT B.TotalQuantity INTO TotalQuantity FROM Book B WHERE B.BookID = NEW.BookID;
IF (LoanedQuantity >= TotalQuantity)
THEN SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Book not available to loan';
END IF;
SELECT COUNT(*) INTO ActiveLoansOfBook FROM Loans L
WHERE L.BookID = NEW.BookID AND L.UserID = NEW.UserID AND L.LoanedStatus != 'RETURNED'
GROUP BY L.BookID;
IF (ActiveLoansOfBook != 0)
THEN SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'User already loaned book';
END IF;
END; //
DELIMITER ;
# Testing Trigger by calling the previous procedure:
CALL LoanBook(4, 2);
# CALL LoanBook(4, 2); Error (already loaned)
CALL LoanBook(6, 2);
CALL LoanBook(1, 2);
# CALL LoanBook(2, 2); Error (no books left)
####################################################################
############################## EVENT ###############################
####################################################################
SET GLOBAL event_scheduler = 1;
DROP EVENT IF EXISTS CreateFinesEvent;
DELIMITER //
CREATE EVENT CreateFinesEvent ON SCHEDULE EVERY 1 DAY
DO
BEGIN
CALL CreateFines();
END; //
DELIMITER ;
# SET GLOBAL event_scheduler = 0;
######################################################################################
############################## SQL TABLE MODIFICATIONS ###############################
######################################################################################
#################################################################################
############################## SQL UPDATE COMMAND ###############################
#################################################################################
# The library decides to buy more copies of a book that's seeing particularly high demand among library users
SET SQL_SAFE_UPDATES = 0;
# BEFORE:
SELECT * FROM BOOK;
UPDATE Book SET TotalQuantity = 10
WHERE Title = 'Database System Concepts, Sixth Edition';
# AFTER:
SELECT * FROM BOOK;
#################################################################################
############################## SQL DELETE COMMAND ###############################
#################################################################################
# Say a library user wants to be deleted from the database,
# and because of GDPR, the library obliges to do so,
# as long as the user doesn't have any unpaid fines
# This user does not have any active fines, therefore it will be deleted
DELETE FROM LibraryUser
WHERE LoanerNumber = '154399'
AND NOT EXISTS
(SELECT FineID
FROM Fine LEFT JOIN LibraryUser
ON LibraryUser.UserID = Fine.UserID
WHERE LoanerNumber = '154399' AND PaymentStatus = 'NOT PAID');
# This user has outstanding fines, therefore it will not be removed from the database
DELETE FROM LibraryUser
WHERE LoanerNumber = '203442'
AND NOT EXISTS
(SELECT FineID
FROM Fine LEFT JOIN LibraryUser
ON LibraryUser.UserID = Fine.UserID
WHERE LoanerNumber = '203442' AND PaymentStatus = 'NOT PAID');