我正在创建一个预订系统:
客户 CUST_ID, CUST_NAME, cust_etc .....
间 ROOM_ID, ROOM_NAME, room_etc
预订 booking_id, 房间号, CUST_NO arrive_date, depart_date
预订表将允许我仅在日历上显示可用性。问题是我想阻止某些时间段被预订。我能看到的唯一方法是在预订表中放入一个条目但不分配cust_id。如果有人能告诉我这是否是最好和最有效的方式,我将不胜感激。
答案 0 :(得分:1)
我建议按以下方式进行:
booking_prevention
。
额外价值:我建议添加一个描述列,其中包含有关当时事件的详细信息。booking_prevention
中的日期重叠,则创建一个阻止向预订表添加新记录的触发器。示例架构:
预订: booking_id,room_no,cust_no arrival_date,depart_date
Booking_prevention: bk_prev_id,date_start,date_end,description
使用PostgreSQL进行测试:
-- Creating a function that would go through every record in booking_prevention table
CREATE FUNCTION trg_prevent_booking ()
RETURNS TRIGGER
STABLE
AS $$
DECLARE
r record;
BEGIN
FOR r IN
SELECT date_start, date_end FROM booking_prevention
LOOP
IF ((NEW.arrive_date, NEW.depart_date) OVERLAPS (r.date_start, r.date_end))
THEN
RAISE EXCEPTION 'You can not book a room on those days! Check booking_prevention table for details'
END IF;
END LOOP;
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
-- Creating a trigger that fires for each row on booking
CREATE TRIGGER prevent_booking BEFORE INSERT ON booking FOR EACH ROW EXECUTE PROCEDURE trg_prevent_booking();
booking_prevention
表中的值:
SELECT * FROM booking_prevention;
id | date_start | date_end | description |
----+------------+------------+--------------
1 | 2015-06-10 | 2015-06-20 | Maintenance |
使用新预订进行测试:
INSERT INTO booking VALUES (default, 5, 1001, '2015-06-03', '2015-06-11');
ERROR: You can not book a room on those days! Check booking_prevention table for details
INSERT INTO booking VALUES (default, 5, 1001, '2015-06-03', '2015-06-09');
INSERT 0 1
考虑优化功能。一个好的开始方法是限制每次触发器触发时记录必须循环的行。
在错误消息中,您还可以从描述中输入值。根据您的需要进行调整。
修改强>
本节是在OP评论担心效率后添加的。
保持booking_prevention
表较小且查找效率较高的一种好方法是创建一个表,该表将保存来自具有date_end < current_date
的预防表的记录。假设您过去不允许系统预订房间,这些记录不再需要检查(我猜这是公平的假设)。
只要您需要存储过去有关预防日期的详细信息,此方法就很有用。如果情况并非如此 - 您可以随时从booking_prevention
表中删除。