航空机票预订系统数据库建模:ER图、数据流图与状态转换图全解析 简介这份航空机票预订系统课程设计文档完整收录系统的结构化分析模型面向前端与后端开发者、系统分析学习者及需要完成课程设计的高校学生。内容以PDF呈现包含实体—关系图、数据流图、状态转换图与数据字典四大部分ER图理清旅行者、航空公司、旅行社、取票通知等实体联系其中旅行者、机票信息、取票通知等核心实体均列出关键属性如姓名、身份证号码、价格、等级、可售机票时间、旅客清单等。数据流图展现订票信息从输入到取票通知的传递路径状态转换图刻画各处理环节迁移数据字典对上述数据项作出清晰定义可直接用于文档撰写、模型校验与答辩演示。资源为单个PDF文件仅57KB轻量易用已有2966人学习下载。适合作为系统分析与设计的参考范本。1. 航空机票预订系统ER图建模文档为什么比代码先走一步这份带ER图、数据流图、状态转换图和数据字典的PDF放在数据库课程设计里经常被当成“交差材料”但它其实是整个系统最先定型的图纸。真正动手写代码前把实体关系、数据流向、订单状态和字段定义在纸面上对齐一遍能省下后面调表结构、改接口的大把时间。适合准备数据库课设、软考案例题或者在航空公司/OTA类项目里做需求分析的从业者。它能回答的问题是“数据从哪里来、到哪里去、怎么变”不负责回答“这个接口用线程池还是消息队列”。2. ER图实体边界怎么定航段与订单的一对多关系是分水岭2.1 先抽实体乘客、订单、航班、舱位四实体是底线拿到一个“航空机票预订系统”的业务描述第一步不是画图而是把业务里的名词挑出来。常见的一组是乘客、订单、航班、舱位这也是很多ER图例题的标配画法。我一般会在这个基础上再加一个“航段”实体因为一张订单可以包含多个飞行段落。“航段”这个概念是航空订座系统的核心。乘客从北京飞上海再转广州在乘客视角是一张票在系统里却是两个航段PEK-CAN、CAN-SHA。如果ER图里只有“订单”和“航班”这两个航段就只能塞进订单属性里要么变成逗号分隔的字符串要么建出非规范化的冗余列。后面做退改签、换开、行李联运都会踩到。实体清单我习惯这样列实体建议主键关键属性一句话定位乘客 PASSENGER乘客ID身份证/护照号、姓名、手机号、常旅客号谁在订票订单 ORDERS订单号下单时间、订单状态、总价一次购买行为航段 SEGMENT航段号航班日期、起降机场、起降时间、舱位、票号一段实际飞行航班 FLIGHT航班号起飞日期机型、计划起飞/到达、出发/到达机场可被预订的班次舱位 CABIN_CLASS航班号日期舱位代码舱位折扣、票价、可售座位数同一航班上的不同价格等级这个表可以直接抄进文档的数据字典草稿但要注意主键那一列在ER图阶段只代表“候选标识”不一定要在图形里全画出来。比如航班在ER图上是一个实体真正落地时它和“起飞日期”往往要合成一张物理表这在后面建表章节再说。2.2 联系与基数不要把所有关系都画成一对多ER图的把关点通常在联系上而不是实体上。一个航空机票预订系统里最常见的联系是乘客和订单一个乘客可以下多张订单一张订单只属于一个乘客1:N。订单和航段一张订单包含多个航段一个航段只属于一张订单1:N。航班和航段一个航班可以对应多个航段同一天同一航班被很多人预订反向一个航段只对应一个航班N:1。航班和舱位一个航班有多个舱位等级Y舱、B舱、F舱1:N。真正需要停下来想的是如果需求描述成“一个乘客可以预订多个航班一个航班可以被多个乘客预订”画出来就是M:N。这时不要直接画一个菱形了事而是拆出一个中间实体最常见的就是“航段”或者“订单航段明细”。拆完之后原来的M:N变成了两个1:N属性也有了归属乘客在哪个航班上坐什么舱位、票价多少钱、票号是多少都挂在“订单航段”上而不是塞在“预订”这个抽象联系里。这一步是很多ER图例题容易翻车的地方。数据库系统概论里那些习题可以接受M:N直接画菱形但机票预订这种带状态、带价格、带票号的业务M:N必然要降级成交叉实体否则后面数据字典没法写建表也没法建。2.3 核心属性取舍字段不在多在于能支撑流程属性抽取的标准是“这个字段将来要有值、要参与计算或状态判断”。我给这份ER图建议的底线属性是乘客证件类型、证件号、姓名、手机号。证件号要加唯一约束因为一个证件号在同一个航班日期上重复订票往往是重复下单。订单订单号、下单时间、订单状态、总票价含税。订单状态的值域要和状态转换图完全一致这是后面避坑章的重点。航段出发机场、到达机场、起飞时间、到达时间、航班号、航班日期、舱位代码、票号。票号在支付完成后才填ETicketNumber允许为空ER图上可以用可空属性标注。航班航班号、机型、计划起降时间、星期几执行。注意只有“航班号日期”才能唯一确定一班可预订的航班所以不要给航班设一个孤立的自增ID除非你同时维护一个航班日期实例表。取舍标准很简单一个属性如果找不到明确的“实体归属”要么是这个实体拆得不够细要么是这个字段根本不该进ER图。很多课程设计会把“备注”挂到所有实体上这不算错但它不参与任何流程属于典型低价值属性文档里出现一两个可以别每个实体都挂。3. 数据流图从顶层到一层逐层分解预订、支付、出票分几步走3.1 顶层图三个外部实体就够了数据流图DFD的第一张不是业务流程而是“上下文图”也叫顶层图。它只有一个加工就是整个系统“航空机票预订系统”外面画外部实体用数据流把系统和外部连起来。这个系统里我推荐只画三个外部实体旅客、支付网关、航司出票/清结算系统。别把“管理员”画进来也别把“数据库表”画出来。管理员维护航班、舱位、价格属于后台配置在核心购票流程里不是必需的外部角色数据库表更不是外部实体它是数据存储画法完全不同。顶层图的数据流建议这样画外部实体输入到系统的数据流系统输出的数据流旅客预订请求、支付请求、退票申请预订结果、待支付信息、出票结果、退票结果支付网关支付成功通知、支付失败通知支付请求、退款请求航司出票系统出票确认票号、退票确认出票申请、取消座位申请如果还要做得严谨一点可以加一个“通知渠道”外部实体接收系统发出的短信/邮件通知。但对于课程设计或内部文档三个外部实体已经能说清楚边界。多画外部实体会让顶层图变得像系统架构图反而丢掉了数据流的重点。3.2 0层图和1层分解预订、支付、出票、退改签四个加工把顶层图里的加工“航空机票预订系统”展开就得到0层图。习惯上拆成四个加工F1预订管理、F2支付管理、F3出票管理、F4退改签管理。数据存储最少四张D1乘客库、D2订单库、D3航段库、D4舱位库存。一条主链路是这样走通的旅客提交“预订请求”流入F1预订管理。F1读D4舱位库存校验可售数预占座位。F1写D2订单库生成“待支付订单”输出“待支付信息”给旅客。旅客发起“支付请求”经支付网关处理返回“支付成功通知”给F2支付管理。F2更新D2订单状态为“已支付”通知F3出票管理。F3向航司出票系统发出票申请收到“出票确认”后把票号写回D2订单库。F3输出“出票结果”给旅客。这一串文字其实比图更值得写进文档说明里。因为DFD只画“谁往谁送了数据”不画时序如果你不配一段这样的文字读者很容易把DFD理解成时序图评审时会被反复追问“支付还没成功为什么就出票了”。如果要画1层图通常只展开F1预订管理。它的子加工可以是1.1校验乘客信息、1.2查询航班舱位与价格、1.3创建订单与航段、1.4预占座位、1.5生成待支付订单。每个子加工都配一条输入流和输出流比如1.4的输入是“已选舱位”输出是“占用结果”数据源是D4舱位库存。这样一层层展开就是从顶层到1层的分解思路。3.3 数据字典配合DFD编号命名不统一最要命DFD图本身只是“骨架”数据字典才是血肉。两者的配合规则是图里出现的每一条数据流、每一个数据存储在数据字典里都必须有对应条目。反过来数据字典里写了但又没在图上出现的流说明图要么画漏了要么该删。我习惯给数据流编号比如“FD-01 预订请求”数据存储编号“D1 乘客库”。编号写在DFD图上数据字典里也用同一套编号。这样评审时从图跳到字典不会出现“图上写订单信息字典里只有订单表”的尴尬。数据流的条目至少要写清楚名称和编号、来源、去向、组成、平均流量。下面是一个示例表格可以直接套用字段内容数据流编号FD-01数据流名称预订请求来源外部实体旅客去向加工F1预订管理组成乘客信息 航班号 起飞日期 航段列表 舱位代码平均流量峰值 20 笔/秒平时 2 笔/秒数据存储的条目则要写清“组成”和“组织方式”。D2订单库的组成是“订单表 订单航段表”组织方式可以是“按订单号索引”。在结构化分析方法里这些条目属于题目标准答案的一部分在实际项目里它决定了开发阶段能不能直接照着写建表脚本。4. 状态转换图与数据字典订单状态机和五类条目必须对得上4.1 状态转换图的状态集电子订单不是只有四个状态很多初学者把订单状态画成“待支付、已支付、已出票、已取消”这就是四条直线。航空机票预订系统的状态转换图至少要区分“用户主动取消”和“支付超时关闭”还要处理“退票中”这个中间态。我建议的最小状态集是状态含义可进入状态待支付订单已创建座位被预占已支付、已取消、已过期已支付支付成功座位锁定等待出票已出票、已取消、已退款已出票票号已返回行程可用退票中、已退票若部分退退票中用户已申请退票等待审核或航司确认已出票审核驳回、已退票已退票票已退金额退还座位释放终态已取消未支付时用户主动取消终态已过期超过支付时限系统自动关闭终态这里“已过期”不是“已取消”的别名。用户主动取消往往发生在下单后几分钟内系统不涉及任何退款超时关闭则是定时任务批量触发还要额外释放预占座位。两个状态背后的触发方式不同在事件统计和座位释放动作上要分开描述合并了后面排查问题会很难受。4.2 事件、动作与守卫条件状态图不画条件字典里要写状态转换图的核心是“状态-事件-动作-下一状态”四元组。这个系统的关键迁移我建议这样列当前状态事件动作下一状态待支付支付成功通知锁定座位、关闭支付倒计时已支付待支付用户主动取消释放座位已取消待支付支付超时释放座位、记录超时原因已过期已支付出票成功写入票号、推送出票结果已出票已支付出票失败释放座位、发起退款已取消已出票用户申请退票记录退票申请、通知航司退票中退票中退票审核通过释放座位、执行退款已退票退票中退票审核驳回恢复可出行状态已出票“支付成功通知”不是唯一事件。同一笔支付可能因为回调延迟、对账差异重复到达状态机里还要考虑“已支付状态下再次收到支付成功通知”怎么办。正确做法是幂等处理事件到达时先判断当前状态如果已经是已支付或已出票则忽略该事件并返回成功响应。状态转换图本身体现不了“支付金额是否一致”“退票时限是否超期”这类守卫条件。我的做法是在数据字典的“加工逻辑说明”里补一段文字加工“F2支付管理”接收支付成功通知校验订单号、支付金额、签名后才触发状态迁移。这样图是干净的校验逻辑也有地方写。4.3 数据字典的五类条目只有数据项列表会被扣分一份完整的数据字典包括数据项、数据结构、数据流、数据存储、加工逻辑五类条目。很多同学只写前两类把后面三类漏了评审时会被直接点出“这不叫数据字典叫字段清单”。数据结构条目描述一个结构的组成例如“订单”由订单号、乘客ID、下单时间、订单状态、总票价组成还可以包含“订单航段列表”。数据流和数据存储条目在前面一节已经给了模板。加工逻辑条目必须针对DFD里的每一个加工写输入数据流、输出数据流、处理逻辑概要。这里给一个DFD加工逻辑条目的示例字段内容加工编号F2加工名称支付管理输入数据流支付成功通知、支付失败通知输出数据流支付结果写订单库、出票触发信号加工逻辑校验订单状态为待支付校验支付金额与订单总价一致更新订单状态为已支付触发F3出票管理数据字典和ER图的属性命名必须一致。我见过一份文档里ER图写“passenger_name”数据字典写“旅客姓名”结果评审会上对不上只能现场改。规范做法是ER图和数据字典统一用英文标识符作为字段名中文名只作为注释出现能少很多扯皮。5. 航空机票预订系统建模避坑六个容易翻车的设计错误与排查5.1 订单不拆航段多个航班塞在属性里现象ER图里“订单”实体属性中同时出现“航班1”“航班2”或者用一个“航班列表”字段包含所有飞行信息。评审时被问“往返票怎么存”“中转票怎么退”答不上来。原因把“订单”和“航班”直接画成多对多联系不愿意引入航段实体属性无法归属。解决把航段(Segment)抽成独立实体订单和航段保持一对多。一张往返订单就是两条航段记录退票时按航段维度处理。这个结构从ER图到关系表都成立。5.2 顶层数据流图里出现数据库表现象有人把“订单表”直接画在顶层图外部和数据流线连在一起看起来像是外部系统在访问表。原因混淆了外部实体和数据存储的符号。数据库表不是系统外的东西它在DFD里属于数据存储只能放在加工边界内部。解决顶层图只保留旅客、支付网关、航司出票系统作为外部实体。订单表、乘客库、舱位库存全部用数据存储符号编号D1、D2、D3放在0层图内部。5.3 状态转换图漏掉“支付超时”迁移现象订单在等待支付时PSP回调始终没到用户也不点取消座位一直占着。测试环境看不出问题生产环境一压测库存就少。原因状态转换图只画了待支付到已支付这一条正向路径忘了定时任务触发的超时关闭。解决在状态转换图里补“待支付 → 已过期”迁移事件名是支付超时动作是释放座位。同时给数据字典的F2加工逻辑写明超时时长和定时任务扫描频率。5.4 数据字典和ER图字段对不上现象文档评审时ER图上写“订单编号 20位”数据字典里“订单号”字段长度写20但类型一个是字符串一个是数值。开发建表时两套标准打架。原因ER图和DFD、数据字典分头编写没人做一致性回读。常见于多人分工完成课程设计的情况。解决用主键字段列表做交叉验证。打开ER图实体清单逐个核对数据字典的数据项条目。我现在的做法是先定ER图再写数据字典写完后把两份文档的字段清单复制到同一张Excel里做VLOOKUP多长一眼就能看出来。5.5 把座位库存画成可随意读写的数据存储现象0层图里D4舱位库存被F1、F2、F3、F4四个加工同时直接读写图面上布满了指向同一个存储的箭头。原因把逻辑数据存储和物理数据库表混为一谈认为“并发扣减”也要画在DFD上。解决DFD里只画“舱位可售数”加工间的读写按业务时序分开。F1预占、F2确认、F4释放虽然底层都操作同一个库存字段但它们在逻辑上是不同的加工。真正的原子扣减逻辑写进加工说明不要用箭头表达并发。5.6 状态转换图里的状态名和代码枚举不一致现象图里写“已支付、已出票”代码里枚举却是PAID和ISSUED测试同学拿着文档对用例发现找不到中文名对应的状态字段。原因状态转换图和数据库设计脱节文档用中文描述代码用英文枚举。解决状态转换图里的状态名直接采用英文枚举名PENDING_PAYMENT、PAID、ISSUED、REFUNDED中文含义放在注释或说明列。这样图、数据字典、数据库、代码四处指向同一套标识走查再也不会出现一对才发现对不上的情况。6. 把ER图转成MySQL建表核心表结构与验证方法6.1 ER图到关系表的两条映射规则ER图转成MySQL表规则只有两条普通实体直接成表属性成列一对多联系把“一”方主键放到“多”方作为外键。基于前面第2章的ER图核心表至少是乘客表、订单表、航段表、航班表、舱位表。航段的航班信息就通过外键关联到航班表不需要在航段表里重复存出发机场、到达机场。下面是订单和航段两个核心表的建表示例可以直接拿去当模板CREATE TABLE orders ( order_id BIGINT PRIMARY KEY AUTO_INCREMENT, passenger_id BIGINT NOT NULL, order_status VARCHAR(20) NOT NULL DEFAULT PENDING_PAYMENT, total_price DECIMAL(10,2) NOT NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_orders_passenger FOREIGN KEY (passenger_id) REFERENCES passenger(passenger_id) ); CREATE TABLE order_segment ( segment_id BIGINT PRIMARY KEY AUTO_INCREMENT, order_id BIGINT NOT NULL, flight_no CHAR(6) NOT NULL, flight_date DATE NOT NULL, cabin_code CHAR(1) NOT NULL, ticket_no VARCHAR(20) NULL, departure_airport CHAR(3) NOT NULL, arrival_airport CHAR(3) NOT NULL, departure_time DATETIME NOT NULL, arrival_time DATETIME NOT NULL, CONSTRAINT fk_segment_order FOREIGN KEY (order_id) REFERENCES orders(order_id) );订单表不直接存航班号而是通过order_segment去关联一个订单可以有多行order_segment这就是“订单和航段1:N”的落库形态。ticket_no允许为空因为出票成功前它确实没有值。这两个表的字段命名、状态枚举必须和文档里完全一致第5章第6条避坑说的就是这里。6.2 用一个中转订单验证全套设计验证ER图、DFD、状态转换图和建表是否一致我习惯拿一个具体业务场景“从头走到尾”。比如乘客张三下了一张北京经上海转广州的单程票订单在ER图里能看到1个乘客、1个订单、2个航段在DFD里能看到F1生成了待支付订单、F3在出票成功后写回两个票号在状态转换图里能看到待支付到已出票经过了四次状态切换在MySQL里应该出现1条订单记录、2条order_segment记录且两条记录的ticket_no都不为空。任何一个环节对不上问题一定出在建模阶段而不是建表阶段。我现在的习惯是先改状态转换图再改代码因为状态图对应着订单状态字段的每一次迁移代码只是它的执行者。顺序反过来就会一边写代码一边跟文档打架。这套“ER图 数据流图 状态转换图 数据字典”的组合本质是把一个黑匣子系统拆成结构、流程、行为、元数据四个维度。花在建模上的时间越多后面改表结构的次数就越少。希望帮到你。本文还有配套的精品资源点击获取