You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免MySQL数据表中电影场次的日期时间范围重叠

解决方案:影院场次插入时的时间重叠检测

问题说明

我正在用Python和MySQL开发影院管理系统,需要实现插入场次时的冲突检测:如果新场次的日期时间范围(从showtimings到showend)和同影厅已有场次的时间范围重叠,就触发错误。目前已经设置了showtimings与hall的复合唯一键,能检测到完全相同的开始时间,但无法处理时间范围部分重叠的情况。

现有SHOWS表字段:

  • movie_name(影片名)
  • showtimings(场次开始时间)
  • showend(场次结束时间)
  • hall(影厅编号)
  • price(普通票价)、pricevip(VIP票价)、pricevipb(VIP包厢票价)、priceprem(高端票价)

当前插入语句:

cur.execute(f"INSERT INTO SHOWS(movie_name, showtimings,showend, hall, price, pricevip, pricevipb, priceprem) VALUES('{movname}', '{showtimings}','{endtime}', {hall}, {price}, {pricevip}, {pricevipb}, {priceprem})")

实现思路与代码

1. 插入前先查询检测重叠场次

在执行插入操作前,先查询同影厅是否存在时间范围重叠的场次。时间重叠的判断逻辑:新场次的开始时间 < 已有场次的结束时间,且新场次的结束时间 > 已有场次的开始时间。

Python代码实现(改用参数化查询避免SQL注入):

# 先执行冲突检测
check_sql = """
SELECT COUNT(*) FROM SHOWS 
WHERE hall = %s 
AND showtimings < %s 
AND showend > %s;
"""
cur.execute(check_sql, (hall, endtime, showtimings))
conflict_count = cur.fetchone()[0]

if conflict_count > 0:
    print("该影厅当前时间段已有场次,无法插入")
    # 也可抛出自定义异常:raise Exception("场次时间冲突")
else:
    # 执行安全的插入操作
    insert_sql = """
    INSERT INTO SHOWS(movie_name, showtimings, showend, hall, price, pricevip, pricevipb, priceprem)
    VALUES(%s, %s, %s, %s, %s, %s, %s, %s);
    """
    cur.execute(insert_sql, (movname, showtimings, endtime, hall, price, pricevip, pricevipb, priceprem))
    conn.commit()

2. 数据库层面用触发器强制约束

如果希望在数据库层面避免应用层逻辑遗漏,可创建BEFORE INSERT触发器,自动检测冲突:

DELIMITER //
CREATE TRIGGER check_show_overlap BEFORE INSERT ON SHOWS
FOR EACH ROW
BEGIN
    DECLARE conflict_count INT;
    SELECT COUNT(*) INTO conflict_count
    FROM SHOWS
    WHERE hall = NEW.hall
    AND showtimings < NEW.showend
    AND showend > NEW.showtimings;
    
    IF conflict_count > 0 THEN
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '该影厅当前时间段已有场次,无法插入';
    END IF;
END //
DELIMITER ;

创建触发器后,Python代码只需捕获数据库异常即可:

try:
    insert_sql = """
    INSERT INTO SHOWS(movie_name, showtimings, showend, hall, price, pricevip, pricevipb, priceprem)
    VALUES(%s, %s, %s, %s, %s, %s, %s, %s);
    """
    cur.execute(insert_sql, (movname, showtimings, endtime, hall, price, pricevip, pricevipb, priceprem))
    conn.commit()
except mysql.connector.Error as err:
    if err.sqlstate == '45000':
        print("错误:该影厅当前时间段已有场次")
    else:
        print(f"数据库错误:{err}")

3. 关键提醒:杜绝SQL注入

你当前使用f-string拼接SQL存在严重安全风险,必须改用参数化查询(上述代码中的%s占位符),既能避免注入,也能防止特殊字符导致的语法错误。


内容的提问来源于stack exchange,提问作者Koshy John

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 10:40:27