数据库系统设计实现与管理完整性增强特性与触发器 7.11,8.11,8.12习题解答
首先先来一道小题
希尔顿是一跨国旅馆经营公司,其数据库系统中有如下4个表:
Hotel (hotelNo, name, city) Room (roomNo, hotelNo, type, price) Booking (hotelNo, guestId, dateFrom, dateTo, roomNo) Guest (guestId, name, guestcity, creditcard)
使用SQL的DDL写出Booking表的定义,要求至少包含一条业务规则约束;
DDL全称是data,definition,language,数据库设计语言,包含CREATE,DROP,ALTER等等重要关键字,这题我理解的是用Sql创建一个booking表
新建规则包括:
1.房间号定为101-999,百位表示楼层,个位和十位表示房间,假定希尔顿酒店只有九楼
2。订房日期必须大于当前日期,到期时间必须大于订房日期
3…所有的外键都设置为级联更新和删除,这样当外键所在表有改变时,可以及时更新
建表语句为
CREATE TABLE Booking( hotelNo INT NOT NULL, guestId INT NOT NULL, dateFrom DATE NOT NULL CHECK (dateFrom>CURRENT_DATE), dateTo DATE NOT NULL CHECK (dateTo>dateFrom), roomNo INT NOT NULL CHECK (roomNo>100 AND roomNo<1000), PRIMARY KEY(hotelNo,guestId ,dateFrom), FOREIGN KEY(hotelNo) REFERENCES hotel(hotelNo) ON DELETE CASCADE ON UPDATE CASCADE, FOREIGN KEY(guestId ) REFERENCES guest(guestId ) ON DELETE CASCADE ON UPDATE CASCADE, FOREIGN KEY(roomNo ) REFERENCES room(roomNo ) ON DELETE CASCADE ON UPDATE CASCADE );
由于之前建好的表guest的主键是guestno,并且已经有了booking表,为了实现建表成功,所以某些细节小改了一下
以下是书中题目
7.11
这道题考察了SQL完整性增强特性,包括非空数据,域约束,实体完整性,引用完整性,一般性约束
为了保证能创建表,所以重新创建了数据库和hotel表
Room表
CREATE TABLE Room( roomNo INT NOT NULL CHECK (roomNo>=1 AND roomNo<=100), hotelNo INT NOT NULL, type VARCHAR(6) NOT NULL CHECK (type IN ("Single","Double","Family")), price INT NOT NULL CHECK (price>=10 AND price<=100), PRIMARY KEY(roomNo,hotelNo), FOREIGN KEY (hotelNo) REFERENCES hotel(hotelNo) );
按照创建顺序,应该Guest表优先创建,比较简单,就不截图了
Guest
CREATE TABLE Guest( guestNo INT, guestName VARCHAR(10) NOT NULL, guestAddress VARCHAR(10) NOT NULL, PRIMARY KEY(guestNo) );
Booking
CHECK语句可以实现字段内容筛选,直接加在字段声明的后面
使用CONSTRAINT约束实现相同房间不能订两次和客人不能重复预订的功能
此外,EXISTS是有"S"的,别记错了!!!(微笑)
CREATE TABLE Booking( hotelNo INT NOT NULL, dateFrom DATE CHECK (dateFrom>CURRENT_DATE), dateTo DATE CHECK (dateTo>CURRENT_DATE), roomNo INT NOT NULL, guestNo INT NOT NULL, PRIMARY KEY(hotelNo,dateFrom,guestNo), FOREIGN KEY(hotelNo) REFERENCES hotel(hotelNo) ON DELETE CASCADE ON UPDATE CASCADE, FOREIGN KEY(roomNo) REFERENCES room(roomNo) ON DELETE CASCADE ON UPDATE CASCADE, FOREIGN KEY(guestNo) REFERENCES guest(guestNo)ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT roombook CHECK (NOT EXISTS (SELECT * FROM Booking b WHERE Booking.hotelNo=b.hotelNo AND Booking.dateTo >b.dateFrom AND Booking.dateFrom<b.dateTo AND Booking.roomNo=b.roomNo)), CONSTRAINT guestbook CHECK (NOT EXISTS (SELECT *FROM Booking b WHERE Booking.hotelNo=b.hotelNo AND Booking.guestNo=b.guestNo AND Booking.dateFrom<b.dateTo AND Booking.dateTo>b.dateFrom)) );
8.11
触发器顾名思义,在对数据进行操作的时候,如果满足了触发器的条件,那么将会触发器会自动执行
一般形式为:
CREATE TRIGGER trigger_name BEFORE | AFTER|INSTEAD OF INSERT | DELETE | UPDATE [OF 触发列表] ON table_name ……
(a)
语句解释:
RAISE_APPLICATION_ERROR 是将应用程序专有的错误从服务器端转达到客户端应用程序(其他机器上的SQLPLUS或者其他前台开发语言)
PROCEDURE RAISE_APPLICATION_ERROR( error_number_in IN NUMBER, error_msg_in IN VARCHAR2);
error_number_in 之容许从 -20000 到 -20999 之间,这样就不会与 ORACLE 的任何错误代码发生冲突。error_msg_in 的长度不能超过 2k,否则截取 2k。
触发器的参数都要在前面加上new.,比如new.type=“Double”,这个很像高级语言中的this
由于BEGIN语句中包含";",会导致mysql直接终结,所有先用DELIMITER修改分隔符为"//"
DELIMITER // CREATE TRIGGER DoubleRoomPrice BEFORE INSERT ON Room FOR EACH ROW WHEN (new.type="Double" AND new.price<=100) BEGIN RAISE_APPLICATION_ERROR(-20000,"所有双人间的价格要大于100镑"); END // DELIMITER ;
(b)
由于要做比较,此时我们需要声明一个变量vMaxSingleRoomPrice
DELIMITER // CREATE TRIGGER DoublebiggerSingle BEFORE INSERT ON Room FOR EACH Room WHEN (new.type="Double") DECLARE vMaxSingleRoomPrice NUMBER; BEGIN SELECT MAX(price) INTO vMaxSingleRoomPrice FROM Room WHERE type="Single"; IF(new.price<vMaxSingleRoomPrice) RAISE_APPLICATION_ERROR(-20000,"所有双人间的价格要大于最贵的单人间, 其价格是" || vMaxSingleRoomPrice); END IF; END // DELIMITER ;
(c)
不能预订同一房间两次,之前我们在CONSTRAINT约束中用NOT EXISTS做了,用触发器貌似不太好用。
这里我们定义BEFORE触发器,所以功能可以是:
当插入一条数据之前,我们将这条数据的酒店号房间号和订房区域放到表中搜索,如果搜到了重叠的订房区域,就不能再插入
DELIMITER // CREATE TRIGGER CannotBookRoomTwice BEFORE INSERT ON Booking FOR EACH ROW DECLARE vTwice NUMBER; BEGIN SELCET COUNT(*) INTO vTwice FROM Booking WHERE hotelNo=new.hotelNo AND dateTo>new.dateFrom AND dateFrom<new.dateTo; IF(vTwice>0) RAISE_APPLICATION_ERROR(-20000,","不能重复订房间")l; END IF; END; DELIMITER ;
(d)
CREATE TRIGGER BookingGuest BEFORE INSERT ON Booking FOR EACH ROW DECLARE vBookingCount NUMBER; BEGIN SELECT COUNT(*) INTO vBookingCount FROM Booking WHERE guestNo = new.guestNo AND dateFrom <= new.dateFrom AND dateTo >= new.dateTo; IF (vBookingCount > 0) raise_application_error(-20000, ‘Guest ‘ || new.guestNo || ‘ is already booked during these dates’); END IF; END;
(e)
CREATE TRIGGER BookingAfterInsert AFTER INSERT ON Booking FOR EACH ROW DECLARE vGuestName Guest.guestName%TYPE; vGuestAddress Guest.guestAddress%TYPE; BEGIN SELECT g.guestName INTO vGuestName, g.guestAddress into vGuestAddress FROM Guest g, Hotel h WHERE g.guestNo = new.bookingNo AND h.hotelNo = new.hotelNo AND h.city = ‘London’; IF (vGuestName IS NOT NULL AND vGuestAddress IS NOT NULL) INSERT INTO GuestAudit VALUES (vGuestName, vGuestAddress); END iF; END;
8.12
解释:INSTEAD OF触发器指定执行触发器而不是执行触发 的SQL 语句,从而替代触发语句的操作。
在表或视图上,每个 INSERT、UPDATE 或 DELETE 语句最多可以定义一个 INSTEAD OF 触发器。然而,可以在每个具有 INSTEAD OF 触发器的视图上定义视图。
CREATE TRIGGER UpdateLondonHotelRoom INSTEAD OF INSERT ON LondonHotelRoom FOR EACH ROW BEGIN INSERT INTO Hotel (hotelNo, hotelName, city) VALUES (new.hotelNo, new.hotelName, "London"); INSERT INTO Room (roomNo, hotelNo, type, price) VALUES (new.roomNo, new.hotelNo, new.type, new.price); END;小松与蘑菇 原创文章 126获赞 414访问量 12万+ 关注 私信
- 基于Java-SQL sever实现人事管理系统-数据库课程设计(附源码)
- “食面埋伏”餐饮管理系统设计与实现--JAVA开发涉及UI界面、POI、连接数据库
- 数据库系统-设计、实现与管理(一)
- 数据库系统设计实现与管理第六版第7章12,13,14,25,26题解析 与存储过程
- 人事档案信息管理系统的面向对象的分析、设计和实现
- 面向搜索引擎的内容管理系统(CMS)设计——利用Squid反相代理缓存实现网站内容静态发布
- 电影院票务管理系统数据库设计(2)
- 实现业务系统中的用户权限管理--设计篇
- 学生成绩数据库管理系统设计!!!!!!跪求
- 实现业务系统中的用户权限管理--设计篇
- 通过触发器实现数据的完整性设计
- 面向搜索引擎的内容管理系统(CMS)设计——利用Squid反相代理缓存实现网站内容静态发布 转贴
- 实现业务系统中的用户权限管理--设计篇
- 一天总结:初步完成试卷管理系统数据库设计
- 电影院票务管理系统数据库设计(1)
- 实现基于组织机构的数据集权限系统的设计思路讲解【提供完整数据库设计下载】
- 学生成绩管理系统的设计与实现:1
- 实现业务系统中的用户权限管理--设计篇(转)
- 重新设计NBearV3中的实体关联设计语言,实现数据库完整性约束和级联更新
- 基于web技术的工作流管理系统设计与实现