酒店预订系统核心是数据关系真实反映业务流转:房间与房型须分离设计,价格动态化需独立pricing表,预订必须绑定具体房间并用应用层+唯一索引防日期重叠,用户与客人信息应解耦,日期统一用DATETIME精确到小时。

酒店预订系统的核心不是功能堆砌,而是数据关系是否能真实反映业务流转——比如一个房间在某天被预订后,必须同时阻断其他订单对该房型+日期的重复占用,这靠外键约束不够,得靠唯一索引+应用层校验双保险。
客房与房型要分离设计,别把房型信息硬编码进 rooms 表
常见错误是把 room_type(如“豪华大床房”)、price_per_night 直接存在 rooms 表里,导致调价时要批量更新、新增房型要改表结构。正确做法是拆出 room_types 表,并用外键关联:
CREATE TABLE room_types ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL, base_price DECIMAL(10,2) NOT NULL, capacity TINYINT DEFAULT 2, description TEXT );CREATE TABLE rooms ( id INT PRIMARY KEY AUTO_INCREMENT, room_number VARCHAR(10) NOT NULL UNIQUE, type_id INT NOT NULL, status ENUM('available', 'cleaning', 'maintenance', 'occupied') DEFAULT 'available', FOREIGN KEY (type_id) REFERENCES room_types(id) );
-
room_number加UNIQUE约束,避免人工录入重复房号 - 别在
rooms表里存实时价格——价格随季节/活动浮动,应走独立的room_pricing表(含start_date/end_date) -
status用ENUM而非字符串,减少存储和误输入风险
预订记录必须绑定具体房间,且日期范围不可重叠
很多设计只记 check_in 和 check_out,却没强制关联到某个 room_id,导致无法精确控制“同一房间同一天只能有一个有效订单”。关键在 bookings 表结构和唯一约束:
CREATE TABLE bookings (
id INT PRIMARY KEY AUTO_INCREMENT,
room_id INT NOT NULL,
guest_name VARCHAR(100) NOT NULL,
check_in DATE NOT NULL,
check_out DATE NOT NULL,
status ENUM('confirmed', 'cancelled', 'checked_in', 'checked_out') DEFAULT 'confirmed',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (room_id) REFERENCES rooms(id),
CHECK (check_out > check_in)
);
-- 阻止同一房间在时间上有交集的预订
CREATE UNIQUE INDEX idx_room_date_overlap
ON bookings (room_id, check_in, check_out);
- 仅靠这个索引还不够——MySQL 的
UNIQUE索引不能自动检测区间重叠(比如 A:2024-05-01~05-03,B:2024-05-02~05-04),它只对三字段组合值唯一。真要防重叠,得在应用层查SELECT 1 FROM bookings WHERE room_id = ? AND check_in ? -
status字段必须,否则无法区分“已取消但占着日期”的脏数据 - 别省略
CHECK (check_out > check_in),防止插入逻辑错误日期
用户和订单解耦,避免用 users 表直接存客人证件信息
酒店常需为非注册用户(如电话预订)下单,若把身份证号、手机号全塞进 users 表,会导致大量空值或滥用主账号。更合理的是分层:
KGOGOMall 是一套采用 Php + MySql 开发的基于 WEB 应用的 B/S 架构的B2C网上商店系统。具有完善的商品管理、订单管理、销售统计、新闻管理、结算系统、税率系统、模板系统、搜索引擎优化,数据备份恢复,会员积分折扣功能,不同的会员有不同的折扣,支持多语言,模板和代码分离等,轻松创建属于自己的个性化用户界面。主要面向企业和大中型网商提供最佳保障,最大化满足客户目前及今后的独立
-
users表只管登录凭证(email、password_hash、is_staff) -
guests表存真实入住人信息(id_card、phone、real_name),可被多个订单复用 -
bookings表加guest_id外键,指向guests.id;同时保留created_by_user_id(可为空),表示谁下的单
这样既支持散客快速下单,又保留会员积分、历史订单归因能力。
别忽略凌晨 0 点的时间精度问题
MySQL 的 DATE 类型会丢掉时间部分,导致 check_in = '2024-05-01' 实际含义模糊——是 5 月 1 日 00:00 还是 12:00?预订系统必须明确:
- 所有日期字段统一用
DATETIME,并约定:check_in指入住日 14:00 后(标准入住时间),check_out指离店日 12:00 前(标准退房时间) - 查询“某日可用房间”时,条件写成:
WHERE ? NOT BETWEEN check_in AND check_out,注意BETWEEN是闭区间,得配合业务规则调整边界 - 应用层入库前,把用户选的“入住日期”自动转为当天 14:00 的
DATETIME,别依赖前端传时间
时间粒度错一层,库存就可能超卖。这个细节在压测时最容易暴露,但设计阶段就该定死。









