[练手]MySQL进销存系统

这是数据库练手,主要就是存储过程和触发器的使用吧
Tip:如选择性阅读请配合右上角的目录食用更佳~

在这里插入图片描述

前言

需求

1.实现药品信息的管理,入库和出库时必须能自动修改库存(使用触发器实现);
2.定义视图查询各仓库中存放的药品信息和数量;
3.实现销售收款,¬收完款后要自动修改销售单的结账标记(结清为‘Y’,未结清为‘N’)(使用触发器实现);
4.定义存储过 程查询日销售明细(包括销售的药品、数量、金额);
5.定义存储过程生成收款员的收款日报(收款员、金额);
6.管理药品的计量单位只能是“瓶”、“袋”,“支”;
7.销售时每一个销售单,可以销售多种药品,并能根据销售的各种药品的数量和单价计算销售小计和总计金额
更新:
删除-新增、修改’药品同步进货触发器’
修改-‘实收金额’ 计算触发器
修改-E-R图
修改-‘结账标记’ 判断触发器
新增-满额自动会员升级 触发器 ‘insert_升级会员’,‘update_升级会员’
新增-自动计算找零 触发器 ‘insert_应找金额’,‘update_应找金额’

已经实现的功能

1.进货数量增加,库存数量自动增加
2.销售数量增加,库存数量自动减少
3.进货增加新单号,总价自动计算
进货修改,总价自动计算
4.销售增加新单号,总价自动计算
销售修改,总价自动计算
5.总销售增加新单号,自动计算折扣,生成实收金额
总销售修改,自动计算折扣,生成实收金额
6.总销售增加新单号,自动对比实收金额和已收金额,判断是否结账
总销售修改,自动对比实收金额和已收金额,判断是否结账
8.总销售增加新单号,自动计算应找金额
总销售修改,自动计算应找金额
9.总销售增加新单号,自动对比用户表是否VIP或普通用户
10.总销售增加新单号,总价自动同步销售总价
总销售修改,总价自动同步销售总价
11.普通用户消费达到10000元,自动升级VIP,本次以及往后自动打折


流程图

在这里插入图片描述


E-R图

在这里插入图片描述


关系模型

厂家(厂家编号,厂家名称)
进货(进货单号,药品编号,数量,单价,总价,时间,厂家编号,采购员编号)
库存(库存编号,药品编号,药品数量,计量单位,备注)
销售(销售单号,药品编号,单价,数量,总价,大单号,备注)
药品(药品编号,药品名称,单价,备注)
用户(用户编号,用户姓名,电话,地址,备注)
员工(员工编号,员工姓名,职位,电话,备注)
总销售(大单号,用户编号,总价,折扣,实收金额,已收金额,应找金额,结账标记,销售员工编号,日期)


数据字典

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述


建表语句

Create Table

CREATE TABLE `厂家` (
 `厂家编号` int(20) NOT NULL,
 `厂家名称` varchar(50) DEFAULT NULL,
 PRIMARY KEY (`厂家编号`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk
Create Table

CREATE TABLE `进货` (
 `进货单号` int(10) NOT NULL AUTO_INCREMENT,
 `药品编号` int(10) DEFAULT NULL,
 `数量` decimal(10,0) DEFAULT NULL,
 `单价` decimal(10,0) DEFAULT NULL,
 `总价` decimal(10,2) DEFAULT NULL,
 `时间` date DEFAULT NULL,
 `厂家` decimal(10,0) DEFAULT NULL,
 `采购员编号` int(11) DEFAULT NULL,
 PRIMARY KEY (`进货单号`),
 KEY `进货_药品_fk` (`药品编号`),
 CONSTRAINT `进货_药品_fk` FOREIGN KEY (`药品编号`) REFERENCES `药品` (`药品编号`)
) ENGINE=InnoDB AUTO_INCREMENT=200 DEFAULT CHARSET=gbk

Create Table

CREATE TABLE `库存` (
 `库存编号` int(11) NOT NULL AUTO_INCREMENT,
 `药品编号` int(11) DEFAULT NULL,
 `药品数量` decimal(20,0) DEFAULT NULL,
 `计量单位` varchar(10) DEFAULT NULL,
 `备注` text,
 PRIMARY KEY (`库存编号`),
 KEY `库存_药品编号_fk` (`药品编号`),
 CONSTRAINT `库存_药品编号_fk` FOREIGN KEY (`药品编号`) REFERENCES `药品` (`药品编号`)
) ENGINE=InnoDB AUTO_INCREMENT=106 DEFAULT CHARSET=gbk
Create Table

CREATE TABLE `销售` (
`销售单号` int(11) NOT NULL AUTO_INCREMENT,
`药品编号` int(11) DEFAULT NULL,
`单价` decimal(10,2) DEFAULT NULL,
`数量` decimal(10,0) DEFAULT NULL,
`总价` decimal(10,2) DEFAULT NULL,
`大单号` int(50) DEFAULT NULL,
`备注` text,
PRIMARY KEY (`销售单号`),
KEY `销售_药品_fk` (`药品编号`),
CONSTRAINT `销售_药品_fk` FOREIGN KEY (`药品编号`) REFERENCES `药品` (`药品编号`)
) ENGINE=InnoDB AUTO_INCREMENT=164 DEFAULT CHARSET=gbk


Create Table

CREATE TABLE `药品` (
`药品编号` int(11) NOT NULL AUTO_INCREMENT,
`药品名称` varchar(30) DEFAULT NULL,
`单价` decimal(10,2) DEFAULT NULL,
`备注` text,
PRIMARY KEY (`药品编号`)
) ENGINE=InnoDB AUTO_INCREMENT=106 DEFAULT CHARSET=gbk





Create Table

CREATE TABLE `用户` (
`用户编号` int(11) NOT NULL AUTO_INCREMENT,
`用户类别` varchar(10) DEFAULT NULL,
`用户姓名` varchar(20) CHARACTER SET gbk COLLATE gbk_chinese_ci DEFAULT NULL,
`电话` varchar(20) DEFAULT NULL,
`地址` varchar(50) DEFAULT NULL,
`备注` text,
PRIMARY KEY (`用户编号`)
) ENGINE=InnoDB AUTO_INCREMENT=106 DEFAULT CHARSET=gbk



Create Table

CREATE TABLE `员工` (
`员工编号` int(11) NOT NULL AUTO_INCREMENT,
`员工姓名` varchar(50) DEFAULT NULL,
`职位` varchar(20) DEFAULT NULL,
`电话` varchar(30) DEFAULT NULL,
`性别` varchar(10) DEFAULT NULL,
`备注` text,
PRIMARY KEY (`员工编号`)
) ENGINE=InnoDB AUTO_INCREMENT=104 DEFAULT CHARSET=gbk



Create Table

CREATE TABLE `总销售` (
`大单号` int(50) DEFAULT NULL,
`用户编号` int(50) DEFAULT NULL,
`总价` decimal(10,2) DEFAULT NULL,
`折扣` varchar(50) CHARACTER SET gbk COLLATE gbk_chinese_ci DEFAULT '无',
`实收金额` decimal(10,2) DEFAULT NULL,
`已收金额` decimal(10,2) DEFAULT '0.00',
`应找金额` decimal(10,2) DEFAULT NULL,
`结账标记` varchar(20) DEFAULT 'N',
`销售员工编号` int(20) DEFAULT NULL,
`日期` date DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=gbk


定义视图查询各仓库中存放的药品信息和数量

无单位的库存视图

DELIMITER $$

ALTER ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `单纯的库存` AS 
SELECT
  `药品`.`药品编号` AS `药品编号`,
  `药品`.`药品名称` AS `药品名称`,
  `库存`.`药品数量` AS `药品数量`
FROM (`药品`
   JOIN `库存`)
WHERE (`药品`.`药品编号` = `库存`.`药品编号`)$$

DELIMITER ;


在这里插入图片描述

有单位的库存视图

DELIMITER $$
ALTER ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `带计量单位的库存` AS 
SELECT
  `药品`.`药品名称` AS `药品名称`,
  CONCAT(`库存`.`药品数量`,`库存`.`计量单位`) AS `库存数量`
FROM (`药品`
   JOIN `库存`)
WHERE (`药品`.`药品编号` = `库存`.`药品编号`)$$
DELIMITER ;

在这里插入图片描述


存储过程封装某些查询语句

查询日销售明细(包括销售的药品、数量、金额)

DELIMITER $$
USE `test_ drugstore`$$
DROP PROCEDURE IF EXISTS `日销售明细`$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `日销售明细`(d DATE)
BEGIN
SELECT 药品.`药品名称`,销售.`数量`,销售.`总价`
FROM 销售,药品,总销售
WHERE 销售.药品编号=药品.药品编号
GROUP BY 销售单号;
END$$
DELIMITER ;

在这里插入图片描述
示例 :CALL 日销售明细(‘2018-09-08’);
输入指定日期可以查看当日销售明细

生成收款员的收款日报(收款员、金额)

DELIMITER $$
USE `test_ drugstore`$$
DROP PROCEDURE IF EXISTS `收款日报`$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `收款日报`(a INT)
BEGIN
SELECT 员工.`员工编号`,员工.`员工姓名`,总销售.总价,总销售.`实收金额`,总销售.日期
FROM 总销售,员工 
WHERE 总销售.销售员工编号=员工.员工编号 AND 员工编号=a;
END$$
DELIMITER ;

示例 :CALL 收款日报(‘101’);
输入指定员工编号可以查看每日该员工收款情况

在这里插入图片描述

销售时每一个销售单,可以销售多种药品,并能根据销售的各种药品的数量和单价计算销售小计和总计金额

销售小计&销售总金额
示例 :CALL 小票小计(‘101’);
输入指定大单号可以查看该单号每种药品总价小计,及总金额

DELIMITER $$
USE `test_ drugstore`$$
DROP PROCEDURE IF EXISTS `小票小计`$$

CREATE DEFINER=`root`@`localhost` PROCEDURE `小票小计`(a INT)
BEGIN
SELECT 总销售.大单号,销售.药品编号,药品.药品名称,销售.单价,SUM(销售.数量),SUM(销售.总价)
FROM 总销售,销售,药品
WHERE  总销售.大单号=销售.大单号 AND 药品.药品编号=销售.`药品编号`  AND 总销售.大单号=a
GROUP BY 药品编号 WITH ROLLUP;
END$$
DELIMITER ;

在这里插入图片描述


触发器

insert_升级会员

触发条件:总销售插入新进货单,计算此用户累计消费
执行操作:如果总消费达到一万,自动升级为会员
如果不到一万,继续以普通用户登记

DELIMITER $$

USE `test_ drugstore`$$

DROP TRIGGER /*!50032 IF EXISTS */ `insert_升级会员`$$

CREATE
    /*!50017 DEFINER = 'root'@'localhost' */
    TRIGGER `insert_升级会员` BEFORE INSERT ON `总销售` 
    FOR EACH ROW BEGIN 
DECLARE a DECIMAL;
DECLARE b DECIMAL;
SET b=new.实收金额;
SELECT SUM(实收金额)+b INTO a FROM 总销售 WHERE 用户编号=new.用户编号;
IF (a>=10000) THEN
SET new.折扣='vip';

Insert_进货

触发条件:进货表 插入新行
执行操作:库存表 药品数量=旧的药品数量+新进货的药品数量

DELIMITER $$
USE `test_ drugstore`$$
DROP TRIGGER /*!50032 IF EXISTS */ `insert_进货`$$
CREATE
    /*!50017 DEFINER = 'root'@'localhost' */
    TRIGGER `insert_进货` AFTER INSERT ON `进货` 
    FOR EACH ROW BEGIN
UPDATE 库存 
SET 药品数量=库存.药品数量+new.数量
WHERE 库存.药品编号=药品编号;
END;
$$
DELIMITER ;

Insert_进货计算总价

触发条件:进货表 插入新行
执行操作:进货表 总价=数量*单价

DELIMITER $$

USE `test_ drugstore`$$

DROP TRIGGER /*!50032 IF EXISTS */ `insert_进货计算总价`$$

CREATE
    /*!50017 DEFINER = 'root'@'localhost' */
    TRIGGER `insert_进货计算总价` BEFORE INSERT ON `进货` 
    FOR EACH ROW BEGIN 
SET new.总价=new.数量*new.单价;
END;
$$

DELIMITER ;

update_进货计算总价

触发条件:进货表 更新数据
执行操作:进货表 总价=数量*单价


DELIMITER $$

USE `test_ drugstore`$$

DROP TRIGGER /*!50032 IF EXISTS */ `update_进货计算总价`$$

CREATE
    /*!50017 DEFINER = 'root'@'localhost' */
    TRIGGER `update_进货计算总价` BEFORE UPDATE ON `进货` 
    FOR EACH ROW BEGIN 
SET new.总价=new.数量*new.单价;
END;
$$

DELIMITER ;

Insert_实收计算

触发条件1:总销售表 插入新行的折扣=vip,
执行操作1:总销售表 总价=数量单价0.5

触发条件2:总销售表 插入新行的折扣不为vip,
执行操作2:总销售表 总价=数量*单价

DELIMITER $$
USE `test_ drugstore`$$
DROP TRIGGER /*!50032 IF EXISTS */ `insert_实收计算`$$
CREATE
    /*!50017 DEFINER = 'root'@'localhost' */
    TRIGGER `insert_实收计算` BEFORE INSERT ON `总销售` 
    FOR EACH ROW BEGIN 
IF (new.折扣='vip')
THEN
SET new.实收金额=(0.5*new.总价);
ELSE 
SET new.实收金额=new.总价;
END IF;
END;
$$
DELIMITER ;

update_实收计算

触发条件1:总销售表 更新数据 折扣=vip,
执行操作1:总销售表 总价=数量单价0.5

触发条件2:总销售表 插入新行的折扣不为vip,
执行操作2:总销售表 总价=数量*单价
DELIMITER $$


USE `test_ drugstore`$$

DROP TRIGGER /*!50032 IF EXISTS */ `update_实收计算`$$

CREATE
    /*!50017 DEFINER = 'root'@'localhost' */
    TRIGGER `update_实收计算` BEFORE UPDATE ON `总销售` 
    FOR EACH ROW BEGIN 
IF (new.折扣='vip')
THEN
SET new.实收金额=(0.5*new.总价);
ELSE 
SET new.实收金额=new.总价;
END IF;
END;
$$

DELIMITER ;

Insert_是否结账

触发条件1:总销售表 插入新行的 实收金额 >= 总价,
执行操作1:总销售表 结账标记=Y

触发条件2:总销售表 插入新行的 实收金额 < 总价,
执行操作2:总销售表 结账标记=N


DELIMITER $$
USE `test_ drugstore`$$
DROP TRIGGER /*!50032 IF EXISTS */ `insert_是否结账`$$
CREATE
    /*!50017 DEFINER = 'root'@'localhost' */
    TRIGGER `insert_是否结账` BEFORE INSERT ON `总销售` 
    FOR EACH ROW BEGIN 
IF (new.实收金额>=new.总价)
THEN
SET new.结账标记='Y';
ELSE 
SET new.结账标记='N';
END IF;
END;
$$
DELIMITER ;

update_是否结账

触发条件1:总销售表 修改数据 实收金额 >= 总价,
执行操作1:总销售表 结账标记=Y

触发条件2:总销售表 插入新行的 实收金额 < 总价,
执行操作2:总销售表 结账标记=N


DELIMITER $$

USE `test_ drugstore`$$

DROP TRIGGER /*!50032 IF EXISTS */ `update_是否结账`$$

CREATE
    /*!50017 DEFINER = 'root'@'localhost' */
    TRIGGER `update_是否结账` BEFORE UPDATE ON `总销售` 
    FOR EACH ROW BEGIN 
IF (new.实收金额>=new.总价)
THEN
SET new.结账标记='Y';
ELSE 
SET new.结账标记='N';
END IF;
END;
$$

DELIMITER ;

Insert_销售

触发条件:销售表 插入新行,
执行操作:库存表 药品数量=旧药品数量+销售的药品数量

DELIMITER $$
USE `test_ drugstore`$$
DROP TRIGGER /*!50032 IF EXISTS */ `insert_销售`$$

CREATE
    /*!50017 DEFINER = 'root'@'localhost' */
    TRIGGER `insert_销售` AFTER INSERT ON `销售` 
    FOR EACH ROW BEGIN
UPDATE 库存 
SET 药品数量=库存.药品数量-new.数量
WHERE 库存.药品编号=药品编号;

END;
$$
DELIMITER ;

Insert_销售计算总价

触发条件:销售表 插入新行,
执行操作:销售的总价= 数量*单价

DELIMITER $$
USE `test_ drugstore`$$
DROP TRIGGER /*!50032 IF EXISTS */ `insert_销售计算总价`$$
CREATE
    /*!50017 DEFINER = 'root'@'localhost' */
    TRIGGER `insert_销售计算总价` BEFORE INSERT ON `销售` 
    FOR EACH ROW BEGIN 
SET new.总价=new.数量*new.单价;
END;
$$
DELIMITER ;

update_销售计算总价

触发条件:销售表 更新数据,
执行操作:销售的总价= 数量*单价

DELIMITER $$

USE `test_ drugstore`$$

DROP TRIGGER /*!50032 IF EXISTS */ `update_销售计算总价`$$

CREATE
    /*!50017 DEFINER = 'root'@'localhost' */
    TRIGGER `update_销售计算总价` BEFORE UPDATE ON `销售` 
    FOR EACH ROW BEGIN 
SET new.总价=new.数量*new.单价;
END;
$$

DELIMITER ;

Insert_折扣判断

触发条件:总销售表 插入新行
执行操作:总销售 的 折扣 = 用户表 的 用户类型

DELIMITER $$

USE `test_ drugstore`$$

DROP TRIGGER /*!50032 IF EXISTS */ `insert_折扣判断`$$

CREATE
    /*!50017 DEFINER = 'root'@'localhost' */
    TRIGGER `insert_折扣判断` BEFORE INSERT ON `总销售` 
    FOR EACH ROW BEGIN 
DECLARE a VARCHAR(50);
SELECT 用户类别 INTO a FROM 用户 WHERE 用户编号=new.用户编号;
SET new.折扣=a;

END;
$$

DELIMITER ;

Insert_总销售同步总价

触发条件:总销售表 插入新行
执行操作:总销售 的 总价 = 销售表 的 同一大单号的总价之和
DELIMITER $$

USE `test_ drugstore`$$

DROP TRIGGER /*!50032 IF EXISTS */ `insert_总销售同步总价`$$

CREATE
    /*!50017 DEFINER = 'root'@'localhost' */
    TRIGGER `insert_总销售同步总价` BEFORE INSERT ON `总销售` 
    FOR EACH ROW BEGIN

DECLARE a DOUBLE;
SELECT SUM(总价) INTO a FROM 销售 WHERE 大单号 =new.大单号;
SET new.总价=a;

END;
$$

DELIMITER ;

update_总销售同步总价

触发条件:总销售表 更新数据
执行操作:总销售 的 总价 = 销售表 的 同一大单号的总价之和

DELIMITER $$

USE `test_ drugstore`$$

DROP TRIGGER /*!50032 IF EXISTS */ `update_总销售同步总价`$$

CREATE
    /*!50017 DEFINER = 'root'@'localhost' */
    TRIGGER `update_总销售同步总价` BEFORE UPDATE ON `总销售` 
    FOR EACH ROW BEGIN

DECLARE a DOUBLE;
SELECT SUM(总价) INTO a FROM 销售 WHERE 大单号 =new.大单号;
SET new.总价=a;

END;
$$

DELIMITER ;

insert_应找金额

触发条件:总销售表 更新数据
执行操作:总销售 的 总价 = 销售表 的 同一大单号的总价之和

DELIMITER $$
CREATE TRIGGER insert_应找金额 BEFORE INSERT ON 总销售 FOR EACH ROW 
BEGIN
SET new.应找金额=new.已收金额-new.实收金额;
END $$
DELIMITER;

update_应找金额

触发条件:总销售表 更新数据
执行操作:总销售 的 总价 = 销售表 的 同一大单号的总价之和

DELIMITER $$
CREATE TRIGGER update_应找金额 BEFORE UPDATE ON 总销售 FOR EACH ROW 
BEGIN
SET new.应找金额=new.已收金额-new.实收金额;
END $$
DELIMITER;

约束

这个地方没来得及完善。。。

ALTER TABLE 员工
ADD CONSTRAINT chk_sex CHECK (性别 IN ('男','女'))

在这里插入图片描述

总结

感觉还是不够用
有时间要看完整本书才行

猜你喜欢

转载自blog.csdn.net/qq_39702030/article/details/86911213