Lecture 9.1 - Views Stored Procedures Transactions - PPTX - 0
Lecture 9.1 - Views Stored Procedures Transactions - PPTX - 0
IS52027E
Lecture 9.1
RDBMS Views, Stored Procs, Transactions
Contents
• Recap
• Views
• Stored Procs
• Transactions
2
Recap
Create the tables
Contact Details
Student ID INT
Address VARCHAR(20) Enrolments
Town VARCHAR(20) Student ID INT
PostCode VARCHAR(10) Module ID INT
Phone VARCHAR(15) Enrolment Date DATE
Students Modules
Student ID INT Module ID INT
Student Name VARCHAR(20) Module Name VARCHAR(20)
Assignment Submissions
Student ID INT
Assignment Code INT
Grade INT
4
Insert the data
5
SELECT
SELECT * SELECT *
FROM students s FROM students
JOIN assignment_submissions a ORDER BY student_name
ON s.student_id = a.student_id;
6
This week…
7
SOC Revisited
Implementing Transactions in MySQL
• Do some research!
https://www.mysqltutorial.org/mysql-transaction.aspx
9
Separation of Concerns
We’ve previously spoken about the value of separation of concerns
10
Looking at the code in Lab 4…
… do we really have separation of concerns?
11
Is there a better way?
• Ideally we want to
• push the “databasey“ logic down to the database
• keep our middleware clean, just containing control code and business logic
12
SQL Views
Create a View in MySQL
Take a working query…
14
Create a View in MySQL
Prefix it with the CREATE VIEW syntax:
15
Simplifies Middleware
• We can then simplify our middleware code:
// View Posts page
app.get('/viewposts',function(req,res){
// Query to select all posts from the database
let sqlquery = `SELECT post_id, p.post_date, t.topic_title, p.post_title, p.post_content
FROM posts p
JOIN topics t
ON t.topic_id=p.topic_id
ORDER BY post_date`;
16
SQL Stored Procedures
Let’s look at some more code from Lab 4
app.post('/postadded', function (req,res) {
let user_id = -1
let topic_id = -1
Second query
// Get the topic id from the topic title
sqlquery = `SELECT * FROM topics WHERE topic_title = ?`
db.query(sqlquery, [req.body.topic], (err, result) => {
if (err) {
return console.error(err.message);
}
if (result.length==0) {
return renderAddNewPost(res, req.body, "Can't find that topic")
}
topic_id = result[0].topic_id
console.log("topic is " + topic_id)
Third query
// Check the user is a member of the topic
sqlquery = `SELECT COUNT(*) as countmembership FROM membership WHERE user_id=? AND topic_id=?;`
db.query(sqlquery, [user_id, topic_id], (err, result) => {
if (err) {
return console.error(err.message);
}
if (result[0].countmembership==0) {
return renderAddNewPost(res, req.body, "User is not a member of that topic")
}
});
});
});
This is quite complicated!
18
Let’s break it down users table:
SELECT * FROM users WHERE username = ? user_id
IF nothing found return error "Can't find that user" firstname
surname
username
country
posts table:
SELECT COUNT(*) as countmembership FROM membership WHERE user_id=? AND topic_id=?; post_id
IF COUNT(*) is 0 return error "User is not a member of that topic" post_date,
post_title
INSERT INTO posts (post_date, post_title, post_content, user_id, topic_id) post_content
VALUES (now(), ?, ?, ?, ?); user_id
topic_id
Yes!!
19
Create a Stored Proc
• Stored procedures are a bit like functions.
DELIMITER //
CREATE PROCEDURE sp_insert_post(
BEGIN
# TODO
END //
DELIMITER ;
20
Create a Stored Proc
DELIMITER //
CREATE PROCEDURE sp_insert_post()
BEGIN
# TODO
END //
DELIMITER ; End the stored proc
21
Create a Stored Proc
DELIMITER //
CREATE PROCEDURE sp_insert_post()
BEGIN
# TODO
END //
DELIMITER ;
22
Create a Stored Proc
DELIMITER //
CREATE PROCEDURE sp_insert_post()
BEGIN
# TODO
END //
DELIMITER ;
This is where the SQL commands will go
23
Add some parameters
DELIMITER //
CREATE PROCEDURE sp_insert_post(
IN p_post_title VARCHAR(30),
IN p_post_content MEDIUMTEXT,
IN p_topic_title VARCHAR(20),
IN p_username VARCHAR(15))
BEGIN
# TODO
END //
DELIMITER ;
24
Add the code to get the user_id from the username
DELIMITER //
CREATE PROCEDURE sp_insert_post(IN p_post_title VARCHAR(30), IN p_post_content MEDIUMTEXT, IN p_topic_title VARCHAR(20), IN p_username VARCHAR(15))
BEGIN
DECLARE v_user_id INT;
SELECT user_id
FROM users Get the user_id
WHERE username = p_username
INTO v_user_id;
IF ISNULL(v_user_id) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'No matching username found';
END IF;
END //
DELIMITER ;
users table:
user_id
firstname
surname
username
country
25
Final Stored Proc
DELIMITER //
CREATE PROCEDURE sp_insert_post(IN p_post_title VARCHAR(30), IN p_post_content MEDIUMTEXT, IN p_topic_title VARCHAR(20), IN p_username VARCHAR(15))
BEGIN
DECLARE v_user_id INT;
DECLARE v_topic_id INT; users table:
DECLARE v_user_is_member INT; user_id
SELECT user_id firstname
FROM users
WHERE username = p_username
surname
INTO v_user_id; username
IF ISNULL(v_user_id) THEN country
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'No matching username found';
END IF;
topics table:
SELECT topic_id topic_id
FROM topics
WHERE topic_title = p_topic_title topic_title
INTO v_topic_id; topic_description
IF ISNULL(v_topic_id) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'No matching topic found'; membership table:
END IF;
user_id
SELECT COUNT(*) AS countmembership
FROM membership
topic_id
WHERE user_id=v_user_id AND topic_id=v_topic_id
INTO v_user_is_member;
posts table:
IF v_user_is_member=0 THEN post_id
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'User is not a member of that topic';
END IF; post_date,
post_title
INSERT INTO posts (post_date, post_title, post_content, user_id, topic_id)
VALUES (now(), p_post_title, p_post_content, v_user_id, v_topic_id); post_content
END // user_id
DELIMITER ;
topic_id
26
Our node.js route handler now becomes:
Much neater!
27
Transactions
Example: Bank Transfer
Say we have this table with
these values:
Name Balance UPDATE account SET Balance = Balance – 1000 WHERE Name= John
John £5,000
UPDATE account SET Balance = Balance + 1000 WHERE Name = Mary
Mary £1,000
Name Balance
John £4,000
Mary £2,000
29
But what happens if the 2nd operation fails?
Say we have this table with
these values:
Name Balance UPDATE account SET Balance = Balance – 1000 WHERE Name = John
John £5,000
UPDATE account SET Balance = Balance + 1000 WHERE Name = Mary
Mary £1,000
Name Balance
John £4,000
Mary £1,000 We’ve lost £1000!
30
Transactions
A transaction wraps a set of database operations such that they will either ALL succeed or the will ALL fail.
START TRANSACTION
Account
Name UPDATE account SET Balance = Balance – 1000 WHERE Name = John
Balance
UPDATE account SET Balance = Balance + 1000 WHERE Name = Mary
END TRANSACTION
Name Balance
John £5,000
Mary £1,000
Name Balance
John £5,000 The transaction failed.
Everything is restored back
Mary £1,000
31
Resources
• https://www.mysqltutorial.org/mysql-views-tutorial.aspx
• https://www.mysqltutorial.org/mysql-stored-procedure-tutorial.aspx
• https://www.mysqltutorial.org/mysql-transaction.aspx
32
END OF SLIDES