在做航班智能客服问答系统时会遇到取消票证的场景,这里涉及数据库的操作时会把指定的票证从数据库中删除,同时也会把票证和航班等相关表中的关联关系一起删除。但在删除之前,需要先检查当前用户是否拥有这张票,只有票主才有权限取消这张票。
下面用 Python 和 SQLAlchemy 举个简单的例子说明每行代码的意思:
def cancel_ticket(current_user_id, ticket_id):
# 查询数据库中指定 ticket_id 的票证
ticket = db.session.query(Ticket).filter_by(id=ticket_id).first()
# 如果找不到票证,直接返回或抛出异常
if ticket is None:
raise Exception("票证不存在!")
# 检查当前用户是否是票的所有者
if ticket.user_id != current_user_id:
raise Exception("您没有权限取消这张票!")
# 删除票证与其他相关数据的关联
# 例如,假设票证和航班表有外键关联,先删除关联记录
related_flights = db.session.query(Flight).filter_by(ticket_id=ticket_id).all()
for flight in related_flights:
db.session.delete(flight)
# 删除票证本身
db.session.delete(ticket)
# 提交事务,将所有变更保存到数据库中
db.session.commit()
代码逐行解释:
-
定义函数
cancel_ticket(current_user_id, ticket_id)
:
接受当前用户的 ID 和要取消的票证 ID 作为参数。 -
查询票证:
ticket = db.session.query(Ticket).filter_by(id=ticket_id).first()
这行代码从数据库中查找票证表(Ticket)中与
ticket_id
匹配的记录。 -
检查票证是否存在:
if ticket is None: raise Exception("票证不存在!")
如果没有找到票证,就抛出异常,提醒票证不存在。
-
验证当前用户是否拥有这张票:
if ticket.user_id != current_user_id: raise Exception("您没有权限取消这张票!")
这行代码确保票证的所有者(
ticket.user_id
)和当前用户的 ID 一致,只有票主才可以取消。 -
删除票证与航班等关联的数据:
related_flights = db.session.query(Flight).filter_by(ticket_id=ticket_id).all() for flight in related_flights: db.session.delete(flight)
这里假设票证和航班表(Flight)有外键关联。首先查询所有与这张票有关联的航班记录,然后逐个删除它们。
-
删除票证本身:
db.session.delete(ticket)
将票证从数据库中删除。
这里的db.session.delete是什么意思
-
提交事务:
db.session.commit()
将所有删除操作一次性提交到数据库,确保数据的持久性。
生活中的比喻:
想象你要取消一个活动的入场券。在你开始取消之前,系统会先检查这个入场券是不是属于你,只有你的票才可以取消。如果票上还印有其他关联的信息(比如座位号、活动安排等),这些信息也会一并清除。这样做确保了只有票主能取消自己的票,并且不会留下无效的关联记录。
为什么代码中没有删除payment的代码,是不需要特意删除payment么?
在代码中没有看到删除 Payment 的部分,可能是因为数据库设计中已经设置了级联删除(Cascade Delete)。这意味着当删除 Ticket 时,与其关联的 Payment 记录会自动被数据库删除,无需在代码中显式地删除。
打个比方:
就像在一个树状结构中,删除了树枝后,所有挂在该树枝上的叶子也会自动掉落,这个过程不需要你手动去摘每一片叶子。
举例说明:
假设在数据库中 Ticket 和 Payment 表之间有外键关联,并且设置了 ON DELETE CASCADE
。例如在 SQL 中创建表时可以这样定义:
CREATE TABLE Ticket (
id SERIAL PRIMARY KEY,
user_id INTEGER,
-- 其他字段...
);
CREATE TABLE Payment (
id SERIAL PRIMARY KEY,
ticket_id INTEGER REFERENCES Ticket(id) ON DELETE CASCADE,
amount DECIMAL,
-- 其他字段...
);
在这种设置下,当删除 Ticket 时,数据库会自动删除所有关联的 Payment 记录。因此,在代码中只需要删除 Ticket:
# 查询并删除票证
ticket = db.session.query(Ticket).filter_by(id=ticket_id).first()
if ticket:
db.session.delete(ticket)
db.session.commit() # 这时 Payment 记录会自动被删除
如果没有设置级联删除,则必须手动删除 Payment 记录,如下所示:
# 手动删除相关的 Payment 记录
payments = db.session.query(Payment).filter_by(ticket_id=ticket_id).all()
for payment in payments:
db.session.delete(payment)
# 删除票证
ticket = db.session.query(Ticket).filter_by(id=ticket_id).first()
if ticket:
db.session.delete(ticket)
db.session.commit()
总结来说,代码中没有专门删除 Payment,可能是因为数据库配置了级联删除,使得删除 Ticket 时,相关的 Payment 会自动删除。
数据库配置级联数删除 ON DELETE CASCADE 请点击查看更多介绍