用户表:编号,用户名,密码,邮箱,角色,用户头像;
影片表:编号,影片名称,国外名称,演职人员,导演,电影详情,电影时长,电影类型,电影评分,票房,电影参评人数,上映时间,制片地区,电影海报地址,电影状态;
影院表:编号,影院名称,影院地址;
放映厅表:编号,放映厅名称,放映厅容量,所属影院编号;
订单表:编号,所属用户编号,所属场次编号,电影票座位信息,订单状态,订单价格,订单支付时间,所属用户对象;
订单详情表:编号,所属放映厅,放映的电影编号,电影放映时间,售价,剩余座位数,场次状态,所属放映厅对象,放映的电影;
评论表:编号,所属用户编号,评论内容,所属电影编号,评论时间,所属用户,评分;

1 需求分析

2 系统设计

2.1 系统结构功能图

根据需求分析,确定系统结构功能如图2-1所示:

图2-1 系统功能结构图

2.2 功能流程图

系统最主要的功能就是管理员登录之后对各种功能的使用。管理员功能如图4-2所示。

图2-2 管理员登录管理流程

2.3 数据库设计

整体功能的E-R图如图2-4所示。
画板
图2-4 系统E-R图
本系统包含的数据表如下:

1. 商品表 (goods)

列名 数据类型 字段类型 长度 是否为空 默认值 备注
gID CHAR 主键 6 - 商品ID
gNAME VARCHAR2 非空 10 - 商品名称
gKIDS VARCHAR2 可空 6 - 商品分类ID
gUNIT NUMBER 检查 - - 单位,必须大于0
gPRICE NUMBER 检查 - - 价格,不能小于0

2. 供应商表 (provider)

列名 数据类型 字段类型 长度 是否为空 默认值 备注
pID CHAR 主键 6 - 供应商ID
pNAME VARCHAR2 非空 10 - 供应商名称
pACC CHAR 可空 19 - 账户信息
pADD VARCHAR2 可空 8 - 地址

3. 仓库表 (store)

列名 数据类型 字段类型 长度 是否为空 默认值 备注
sID CHAR 主键 6 - 仓库ID
sADD VARCHAR2 可空 8 - 地址
sLEAD VARCHAR2 可空 4 - 联系负责人

4. 门店表 (shop)

列名 数据类型 字段类型 长度 是否为空 默认值 备注
shID CHAR 主键 6 - 门店ID
shNAME VARCHAR2 非空 10 - 门店名称
shADD VARCHAR2 可空 8 - 地址

5. 营业员表 (assistant)

列名 数据类型 字段类型 长度 是否为空 默认值 备注
aID CHAR 主键 6 - 营业员ID
aNAME VARCHAR2 非空 4 - 营业员姓名
aFEAT NUMBER 可空 - - 业绩特征
shID CHAR 外键 6 - 关联的门店ID

6. 管理员表 (manager)

列名 数据类型 字段类型 长度 是否为空 默认值 备注
mID CHAR 主键 6 - 管理员ID
mNAME VARCHAR2 非空 4 - 管理员姓名
mFEAT NUMBER 可空 - - 管理员特征

7. 采购员表 (shopper)

列名 数据类型 字段类型 长度 是否为空 默认值 备注
shopperID CHAR 主键 6 - 采购员ID
shopperNAME VARCHAR2 非空 4 - 采购员姓名
shopperFEAT NUMBER 可空 - - 采购员特征

8. 商品库存更新历史表 (goods_history)

列名 数据类型 字段类型 长度 是否为空 默认值 备注
hID NUMBER 主键 - - 历史记录ID
gID CHAR 外键 6 - 关联的商品ID
oldQuantity NUMBER 可空 - - 旧数量
newQuantity NUMBER 可空 - - 新数量
changeDate TIMESTAMP - - - 更改日期

9. 销售表 (sales)

列名 数据类型 字段类型 长度 是否为空 默认值 备注
saleID NUMBER 主键 - - 销售记录ID
gID CHAR 外键 6 - 关联的商品ID
quantity NUMBER 检查 - - 销售数量,必须大于0
salesPrice NUMBER 检查 - - 售价,不能小于0
aID CHAR 外键 6 - 关联的营业员ID
saleDate TIMESTAMP - - DEFAULT SYSTIMESTAMP 销售日期

3 SQL**实现**

建表

-- 创建商品表
CREATE TABLE goods (
gID CHAR(6) PRIMARY KEY,
gNAME VARCHAR2(10) NOT NULL,
gKIDS VARCHAR2(6),
gUNIT NUMBER CHECK(gUNIT > 0),
gPRICE NUMBER CHECK(gPRICE >= 0)
);

-- 创建供应商表
CREATE TABLE provider (
pID CHAR(6) PRIMARY KEY,
pNAME VARCHAR2(10) NOT NULL,
pACC CHAR(19),
pADD VARCHAR2(8)
);

-- 创建仓库表
CREATE TABLE store (
sID CHAR(6) PRIMARY KEY,
sADD VARCHAR2(8),
sLEAD VARCHAR2(4)
);

-- 创建门店表
CREATE TABLE shop (
shID CHAR(6) PRIMARY KEY,
shNAME VARCHAR2(10) NOT NULL,
shADD VARCHAR2(8)
);

-- 创建营业员表
CREATE TABLE assistant (
aID CHAR(6) PRIMARY KEY,
aNAME VARCHAR2(4) NOT NULL,
aFEAT NUMBER,
shID CHAR(6),
FOREIGN KEY (shID) REFERENCES shop(shID)
);

-- 创建管理员表
CREATE TABLE manager (
mID CHAR(6) PRIMARY KEY,
mNAME VARCHAR2(4) NOT NULL,
mFEAT NUMBER
);

-- 创建采购员表
CREATE TABLE shopper (
shopperID CHAR(6) PRIMARY KEY,
shopperNAME VARCHAR2(4) NOT NULL,
shopperFEAT NUMBER
);

-- 创建商品库存更新历史表
CREATE TABLE goods_history (
hID NUMBER PRIMARY KEY,
gID CHAR(6),
oldQuantity NUMBER,
newQuantity NUMBER,
changeDate TIMESTAMP
);

-- 创建销售表
CREATE TABLE sales (
saleID NUMBER PRIMARY KEY, -- 销售记录ID
gID CHAR(6), -- 商品ID
quantity NUMBER CHECK(quantity > 0), -- 销售数量
salesPrice NUMBER CHECK(salesPrice >= 0), -- 售价
aID CHAR(6), -- 营业员ID
saleDate TIMESTAMP DEFAULT SYSTIMESTAMP, -- 销售日期
FOREIGN KEY (gID) REFERENCES goods(gID), -- 外键关联商品
FOREIGN KEY (aID) REFERENCES assistant(aID) -- 外键关联营业员
);

索引

-- 在商品表上创建索引
CREATE INDEX idx_goods_name ON goods(gNAME);

-- 在供应商表上创建索引
CREATE INDEX idx_provider_name ON provider(pNAME);
CREATE INDEX idx_provider_acc ON provider(pACC);

-- 在仓库表上创建索引
CREATE INDEX idx_store_address ON store(sADD);

-- 在门店表上创建索引
CREATE INDEX idx_shop_name ON shop(shNAME);
CREATE INDEX idx_shop_address ON shop(shADD);

-- 在营业员表上创建索引
CREATE INDEX idx_assistant_name ON assistant(aNAME);
CREATE INDEX idx_assistant_store_id ON assistant(shID);

-- 在管理员表上创建索引
CREATE INDEX idx_manager_name ON manager(mNAME);

-- 在采购员表上创建索引
CREATE INDEX idx_shopper_name ON shopper(shopperNAME);

-- 如果需要在采购员表上添加唯一索引
CREATE UNIQUE INDEX idx_shopper_id ON shopper(shopperID);

视图

CREATE VIEW vw_goods_suppliers AS
SELECT
g.gID,
g.gNAME,
g.gKIDS,
g.gUNIT,
g.gPRICE,
p.pID AS supplier_id,
p.pNAME AS supplier_name
FROM
goods g
LEFT JOIN
provider p ON g.gID = p.pID;


CREATE VIEW vw_assistants_shops AS
SELECT
a.aID,
a.aNAME,
a.aFEAT,
s.shID AS shop_id,
s.shNAME AS shop_name
FROM
assistant a
LEFT JOIN
shop s ON a.shID = s.shID;


CREATE VIEW vw_inventory_summary AS
SELECT
g.gID,
g.gNAME,
g.gUNIT,
SUM(g.gPRICE) AS total_value
FROM
goods g
GROUP BY
g.gID, g.gNAME, g.gUNIT;


CREATE VIEW vw_manager_performance AS
SELECT
m.mID,
m.mNAME,
SUM(m.mFEAT) AS total_performance
FROM
manager m
GROUP BY
m.mID, m.mNAME;


CREATE VIEW vw_shop_store_info AS
SELECT
sh.shID AS shop_id,
sh.shNAME AS shop_name,
sh.shADD AS shop_address,
st.sID AS store_id,
st.sADD AS store_address
FROM
shop sh
LEFT JOIN
store st ON sh.shID = st.sID;

存储过程、函数

-- 1. 存储过程:添加新商品
CREATE OR REPLACE PROCEDURE add_new_goods (
p_gID IN CHAR(6),
p_gNAME IN VARCHAR2,
p_gKIDS IN VARCHAR2,
p_gUNIT IN NUMBER,
p_gPRICE IN NUMBER,
p_pID IN CHAR(6),
p_pNAME IN VARCHAR2,
p_pACC IN CHAR(19),
p_pADD IN VARCHAR2
) AS
v_count NUMBER;
BEGIN
-- 检查供应商是否存在
SELECT COUNT(*) INTO v_count
FROM provider
WHERE pID = p_pID;

-- 如果供应商不存在,则插入
IF v_count = 0 THEN
INSERT INTO provider (pID, pNAME, pACC, pADD)
VALUES (p_pID, p_pNAME, p_pACC, p_pADD);
END IF;

-- 添加新商品
INSERT INTO goods (gID, gNAME, gKIDS, gUNIT, gPRICE)
VALUES (p_gID, p_gNAME, p_gKIDS, p_gUNIT, p_gPRICE);

COMMIT; -- 提交更改
EXCEPTION
WHEN OTHERS THEN
ROLLBACK; -- 出错时回滚
RAISE; -- 重新引发错误
END add_new_goods;


-- 2. 存储过程:更新商品库存
CREATE OR REPLACE PROCEDURE update_goods_stock (
p_gID IN CHAR(6),
p_newQuantity IN NUMBER
) AS
BEGIN
-- 更新商品数量
UPDATE goods
SET gUNIT = p_newQuantity
WHERE gID = p_gID;

IF SQL%ROWCOUNT = 0 THEN
RAISE_APPLICATION_ERROR(-20001, '未找到该商品。');
END IF;

COMMIT; -- 提交更改
EXCEPTION
WHEN OTHERS THEN
ROLLBACK; -- 出错时回滚
RAISE; -- 重新引发错误
END update_goods_stock;


-- 3. 存储过程:记录销售
CREATE OR REPLACE PROCEDURE record_sale (
p_gID IN CHAR(6), -- 商品ID
p_quantity IN NUMBER, -- 销售数量
p_salesPrice IN NUMBER, -- 销售价格
p_aID IN CHAR(6) -- 营业员ID
) AS
v_current_stock NUMBER;
BEGIN
-- 检查库存量
SELECT gUNIT INTO v_current_stock
FROM goods
WHERE gID = p_gID;

-- 验证库存是否足够
IF v_current_stock < p_quantity THEN
RAISE_APPLICATION_ERROR(-20002, '库存不足,无法完成销售。');
END IF;

-- 扣减库存
UPDATE goods
SET gUNIT = gUNIT - p_quantity
WHERE gID = p_gID;

-- 记录销售详细信息(假设存在销售表)
INSERT INTO sales (saleID, gID, quantity, salesPrice, aID, saleDate)
VALUES (sales_seq.NEXTVAL, p_gID, p_quantity, p_salesPrice, p_aID, SYSDATE);

COMMIT; -- 提交更改
EXCEPTION
WHEN OTHERS THEN
ROLLBACK; -- 出错时回滚
RAISE; -- 重新引发错误
END record_sale;


-- 4. 函数:计算总库存价值
CREATE OR REPLACE FUNCTION calculate_total_value (
p_gID IN CHAR(6)
) RETURN NUMBER IS
v_total_value NUMBER;
BEGIN
-- 计算库存总价值
SELECT gPRICE * gUNIT
INTO v_total_value
FROM goods
WHERE gID = p_gID;

RETURN v_total_value; -- 返回计算结果
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN 0; -- 如果未找到商品,返回0
WHEN OTHERS THEN
RAISE; -- 重新引发其他错误
END calculate_total_value;


-- 5. 函数:获取供应商信息
CREATE OR REPLACE FUNCTION get_supplier_info (
p_pID IN CHAR(6)
) RETURN VARCHAR2 IS
v_supplier_info VARCHAR2(100);
BEGIN
-- 检索供应商名称和账户
SELECT pNAME || ', ' || pACC
INTO v_supplier_info
FROM provider
WHERE pID = p_pID;

RETURN v_supplier_info; -- 返回供应商信息
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN '未找到该供应商。';
WHEN OTHERS THEN
RAISE; -- 重新引发其他错误
END get_supplier_info;


-- 6. 计算总收入
CREATE OR REPLACE FUNCTION calculate_total_revenue (
p_gID IN CHAR(6)
) RETURN NUMBER IS
v_total_revenue NUMBER;
BEGIN
-- 计算该商品的总收入
SELECT SUM(quantity * salesPrice)
INTO v_total_revenue
FROM sales
WHERE gID = p_gID;

IF v_total_revenue IS NULL THEN
RETURN 0; -- 如果没有销售记录,返回0
END IF;

RETURN v_total_revenue; -- 返回总收入
EXCEPTION
WHEN OTHERS THEN
RAISE; -- 重新引发其他错误
END calculate_total_revenue;

触发器

-- 插入商品时检查商品数量的触发器
CREATE OR REPLACE TRIGGER trg_check_goods_quantity
BEFORE INSERT ON goods
FOR EACH ROW
BEGIN
IF :NEW.gUNIT <= 0 THEN
RAISE_APPLICATION_ERROR(-20001, '商品数量必须大于零。');
END IF;
END trg_check_goods_quantity;
/

-- 更新库存时记录历史的触发器
CREATE OR REPLACE TRIGGER trg_update_goods_stock_history
AFTER UPDATE OF gUNIT ON goods
FOR EACH ROW
BEGIN
INSERT INTO goods_history (hID, gID, oldQuantity, newQuantity, changeDate)
VALUES (goods_history_seq.NEXTVAL, :OLD.gID, :OLD.gUNIT, :NEW.gUNIT, SYSTIMESTAMP);
END trg_update_goods_stock_history;
/

-- 插入销售记录后更新库存的触发器
CREATE OR REPLACE TRIGGER trg_update_stock_after_sale
AFTER INSERT ON sales
FOR EACH ROW
BEGIN
UPDATE goods
SET gUNIT = gUNIT - :NEW.quantity
WHERE gID = :NEW.gID;

IF SQL%ROWCOUNT = 0 THEN
RAISE_APPLICATION_ERROR(-20002, '更新库存失败:未找到商品。');
END IF;
END trg_update_stock_after_sale;
/



-- 插入销售记录后更新库存的触发器
CREATE OR REPLACE TRIGGER trg_update_stock_after_sale
AFTER INSERT ON sales
FOR EACH ROW
BEGIN
UPDATE goods
SET gUNIT = gUNIT - :NEW.quantity
WHERE gID = :NEW.gID;

IF SQL%ROWCOUNT = 0 THEN
RAISE_APPLICATION_ERROR(-20002, '更新库存失败:未找到商品。');
END IF;
END trg_update_stock_after_sale;
/

数据操纵

-- 插入产品数据
INSERT INTO goods (gID, gNAME, gKIDS, gUNIT, gPRICE) VALUES
('P001', '笔记本', '001', 50, 20);

INSERT INTO goods (gID, gNAME, gKIDS, gUNIT, gPRICE) VALUES
('P002', '铅笔', '001', 100, 5);

-- 插入供应商数据
INSERT INTO provider (pID, pNAME, pACC, pADD) VALUES
('PR001', '供应商A', '1234567890123456789', '地址1');

INSERT INTO provider (pID, pNAME, pACC, pADD) VALUES
('PR002', '供应商B', '9876543210123456789', '地址2');

-- 插入门店数据
INSERT INTO shop (shID, shNAME, shADD) VALUES
('SH001', '商店A', '地址A');

INSERT INTO shop (shID, shNAME, shADD) VALUES
('SH002', '商店B', '地址B');

-- 插入营业员数据
INSERT INTO assistant (aID, aNAME, aFEAT, shID) VALUES
('A001', '11', 1, 'SH001');

INSERT INTO assistant (aID, aNAME, aFEAT, shID) VALUES
('A002', '12', 1, 'SH002');

-- 插入销售记录
INSERT INTO sales (saleID, gID, quantity, salesPrice, aID) VALUES
(1, 'P001', 5, 20, 'A001');

INSERT INTO sales (saleID, gID, quantity, salesPrice, aID) VALUES
(2, 'P002', 2, 5, 'A002');


-- 删除指定的销售记录
DELETE FROM sales
WHERE saleID = 1;

-- 删除指定的商品
DELETE FROM goods
WHERE gID = 'P002';

-- 删除供应商
DELETE FROM provider
WHERE pID = 'PR002';

-- 查询所有商品信息
SELECT * FROM goods;

-- 查询所有供应商的名称和地址
SELECT pNAME, pADD FROM provider;

-- 查询门店信息
SELECT * FROM shop;

-- 查询所有营业员
SELECT * FROM assistant;

-- 查询销售记录及其对应的商品名称和营业员姓名
SELECT s.saleID, g.gNAME, s.quantity, s.salesPrice, a.aNAME
FROM sales s
JOIN goods g ON s.gID = g.gID
JOIN assistant a ON s.aID = a.aID;

-- 查询所有销售记录
SELECT * FROM sales;

电脑销售系统oracle.zip