数据库课程设计:某自来水公司收费管理系统(SQL Server)

  • 要求
  • 设计
    • 思路
    • 代码
  • 问题及分析
  • 后续补充

要求

  • 实现客户信息、用水类型(类别号、类别名、水价)及业务员管理;
  • 实现客户用水信息管理(客户号、月份、用水类别号、用水量);
  • 实现客户费用管理(客户号、月份、费用、收费标志),收费标志的默认值为‘未收’;
  • 实现收费登记(客户、月份、应收费用、实收费用、业务员),并自动修改收费标志(用触发器实现);
  • 创建触发器,实现收费时自动更加应收费用和实收费用,计算本次结余,然后修改客户信息表中的结余金额;
  • 创建存储过程统计指定月份应收费用和实收费用;
  • 创建存储过程查询指定月份未交费的用户信息,以便催费;
  • 创建规则使得月份符合格式“xxxx年xx月”,并绑定到表中相应字段;
  • 建立表间关系

设计

思路

每个要求创建一个相应的表,建立联系,再根据具体需求选择增加或者删除表
我的理解是有这么几个要求:

  • 客户信息
  • 用水类型
  • 业务员管理

这三个是基本信息表

  • 用水信息管理
  • 费用管理
  • 收费登记

这三个是管理表,具体表中的属性题目中已经给出
由于要收费自动更加应收费用和实收费用,且要计算结余并更新,所以我选择增加一个表

  • 订单管理

这样的话,整体的结构是这样的:

  1. 基本信息表用于建立客户、业务员以及水类的基本信息供管理表引用
  2. 用水信息管理负责进行水费的计算并赋给收费登记的应收费用(实现应收费用的自动更加)
  3. 订单管理负责将收取的费用赋给收费登记的实收费用(实现实收费用的自动更加)
  4. 收费登记负责统计应收费用和实收费用并进行比较用于确定结余金额以及是否已收费

根据以上思路,就能知道大概需要多少个触发器

  • 用水信息管理需要一个
  • 订单管理需要一个
  • 收费登记需要至少一个

代码

首先是创建表(虽然这个应该都会,触发器里面用到局部变量需要格式相同我就一起写在这)

/* 由于方便自己看(中文不会一时宕机不记得这是什么表)就全部用中文建表了 */
DROP TABLE IF EXISTS 客户信息;              /* 防止验证时候删除数据麻烦直接这里连表一起删除重建 */
DROP TABLE IF EXISTS 业务员信息;/* 目的是防止重复建表导致报错,如果只建一次表或者选择自己删除表内数据可以不用这几条语句 */
DROP TABLE IF EXISTS 用水类型;
DROP TABLE IF EXISTS 用水信息管理;
DROP TABLE IF EXISTS 收费登记;
DROP TABLE IF EXISTS 费用管理;
DROP TABLE IF EXISTS 订单管理;CREATE TABLE 客户信息(                                                /* 客户信息表 */客户号 varchar(10),客户名 varchar(10),结余金额 float NOT NULL,PRIMARY KEY(客户号)
)CREATE TABLE 业务员信息(                                            /* 业务员信息表 */业务员号 varchar(10),业务员名 varchar(10),PRIMARY KEY(业务员号)
)CREATE TABLE 用水类型(                                             /* 用水类型表 */类别号 varchar(10),类别名 varchar(10),单位水价 float NOT NULL,PRIMARY KEY(类别号),
)CREATE TABLE 用水信息管理(                                           /* 用水信息管理表 */客户号 varchar(10) references 客户信息(客户号),月份 varchar(20),用水类别号 varchar(10) references 用水类型(类别号),用水量 float,PRIMARY KEY (客户号,月份)
)CREATE TABLE 收费登记(                                             /* 收费登记表 */客户号 varchar(10) references 客户信息(客户号),月份 varchar(20),应收费用 float DEFAULT 0,实收费用 float DEFAULT 0,业务员 varchar(10) references 业务员信息(业务员号),PRIMARY KEY(客户号,月份)
)CREATE TABLE 费用管理(                                             /* 费用管理表 */客户号 varchar(10) references 客户信息(客户号),月份 varchar(20),费用 float ,收费标志 varchar(10) default ('未收费'),PRIMARY KEY(客户号,月份),CHECK (收费标志='已收费' or 收费标志='未收费')
)CREATE TABLE 订单管理                                                  /* 订单管理表 */
(订单号 varchar(20),客户号 varchar(10) references 客户信息(客户号),月份 varchar(20),收取费用 float,业务员号 varchar(10) references 业务员信息(业务员号),PRIMARY KEY(订单号)
)

接下来是触发器部分,本题我用了四个,实际应该可以调整一下结构,可以减少或者改变一下每个触发器的功能的

DROP TRIGGER IF EXISTS 用水消费记录_插入;            /* 方便触发器出问题删掉改完再建懒得create改成alter */CREATE TRIGGER 用水消费记录_插入                                 /* 用水信息管理(插入)触发器 */
ON 用水信息管理
AFTER INSERT
AS
DECLARE @客户号 varchar(10)
DECLARE @用水类别 varchar(10)
DECLARE @单位水价 float
DECLARE @用水量 float
DECLARE @水价 float
DECLARE @月份 varchar(20)
SELECT @用水量=用水量,@月份=月份,@客户号=客户号
FROM INSERTED
SELECT @单位水价=单位水价,@用水类别=类别号
FROM 用水类型
BEGININSERT INTO 收费登记(客户号,月份,应收费用) VALUES((select @客户号 from inserted),(select @月份 from inserted),(@用水量*@单位水价))
ENDDROP TRIGGER IF EXISTS 用水消费记录_更改;CREATE TRIGGER 用水消费记录_更改                                    /* 用水信息管理(更改)触发器 */
ON 用水信息管理
AFTER UPDATE
AS
DECLARE @客户号 varchar(10)
DECLARE @用水类别 varchar(10)
DECLARE @单位水价 float
DECLARE @用水量 float
DECLARE @水价 float
DECLARE @月份 varchar(20)
SELECT @用水量=用水量,@月份=月份,@客户号=客户号
FROM INSERTED
SELECT @单位水价=单位水价,@用水类别=类别号
FROM 用水类型
BEGINUPDATE 收费登记 SET 应收费用=@用水量*@单位水价 WHERE @客户号=收费登记.客户号 AND @月份=收费登记.月份
END

这两个触发器是用于“用水信息管理”的,目的是计算水价然后将计算后的水价输入到“收费登记”表中的“应收费用
实际上这两个触发器可以合并,之前是不知道怎么判断是该插入还是更改数据,后面知道了也懒得改了

DROP TRIGGER IF EXISTS 收费记录;CREATE TRIGGER 收费记录                                  /* 收费记录(插入)触发器 */
ON 收费登记
AFTER INSERT,UPDATE
AS
DECLARE @应收费用 float
DECLARE @实收费用 float
DECLARE @客户号 varchar(10)
DECLARE @用水信息管理_客户号 varchar(10)
DECLARE @月份 char(20)
DECLARE @用水信息管理_月份 char(20)
DECLARE @收费标志 varchar(10)
DECLARE @结余金额 float
SELECT  @应收费用=应收费用,@实收费用=实收费用,@客户号=客户号,@月份=月份
FROM INSERTED
SELECT @收费标志=收费标志 from 费用管理
/*SELECT @结余金额=结余金额  from 客户信息*/
SELECT @用水信息管理_客户号=客户号,@用水信息管理_月份=月份 FROM 用水信息管理
BEGINSELECT @结余金额=结余金额FROM 客户信息where 客户号=@客户号if @结余金额>0beginupdate 收费登记set @实收费用=@实收费用+@结余金额,实收费用=@实收费用where @应收费用>@实收费用 and @客户号=客户号 and @月份=月份update 客户信息 set 结余金额=0 where 客户号=@客户号endif @应收费用<=@实收费用beginset @收费标志='已收费'SELECT @结余金额=结余金额 from 客户信息 where 客户号=@客户号print(@结余金额)update 客户信息 set 结余金额=@结余金额+@实收费用-@应收费用where 客户信息.客户号=@客户号update 收费登记set 实收费用=@应收费用where 客户号=@客户号 and 月份=@月份endelsebeginset @收费标志='未收费'      /* 这里由于收费标志已经默认是“未收费,所以其实可以不用这个else的” */endIF NOT EXISTS (SELECT 客户号,月份 FROM 费用管理 WHERE 客户号=@客户号 AND 月份=@月份)beginINSERT INTO 费用管理(客户号,月份,费用,收费标志)VALUES((select @客户号 from inserted),(select @月份 from inserted),@应收费用,@收费标志)  endELSEbeginUPDATE 费用管理 SET 费用=@应收费用,收费标志=@收费标志 where @客户号=费用管理.客户号 and 费用管理.月份=@月份end
END

这个触发器就是合并了插入和更新的,它是作用于“收费登记“”表的,主要作用是:

  • 收费登记中的记录有插入或者更改时,判断此时客户是否有结余金额,有的话就把结余金额置入“实收费用”中用于支付费用
  • 然后比较此时的“应收费用”和“实收费用”。如果应收费用大于实收费用,那就是还没交完费,收费标志保持“未收费”;如果应收费用小于等于实收费用,那就是交完了费,收费标志变成“已收费”,把实收费用减去应收费用,剩下的置入结余金额中
  • 如果是自己缴费也是同理,订单管理得到的费用置入了“实收费用”,结余金额不够的情况下,实收费用=结余金额提供的+订单管理提供的费用,比较同上

这里我是认为一个触发器可以,但是要分的话好像也可以分成两个触发器

DROP TRIGGER IF EXISTS 订单信息管理;CREATE TRIGGER 订单信息管理                                              /* 订单管理触发器 */
ON 订单管理
AFTER INSERT
AS
DECLARE @客户号 varchar(10)
DECLARE @月份 varchar(20)
DECLARE @实收费用 float
DECLARE @收取费用 float
DECLARE @业务员号 varchar(10)
SELECT @客户号=客户号,@月份=月份,@收取费用=收取费用,@业务员号=业务员号
FROM INSERTED
SELECT @实收费用=实收费用 FROM 收费登记 where 客户号=@客户号 AND 月份=@月份
BEGINIF (SELECT 收费标志 FROM 费用管理 WHERE 客户号=@客户号 AND 月份=@月份)='已收费'ROLLBACKELSEUPDATE 收费登记 SET 业务员=@业务员号,@实收费用=@实收费用+@收取费用,实收费用=@实收费用 where @客户号=收费登记.客户号 and @月份=收费登记.月份   print(@实收费用)
END

这个触发器就是订单管理的触发器,很简单,就是订单管理输入数据,然后将输入的费用置入“收费登记”表中的“实收金额

最后就是创建规则和存储结构

CREATE RULE 月份           /* 规则 */
AS
@月份 like'%年%月'

规则我是直接某年某月就行,没有具体要求必须是xxxx(四个x)年xx(两个x)月
然后和月份有关的就是下面这个四个表,所以应用在这四个表上

exec sp_bindrule 月份,'收费登记.月份'
exec sp_bindrule 月份,'订单管理.月份'
exec sp_bindrule 月份,'用水信息管理.月份'
exec sp_bindrule 月份,'费用管理.月份'

两个存储过程如下,也很简单

CREATE PROCEDURE 客户费用管理统计                                /* 客户费用管理统计存储过程(应收费用,未收费用) */
@月份 varchar(20)
AS
SELECT 收费登记.客户号,收费登记.应收费用,收费登记.实收费用,费用管理.收费标志
FROM 收费登记,费用管理
WHERE 收费登记.月份=@月份 AND 收费登记.客户号=费用管理.客户号 AND 费用管理.月份=@月份CREATE PROCEDURE 客户欠费统计                                 /* 客户欠费统计存储过程 */
@月份 varchar(20)
AS
SELECT 费用管理.客户号,客户信息.客户名,(应收费用-实收费用) 拖欠费用
FROM 费用管理,客户信息,收费登记
WHERE 客户信息.客户号=费用管理.客户号 AND 费用管理.客户号=收费登记.客户号 AND 收费登记.月份=费用管理.月份 AND 费用管理.月份=@月份

以上为我设计时编写的全部代码,如果想看下又实在不想一段一段复制的话这里有成品资源

问题及分析

在我写出来以后做了一些测试(毕竟这也是我的作业肯定要测试没什么问题才敢验收),出现了一些问题(当然是已修复的,起码我验收的时候没出现),在这里分享下(下面放出的图片均为本代码运行后得到的正常结果,错误结果以及原因用文字描述


首先,先创建以上一些基本信息
接下来是问题

  • 问题一:刚插入用水信息,结余金额用于充费时

由图可知在2000年1月001号用户张三使用了150单位的生活用水,应收费用3000,结余金额自动支付500
当时出现了实收费用为100的情况,无论哪个客户(有结余金额)都是一样,或者是把所有客户的结余金额都吞了只算了第一个客户的结余金额用于缴费,这种情况是没有确定客户,应该去客户确定的语句那里查找错误

  • 问题二:缴费大于应收费用时


    张三充了7000元进去,结余金额应当是(7000+500-3000=4500),会出现结余为4600的情况,每个用户都是多100,这种情况我的解决方法是使用局部变量。先用**@实收费用**计算得到7500,再赋值给收费登记表中的实收费用

  • 问题三:结余金额大于应收费用时

    这种情况出现过当下次再用水到不够时,之前的实收费用也变成最后未收费的费用(下面的是目前已修复后得到的理想结果)

    这种情况是收费登记的记录没有确定,我没记错的话应该是用下面红线圈的部分确定的

  • 问题四:已充费后当月再次用水直至欠费时
    先把二月份的充值到有结余金额


    此时张三还剩余3500,如果3月用水量增加到400单位(水价=400*20=8000>3500+3000)
    结果为


    这是正常情况,张三欠费,结余金额为0,也显示未收费
    在之前的几个版本里出现了更改后结余金额仍为3500,实收费用仍为3000,显示未收费情况,再充值5500后(即实收费用为5500+3000=8500),此时结余金额应为(8500-8000+3500=4000),但实际结果为500(5500+3000-8000=500)
    这里应该是结余金额的判断出现问题,问题大概率是出现在收费记录里面关于结余金额的取值(也就是说没有取到,后面结余时直接替换了结余金额),这里我是改了下面画圈的部分来确定结余金额,后面好像也改了一点,不过是局部变量的改变(比如结余金额的赋值先赋给@结余金额再给结余金额)和客户身份的进一步确定避免加错结余金额,应该关系不大。这个问题是我后面准备死马当活马医直接验收和老师说这个问题的时候发现好了,所以只知道是这里除了问题,解决方法不是很清楚

总结:目前实现了以下几个功能
(1)需要缴费时有结余金额自动用于缴费,多余的自动收回结余金额
(2)交费后盈余部分自动收入结余金额
(3)多个客户之间不冲突
(4)缴费后若当月再次用水需要缴费,重复(1)中步骤

因为我自己弄得时候也出现了不少问题,所以我知道如果这些地方(或类似
的)出现问题一时半会找不到解决方法会很难受,所以这里整理了一下我碰到的问题及解决方法。本人对SQL Server及代码的编写也不是很熟悉,如果有错误或遗漏的还望指出,也欢迎提出别的问题以及解决方案,亦或者是一些改进的建议。


后续补充

2022.5.23 附
因为有人问到这个的E-R图,我去翻了下,当时我交实验报告的时候画的图应该是这样的:

不过我已经有段时间没碰这个了,当时的思路有没有问题我也不确定。姑且说下我的理解,这里的整个系统应该是以某个或某些表为核心,其他表围绕核心表执行相应功能。在这里我的核心是收费登记,但是实际要做成个系统的话,可能要把用水信息管理作为核心更正确点。

数据库课程设计:某自来水公司收费管理系统(SQL Server)相关推荐

  1. 数据库课程设计——某煤气公司送气管理系统(附课设报告)

    下面都是我在CSDN发的文章,这算广告???审核你有毛病? 数据库课程设计--某工厂的物料管理系统(附Java源码与课程设计报告) 数据库课程设计--某商店进销存管理系统(附Java源码与课程设计报告 ...

  2. 停车场计费算法 php,《算法与数据结构》课程设计之停车场的收费管理系统

    <算法与数据结构>课程设计 题目:停车场的收费管理系统 一. 设计目的与内容 1. 问题描述 任务:停车场可以同时停放M辆车,停车场的入口和出口可分别有N辆车排队.停车每小时收费5元,每天 ...

  3. ♥数据库课程设计之《学生成绩管理系统》♥

    0.写在前面 展示的是很常规的<学生成绩管理系统>,但是可修改为任何管理系统,只需要改些字段即可,具备java基础即可 简单的增删改查均可实现,本来很简单的几页文档就能交了,老师非得让详细 ...

  4. Java课程设计源码——学生信息管理系统 SQL

    2022.6.9 更新 这个课程作业的代码有小伙伴反馈有问题(数据库无法连接等),但博主最近学业不用Java了,暂时没时间看,如果有同学有解决方案,可以在下面评论帮助一下其他同学.实在抱歉啦. pac ...

  5. 【sql+python】数据库与程序实践——某自来水公司收费系统

    题目 某自来水公司收费管理系统 要求 实现客户信息.用水类型(类别号.类别名.水价)及业务员管理: 实现客户用水信息管理(客户号.月份.用水类别号.用水量): 实现客户费用管理(客户号.月份.费用.收 ...

  6. 数据库课程设计——1、登陆界面

    关于我用androidstudio去完成我的数据库课程设计 题目:<健康管理系统> 语言:kotlin 数据库:sqlite 1.登陆界面: 用了一个线性布局,去写的登陆界面 <?x ...

  7. 数据库课程设计-员工信息管理系统(基于python和MySQL实现)

    一.项目地址 具体项目相关信息可移步至我的Github查看,那里有整套项目文件以及课程设计报告等,仅供交流学习和参考,如有错误之处请多多指正哦. 二.系统定义 随着计算机技术的不断发展,计算机作为知识 ...

  8. C++/数据库课程设计_诊所信息管理系统_系统介绍

    系统介绍 本系统是一个诊所信息管理系统,可以作为C++或者数据库课程设计的参考,实现了患者挂号.支付.电子病历, 医生诊断.开处方.查看病历,医生.患者.药房.科室管理以及药品进销存. 针对用户的具体 ...

  9. JAVA+MYSQL数据库课程设计“迪士尼票务与信息管理系统“(一)附带详细资源

    目录 背景介绍 需求分析 外部接口需求 系统功能需求 用户需求 性能需求 安全性需求 可行性分析 技术可行性 应用可行性 经济可行性 概念设计 局部E-R图设计 门票信息局部E-R图 游乐项目信息局部 ...

  10. 查询学生选修课程管理系统java_JAVA数据库课程设计学生选课管理系统的

    <JAVA数据库课程设计学生选课管理系统的>由会员分享,可在线阅读,更多相关<JAVA数据库课程设计学生选课管理系统的(59页珍藏版)>请在人人文库网上搜索. 1.一.课程设计 ...

最新文章

  1. 栈与队列7——单调栈结构(初阶问题)
  2. outlook从服务器中恢复已删除项目,Exchange 恢复已删除项目
  3. java厨房_JAVA环境搭建,厨房安装图文教程!
  4. 钉钉实现企业级微应用免登陆详解
  5. c语言飞扬的小鸟程序,C语言实现flappy bird游戏
  6. C++之关于虚函数和多态的分析和补充
  7. 两种查找bapi的方法
  8. 嘉楠勘智 K210 RISC-V 64位双核处理器开发板(荔枝丹)
  9. 防火墙端口大全(转)
  10. 利好:北京医改鼓励医生个体行医异地行医
  11. hive 的tmp文件
  12. TweenMax 参数说明
  13. 倾斜模型精细化处理_无人机倾斜摄影技术的三维精细模型制作
  14. 怒了!!!专科怎么了?搞学历歧视?专科这样做,照样牛掰!
  15. cache line对内存访问的影响
  16. Invariance Matters: Exemplar Memory for Domain Adaptive Person Re-identification
  17. Google结构化数据
  18. 广数980TDI/980MDI/988系列CNC机床 IP地址设置步骤教程详解
  19. 悟空CRM JAVA版 (基于jfinal+vue+ElementUI的前后端分离CRM系统)
  20. 十大高明的Google搜索技巧

热门文章

  1. 大数据导入Excel
  2. 简单的U盘病毒清理工具 v0.5
  3. 实况足球2015pc版
  4. 台式计算机显卡驱动位置,如何在HP台式计算机上安装图形驱动程序
  5. android布局详解
  6. Android TableLayout 表格布局详解
  7. FAT32 文件系统 实践
  8. linux修改vcf编码格式,VCF乱码终极解决大法
  9. JavaScript 检测当前浏览器内核并提示下载谷歌Chrome浏览器
  10. crio电压采集 labview_基于LabVIEW和CompactRIO开发的EDM过程控制器