将购票和取消订单改为存储过程和触发器

This commit is contained in:
Jingfan Ke 2024-06-14 21:26:48 +08:00
parent e435ae4035
commit 97e7382a6d
6 changed files with 84 additions and 50 deletions

View File

@ -13,5 +13,6 @@ GRANT ALL PRIVILEGES ON ServiceDatabase.Airports TO 'serviceAgent'@'%';
GRANT ALL PRIVILEGES ON ServiceDatabase.Tickets TO 'serviceAgent'@'%'; GRANT ALL PRIVILEGES ON ServiceDatabase.Tickets TO 'serviceAgent'@'%';
GRANT SELECT, UPDATE (First_class_seats_remaining, Business_class_seats_remaining, Economy_class_seats_remaining) GRANT SELECT, UPDATE (First_class_seats_remaining, Business_class_seats_remaining, Economy_class_seats_remaining)
ON ServiceDatabase.Flights TO 'serviceAgent'@'%'; ON ServiceDatabase.Flights TO 'serviceAgent'@'%';
GRANT EXECUTE ON PROCEDURE ServiceDatabase.AddPassengerAndTicket TO 'serviceAgent'@'%';
FLUSH PRIVILEGES; FLUSH PRIVILEGES;

View File

@ -68,4 +68,64 @@ CREATE TABLE ServiceDatabase.Tickets (
FOREIGN KEY (PassengerID) REFERENCES Passengers(ID) ON DELETE CASCADE, FOREIGN KEY (PassengerID) REFERENCES Passengers(ID) ON DELETE CASCADE,
FOREIGN KEY (OrderID) REFERENCES Orders(ID) ON DELETE CASCADE, FOREIGN KEY (OrderID) REFERENCES Orders(ID) ON DELETE CASCADE,
CHECK (Seat_class IN ('First Class', 'Business Class', 'Economy Class')) CHECK (Seat_class IN ('First Class', 'Business Class', 'Economy Class'))
); );
USE ServiceDatabase;
DELIMITER //
CREATE PROCEDURE AddPassengerAndTicket(
IN p_passenger_id VARCHAR(18),
IN p_name VARCHAR(255),
IN p_phone_number BIGINT,
IN p_seat_class VARCHAR(255),
IN p_flight_id VARCHAR(255),
IN p_price DECIMAL(7, 2),
IN p_order_id INT
)
BEGIN
-- 插入或更新乘客信息
INSERT INTO Passengers (ID, Name, Phone_number)
VALUES (p_passenger_id, p_name, p_phone_number)
ON DUPLICATE KEY UPDATE Name=VALUES(Name), Phone_number=VALUES(Phone_number);
-- 更新航班座位数
IF p_seat_class = 'First Class' THEN
UPDATE Flights
SET First_class_seats_remaining = First_class_seats_remaining - 1
WHERE ID = p_flight_id;
ELSEIF p_seat_class = 'Business Class' THEN
UPDATE Flights
SET Business_class_seats_remaining = Business_class_seats_remaining - 1
WHERE ID = p_flight_id;
ELSEIF p_seat_class = 'Economy Class' THEN
UPDATE Flights
SET Economy_class_seats_remaining = Economy_class_seats_remaining - 1
WHERE ID = p_flight_id;
END IF;
-- 插入机票信息
INSERT INTO Tickets (Price, FlightID, Seat_class, PassengerID, OrderID)
VALUES (p_price, p_flight_id, p_seat_class, p_passenger_id, p_order_id);
END //
CREATE TRIGGER restore_seats
BEFORE DELETE ON Tickets
FOR EACH ROW
BEGIN
IF OLD.Seat_class = 'First Class' THEN
UPDATE Flights
SET First_class_seats_remaining = First_class_seats_remaining + 1
WHERE ID = OLD.FlightID;
ELSEIF OLD.Seat_class = 'Business Class' THEN
UPDATE Flights
SET Business_class_seats_remaining = Business_class_seats_remaining + 1
WHERE ID = OLD.FlightID;
ELSEIF OLD.Seat_class = 'Economy Class' THEN
UPDATE Flights
SET Economy_class_seats_remaining = Economy_class_seats_remaining + 1
WHERE ID = OLD.FlightID;
END IF;
END //
DELIMITER ;

View File

@ -37,7 +37,7 @@ def book():
if not passengers: if not passengers:
flash("请至少添加一位乘客", "error") flash("请至少添加一位乘客", "error")
return redirect(url_for('index')) return redirect(url_for('search'))
conn = pymysql.connect(**db) conn = pymysql.connect(**db)
cursor = conn.cursor() cursor = conn.cursor()
@ -62,25 +62,8 @@ def book():
cursor.execute(price_sql, (flight_id,)) cursor.execute(price_sql, (flight_id,))
price = cursor.fetchone()[0] price = cursor.fetchone()[0]
insert_passenger_sql = """ # 调用存储过程
INSERT INTO Passengers (ID, Name, Phone_number) cursor.callproc('AddPassengerAndTicket', (passenger_id, name, phone_number, seat_class, flight_id, price, order_id))
VALUES (%s, %s, %s)
ON DUPLICATE KEY UPDATE Name=VALUES(Name), Phone_number=VALUES(Phone_number);
"""
cursor.execute(insert_passenger_sql, (passenger_id, name, phone_number))
update_seat_sql = f"""
UPDATE Flights
SET {seat_class.replace(' ', '_').lower()}_seats_remaining = {seat_class.replace(' ', '_').lower()}_seats_remaining - 1
WHERE ID = %s
"""
cursor.execute(update_seat_sql, (flight_id,))
insert_ticket_sql = """
INSERT INTO Tickets (Price, FlightID, Seat_class, PassengerID, OrderID)
VALUES (%s, %s, %s, %s, %s)
"""
cursor.execute(insert_ticket_sql, (price, flight_id, seat_class, passenger_id, order_id))
conn.commit() conn.commit()
return redirect(url_for('order', order_id=order_id)) return redirect(url_for('order', order_id=order_id))
@ -89,8 +72,8 @@ def book():
conn.rollback() conn.rollback()
print(e) print(e)
flash("订票失败", "error") flash("订票失败", "error")
return redirect(url_for('index')) return redirect(url_for('search'))
finally: finally:
cursor.close() cursor.close()
conn.close() conn.close()

View File

@ -1,4 +1,4 @@
from flask import request, redirect, url_for, g from flask import request, redirect, url_for, g, flash
from .config import db from .config import db
import pymysql import pymysql
@ -19,33 +19,23 @@ def cancel_order():
conn.close() conn.close()
return redirect(url_for("order_list")) return redirect(url_for("order_list"))
# 查询订单中所有机票的航班ID和座位级别 try:
tickets_sql = "SELECT FlightID, Seat_class FROM Tickets WHERE OrderID = %s" # 删除对应的机票
cursor.execute(tickets_sql, (order_id,)) delete_tickets_sql = "DELETE FROM Tickets WHERE OrderID = %s"
tickets = cursor.fetchall() cursor.execute(delete_tickets_sql, (order_id,))
# 恢复航班的对应余座数 # 删除订单
for ticket in tickets: delete_order_sql = "DELETE FROM Orders WHERE ID = %s"
flight_id = ticket['FlightID'] cursor.execute(delete_order_sql, (order_id,))
seat_class = ticket['Seat_class']
seat_column = seat_class.replace(' ', '_').lower() + "_seats_remaining"
update_seat_sql = f"""
UPDATE Flights
SET {seat_column} = {seat_column} + 1
WHERE ID = %s
"""
cursor.execute(update_seat_sql, (flight_id,))
# 删除对应的机票 conn.commit()
delete_tickets_sql = "DELETE FROM Tickets WHERE OrderID = %s" flash("订单取消成功", "success")
cursor.execute(delete_tickets_sql, (order_id,)) except Exception as e:
conn.rollback()
# 删除订单 print(e)
delete_order_sql = "DELETE FROM Orders WHERE ID = %s" flash(f"订单取消失败:{e}", "error")
cursor.execute(delete_order_sql, (order_id,)) finally:
cursor.close()
conn.commit() conn.close()
cursor.close()
conn.close()
return redirect(url_for('order_list')) return redirect(url_for('order_list'))