数据库设计——医药销售管理系统

article/2025/8/21 8:30:56

开发环境和开发工具

操作系统:win8.1
开发环境:Mysql、Web
开发工具:Workbench、Eclipse、JDBC

功能需求分析

  • 员工有权查看、添加会员,查看、添加供应商,查询药品(输入药品编号或名称、类别等查询该药品或该类药品库存),添加药品采购记录,销售药品,处理退货,盘点仓库,查看销售、退货、入库记录,修改个人信息
  • 经理有权查看、添加、删除会员,查看、添加、删除供应商,查看、添加、删除员工,盘点仓库,查看销售、退货、入库记录,修改个人信息,无权进行销售和退货业务
  • 供应商和顾客对此系统没有使用权限 系统设计

这里写图片描述

系统设计

  • 数据流
    这里写图片描述
  • E-R图
    这里写图片描述
  • 数据库关系模式设计

    登录用户(用户编号,用户名,密码,类别)
    员工(员工编号,员工姓名,联系电话,用户编号)
    经理(经理编号,用户编号)
    财政收支(收支编号,药品编号,员工编号,数量,日期,总额,类型)
    供应商(供应商编号,供应商名称,联系人,联系方式,所在城市)
    会员(客户编号,客户姓名,联系方式)
    入库记录(入库记录编号,供应商编号,收支编号)
    退货管理(退货编号,销售编号,收支编号)
    销售管理(销售编号,客户编号,收支编号)
    药品(药品编号,药品名称,供应商编号,生产批号,产地,所属类别,进价,单价,会员折扣,库存,包装规格,生产日期,有效期)

  • 数据库物理结构设计

    本次项目使用的引擎是InnoDB,MySQL的数据库引擎之一。InnoDB存储引擎为在主内存中缓存数据和索引而维持它自己的缓冲池。InnoDB存储它的表&索引在一个表空间中,表空间可以包含数个文件(或原始磁盘分区)。这与MyISAM表不同,比如在MyISAM表中每个表被存在分离的文件中。InnoDB 表可以是任何尺寸,即使在文件尺寸被限制为2GB的操作系统上。InnoDB默认地被包含在MySQL二进制分发中。Windows Essentials installer使InnoDB成为Windows上MySQL的默认表。

    此外还使用了数据库索引,索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息。各表索引如下:
    会员:primary key(客户编号)
    药品:primary key(药品编号),
    INDEX 供应商编号_idx (供应商编号 ASC),
    供应商:primary key(供应商编号)
    登录用户:primary key(用户编号)
    用户名 unique,
    经理:primary key(经理编号),
    INDEX 经理编号_idx (用户编号 ASC),
    员工:primary key(员工编号),
    INDEX 员工编号_idx (用户编号 ASC),
    财政收支:PRIMARY KEY (收支编号),
    INDEX 药品编号_idx (药品编号 ASC),
    INDEX 员工编号_idx (员工编号 ASC),
    入库记录:primary key(入库记录编号),
    INDEX 供应商编号_idx (供应商编号 ASC),
    INDEX 收支编号_idx (收支编号 ASC),
    销售管理:PRIMARY KEY (销售编号),
    INDEX 客户编号_idx (客户编号 ASC),
    INDEX 收支编号_idx (收支编号 ASC),
    退货管理:PRIMARY KEY (退货编号),
    INDEX 销售编号_idx (销售编号 ASC),
    INDEX 收支编号_idx (收支编号 ASC),

系统功能的实现

  • 建表

    drop database if exists 医药销售管理系统;
    create database 医药销售管理系统;
    use 医药销售管理系统;
    //建立表 会员
    create table `会员`(客户编号      int auto_increment,客户姓名      varchar(50),联系方式      varchar(100),
    primary key(客户编号));
    //建立表 供应商
    create table `供应商`(供应商编号     int auto_increment,供应商名称     varchar(50),联系人         varchar(50),联系方式       varchar(50),所在城市       varchar(50),
    primary key(供应商编号));
    //建立表 药品
    create table `药品`(药品编号    int auto_increment,药品名称    varchar(50) not null,供应商编号  int not null,生产批号    varchar(100),产地        varchar(50),所属类别    varchar(50),进价        decimal(10,2) not null,单价        decimal(10,2) not null,会员折扣    decimal(3,2),库存        int not null,包装规格    varchar(50),生产日期    varchar(50),有效期      varchar(50),
    primary key(药品编号),
    INDEX `供应商编号_idx` (`供应商编号` ASC),
    CONSTRAINT `供应商编号`
    FOREIGN KEY (`供应商编号`)
    REFERENCES `医药销售管理系统`.`供应商` (`供应商编号`)
    ON DELETE CASCADE
    ON UPDATE CASCADE);
    //建立表登录用户,可以登录医药销售管理系统,类别为1代表员工,2代表经理
    create table `登录用户`(用户编号         int auto_increment,用户名          varchar(40) not null unique,密码           varchar(40) not null,类别             int not null,
    primary key(用户编号));
    //建立表经理,具有登录用户编号,可登录系统
    create table `经理`(经理编号      int auto_increment,用户编号      int not null,
    primary key(经理编号),
    INDEX `经理编号_idx` (`用户编号` ASC),
    CONSTRAINT `经理登陆编号`
    FOREIGN KEY (`用户编号`)
    REFERENCES `医药销售管理系统`.`登录用户` (`用户编号`)
    ON DELETE CASCADE
    ON UPDATE CASCADE);
    //建立表员工,具有登录用户编号,可登录系统
    create table `员工`(员工编号      int auto_increment,员工姓名      varchar(50),联系电话      varchar(100),用户编号      int not null,
    primary key(员工编号),
    INDEX `员工编号_idx` (`用户编号` ASC),
    CONSTRAINT `员工登陆编号`
    FOREIGN KEY (`用户编号`)
    REFERENCES `医药销售管理系统`.`登录用户` (`用户编号`)
    ON DELETE CASCADE
    ON UPDATE CASCADE);
    //建立表财政开支,涉及药品编号、负责员工、数量、金额等信息,类型有入库、销售、退货等
    CREATE TABLE `财政收支` (
    `收支编号` int auto_increment,
    `药品编号` int,
    `员工编号` int not null,
    `数量` int,
    `日期` datetime NOT NULL,
    `总额` decimal(10,2) NOT NULL,
    `类型` VARCHAR(20)  NOT NULL,
    PRIMARY KEY (`收支编号`),
    INDEX `药品编号_idx` (`药品编号` ASC),
    CONSTRAINT `药品编号`
    FOREIGN KEY (`药品编号`)
    REFERENCES `医药销售管理系统`.`药品` (`药品编号`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
    INDEX `员工编号_idx` (`员工编号` ASC),
    CONSTRAINT `负责员工编号`
    FOREIGN KEY (`员工编号`)
    REFERENCES `医药销售管理系统`.`员工` (`员工编号`)
    ON DELETE CASCADE
    ON UPDATE CASCADE);
    //建立表入库记录,包含供应商、收支编号
    create table `入库记录`(入库记录编号   int auto_increment,供应商编号     int not null,收支编号       int not null,
    primary key(入库记录编号),
    INDEX `供应商编号_idx` (`供应商编号` ASC),
    INDEX `收支编号_idx` (`收支编号` ASC),
    CONSTRAINT `入货供应商编号`
    FOREIGN KEY (`供应商编号`)
    REFERENCES `医药销售管理系统`.`供应商` (`供应商编号`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
    CONSTRAINT `入库收支编号`
    FOREIGN KEY (`收支编号`)
    REFERENCES `医药销售管理系统`.`财政收支` (`收支编号`)
    ON DELETE CASCADE
    ON UPDATE CASCADE);
    //建立表销售管理,包含客户、收支编号
    CREATE TABLE `销售管理`(
    `销售编号` int auto_increment,
    `客户编号` int,
    `收支编号` int not null,
    PRIMARY KEY (`销售编号`),
    INDEX `客户编号_idx` (`客户编号` ASC),
    INDEX `收支编号_idx` (`收支编号` ASC),
    CONSTRAINT `销售客户编号`
    FOREIGN KEY (`客户编号`)
    REFERENCES `医药销售管理系统`.`会员` (`客户编号`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
    CONSTRAINT `销售收支编号`
    FOREIGN KEY (`收支编号`)
    REFERENCES `医药销售管理系统`.`财政收支` (`收支编号`)
    ON DELETE CASCADE
    ON UPDATE CASCADE);
    //建立表退货管理,包含销售、收支编号
    CREATE TABLE `退货管理` (
    `退货编号` int auto_increment,
    `销售编号` int NOT NULL,
    `收支编号` int NOT NULL,
    PRIMARY KEY (`退货编号`),
    INDEX `销售编号_idx` (`销售编号` ASC),
    INDEX `收支编号_idx` (`收支编号` ASC),
    CONSTRAINT `退货销售编号`
    FOREIGN KEY (`销售编号`)
    REFERENCES `医药销售管理系统`.`销售管理` (`销售编号`)
    ON DELETE CASCADE
    ON UPDATE CASCADE,
    CONSTRAINT `退货收支编号`
    FOREIGN KEY (`收支编号`)
    REFERENCES `医药销售管理系统`.`财政收支` (`收支编号`)
    ON DELETE CASCADE
    ON UPDATE CASCADE);
  • 创建视图方便查询

    
    /*仓库*/
    drop view if exists warehouse; 
    create view warehouse as
    select 药品编号,药品名称,供应商名称,生产批号,产地,所属类别,进价,单价,会员折扣,库存,包装规格,生产日期,有效期
    from 药品,供应商 where 药品.供应商编号=供应商.供应商编号; 
    /*入库记录*/
    drop view if exists InDrug_records; 
    create view InDrug_records as
    select 入库记录编号,药品名称,供应商名称,员工姓名,数量,日期,总额 
    from 入库记录,供应商,财政收支,员工,药品
    where 入库记录.供应商编号=供应商.供应商编号 and 入库记录.收支编号=财政收支.收支编号 and
    财政收支.员工编号=员工.员工编号 and 财政收支.药品编号=药品.药品编号;
    /*销售记录*/
    drop view if exists sales_records; 
    create view sales_records as
    select 销售编号,药品.药品编号,药品名称,单价,会员折扣,库存,客户姓名,员工姓名,数量,日期,总额
    from 销售管理,会员,财政收支,员工,药品
    where 销售管理.客户编号=会员.客户编号 and 销售管理.收支编号=财政收支.收支编号
    and 财政收支.员工编号=员工.员工编号 and 财政收支.药品编号=药品.药品编号;
    /*退货记录*/
    drop view if exists reject_records;
    create view reject_records as
    select 退货编号,退货管理.销售编号,药品名称,客户姓名,员工姓名,数量,日期,总额
    from 退货管理,销售管理,会员,财政收支,员工,药品
    where 退货管理.销售编号=销售管理.销售编号 and 销售管理.客户编号=会员.客户编号 
    and 退货管理.收支编号=财政收支.收支编号 and 财政收支.员工编号=员工.员工编号 
    and 财政收支.药品编号=药品.药品编号;
    /*员工信息*/
    drop view if exists employee_info;
    create view employee_info as
    select 员工编号,员工姓名,联系电话,员工.用户编号,用户名 from `员工` natural join `登录用户`;
    /*收支记录*/
    drop view if exists financial_records;
    create view financial_records as
    select 类型,药品名称,数量,日期,总额 
    from `财政收支` left join `药品` on `财政收支`.药品编号=`药品`.`药品编号`;
  • 使用过程实现“带参数的视图“

    drop procedure if exists payments_statistics;
    delimiter //
    create procedure payments_statistics(in date_limit varchar(20))
    beginselect count(*) as 数目,sum(`总额`) as 盈亏, (select sum(`总额`) from `财政收支` where `总额` < 0 and `日期` like date_limit) as '支出', (select sum(`总额`) from `财政收支` where `总额` >= 0 and `日期` like date_limit) as '收入' from `财政收支` where `日期` like date_limit;
    end//

    JDBC调用方法如下

                //调用过程  -- 统计盈亏、收入、支出CallableStatement cStmt = con.prepareCall("{call payments_statistics(?)}");cStmt.setString(1,"%"+date+"%");cStmt.execute();rs = cStmt.getResultSet();if(rs.next()){count = rs.getInt(1);all = rs.getString(2);allOut = rs.getString(3);allIn = rs.getString(4);}rs.close();
  • 建立触发器保证逻辑正确

    
    drop trigger if exists stock_update;
    delimiter //
    create trigger stock_update before update on 药品
    for each row
    beginif new.库存 < 0/* MySQL不支持直接使用rollback回滚事务,可以利用delete当前表造成异常使事务回滚 */then delete from 药品 where 药品编号=new.药品编号;  end if;
    end //
    update 药品 set 库存=-2 where 药品编号=1;drop trigger if exists drugs_insert;
    delimiter //
    create trigger drugs_insert before insert on 药品
    for each row
    beginif new.库存 < 0 or new.单价 < 0 or new.进价 < 0 or new.会员折扣 > 1 or new.会员折扣 < 0then delete from 药品 where 药品编号=new.药品编号;end if;
    end //
    /*退货数量不应比售出的多*/
    drop trigger if exists refunds_insert;
    delimiter //
    create trigger refunds_insert after insert on 退货管理
    for each row
    beginif (select 数量 from sales_records where 销售编号 = new.销售编号) < (select 数量 from reject_records where 退货编号 = new.退货编号)then delete from 退货管理 where 退货编号=new.退货编号;end if;
    end //
  • 将业务逻辑封装为事务,如销售事务

    PreparedStatement ps=null;Connection con = DriverManager.getConnection(connectString,"root", "2333");...con.setAutoCommit(false);//设置自动提交为false...//销售事务 //更新库存String fmt1="update 药品  set `库存`='%d' where `药品编号`='%s'";String sql1 = String.format(fmt1,drug_rest-pcount,drug_id); ps = con.prepareStatement(sql1);ps.executeUpdate();//插入财政收支记录String fmt2="INSERT INTO `财政收支` (`药品编号`,`员工编号`,`数量`,`日期`,`总额`,`类型`) VALUES ('%s','%d','%d','%s','%s','销售')";String sql2 = String.format(fmt2,drug_id,employee_id,pcount,today,money); ps = con.prepareStatement(sql2);ps.executeUpdate(); //获取插入的财政收支编号ps = con.prepareStatement("select @@identity;");rs = ps.executeQuery();if(rs.next()){financial_id=rs.getInt(1);}rs.close();//插入销售记录String fmt3="insert into 销售管理(客户编号,收支编号) values(%s,'%d')";String sql3 = String.format(fmt3,customer_id,financial_id); ps = con.prepareStatement(sql3);ps.executeUpdate();//提交事务con.commit();}catch(Exception e){try {con.rollback();} catch (Exception e1) {e1.printStackTrace();}

界面效果

登陆
这里写图片描述
主页
这里写图片描述
仓库
这里写图片描述
点击新增进行药品入库
这里写图片描述
入库/销售/退货记录
这里写图片描述
员工可查看/增加客户,供应商
这里写图片描述
经理可增删员工、客户、供应商
这里写图片描述
销售药品
这里写图片描述
这里写图片描述
退货
这里写图片描述
财务统计
这里写图片描述

(项目见https://github.com/14353350/Drug_Sales_Management)


http://chatgpt.dhexx.cn/article/N5UU9DFk.shtml

相关文章

医院管理系统/医院药品管理系统

摘 要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#xff0c;科学化的管理&#xff0c;使信息存…

基于SSM实现的医院医药药品管理系统-JAVA【毕业设计定制、快速开发、源码、开题报告】

功能介绍 登录系统&#xff1a;管理员需要输入正确的用户名和密码来登录系统&#xff0c;从而完成各类信息的管理工作&#xff1b; 信息查询&#xff1a;查询客户信息、查询经办人信息、查询药品信息&#xff1b; 信息录入&#xff1a;录入顾客信息、录入经办人信息、录入药…

ec java sm2证书_国密算法SM2证书制作

前段时间将系统的RSA算法全部升级为SM2国密算法&#xff0c;密码机和UKey硬件设备大都同时支持RSA和SM2算法&#xff0c;只是应用系统的加解密签名验证需要修改&#xff0c;这个更改底层调用的加密动态库来&#xff0c;原来RSA用的对称加密算法DES(AES)和摘要MD5(SHA1)也相应改…

SM2椭圆曲线

文章目录 题目环境方案设计背景原理算法步骤 方案实现流程图加密解密 主要函数C代码测试数据结果 注意问题 说明 题目 实现SM2椭圆曲线公钥密码算法&#xff0c;对给出的英文消息进行加密得到密文&#xff0c;并能通过密文解密出明文。 环境 Windows10&#xff0c;MinGW-W64…

JAVA集成国密SM2

JAVA集成国密SM2加解密 一、pom配置二、代码集成2.1、目录结构2.2、源码2.3、测试 三、相关链接 国密算法概述&#xff1a;https://blog.csdn.net/qq_38254635/article/details/131801527 SM2椭圆曲线公钥密码算法 为非对称加密&#xff0c;基于ECC。该算法已公开。由于该算法…

Java SM2

pom <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 http…

ECCSM2

ECC&SM2 ECC 基本内容 概念 ECC 全称为椭圆曲线加密&#xff0c;EllipseCurve Cryptography&#xff0c;是一种基于椭圆曲线数学的公钥密码。与传统的基于大质数因子分解困难性的加密方法(RSA)不同&#xff0c;ECC 依赖于解决椭圆曲线离散对数问题的困难性。它的优势主要…

C# SM2

Cipher using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Digests; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Math.EC;namespace SM2Test {/// <summary>/// 密码计算/// </summary>public…

Springboot整合SM2加密的笔记

首先要明白公钥是加密&#xff0c;私钥用来解密。 国密公钥格式&#xff1a;公钥为64位&#xff0c;前后各32位&#xff0c;对应椭圆算法中BigInteger X 和 BigInteger X &#xff0c;私钥为32位&#xff0c;对应算法中的BigInteger d。 工具类&#xff1a; 可以参考https:/…

SM2加解密、签名验签

导论 SM2是国家密码管理局于2010年12月17日发布的椭圆曲线公钥密码算法&#xff0c;在我们国家商用密码体系中被用来替换RSA算法。 国产SM2算法&#xff0c;是基于ECC的&#xff0c;但二者在签名验签、加密解密过程中或许有些许区别&#xff0c;目前鄙人还不太清楚&#xff0c…

sm2和sm4加密算法浅析

sm2和sm4加密算法浅析 一: SM2 简介&#xff1a;SM2是国家密码管理局于2010年12月17日发布的椭圆曲线公钥密码算法 &#xff0c;SM2为非对称加密&#xff0c;基于ECC。该算法已公开。由于该算法基于ECC&#xff0c;故其签名速度与秘钥生成速度都快于RSA。ECC 256位&#xff0…

国密算法(SM2)简介及SM2生成秘钥

国密算法&#xff08;SM2&#xff09;生成秘钥 一、国密算法介绍二、SM2算法和RSA算法比较三、生成SM2秘钥1、openssl生成SM2秘钥1.1、安装openssl1.2、生成SM2私钥1.3、生成SM2公钥 2、nodejs:使用sm-crypto包生成SM2秘钥3、c生成秘钥 参考 一、国密算法介绍 国密即国家密码局…

向量积(叉积)

a和b叉积可表示为ab&#xff0c;结果是一个和这两个向量都垂直的伪向量 ab absinθ*n &#xff0c;ab为两向量的模长&#xff0c;θ是两向量的夹角&#xff0c;n是垂直二者的单位向量。 叉积的长度可以理解为以ab为邻边的平行四边形面积 叉积的运算 反交换律 ab-ba 分配律…

向量的点乘(内积)和叉乘(外积)

向量点乘&#xff1a;a * b&#xff08;常被写为a b&#xff09; 点乘,也叫向量的内积、数量积.顾名思义,求下来的结果是一个数. 向量a向量b|a||b|cos 在物理学中,已知力与位移求功,实际上就是求向量F与向量s的内积,即要用点乘. 向量叉乘&#xff1a;a ∧ b&#xff08;常被…

向量的内积(点乘)与外积(叉乘)

向量的内积&#xff08;点乘&#xff09;与外积&#xff08;叉乘&#xff09; 向量的内积点乘 向量的外积叉乘 向量的内积&#xff08;点乘&#xff09; 内积的几何意义&#xff1a; 用来表征或计算两个向量之间的夹角在b向量在a向量方向上的投影。 向量的外积&#xff08;叉…

两向量的向量积

两向量的向量积 两向量 a 与 b 的向量积&#xff08;外积&#xff09;是一个向量&#xff0c;记做 a b \mathbf{a}\times \mathbf{b} ab 或 [ a b ] [\mathbf{a}\mathbf{b}] [ab]&#xff0c;它的模是 ∣ a b ∣ ∣ a ∣ ∣ b ∣ sin ⁡ ∠ ( a , b ) |\mathbf{a}\times…

8.2 向量数量积与向量积(点乘与叉乘)

本篇内容依然是向量的运算&#xff0c;只不过不属于线性运算&#xff0c;内容包括向量的数量积与向量积。 一、向量的数量积&#xff08;内积、点乘&#xff0c;参与运算的是向量&#xff0c;结果是数&#xff09; &#xff08;一&#xff09;问题产生的背景与表达 &#x…

【口诀】巧记泰勒公式

函数 多项式函数 可以计算出精确值 非多项式函数 无法计算出精确值 泰勒公式的本质 多项式函数逼近非多项式函数 随着项数累加&#xff0c;逼近的误差就会越小 规律&#xff1a; 只需要确定x的指数符号只有两种情况 要么符号相同(全为) 要么符号交替( -)开头要么1&am…

matlab泰勒公式含义,泰勒公式的哲学意义与敏捷研发

学过微积分的人都知道泰勒展开公式,它是将一个在x=x0处具有n阶导数的函数f(x)利用关于(x-x0)的n次多项式来逼近函数的方法,用标准的数学术语来描述是这样的:若函数f(x)在包含x0的某个闭区间[a,b]上具有n阶导数,且在开区间(a,b)上具有(n 1)阶导数,则对闭区间[a,b]上任意一点…

泰勒公式及泰勒级数

目录 一、背景二、提出问题三、解决问题四、应用——泰勒级数※ 函数的幂级数展开 参考文献 一、背景 对于一些复杂的函数&#xff0c;通常会找简单的函数做近似&#xff0c;而多项式函数就是常用的一种简单函数。 比如当 ∣ x ∣ |x| ∣x∣ 很小时&#xff0c;有以下近似&a…