如何设置SQL约束限制每个航班每日的最大可预订乘客数量?
你想要的跨行聚合校验逻辑,无法通过普通的CHECK、UNIQUE这类单表原生约束实现,必须通过以下方案落地:
更优的配置方式(替代硬编码CASE)
首先不要把航班限额写死在逻辑中,新增一张独立的航班日配额配置表,后续新增航班、调整限额只需要修改这张表的数据即可,不需要改动任何约束/业务代码:
CREATE TABLE dbo.FlightQuota ( FlightNum char(6) PRIMARY KEY, DailyMaxBookings int NOT NULL CHECK (DailyMaxBookings > 0) ); -- 写入现有航班的配额 INSERT INTO dbo.FlightQuota (FlightNum, DailyMaxBookings) VALUES ('AIR001',5), ('AIR002',6);
方案1:INSERT/UPDATE触发器(全数据库兼容,逻辑直观)
在预订表上新增触发器,每次新增、修改预订记录时自动校验对应航班当日的预订人数是否超出配额,超额则直接回滚操作:
CREATE TRIGGER trg_Airline_CheckBookingQuota ON dbo.Airline AFTER INSERT, UPDATE AS BEGIN SET NOCOUNT ON; -- 校验本次操作涉及的所有航班+日期组合是否超额 IF EXISTS ( SELECT 1 FROM inserted i INNER JOIN dbo.FlightQuota q ON i.FlightNum = q.FlightNum INNER JOIN dbo.Airline a ON a.FlightNum = i.FlightNum AND a.FlightDate = i.FlightDate GROUP BY i.FlightNum, i.FlightDate, q.DailyMaxBookings HAVING COUNT(a.FlightNum) > q.DailyMaxBookings ) BEGIN RAISERROR('指定航班当日预订名额已满,操作失败', 16, 1); ROLLBACK TRANSACTION; END END
方案2:索引视图+CHECK约束(SQL Server专属,性能更优)
如果你使用的是SQL Server数据库,可以用索引视图自动维护预订人数统计,再通过约束限制超额,不需要手动写触发器逻辑,性能更高:
- 建绑定Schema的统计视图
CREATE VIEW vw_FlightDailyBookingCount WITH SCHEMABINDING AS SELECT a.FlightNum, a.FlightDate, COUNT_BIG(*) AS BookingCount, MAX(q.DailyMaxBookings) AS DailyMaxQuota FROM dbo.Airline a INNER JOIN dbo.FlightQuota q ON a.FlightNum = q.FlightNum GROUP BY a.FlightNum, a.FlightDate;
- 给视图建聚集索引,让数据库自动维护统计数据
CREATE UNIQUE CLUSTERED INDEX idx_vw_FlightDailyBookingCount ON vw_FlightDailyBookingCount (FlightNum, FlightDate);
- 给视图加CHECK约束实现超额限制
ALTER VIEW vw_FlightDailyBookingCount ADD CONSTRAINT ck_BookingCount_Not_Exceed_Quota CHECK (BookingCount <= DailyMaxQuota);
内容的提问来源于stack exchange,提问作者Shmiel
相关产品推荐
相关产品推荐

