本文已上传SQL源码及设计报告文档供参考
目录
课程设计报告格式及要求:
课程设计作业要求:
(1)以《数据库系统的设计与实现》为题目完成课程设计报告,内容及写法可以参照教材。
(2)所选应用系统不能与教材三个应用系统相同,可以参考项目库中题目,推荐大家自拟题目。
(3)具体内容应该包括如下:
- 系统需求分析
- 数据库设计(概念结构、逻辑结构、其他模式对象设计(序列视图等))
- PL/SQL 功能模块设计
- 数据库实现(主要是模式对象和 PL/SQL 程序的实现)
- 数据库运营维护(主要是安全管理、备份与恢复管理等)
- 设计报告中有八九个表,存储过程六七个, 6 个 sql 案例。
一、封面;
二、目录;
三、设计任务书; - 课程设计系统名称
- 系统功能说明
- 测试说明
- 进度安排
四、
五、程序功能简介;
六、主体内容:
1.需求分析
2.概念模型设计(画 E-R 图)
3.逻辑结构设计,转换成关系模型 - 数据库的实现,创建表空间及表的代码及主要查询代码
5.创建视图、存储过程、触发器等的主要代码
6.权限设置及数据库备份 - 系统用户界面设计与实现
七、设计体会。
需求分析
本文设计的基于Oracle数据库的停车场管理系统旨在解决当前城市停车难的问题。
通过对停车场内的车辆信息进行有效管理,可以提高停车场的使用率,缓解停车难问题。
此外,该系统还可以为政府部门提供有关停车场使用情况的数据支持,有助于城市规划和建设。
一个常见的停车场收费管理系统可以包含如下几个功能模块:
- 车辆信息模块:此模块的功能是管理车辆的基本信息。包括车辆的ID,品牌,型号,颜色,车主ID等。用户(通常是管理员或车主)可以通过此模块进行车辆信息的添加,修改或删除。
- 车辆进入停车场记录模块:此模块用于记录车辆进入停车场的时间以及该车辆所使用的停车位。当车辆进入停车场时,系统会自动记录进入时间,同时将该车辆与所使用的停车位相关联。
- 车辆离开停车场记录模块:此模块用于记录车辆离开停车场的时间以及该车辆所使用的停车位。当车辆离开停车场时,系统会自动记录离开时间,同时将该停车位解除与该车辆的关联。
- 停车费用支付信息模块:此模块管理停车费用的支付信息。当车辆离开停车场并产生停车费用时,系统会自动记录支付信息,包括支付时间,支付方式(如现金,信用卡等),应付款项和已付款项。
- 停车位信息模块:此模块的功能是管理停车位的基本信息。包括停车位的ID,类型(如普通,VIP等),状态(如空闲,占用等),以及停车场ID。管理员可以通过此模块进行停车位信息的添加,修改或删除,也可以查看停车位的占用情况。
- 车主信息模块:此模块的功能是管理车主的基本信息。包括车主的ID,姓名,联系方式,地址,拥有的车辆数量以及停车场ID(如果车主拥有自己的停车场)。管理员可以通过此模块进行车主信息的添加,修改或删除。
概念结构设计
根据系统需求分析,我们预计将使用到6个实体。
- 车辆信息是一个实体,它代表了一辆汽车的具体描述和详情。这些详情可能包括车辆的ID、品牌、型号、颜色、车主ID等。
- 车辆进入停车场记录也是一个实体,它代表了车辆进入停车场的时间和事件。这个实体包含进入时间以及与该车辆关联的停车位信息。
- 车辆离开停车场记录是另一个实体,它代表了车辆离开停车场的时间和事件。这个实体包含离开时间以及与该车辆关联的停车位信息。
- 停车费用支付信息是一个实体,它代表了有关停车费用的支付详情。这些详情可能包括支付时间、支付费用等信息。
- 停车位信息是一个实体,它代表了一个停车位的具体描述和详情。这些详情可能包括停车位的ID状态(如空闲、占用等)。
- 车主信息是一个实体,它代表了车主的具体描述和详情。这些详情可能包括车主的ID、姓名、联系方式、地址。
逻辑结构设计及ER关系说明
根据上述系统的概念设计,下面是对数据库逻辑结构的设计和ER关系的描述:
实体:
- PKS_CAR: 此表对应一个实体,即“车辆”。
- PKS_ENTRY: 此表对应一个实体,即“进入停车场的记录”。
- PKS_EXIT: 此表对应一个实体,即“离开停车场的记录”。
- PKS_PAYMENT: 此表对应一个实体,即“停车费用付款”。
- PKS_SPACE: 此表对应一个实体,即“停车场中的空位”。
- PKS_CAR_OWNER: 此表对应一个实体,即“车主”。
关系:
- PKS_CAR与PKS_ENTRY、PKS_EXIT:每辆车可以有多个进入和离开停车场的记录。车辆与进入停车场的记录、离开停车场的记录之间是多对一的关系。
- PKS_ENTRY与PKS_SPACE:每个进入停车场的记录对应一个停车场中的空位。进入停车场的记录与停车场中的空位之间是一对一的关系。
- PKS_PAYMENT与PKS_CAR: 每个付款记录对应一辆车。付款记录与车辆之间是一对一的关系。
- PKS_CAR与PKS_CAR_OWNER:每辆车有一个车主。车辆与车主之间是一对一的关系。
- 每个表(实体)的属性设计:
- PKS_CAR: 此表存储车辆的详细信息,如车辆ID(主键)、车牌号码、车辆颜色、车辆类型和车主ID(外键,关联到PKS_CAR_OWNER表的OWNER_ID列)。
- PKS_ENTRY: 此表存储车辆进入停车场的记录,包括记录ID(主键)、车辆ID(外键,关联到PKS_CAR表的CAR_ID列)、进入时间以及停车位ID(外键,关联到PKS_SPACE表的SPACE_ID列)。
- PKS_EXIT: 此表存储车辆离开停车场的记录,包括记录ID(主键)、车辆ID(外键,关联到PKS_CAR表的CAR_ID列)和离开时间。
- PKS_PAYMENT: 此表存储停车费用付款的记录,包括记录ID(主键)、车辆ID(外键,关联到PKS_CAR表的CAR_ID列)、付款金额和付款时间。
- PKS_SPACE: 此表存储停车场中的空位的信息,包括空位ID(主键)、空位号码和空位状态。
- PKS_CAR_OWNER: 此表存储车主的信息,包括车主ID(主键)、车主姓名、车主电话和车主电子邮件地址。
以上是对数据库逻辑结构的设计和关系描述,绘制ER图如下:
物理结构设计
根据系统的逻辑结构设计最终设计6个数据表如下:
表名 | 列名 | 数据类型 | 说明 |
PKS_CAR | CAR_ID | NUMBER | 车辆ID,主键 |
CAR_NUMBER | VARCHAR2(20) | 车牌号码 | |
CAR_COLOR | VARCHAR2(20) | 车辆颜色 | |
CAR_TYPE | VARCHAR2(20) | 车辆类型 | |
OWNER_ID | NUMBER | 车主ID,外键关联到 PKS_CAR_OWNER表的OWNER_ID列 |
表名 | 列名 | 数据类型 | 说明 |
PKS_ENTRY | ENTRY_ID | NUMBER | 记录ID,主键 |
CAR_ID | NUMBER | 车辆ID,外键关联到 PKS_CAR表的CAR_ID列 | |
ENTRY_TIME | DATE | 进入时间 | |
SPACE_ID | NUMBER | 停车位ID,外键关联到 PKS_SPACE表的SPACE_ID列 |
表名 | 列名 | 数据类型 | 说明 |
PKS_EXIT | EXIT_ID | NUMBER | 记录ID,主键 |
CAR_ID | NUMBER | 车辆ID,外键关联到 PKS_CAR表的CAR_ID列 | |
EXIT_TIME | DATE | 离开时间 |
表名 | 列名 | 数据类型 | 说明 |
PKS_PAYMENT | PAYMENT_ID | NUMBER | 记录ID,主键 |
CAR_ID | NUMBER | 车辆ID,外键关联到 PKS_CAR表的CAR_ID列 | |
AMOUNT | NUMBER | 停车费用 | |
PAYMENT_TIME | DATE | 支付时间 |
表名 | 列名 | 数据类型 | 说明 |
PKS_SPACE | SPACE_ID | NUMBER | 停车位ID,主键 |
SPACE_NUMBER | NUMBER | 停车位号码 | |
SPACE_STATUS | VARCHAR2(10) | 停车位状态 |
表名 | 列名 | 数据类型 | 说明 |
PKS_CAR_OWNER | OWNER_ID | NUMBER | 车主ID,主键 |
OWNER_NAME | VARCHAR2(50) | 车主姓名 | |
OWNER_PHONE | VARCHAR2(20) | 车主电话号码 | |
OWNER_EMAIL | VARCHAR2(50) | 车主电子邮件地址 | |
MEMBER_END_DATE | DATE | 车主会员截止日期 |
在Oracle中创建表空间及表
- 创建数据表:
使用以下命令在Oracle中创建数据表:
CREATE TABLE PKS_CAR_OWNER (
OWNER_ID NUMBER PRIMARY KEY,
OWNER_NAME VARCHAR2(50),
OWNER_PHONE VARCHAR2(20),
OWNER_EMAIL VARCHAR2(50),
MEMBER_END_DATE DATE
);
CREATE TABLE PKS_CAR (
CAR_ID NUMBER PRIMARY KEY,
CAR_NUMBER VARCHAR2(20),
CAR_COLOR VARCHAR2(20),
CAR_TYPE VARCHAR2(20),
OWNER_ID NUMBER,
FOREIGN KEY (OWNER_ID ) REFERENCES PKS_CAR_OWNER(OWNER_ID)
);
CREATE TABLE PKS_SPACE (
SPACE_ID NUMBER PRIMARY KEY,
SPACE_NUMBER NUMBER,
SPACE_STATUS VARCHAR2(10)
);
CREATE TABLE PKS_ENTRY (
ENTRY_ID NUMBER PRIMARY KEY,
CAR_ID NUMBER,
ENTRY_TIME DATE,
SPACE_ID NUMBER,
FOREIGN KEY (CAR_ID) REFERENCES PKS_CAR(CAR_ID),
FOREIGN KEY (SPACE_ID) REFERENCES PKS_SPACE(SPACE_ID)
);
CREATE TABLE PKS_EXIT (
EXIT_ID NUMBER PRIMARY KEY,
CAR_ID NUMBER,
EXIT_TIME DATE,
FOREIGN KEY (CAR_ID) REFERENCES PKS_CAR(CAR_ID)
);
CREATE TABLE PKS_PAYMENT (
PAYMENT_ID NUMBER PRIMARY KEY,
CAR_ID NUMBER,
AMOUNT NUMBER,
PAYMENT_TIME DATE,
FOREIGN KEY (CAR_ID) REFERENCES PKS_CAR(CAR_ID)
);
以上命令将创建每个数据表,并使用适当的列和数据类型定义表结构。
表数据插入
在 PKS_CAR 表中插入数据:
INSERT INTO PKS_CAR (CAR_ID, CAR_NUMBER, CAR_COLOR, CAR_TYPE, OWNER_ID) VALUES
(1, '粤A12345', '红色', '轿车', 1),
INSERT INTO PKS_CAR (CAR_ID, CAR_NUMBER, CAR_COLOR, CAR_TYPE, OWNER_ID) VALUES
(2, '粤B67890', '蓝色', 'SUV', 2),
(3, '粤C3456', '绿色', '皮卡', 3),
INSERT INTO PKS_CAR (CAR_ID, CAR_NUMBER, CAR_COLOR, CAR_TYPE, OWNER_ID) VALUES
(4, '粤D78901', '黄色', '跑车', 4)
INSERT INTO PKS_CAR (CAR_ID, CAR_NUMBER, CAR_COLOR, CAR_TYPE, OWNER_ID) VALUES
(5, '粤E2345', '白色', '轿车', 5)
INSERT INTO PKS_CAR (CAR_ID, CAR_NUMBER, CAR_COLOR, CAR_TYPE, OWNER_ID) VALUES
(6, '粤F9012', '黑色', 'SUV', 6)
INSERT INTO PKS_CAR (CAR_ID, CAR_NUMBER, CAR_COLOR, CAR_TYPE, OWNER_ID) VALUES
(7, '粤G3456', '红色', '皮卡', 7)
INSERT INTO PKS_CAR (CAR_ID, CAR_NUMBER, CAR_COLOR, CAR_TYPE, OWNER_ID) VALUES
(8, '粤H7890', '蓝色', '跑车', 8)
INSERT INTO PKS_CAR (CAR_ID, CAR_NUMBER, CAR_COLOR, CAR_TYPE, OWNER_ID) VALUES
(9, '粤I2345', '绿色', '轿车', 9)
INSERT INTO PKS_CAR (CAR_ID, CAR_NUMBER, CAR_COLOR, CAR_TYPE, OWNER_ID) VALUES
(10, '粤J6789', '黄色', 'SUV', 10)
在 PKS_SPACE 表中插入数据:
INSERT INTO PKS_SPACE (SPACE_ID, SPACE_NUMBER, SPACE_STATUS)
VALUES (1, 'A1', 'Available');
INSERT INTO PKS_SPACE (SPACE_ID, SPACE_NUMBER, SPACE_STATUS)
VALUES (2, 'B2', 'Available');
INSERT INTO PKS_SPACE (SPACE_ID, SPACE_NUMBER, SPACE_STATUS)
VALUES (3, 'C3', 'Occupied');
INSERT INTO PKS_SPACE (SPACE_ID, SPACE_NUMBER, SPACE_STATUS)
VALUES (4, 'D4', 'Maintenance');
INSERT INTO PKS_SPACE (SPACE_ID, SPACE_NUMBER, SPACE_STATUS)
VALUES (5, 'E5', 'Available');
INSERT INTO PKS_SPACE (SPACE_ID, SPACE_NUMBER, SPACE_STATUS)
VALUES (6, 'F6', 'Occupied');
INSERT INTO PKS_SPACE (SPACE_ID, SPACE_NUMBER, SPACE_STATUS)
VALUES (7, 'G7', 'Maintenance');
INSERT INTO PKS_SPACE (SPACE_ID, SPACE_NUMBER, SPACE_STATUS)
VALUES (8, 'H8', 'Available');
INSERT INTO PKS_SPACE (SPACE_ID, SPACE_NUMBER, SPACE_STATUS)
VALUES (9, 'I9', 'Occupied');
INSERT INTO PKS_SPACE (SPACE_ID, SPACE_NUMBER, SPACE_STATUS)
VALUES (10, 'J10', 'Maintenance');
在 PKS_CAR_OWNER表中插入数据:
INSERT INTO PKS_CAR_OWNER (OWNER_ID, OWNER_NAME, OWNER_PHONE, OWNER_EMAIL, MEMBER_END_DATE)
VALUES (1, '张三', '1234567890', 'zhangsan@example.com', TO_DATE('2023-12-31', 'YYYY-MM-DD'));
INSERT INTO PKS_CAR_OWNER (OWNER_ID, OWNER_NAME, OWNER_PHONE, OWNER_EMAIL, MEMBER_END_DATE)
VALUES (2, '李四', '0987654321', 'lisi@example.com', TO_DATE('2024-06-30', 'YYYY-MM-DD'));
INSERT INTO PKS_CAR_OWNER (OWNER_ID, OWNER_NAME, OWNER_PHONE, OWNER_EMAIL, MEMBER_END_DATE)
VALUES (3, '王五', '123456789', 'wangwu@example.com', TO_DATE('2023-11-30', 'YYYY-MM-DD'));
INSERT INTO PKS_CAR_OWNER (OWNER_ID, OWNER_NAME, OWNER_PHONE, OWNER_EMAIL, MEMBER_END_DATE)
VALUES (4, '赵六', '098765432', 'zhaoliu@example.com', TO_DATE('2024-05-31', 'YYYY-MM-DD'));
INSERT INTO PKS_CAR_OWNER (OWNER_ID, OWNER_NAME, OWNER_PHONE, OWNER_EMAIL, MEMBER_END_DATE)
VALUES (5, '孙七', '1234567890', 'sunqi@example.com', TO_DATE('2023-10-31', 'YYYY-MM-DD'));
INSERT INTO PKS_CAR_OWNER (OWNER_ID, OWNER_NAME, OWNER_PHONE, OWNER_EMAIL, MEMBER_END_DATE)
VALUES (6, '周八', '0987654321', 'zhouba@example.com', TO_DATE('2024-04-30', 'YYYY-MM-DD'));
INSERT INTO PKS_CAR_OWNER (OWNER_ID, OWNER_NAME, OWNER_PHONE, OWNER_EMAIL, MEMBER_END_DATE)
VALUES (7, '吴九', '1234567890', 'wujiu@example.com', TO_DATE('2023-09-30', 'YYYY-MM-DD'));
INSERT INTO PKS_CAR_OWNER (OWNER_ID, OWNER_NAME, OWNER_PHONE, OWNER_EMAIL, MEMBER_END_DATE)
VALUES (8, '杨千', '0987654321', 'yangqian@example.com', TO_DATE('2024-03-31', 'YYYY-MM-DD'));
INSERT INTO PKS_CAR_OWNER (OWNER_ID, OWNER_NAME, OWNER_PHONE, OWNER_EMAIL, MEMBER_END_DATE)
VALUES (9, '朱百', '123456789', 'zhubai@example.com', TO_DATE('2023-08-31', 'YYYY-MM-DD'));
INSERT INTO PKS_CAR_OWNER (OWNER_ID, OWNER_NAME, OWNER_PHONE, OWNER_EMAIL, MEMBER_END_DATE)
VALUES (10, '魏万', '098765432', 'weiwan@example.com', TO_DATE('2024-02-28', 'YYYY-MM-DD'));
往表PKS_ENTRY中插入数据:
INSERT INTO PKS_ENTRY (ENTRY_ID, CAR_ID, ENTRY_TIME, SPACE_ID)
VALUES (1, 1, TO_DATE('2023-07-19 09:00:00', 'YYYY-MM-DD HH24:MI:SS'), 1);
INSERT INTO PKS_ENTRY (ENTRY_ID, CAR_ID, ENTRY_TIME, SPACE_ID)
VALUES (2, 2, TO_DATE('2023-07-19 09:15:00', 'YYYY-MM-DD HH24:MI:SS'), 2);
INSERT INTO PKS_ENTRY (ENTRY_ID, CAR_ID, ENTRY_TIME, SPACE_ID)
VALUES (3, 3, TO_DATE('2023-07-19 09:30:00', 'YYYY-MM-DD HH24:MI:SS'), 3);
INSERT INTO PKS_ENTRY (ENTRY_ID, CAR_ID, ENTRY_TIME, SPACE_ID)
VALUES (4, 4, TO_DATE('2023-07-19 10:00:00', 'YYYY-MM-DD HH24:MI:SS'), 4);
INSERT INTO PKS_ENTRY (ENTRY_ID, CAR_ID, ENTRY_TIME, SPACE_ID)
VALUES (5, 5, TO_DATE('2023-07-19 10:15:00', 'YYYY-MM-DD HH24:MI:SS'), 5);
INSERT INTO PKS_ENTRY (ENTRY_ID, CAR_ID, ENTRY_TIME, SPACE_ID)
VALUES (6, 6, TO_DATE('2023-07-19 11:00:00', 'YYYY-MM-DD HH24:MI:SS'), 6);
INSERT INTO PKS_ENTRY (ENTRY_ID, CAR_ID, ENTRY_TIME, SPACE_ID)
VALUES (7, 7, TO_DATE('2023-07-19 11:15:00', 'YYYY-MM-DD HH24:MI:SS'), 7);
INSERT INTO PKS_ENTRY (ENTRY_ID, CAR_ID, ENTRY_TIME, SPACE_ID)
VALUES (8, 8, TO_DATE('2023-07-19 12:00:00', 'YYYY-MM-DD HH24:MI:SS'), 8);
INSERT INTO PKS_ENTRY (ENTRY_ID, CAR_ID, ENTRY_TIME, SPACE_ID)
VALUES (9, 9, TO_DATE('2023-07-19 12:15:00', 'YYYY-MM-DD HH24:MI:SS'), 9);
INSERT INTO PKS_ENTRY (ENTRY_ID, CAR_ID, ENTRY_TIME, SPACE_ID)
VALUES (10, 10, TO_DATE('2023-07-19 13:00:00', 'YYYY-MM-DD HH24:MI:SS'), 10);
在 PKS_EXIT 表中插入数据:
-- 假设车辆信息表PKS_CAR、车主信息表PKS_CAR_OWNER和停车位信息表PKS_SPACE已经存在并且包含相应的数据
INSERT INTO PKS_EXIT (EXIT_ID, CAR_ID, EXIT_TIME)
VALUES (1, 1, TO_DATE('2023-07-19 10:00:00', 'YYYY-MM-DD HH24:MI:SS'));
INSERT INTO PKS_EXIT (EXIT_ID, CAR_ID, EXIT_TIME)
VALUES (2, 2, TO_DATE('2023-07-19 10:30:00', 'YYYY-MM-DD HH24:MI:SS'));
INSERT INTO PKS_EXIT (EXIT_ID, CAR_ID, EXIT_TIME)
VALUES (3, 3, TO_DATE('2023-07-19 11:00:00', 'YYYY-MM-DD HH24:MI:SS'));
INSERT INTO PKS_EXIT (EXIT_ID, CAR_ID, EXIT_TIME)
VALUES (4, 4, TO_DATE('2023-07-19 11:30:00', 'YYYY-MM-DD HH24:MI:SS'));
INSERT INTO PKS_EXIT (EXIT_ID, CAR_ID, EXIT_TIME)
VALUES (5, 5, TO_DATE('2023-07-19 12:00:00', 'YYYY-MM-DD HH24:MI:SS'));
INSERT INTO PKS_EXIT (EXIT_ID, CAR_ID, EXIT_TIME)
VALUES (6, 6, TO_DATE('2023-07-19 12:30:00', 'YYYY-MM-DD HH24:MI:SS'));
INSERT INTO PKS_EXIT (EXIT_ID, CAR_ID, EXIT_TIME)
VALUES (7, 7, TO_DATE('2023-07-19 13:00:00', 'YYYY-MM-DD HH24:MI:SS'));
INSERT INTO PKS_EXIT (EXIT_ID, CAR_ID, EXIT_TIME)
VALUES (8, 8, TO_DATE('2023-07-19 13:30:00', 'YYYY-MM-DD HH24:MI:SS'));
INSERT INTO PKS_EXIT (EXIT_ID, CAR_ID, EXIT_TIME)
VALUES (9, 9, TO_DATE('2023-07-19 14:00:00', 'YYYY-MM-DD HH24:MI:SS'));
INSERT INTO PKS_EXIT (EXIT_ID, CAR_ID, EXIT_TIME)
VALUES (10, 10, TO_DATE('2023-07-19 14:30:00', 'YYYY-MM-DD HH24:MI:SS'));
往表PKS_PAYMENT中插入数据:
INSERT INTO PKS_PAYMENT (PAYMENT_ID, CAR_ID, PAYMENT_TIME, SPACE_ID, PAYMENT_AMOUNT)
VALUES (1, 1, TO_DATE('2023-07-19 10:00:00', 'YYYY-MM-DD HH24:MI:SS'), 1, 50);
INSERT INTO PKS_PAYMENT (PAYMENT_ID, CAR_ID, PAYMENT_TIME, SPACE_ID, PAYMENT_AMOUNT)
VALUES (2, 2, TO_DATE('2023-07-19 10:30:00', 'YYYY-MM-DD HH24:MI:SS'), 2, 60);
INSERT INTO PKS_PAYMENT (PAYMENT_ID, CAR_ID, PAYMENT_TIME, SPACE_ID, PAYMENT_AMOUNT)
VALUES (3, 3, TO_DATE('2023-07-19 11:00:00', 'YYYY-MM-DD HH24:MI:SS'), 3, 55);
INSERT INTO PKS_PAYMENT (PAYMENT_ID, CAR_ID, PAYMENT_TIME, SPACE_ID, PAYMENT_AMOUNT)
VALUES (4, 4, TO_DATE('2023-07-19 11:30:00', 'YYYY-MM-DD HH24:MI:SS'), 4, 70);
INSERT INTO PKS_PAYMENT (PAYMENT_ID, CAR_ID, PAYMENT_TIME, SPACE_ID, PAYMENT_AMOUNT)
VALUES (5, 5, TO_DATE('2023-07-19 12:00:00', 'YYYY-MM-DD HH24:MI:SS'), 5, 65);
INSERT INTO PKS_PAYMENT (PAYMENT_ID, CAR_ID, PAYMENT_TIME, SPACE_ID, PAYMENT_AMOUNT)
VALUES (6, 6, TO_DATE('2023-07-19 12:30:00', 'YYYY-MM-DD HH24:MI:SS'), 6, 50);
INSERT INTO PKS_PAYMENT (PAYMENT_ID, CAR_ID, PAYMENT_TIME, SPACE_ID, PAYMENT_AMOUNT)
VALUES (7, 7, TO_DATE('2023-07-19 13:00:00', 'YYYY-MM-DD HH24:MI:SS'), 7, 60);
INSERT INTO PKS_PAYMENT (PAYMENT_ID, CAR_ID, PAYMENT_TIME, SPACE_ID, PAYMENT_AMOUNT)
VALUES (8, 8, TO_DATE('2023-07-19 13:30:00', 'YYYY-MM-DD HH24:MI:SS'), 8, 55);
INSERT INTO PKS_PAYMENT (PAYMENT_ID, CAR_ID, PAYMENT_TIME, SPACE_ID, PAYMENT_AMOUNT)
VALUES (9, 9, TO_DATE('2023-07-19 14:00:00', 'YYYY-MM-DD HH24:MI:SS'), 9, 70);
INSERT INTO PKS_PAYMENT (PAYMENT_ID, CAR_ID, PAYMENT_TIME, SPACE_ID, PAYMENT_AMOUNT)
VALUES (10, 10, TO_DATE('2023-07-19 14:30:00', 'YYYY-MM-DD HH24:MI:SS'), 10, 65);
添加索引
在数据库中添加合适的索引可以显著提高查询性能。
以下是在每个表中添加索引:
在 PKS_CAR 表中添加索引:
CREATE INDEX idx_car_id ON PKS_CAR (CAR_ID);
CREATE INDEX idx_owner_id ON PKS_CAR (OWNER_ID);
在 PKS_ENTRY 表中添加索引:
CREATE INDEX idx_entry_car_id ON PKS_ENTRY (CAR_ID);
CREATE INDEX idx_entry_space_id ON PKS_ENTRY (SPACE_ID);
在 PKS_EXIT 表中添加索引:
CREATE INDEX idx_exit_car_id ON PKS_EXIT (CAR_ID);
在 PKS_PAYMENT 表中添加索引:
CREATE INDEX idx_payment_car_id ON PKS_PAYMENT (CAR_ID);
在 PKS_SPACE 表中添加索引:
CREATE INDEX idx_space_id ON PKS_SPACE (SPACE_ID);
在 PKS_CAR_OWNER 表中添加索引:
CREATE INDEX idx_owner_id ON PKS_CAR_OWNER (OWNER_ID);
这些索引将加速基于这些列的查询,并提高数据库的整体性能。
查询示例
单条件查询
查询所有车辆的信息:
SELECT * FROM PKS_CAR;
查询所有车辆的颜色:
SELECT CAR_COLOR FROM PKS_CAR;
查询所有车辆的进入记录:
SELECT * FROM PKS_ENTRY;
组合条件查询
查询所有红色车辆的所属人:
SELECT OWNER_ID FROM PKS_CAR WHERE CAR_COLOR = '红色';
查询所有在2023年7月19日12:00之后进入停车场的车辆:
SELECT CAR_ID FROM PKS_ENTRY WHERE ENTRY_TIME >= TO_DATE('2023-07-19 12:00:00', 'YYYY-MM-DD HH24:MI:SS');
查询所有在2023年7月19日12:00之前离开停车场的车辆:
SELECT CAR_ID FROM PKS_EXIT WHERE EXIT_TIME <= TO_DATE('2023-07-19 12:00:00', 'YYYY-MM-DD HH24:MI:SS');
查询所有车辆的平均停车时间:
SELECT AVG(ENTRY_TIME - EXIT_TIME) AS AVG_PARKING_TIME FROM PKS_ENTRY, PKS_EXIT
WHERE ENTRY_ID = EXIT_ID;
查询所有车辆的平均支付金额:
SELECT AVG(PAYMENT_AMOUNT) AS AVG_PAYMENT FROM PKS_PAYMENT;
多表查询
查询所有车辆的信息及其所属人的信息:
SELECT PKS_CAR.CAR_ID, PKS_CAR.CAR_TYPE, PKS_CAR.CAR_COLOR, PKS_CAR_OWNER.OWNER_NAME
FROM PKS_CAR
INNER JOIN PKS_CAR_OWNER ON PKS_CAR.OWNER_ID = PKS_CAR_OWNER.OWNER_ID;
查询所有停车位的状态及其进入和离开记录:
SELECT PKS_SPACE.SPACE_ID, PKS_SPACE.SPACE_STATUS, PKS_ENTRY.ENTRY_TIME, PKS_EXIT.EXIT_TIME
FROM PKS_SPACE
INNER JOIN PKS_ENTRY ON PKS_SPACE.SPACE_ID = PKS_ENTRY.SPACE_ID
INNER JOIN PKS_EXIT ON PKS_ENTRY.CAR_ID = PKS_EXIT.CAR_ID
;
查询所有车辆的编号、类型、颜色、进入和离开记录以及支付记录:
SELECT PKS_CAR.CAR_ID, PKS_CAR.CAR_TYPE, PKS_CAR.CAR_COLOR, PKS_ENTRY.ENTRY_TIME, PKS_EXIT.EXIT_TIME, PKS_PAYMENT.PAYMENT_AMOUNT
FROM PKS_CAR
INNER JOIN PKS_ENTRY ON PKS_CAR.CAR_ID = PKS_ENTRY.CAR_ID
INNER JOIN PKS_EXIT ON PKS_CAR.CAR_ID = PKS_EXIT.CAR_ID
INNER JOIN PKS_PAYMENT ON PKS_CAR.CAR_ID = PKS_PAYMENT.CAR_ID;
查询所有车辆的所属人、电话号码、电子邮件地址以及其进入和离开记录:
SELECT PKS_CAR_OWNER.OWNER_NAME, PKS_CAR_OWNER.OWNER_PHONE, PKS_CAR_OWNER.OWNER_EMAIL, PKS_ENTRY.ENTRY_TIME
FROM PKS_CAR_OWNER
INNER JOIN PKS_CAR ON PKS_CAR.CAR_ID = PKS_CAR_OWNER.CAR_ID
INNER JOIN PKS_ENTRY ON PKS_ENTRY.CAR_ID = PKS_CAR.CAR_ID;
存储过程
1.存储过程:GET_CAR_INFO
CREATE OR REPLACE PROCEDURE get_car_info (
id IN NUMBER,
color OUT VARCHAR2
) AS
BEGIN
SELECT
car_color
INTO color
FROM
pks_car
WHERE
car_id = id;
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('no_data_found');
END;
/
该存储过程接受一个车辆ID作为输入参数,返回该车辆的颜色信息。
执行存储过程:
--调用存储过程
SET SERVEROUTPUT ON;
-- 打开DBMS_OUTPUT输出
DECLARE
ID NUMBER;
COLOR VARCHAR2(200);
BEGIN
ID := 1;
GET_CAR_INFO(
ID => ID,
COLOR => COLOR
);
/* Legacy output:
DBMS_OUTPUT.PUT_LINE('COLOR = ' || COLOR);
*/
:COLOR := COLOR;
--rollback;
END;
/
2.存储过程:update_car_info
create or replace PROCEDURE update_car_info (
id IN NUMBER,
v_color IN VARCHAR2,
v_type IN VARCHAR2
) AS
BEGIN
UPDATE
pks_car
SET car_color = v_color , car_type = v_type
WHERE
car_id = id;
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('no_data_found');
END;
该存储过程接受一个车辆ID,颜色和类型作为输入参数,更新该车辆的颜色和类型。
执行存储过程:
DECLARE
ID NUMBER;
V_COLOR VARCHAR2(200);
V_TYPE VARCHAR2(200);
BEGIN
ID := 1;
V_COLOR := '蓝色';
V_TYPE := '皮卡';
UPDATE_CAR_INFO(
ID => ID,
V_COLOR => V_COLOR,
V_TYPE => V_TYPE
);
--rollback;
END;
3.存储过程:CALCULATE_TOTAL_PAYMENT
create or replace PROCEDURE calculate_total_payment (
c_id IN NUMBER,
total_payment OUT NUMBER
) AS
BEGIN
SELECT
SUM(payment_amount)
INTO total_payment
FROM
pks_payment
WHERE
car_id = c_id;
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('no_data_found');
END;
/
该存储过程接受一个车辆ID作为输入参数,计算该车辆的总支付金额,并将结果作为输出参数返回。
执行存储过程:
--调用存储过程
SET SERVEROUTPUT ON;
-- 打开DBMS_OUTPUT输出
DECLARE
C_ID NUMBER;
TOTAL_PAYMENT NUMBER;
BEGIN
C_ID := 2;
CALCULATE_TOTAL_PAYMENT(
C_ID => C_ID,
TOTAL_PAYMENT => TOTAL_PAYMENT
);
-- /* Legacy output:
DBMS_OUTPUT.PUT_LINE('TOTAL_PAYMENT = ' || TOTAL_PAYMENT);
:TOTAL_PAYMENT := TOTAL_PAYMENT;
--rollback;
END;
查询函数示例
1.查询函数:GET_CAR_INFO_FUNC
CREATE OR REPLACE FUNCTION get_car_info_func (
c_id IN NUMBER
) RETURN VARCHAR2 AS
c_type VARCHAR2(50);
c_color VARCHAR2(50);
BEGIN
SELECT
car_type,
car_color
INTO
c_type,
c_color
FROM
pks_car
WHERE
car_id = c_id;
RETURN c_type
|| ', '
|| c_color;
END;
执行函数:
--调用函数过程
SET SERVEROUTPUT ON;
-- 打开DBMS_OUTPUT输出
DECLARE
c_id NUMBER;
v_return VARCHAR2(200);
BEGIN
c_id := 1;
v_return := get_car_info_func(c_id => c_id);
-- Legacy output:
dbms_output.put_line('v_Return = ' || v_return);
:v_return := v_return;
--rollback;
END;
该查询函数接受一个车辆ID作为输入参数,返回该车辆的类型和颜色信息,以逗号分隔的字符串形式返回。
2.查询函数:GET_OWNER_INFO_FUNC
create or replace FUNCTION get_owner_info_func (
o_id IN NUMBER
) RETURN VARCHAR2 AS
o_name VARCHAR2(50);
o_phone VARCHAR2(50);
o_email VARCHAR2(50);
BEGIN
SELECT
owner_name,
owner_phone,
owner_email
INTO
o_name,
o_phone,
o_email
FROM
pks_car_owner
WHERE
owner_id = o_id;
RETURN o_name
|| ', '
|| o_phone
|| ', '
|| o_email;
END;
/
该查询函数接受一个所属人ID作为输入参数,返回该所属人的姓名、电话号码和电子邮件地址信息,以逗号分隔的字符串形式返回。
调用函数:GET_OWNER_INFO_FUNC
SET SERVEROUTPUT ON;
-- 打开DBMS_OUTPUT输出
DECLARE
O_ID NUMBER;
v_Return VARCHAR2(200);
BEGIN
O_ID := 2;
v_Return := GET_OWNER_INFO_FUNC(
O_ID => O_ID
);
DBMS_OUTPUT.PUT_LINE('v_Return = ' || v_Return);
:v_Return := v_Return;
--rollback;
END;
3.查询函数:GET_ENTRY_INFO_FUNC
create or replace FUNCTION get_entry_info_fuc (
e_id IN NUMBER
) RETURN VARCHAR2 AS
c_id NUMBER;
s_id NUMBER;
e_time DATE;
BEGIN
SELECT
car_id,
space_id,
entry_time
INTO
c_id,
s_id,
e_time
FROM
pks_entry
WHERE
entry_id = e_id;
RETURN to_char(e_time, 'YYYY-MM-DD HH24:MI:SS')
|| ', '
|| c_id
|| ', '
|| s_id;
END;
/
该查询函数接受一个进入记录ID作为输入参数,返回该记录所对应的车辆ID、停车位ID和进入时间信息,以逗号分隔的字符串形式返回。
执行函数:get_entry_info_fuc
--调用存储过程
SET SERVEROUTPUT ON;
-- 打开DBMS_OUTPUT输出
DECLARE
E_ID NUMBER;
v_Return VARCHAR2(200);
BEGIN
E_ID := 3;
v_Return := GET_ENTRY_INFO_FUC(
E_ID => E_ID
);
DBMS_OUTPUT.PUT_LINE('v_Return = ' || v_Return);
:v_Return := v_Return;
--rollback;
END;
触发器
以下是3个触发器示例:
1.触发器:UPDATE_SPACE_STATUS
create or replace TRIGGER update_space_status AFTER
INSERT OR UPDATE ON pks_entry
FOR EACH ROW
DECLARE
space_status VARCHAR2(50);
BEGIN
SELECT
space_status
INTO space_status
FROM
pks_space
WHERE
space_id = :new.space_id;
IF space_status = '可用' THEN
UPDATE pks_space
SET
space_status = '已占用'
WHERE
space_id = :new.space_id;
END IF;
END;
/
该触发器在PKS_ENTRY表的每行插入或更新后触发,检查对应的停车位状态,如果停车位状态为"可用",则更新为"已占用"。
插入一条入场记录可以看到触发器应用结果。
INSERT INTO PKS_ENTRY (ENTRY_ID, CAR_ID, ENTRY_TIME, SPACE_ID)
VALUES (14, 2, TO_DATE('2023-10-19 09:15:00', 'YYYY-MM-DD HH24:MI:SS'), 1);
2.触发器:CALCULATE_PARKING_FEE
CREATE OR REPLACE TRIGGER calculate_parking_fee AFTER
INSERT OR UPDATE ON pks_exit
FOR EACH ROW
BEGIN
DECLARE
payment_amount NUMBER;
entry_time DATE;
exit_time DATE;
fee NUMBER;
space_id VARCHAR(200);
payment_id NUMBER;
BEGIN
SELECT
entry_time,
space_id
INTO
entry_time,
space_id
FROM
pks_entry
WHERE
car_id = :new.car_id
AND ROWNUM = 1
ORDER BY
entry_time DESC;
fee := ( :new.exit_time - entry_time ) * 2;
--2元每小时
SELECT
MAX(payment_id)
INTO payment_id
FROM
pks_payment;
payment_id := payment_id + 1;
-- 插入停车收费记录
INSERT INTO pks_payment (
payment_id,
car_id,
payment_amount,
payment_time,
space_id
) VALUES (
payment_id,
:new.car_id,
fee,
:new.exit_time,
space_id
);
END;
END;
/
该触发器在PKS_EXIT表的每行插入或更新后触发,计算停车费用(假设费用是2元每小时),并在表PKS_PAYMENT中新增并插入一条收费记录。
用户和权限
在本数据库设计中我们创建三个用户并赋予他们不同权限。
在Oracle中分别创建三个用户:
1.用户名:PksUser1,密码:password
CREATE USER PksUser1 IDENTIFIED BY password;
2.用户名:PksUser2,密码:password
CREATE USER PksUser2 IDENTIFIED BY password;
3.用户名:PksUser3,密码:password
CREATE USER PksUser3 IDENTIFIED BY password;
给这些用户分别授予不同的权限。
1.给PksUser1授予数据库所有权限:
GRANT CONNECT, SELECT ANY TABLE, INSERT ANY TABLE, UPDATE ANY TABLE, DELETE ANY TABLE TO PksUser1;
2.给PksUser2授予完全的访问和修改ParkingLot和PKS_CAR表的权限:
GRANT ALL PRIVILEGES ON PKS_CAR_OWNER TO PksUser2;
GRANT ALL PRIVILEGES ON PKS_CAR TO PksUser2;
3.给PksUser3只授予查看PKS_CAR表的权限:
GRANT SELECT ON PKS_CAR TO PksUser3;
备份策略
以下是一个简单的备份策略,可以根据实际情况进行调整:
创建备份表空间:
CREATE TABLESPACE backup_tablespace
DATAFILE 'backup_tablespace.dbf' SIZE 10G;
创建备份日志文件:
ALTER SYSTEM ADD LOGFILE 'backup_logfile.log' SIZE 50M AUTOEXTEND ON NEXT 50M MAXSIZE UNLIMITED;
启用备份表空间:
ALTER TABLESPACE backup_tablespace ENABLE;
创建备份策略:
CREATE CONTROLFILE REUSE DATABASE "BACKUP" NORESETLOGS MAXLOGFILES 16;
ALTER CONTROLFILE SET RESERVE MAXLOGARCHS 2;
ALTER CONTROLFILE SET BACKUP TYPE TO BACKUPSET;
ALTER CONTROLFILE SET BACKUP SET NAME TO 'full_database_backup';
ALTER CONTROLFILE SET BACKUP SET EXPIREDATE TO 'TODAY+1';
创建备份集:
CREATE BACKUPSET backup_set FORMAT '$ORACLE_HOME/dbs/backup/%F';
执行备份:
RUN {
ALLOCATE CHANNEL ch1 DEVICE TYPE DISK FORMAT '$ORACLE_HOME/dbs/backup/%U';
BACKUP AS COMPRESSED BACKUPSET backup_set TO CHANNEL ch1;
}
清理备份集:
DROP BACKUPSET backup_set;
删除备份表空间和日志文件:
DROP TABLESPACE backup_tablespace INCLUDING CONTENTS AND DATAFILES;
DROP LOGFILE backup_logfile;
以上备份策略将每天进行一次全量备份,并将备份存储在指定的表空间中。备份集将在备份集中过期后自动删除。可以根据实际需求调整备份策略,例如增加增量备份、压缩备份等。