资讯动态

Oracle数据库课程设计:机票预订系统建表、视图、存储过程与避坑指南

发布时间:2026/10/3 5:18:12 来源:尧图企业网站定制
简介这是一份数据库课程设计文档主题为机票预订系统适合高校计算机、软件工程专业学生完成大型数据库课程设计或Oracle综合实验时参考。文档围绕航空客运订票业务从需求分析入手确定航班、机票、乘客、业务员等核心实体及联系绘制E-R模型并转换为关系模型再在Oracle环境下完成表空间创建、数据库表设计、参数化视图、存储过程、函数与触发器编写同时规划系统角色、用户权限及数据备份与恢复方案完整展现了从业务建模到数据库落地实现的过程。资源仅含1个doc格式文件大小约1.2MB文档中包含详细的设计步骤、E-R图说明及可参考的SQL语句能够帮助读者快速理解数据库设计规范。已有84人学习使用适合需要完成同类课程设计、撰写实验报告或复习Oracle数据库开发的同学查阅。1. 从一份课程设计文档拆出的机票预订系统交付物不止是建表SQL你下载的这份《数据库课程设计机票预订系统.doc》说白了是一整套能在 Oracle 里直接跑起来的数据库方案不是那种只堆概念凑字数的论文。最反直觉的一点Oracle 原生不支持带参数的视图但这份设计偏偏用全局临时表把参数传了进去实现了按航班号、按出发地和目的地动态查询航班信息的效果。整套方案包含 E-R 图、八张业务表的完整建表 SQL、四个业务视图、批量生成机票的存储过程、触发器以及角色权限和备份方案的规划。它解决的核心问题是数据库课程设计验收时评委想看的不只是建了几张表而是从需求分析到备份恢复的完整链路。适合三类人——正在做 Oracle 课程设计的学生、要把这份文档复现成实际库的人、以及想学 PL/SQL 视图传参和存储过程批量生成模板的开发者。2. 从E-R模型到表空间实体关系先理清库表才不散2.1 实体、属性与关系一张图看清业务骨架这份设计的第一步是梳理业务实体。系统里一共有七个实体航空公司、飞机、航班、机舱、机票、乘客、业务员外加一个“售票”联系。实体和属性的划分直接影响后面的表设计先看清楚再动手建库。实体核心属性与哪些实体发生关系航空公司 company企业编号、企业名、企业电话、企业地址拥有一架飞机、多名业务员飞机 airplane飞机编号、飞机名称隶属于航空公司、执飞多个航班航班 flight航班号、出发地、目的地、起飞时刻、飞行时间由某飞机执飞、下挂多个机舱等级机舱 cabin机舱等级、座位数、定价、折扣属于某航班、容纳多张机票机票 ticket机票编号、登机日期、预定状态、座位号属于某机舱等级、被业务员售出乘客 passenger身份证号、姓名、联系电话、住址购买机票业务员 salesman业务员编号、姓名、身份证号、联系电话、住址属于某航空公司、办理售票这里有一个容易被忽略的设计点机票和乘客之间不是直接外键而是通过 ticketsale 表来桥接。ticketsale 有三个外键机票号、乘客身份证、业务员号还带一个售票日期属性。这种中间表设计能支持“一个乘客买多张票”“一个业务员卖多张票”的多对多关系也方便后面做销售业绩统计。如果你在课程设计答辩时被问“为什么多一张 ticketsale 表”答案就是E-R 图里的多对多联系必须转换成独立的关系表。2.2 表空间分配数据量决定分布策略文档里的表空间分配逻辑很直白乘客表、机票表和售票表数据量大单独分配表空间其他表数据量小共用一个。这个判断在真实业务里是合理的——机票表会随着日期和座位数快速增长乘客表会持续积累把它们和字典表混在同一个数据文件里会加剧碎片化和 I/O 竞争。CREATE SMALLFILE TABLESPACE PASSENGER DATAFILE F:\APP\ORACLE\ORADATA\ORCL\TICKETSALE\passenger.dbf SIZE 100M AUTOEXTEND ON NEXT 5M MAXSIZE UNLIMITED LOGGING EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO; CREATE SMALLFILE TABLESPACE TICKET DATAFILE F:\APP\ORACLE\ORADATA\ORCL\TICKETSALE\ticket.dbf SIZE 100M AUTOEXTEND ON NEXT 5M MAXSIZE UNLIMITED LOGGING EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO; CREATE SMALLFILE TABLESPACE TICKETSALE DATAFILE F:\APP\ORACLE\ORADATA\ORCL\TICKETSALE\ticketsale.dbf SIZE 100M AUTOEXTEND ON NEXT 5M MAXSIZE UNLIMITED LOGGING EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO; CREATE SMALLFILE TABLESPACE OTHERS DATAFILE F:\APP\ORACLE\ORADATA\ORCL\TICKETSALE\others.dbf SIZE 100M AUTOEXTEND ON NEXT 5M MAXSIZE UNLIMITED LOGGING EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO;参数说明SMALLFILE表示传统小文件表空间适合课程设计这种单数据文件的场景AUTOEXTEND ON NEXT 5M表示文件满了自动扩展每次扩 5MMAXSIZE UNLIMITED表示不设上限EXTENT MANAGEMENT LOCAL是本地化管理区现代 Oracle 默认值避免数据字典表的争用SEGMENT SPACE MANAGEMENT AUTO让段空间用位图自动管理比较省心。常见的坑是数据文件路径。文档里的F:\APP\ORACLE\ORADATA\ORCL\TICKETSALE\是原作者机器上的路径你换一台电脑复现时如果那个目录不存在Oracle 会直接报 ORA-01119。我一般会把路径改成自己本机 Oracle 的ORADATA路径先建好目录再执行。这里提一句容量估算单表空间初始 100M 对课程设计完全够用但 title 表按日期和座位数增长后一个月的机票记录可能达到上万行AUTOEXTEND这时候就是后悔药不会因为忘记手动扩文件导致插入失败。2.3 建表与主外键从关系模型到 Oracle 表关系模型在文档里已经推导得很完整建表就是照着关系模型逐张落地。注意原设计把表建在了SYSTEM用户下这在实际工程里不推荐但课程设计为了答辩方便能跑就行这里保留原样。CREATE TABLE SYSTEM.COMPANY ( CNO VARCHAR2(10) NOT NULL, CNAME VARCHAR2(20) NOT NULL, CTEL VARCHAR2(20), CADDRESS VARCHAR2(50), PRIMARY KEY (CNO) VALIDATE ) TABLESPACE OTHERS; CREATE TABLE SYSTEM.PASSENGER ( PID VARCHAR2(20) NOT NULL, PNAME VARCHAR2(20) NOT NULL, PTEL VARCHAR2(20), PADDRESS VARCHAR2(50), PRIMARY KEY (PID) VALIDATE ) TABLESPACE PASSENGER; CREATE TABLE SYSTEM.SALESMAN ( SNO VARCHAR2(10) NOT NULL, SID VARCHAR2(20) NOT NULL, SNAME VARCHAR2(20) NOT NULL, STEL VARCHAR2(20), SADDRESS VARCHAR2(50), CNO VARCHAR2(10) NOT NULL, PRIMARY KEY (SNO) VALIDATE, FOREIGN KEY (CNO) REFERENCES SYSTEM.COMPANY (CNO) VALIDATE ) TABLESPACE OTHERS;字段类型的选择有几个细节值得在答辩时说清楚。CNO、SNO这类编号用VARCHAR2而不是NUMBER因为业务编号通常带前缀且不会参与数值计算PID用 20 位VARCHAR2是考虑到身份证号有 X 结尾PRICE用NUMBER(5)能存 99999 以内的价格DISCOUNT用NUMBER(3,2)表示 0.00 到 9.99 之间的折扣系数精确到小数点后两位。这些类型看着琐碎但答辩时老师最喜欢追问“为什么不用 NUMBER”。CREATE TABLE SYSTEM.FLIGHT ( FNO VARCHAR2(10) NOT NULL, DEPARTURE VARCHAR2(20) NOT NULL, ARRIVAL VARCHAR2(20) NOT NULL, TIME DATE NOT NULL, FLYTIME INTERVAL DAY TO SECOND NOT NULL, ANO VARCHAR2(10) NOT NULL, PRIMARY KEY (FNO) VALIDATE, FOREIGN KEY (ANO) REFERENCES SYSTEM.AIRPLANE (ANO) VALIDATE ) TABLESPACE OTHERS;FLYTIME用INTERVAL DAY TO SECOND是这份设计里比较讲究的地方。飞行时长不是某个时间点而是一段时长用INTERVAL类型表达语义最准确还能直接参与时间运算——视图里那句time flytime就是靠它算出抵达时间的。如果当初用NUMBER存小时数每次算抵达时间都得手动换算视图的写法会丑很多。TIME字段起名要注意它不是 Oracle 保留字能直接建但如果用别的数据库工具连接可能触发关键字校验稳妥的做法是叫DEPARTURE_TIME。CREATE TABLE SYSTEM.TICKET ( TNO NUMBER(10) NOT NULL, FNO VARCHAR2(10) NOT NULL, CBLEVEL NUMBER(1) NOT NULL, FLYDATE DATE NOT NULL, STATUS NUMBER(1) DEFAULT 1 NOT NULL, SEAT NUMBER(3) NOT NULL, DISCOUNT NUMBER(3,2) NOT NULL, PRIMARY KEY (TNO) VALIDATE, FOREIGN KEY (FNO,CBLEVEL) REFERENCES SYSTEM.CABIN (FNO,CBLEVEL) VALIDATE ) TABLESPACE TICKET;STATUS NUMBER(1) DEFAULT 1这里的 1 表示未售、0 表示已售用数值而不是字符串是为了让存储过程里判断更轻量。复合外键(FNO,CBLEVEL)对应 cabin 的复合主键保证机票一定挂在某个有效航班的有效舱位上。ticketsale 的主键是(TNO, PID, SNO)三列联合也是从 E-R 图多对多联系直接映射来的。整张表建完后建议自查一遍各表是否都放到了规划的表空间里常见错误是忘了在 CREATE TABLE 末尾写TABLESPACE结果全部落进默认 USERS 表空间答辩时被问“你设计的表空间分配在哪”就露馅了。3. 参数化视图用全局临时表绕过 Oracle 的视图参数限制3.1 为什么 Oracle 视图不能带参数而业务又需要参数化先讲一个反直觉的事实Oracle 的普通视图不支持参数。MySQL 里可以定义带输入参数的视图但 Oracle 里视图就是一个被固化的 SELECT 语句每次查询只能通过 WHERE 条件来限定无法像调用存储过程那样传入“航班号”“出发地”这样的运行时参数。而这份机票系统的业务恰恰是参数化的——用户查航班得输出发地和目的地查余票得输航班号和日期。常见做法有两种一种是用包PACKAGE里的游标函数返回结果集另一种就是这份设计采用的全局临时表传参。临时表方案对课程设计更友好直观而且好讲步骤就是“先往临时表插参数再查视图”视图内部去临时表取参数拼接条件。这种设计在真实业务里也有应用但要注意它有个天然限制临时表的数据是会话级的会话之间互相隔离且必须在同一会话里先插参数再查视图跨会话就会翻车。3.2 传参通道INPUT_TO_FLIGHT 临时表的设计这份设计的传参载体是一张全局临时表专门用来接收应用端传入的查询条件。它的四个字段对应四个查询维度航班号、出发地、目的地、航班日期。CREATE GLOBAL TEMPORARY TABLE SYSTEM.INPUT_TO_FLIGHT ( T_FNO VARCHAR2(10), T_DEPARTURE VARCHAR2(20), T_ARRIVAL VARCHAR2(20), T_FLYDATE DATE ) ON COMMIT PRESERVE ROWS;参数说明GLOBAL TEMPORARY TABLE表示全局临时表数据只在当前会话可见ON COMMIT PRESERVE ROWS表示事务提交后数据仍然保留到会话结束选这个模式是因为应用端需要先插参数、再执行视图查询如果提交后数据被清空ON COMMIT DELETE ROWS两步操作之间就断了。这种做法也带来一个使用约定每次查询前必须先写临时表查询结束后最好清掉这几行否则下一次查询的参数会被旧数据污染。我在复现时踩过这个坑查完“广州到长沙”后没清表直接插了一个航班号参数去查余票结果 flight 视图因为同时匹配到了旧参数和新参数返回结果要么为空要么串了数据。解决办法很简单应用端每次查询前先DELETE FROM input_to_flight再插新参数养成习惯。3.3 三个核心视图航班查询、余票视图、机票打印第一个视图是航班信息查询支持按航班号精确查也支持按出发地和目的地组合查。视图里 JOIN 了 flight、airplane、company 三张表把航班号对应的公司名、飞机名带出来同时用time flytime动态计算抵达时间。CREATE OR REPLACE VIEW SYSTEM.FLIGHT_VIEW_BYFNO ( FNO,CNAME,ANAME,TIME,ARRIVAL_TIME,DEPARTURE,ARRIVAL ) AS SELECT fno, cname, aname, time, time flytime, departure, arrival FROM flight, company, airplane, input_to_flight WHERE flight.ano airplane.ano AND airplane.cno company.cno AND fno input_to_flight.T_fno;这个视图的巧妙之处在最后的关联条件fno input_to_flight.T_fno让视图结果完全由临时表里的参数决定。你插 F0001视图就只返回 F0001 的信息你插别的号结果跟着变。这样普通视图就实现了参数化查询的效果。同理按出发地和目的地查询的版本叫 FLIGHT_VIEW_BYSITE条件改为departure input_to_flight.T_departure AND arrival input_to_flight.T_arrival其余 JOIN 完全一样。第二个视图是余票查询文档里叫 REMAIN_SEATS_VIEW它需要调用后面会讲的 count_ticket 函数来算某航班某日期某舱位的剩余座位数。SQL 里有一个细节视图用了SELECT DISTINCT因为 ticket 表对同一航班同一日期同一舱位会有多行记录每行都会触发一次函数调用不用 DISTINCT 就会出现一排重复的余票数。第三个视图是售票后打印机票用的 TICKET_INFO_VIEW。乘客买完票票面上要印出公司名、飞机名、出发地、目的地、日期、起飞抵达时间、舱位、座位、原价、折扣、实付金额、乘客姓名身份证、业务员姓名。这个视图 JOIN 了 ticket、flight、airplane、company、passenger、salesman、ticketsale、cabin 一共八张表核心计算是price * discount得出实付价。这属于典型的多表关联查询答辩时能把这八张表的连接关系讲清楚基本就是加分项。查这个视图时同样要先往临时表里插参数视图内部靠ticket.fno flight.fno链条和临时表参数联动。3.4 查询方式与调用边界同一会话里完成两步参数化视图的调用方式很固定先插参数再查视图。假设要查“茂名到长沙”的航班INSERT INTO input_to_flight VALUES (, 茂名, 长沙, ); SELECT * FROM flight_view_bysite;这时视图返回 F0007、F0008 这类满足条件的航班。注意插入参数时不需要的条件要传空字符串或 NULL视图里的 WHERE 条件会忽略掉空值对应的列。这里有个边界一定要记住临时表是会话级的SQL*Plus 里连的是同一个会话两步能跑通但如果用连接池的应用连接数据库两次请求可能落在不同会话里第二步查视图时临时表是空的结果就是空表。解决方法是把两步包在同一个事务短连接里或者干脆把插参数和查询封装成一个存储过程对外提供。文档里余票查询那段 SQL 有个笔误SELECT * FROM remain_seats_view ORER BY cblevel里的ORER是ORDER的拼写错误复现时直接改成ORDER BY cblevel就行。这种 OCR 类文档里的小错不少照着抄 SQL 前最好过一遍语法。4. 存储过程、函数与触发器把重复劳动交给数据库4.1 create_ticket按航班舱位批量生成机票机票表的数据量是最大的一个航班多个舱位每个舱位几十上百个座位一天一个航班就要生成几百行手工 INSERT 不现实。文档用存储过程 CREATE_TICKET 解决了批量生成问题。它的核心是一个双循环外层循环舱位等级内层循环该舱位的座位数逐行插入 ticket 表。为了让票号有序不重复还专门建了一张 T_NUMBER 表保存当前票号。CREATE TABLE SYSTEM.T_NUMBER ( TNO NUMBER(10) ); CREATE OR REPLACE PROCEDURE SYSTEM.CREATE_TICKET ( p_fno varchar2, p_flydate date, p_discount number ) AS v_cblevel_count number; v_ticket_count_by_cblevel number; v_tno number; BEGIN SELECT count(1) INTO v_cblevel_count FROM cabin WHERE fno p_fno; SELECT tno INTO v_tno FROM t_number; FOR v_i in 1..v_cblevel_count LOOP SELECT seats INTO v_ticket_count_by_cblevel FROM cabin WHERE fno p_fno AND cblevel v_i; FOR v_j IN 1..v_ticket_count_by_cblevel LOOP INSERT INTO ticket VALUES (v_tno, p_fno, v_i, p_flydate, 1, v_j, p_discount); v_tno : v_tno 1; END LOOP; END LOOP; UPDATE t_number SET tno v_tno; END;参数说明p_fno是航班号p_flydate是航班日期p_discount是本次统一折扣率。过程先查该航班有几个舱位等级再读 T_NUMBER 里当前票号作为起始编号外层循环每个舱位内层循环根据 seats 字段生成对应数量的票票号逐张累加最后把新票号写回 T_NUMBER。内层 INSERT 里第 5 个参数固定是 1表示新票状态都是“未售”第 6 个参数v_j就是座位号从 1 排到 seats保证一张票一个座。调用示例CALL create_ticket(F0003, to_date(2020-06-10, yyyy-mm-dd), 0.7);注意我这里的日期写成了2020-06-10文档里的写法是to_date(-6-10,yyyy-mm-dd)年份缺失Oracle 会报 ORA-01861这在第 5 章展开说。执行成功后ticket 表会新增该航班所有舱位、所有座位的票每张票的状态都是未售、折扣统一 0.7。这个存储过程有几个可以优化的点T_NUMBER 表只有一行两个会话同时调用时可能取到同一个票号还有删除的票号不会回收票号会一直涨。真实工程里一般用序列或者SELECT ... FOR UPDATE来控制课程设计做到这个程度已经够用了。4.2 count_ticket 函数余票计算与视图联动余票视图调用了 count_ticket 函数它的逻辑很直接统计 ticket 表里某航班某日期某舱位且状态为未售的票数。文档只给了调用它的视图函数体没有展开但按视图使用方式函数签名和内部逻辑是可以明确补全的。CREATE OR REPLACE FUNCTION count_ticket ( p_fno varchar2, p_flydate date, p_cblevel number ) RETURN number IS v_count number; BEGIN SELECT count(1) INTO v_count FROM ticket WHERE fno p_fno AND flydate p_flydate AND cblevel p_cblevel AND status 1; RETURN v_count; END;参数说明三个入参分别对应用户要查的航班号、日期、舱位等级返回值是该条件下未售票的数量。视图里对每行调用函数配合SELECT DISTINCT避免重复输出。这种“函数包在视图里”的写法在课程设计层面很讨巧但性能上有隐患——视图每返回一行都会执行一次函数ticket 表一大了查询会很慢实际项目一般会把聚合逻辑写成 JOIN 或 GROUP BY而不是对每行调函数。答辩时如果被问到性能能答出这一点会显得你真的跑过数据。4.3 触发器售票数据完整性的一道保险需求里要求至少有 1 个触发器文档 3.5 节只列了“触发器设计”这个标题没有给出具体 SQL。按这套表结构最值得做的触发器是售票前校验票状态。ticketsale 表插入一条售票记录时触发器检查对应票是否未售已售则报错否则插入成功后把票状态改为已售。这样即使应用端忘了更新状态数据库层也能兜底。CREATE OR REPLACE TRIGGER trg_ticketsale_insert BEFORE INSERT ON ticketsale FOR EACH ROW DECLARE v_status NUMBER; BEGIN SELECT status INTO v_status FROM ticket WHERE tno :NEW.tno; IF v_status ! 1 THEN RAISE_APPLICATION_ERROR(-20001, 该机票已售出无法重复销售); END IF; UPDATE ticket SET status 0 WHERE tno :NEW.tno; END;触发器的关键是FOR EACH ROW行级触发和:NEW伪记录。:NEW.tno代表正在插入的这行 ticketsale 的机票号先查 ticket 的当前状态不是 1 就抛异常中断插入是 1 就把票状态改成 0。这里有个隐患两张表之间没有显式事务包裹的话如果 UPDATE 成功但 INSERT 因为其他原因回滚票状态会被错误改成已售。稳妥做法是在触发器里同时处理或者干脆把两步写成一个存储过程由应用端统一调用。课程设计场景里触发器能拦住“同一张票卖两次”的核心翻车点就够了。4.4 角色、用户与权限不要三个业务员共用一个账号文档 3.6 节规划了角色、用户、权限但没有给出落地 SQL。按这套系统的业务至少分三类角色管理员负责录航班、生成机票业务员负责售票、查自己的业绩普通游客只能查航班和余票。Oracle 里的落地方式是先建角色再把角色授权给具体的用户。CREATE ROLE ticket_admin; CREATE ROLE ticket_salesman; CREATE ROLE ticket_guest; GRANT SELECT ON flight_view_bysite TO ticket_guest; GRANT SELECT ON remain_seats_view TO ticket_guest; GRANT INSERT, UPDATE ON ticketsale TO ticket_salesman; GRANT SELECT ON salerecord_view TO ticket_salesman; GRANT SELECT ON sale_grade_view TO ticket_salesman; GRANT EXECUTE ON create_ticket TO ticket_admin; CREATE USER sales_zhang IDENTIFIED BY sales_zhang_pwd; GRANT ticket_salesman TO sales_zhang;权限规划的原则是最小权限。业务员只需要售票相关的插入和查询不需要碰 ticket 表本身的批量生成批量生成票是管理员的事所以EXECUTE ON create_ticket只给了 admin 角色。文档把表都建在 SYSTEM 名下实际是拿超级用户当业务库用这不安全但要改会动到整篇 SQL 的所有者前缀课程设计验收一般不看这么深复现时能跑通就行。真要按照规范做我会单独建一个 TICKET_USER 用户把这些表全部归到这个用户下再按角色授权。5. 避坑复现这个课程设计最容易翻车的五个地方5.1 日期传参翻车to_date 少年份直接报错现象按照文档里to_date(-6-10,yyyy-mm-dd)执行 create_ticket 或查询余票Oracle 直接报ORA-01861: literal does not match format string。原因格式串要求四位年份但传入的字符串只有月和日格式对不上。解决改成完整的四位年份如to_date(2020-06-10,yyyy-mm-dd)。文档里因为排版省略了年份复现时尤其要注意所有涉及日期的 INSERT 和 CALL 都要补全年份。5.2 临时表参数残留上一次查询污染下一次结果现象先查“广州到长沙”的航班再查“F0003 余票”结果返回空或者数据对不上。原因input_to_flight 表里有上一次查询留下的出发地和目的地余票视图的fno input_to_flight.t_fno AND flydate input_to_flight.T_FLYDATE虽然只用了航班号和日期但如果旧参数里有别的值视图关联时语义会混乱。解决每次查询前先DELETE FROM input_to_flight再插入本次参数查询顺序保持“清空→插入→SELECT”。这个操作要固化到应用端的查询方法里别指望人工每次记得。5.3 T_NUMBER 并发取号两个会话拿到同一个票号现象两个终端同时执行 create_ticket生成的 ticket 表里出现重复 TNO主键冲突或数据错乱。原因T_NUMBER 表存的是当前票号两个会话同时执行SELECT tno INTO v_tno FROM t_number拿到同一个起始值。解决把读票号的语句改成SELECT tno INTO v_tno FROM t_number FOR UPDATE锁住这行直到事务结束或者干脆换成 Oracle 序列CREATE SEQUENCE seq_ticket循环里直接用seq_ticket.NEXTVAL取号。课程设计单人单机跑一般碰不到但我做过演示时现场被老师开两个 SQL*Plus 窗口测试当场就重现了。5.4 count_ticket 逐行调用函数数据一大查询就慢现象余票视图查一个航班 30 天的余票SQL 跑了十几秒才出结果。原因视图对返回的每一行都执行一次 count_ticket 函数等于在结果集上隐式做循环机票数据越多函数调用次数越多。解决把函数改写成 GROUP BY 聚合直接关联或者限制查询范围只查单日单航班。原设计方案为了演示“函数和视图联动”牺牲了性能。实际开发时我会把余票查询落成一条原生 SQLSELECT fno, cblevel, count(1) FROM ticket WHERE fno? AND flydate? AND status1 GROUP BY fno, cblevel。5.5 表空间路径写死换机器复现必报 ORA-01119现象执行 CREATE TABLESPACE 时报ORA-01119: error in creating database file。原因文档里的F:\APP\ORACLE\ORADATA\ORCL\TICKETSALE\是原作者电脑的路径你的 Oracle 安装路径大概率不一样目录也不存在。解决先看自己 Oracle 的ORACLE_BASE和ORACLE_HOME路径手动创建TICKETSALE目录把四段 CREATE TABLESPACE 里的路径全部替换掉。顺便说一句路径里别带中文Oracle 对中文路径的支持一直很玄学装上能跑是运气跑不起来才是常态。6. 验证方法一条链路走完从建库到出票整个系统的验证不需要搞复杂的测试框架按业务顺序走一遍 SQL 就能确认每个模块是通的。我每次拿到这类课程设计资源都会强制自己把全链路脚本按顺序执行一遍不跳过任何一步。第一段验证库结构。表空间、八张表、临时表建好后执行SELECT table_name, tablespace_name FROM user_tables ORDER BY table_name核对每张表是否落在规划的表空间里重点看 ticket 是否在 TICKET 表空间、passenger 是否在 PASSENGER 表空间。第二段验证参数化视图。这是整套设计最出彩的部分DELETE FROM input_to_flight; INSERT INTO input_to_flight VALUES (, 广州, 长沙, ); SELECT * FROM flight_view_bysite; DELETE FROM input_to_flight; INSERT INTO input_to_flight VALUES (F0003, , , to_date(2020-06-10, yyyy-mm-dd)); SELECT * FROM remain_seats_view ORDER BY cblevel;查完航班再查余票两次查询之间必须重写临时表把第一步的旧参数清掉。第三段验证存储过程生成机票。调用 create_ticket 后查SELECT count(1) FROM ticket WHERE fnoF0003 AND flydateto_date(2020-06-10,yyyy-mm-dd)数量应该等于该航班所有舱位座位数之和。然后模拟一次完整售票INSERT INTO ticketsale VALUES (1, 440902199001011234, S0001, sysdate); SELECT * FROM ticket_info_view WHERE tno 1;能查出印有乘客姓名、业务员姓名、折扣后实付价的完整记录说明八表关联视图的 JOIN 条件全部正确。再查一次SELECT * FROM sale_grade_view确认销售总额统计是按price*discount正确聚合的。第四段验证权限和备份。用一个业务员账号登录后它应该能查 salerecord_view 和 sale_grade_view但不能执行 create_ticket这能确认 GRANT 授权生效。备份命令我一般是这么验证-- 数据泵导出验证备份方案可执行 expdp system/oracle schemassystem directoryDATA_PUMP_DIR dumpfileticket_backup.dmp logfileticket_backup.logEXPDP 能正常完成就没有大问题。容量估算可以用一个简单公式ticket 表的行数约等于“航班数 × 每个航班的座位总数 × 运营天数”。按文档示例数据8 个航班、每个航班两个舱位共 130 座、运营 30 天就是8 * 130 * 30 31200行这个量级对 100M 初始表空间是安全的。从那以后我每次复现数据库课程设计资源都强制自己把“建库→建表→查视图→跑存储过程→模拟售票→导出备份”完整走一遍中途所有报错全部记下来恰恰是这些报错让这个资源真正变成自己的。希望这份拆解帮到你少踩几个我已经替你踩过的坑。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑