數據庫課程設計之工程薪資基本項目管理(基於mysql命令行)

數據庫課程設計(mysql命令行)

------必做內容(工程薪資基本項目管理):

前言(課設要求)

1、項目需求簡述

  • 每位職工可以參加幾個不同的工程,且每個工程有多名職工參與;
  • 每位職工有一個職位,且多名職工可能有相同的職位;
  • 職位決定小時工資率,相同的職位具有相同的小時工資率;
  • 工程的基本信息包括:工程號和工程名稱,工程所在地址,起始時間,結束時間;
  • 職工的相關信息包括:職工號、姓名(職位和酬金?);
  • 企業按職工在每一個工程中完成的工時,計算酬金。
  • 員工檔案管理 員工有新增、離開、部門變更
  • 其它業務:企業有不同的部門(部門編號及名稱)組成,每個員工隸屬於部門之一; 職工參加工程上班簽到和下班簽到

2、要求

  • 應用規範設計法設計該數據庫,要求達到3NF。請給出詳細設計過程(E-R及E-R到關係表清晰的轉換關係說明)。
  • 指出每個關係的主碼和外碼。
  • 設計一個存儲過程(函數),以工程編號作爲輸入參數,實現計算某工程所支付的工人酬金。沒有該工程返回-1
  • 實現員工變更部門的存儲過程,成功返回 1,否則返回0;變更過程計入檔案;職工號/變更類型/原先部分(新增null)/新的部門(離開null)/日期/經手人
  • 員工參加工程的上班和下班 存儲過程/函數(注意時間點 早上6:之前和晚上12點後 不允許操作,當天沒有上班的不允許下班的操作…)

3、成果形式

  • 文檔 E-R總體圖(實體名稱/聯繫屬性/聯繫類型),每個實體詳細的屬性及其候選碼屬性可以另行標註(實體圖或者實體名(x,x…))
  • DDL語句 建表/約束、存儲過程或函數
  • 數據初始化 一定數量的
  • 測試存儲過程/函數 截圖記錄
  • 實驗體會

正文

根據項目需求簡述,我們可以分析出以下幾條基本的結論:

  • 職工與工程之間的關係: 多對多
  • 職工與職位之間的關係: 多對1
  • 職工與部門之間的關係: 多對1
  • 職位與小時工資率之間的關係: 一對一
  • 工程具有的屬性: 工程號,工程名稱,工程所在地址,起始時間,結束時間
  • 職工具有的屬性:職工號,職工姓名
  • 部門具有的屬性: 部門編號,部門名稱
  • 職位具有的屬性: 職位名,小時工資率

1)需求設計

實體呈現

根據上述分析,我決定將 職工,職位,工程,部門當做基本的實體,如下
在這裏插入圖片描述

注:加粗部分爲候選碼

ER圖呈現

在這裏插入圖片描述

關係模型+轉換步驟

1)ER圖轉爲關係表

根據ER圖先將其轉化爲幾個基本的關係表,轉換原則

  • 1:n 1端的候選碼屬性必須放入n端擴充
  • m:n 兩端的候選碼都要加入到派生表中

得到如下四個表

其中職位名和部門編號爲外鍵, 酬金錶是職工和工程的派生表

工程(工程號,工程名,工程所在地,工程開始時間,工程結束時間)

職工(職工號,職工姓名, 職位名, 部門編號

職位 (職位名, 小時工薪率)

酬金(工程號,職工號,工時)

部門(部門編號,部門名稱)

2)修改表結構

目標:達到3NF範式

顯然 工程表,酬金錶,部門表,職工表都 滿足 3NF

所以這裏無需修改表結構

3)最終關係表

注(加粗代表主鍵,下劃線代表外鍵)

工程表(工程號,工程名,工程所在地,工程開始時間,工程結束時間)

職工表(職工號,職工姓名, 職位名, 部門編號

職位表 (職位名, 小時工薪率)

酬金錶(工程號,職工號,工時)

部門表(部門編號,部門名稱)

2)創建表+插入數據

1.數據庫創建

CREATE DATABASE  IF NOT EXISTS `salary`
USE `salary`;

2.表的操作

部門表
DROP TABLE IF EXISTS `department`;
CREATE TABLE `department` (
  `dno` varchar(20) NOT NULL,
  `dname` varchar(45) NOT NULL,
  PRIMARY KEY (`dno`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
LOCK TABLES `department` WRITE;
INSERT INTO `department` VALUES ('CW','財務部'),('RS','人事部'),('SC','市場部'),('YF','研發部');
UNLOCK TABLES;
職工表
DROP TABLE IF EXISTS `employee`;
CREATE TABLE `employee` (
  `eno` varchar(20) NOT NULL,
  `ename` varchar(45) NOT NULL,
  `epost` varchar(45) NOT NULL,
  `dno` varchar(20) NOT NULL,
  PRIMARY KEY (`eno`),
  KEY `c1_idx` (`dno`),
  KEY `e2_idx` (`epost`),
  CONSTRAINT `e1` FOREIGN KEY (`dno`) REFERENCES `department` (`dno`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `e2` FOREIGN KEY (`epost`) REFERENCES `job` (`epost`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
LOCK TABLES `employee` WRITE;
INSERT INTO `employee` VALUES ('CW01','方平','會計','CW'),('RS01','張峯','主任','RS'),('SC01','楚陽','業務員','SC'),('SC02','寧缺','服務員','SC'),('YF01','君陌','技術員','YF');
UNLOCK TABLES;
職位表
DROP TABLE IF EXISTS `job`;
CREATE TABLE `job` (
  `epost` varchar(45) NOT NULL,
  `hourrate` varchar(45) NOT NULL,
  PRIMARY KEY (`epost`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
LOCK TABLES `job` WRITE;
INSERT INTO `job` VALUES ('業務員','250'),('主任','500'),('會計','200'),('技術員','300'),('服務員','80');
UNLOCK TABLES;
工程表
DROP TABLE IF EXISTS `project`;
CREATE TABLE `project` (
  `pno` varchar(20) NOT NULL,
  `pname` varchar(45) NOT NULL,
  `paddr` varchar(45) NOT NULL,
  `pstart` date DEFAULT NULL,
  `pfinal` date DEFAULT NULL,
  PRIMARY KEY (`pno`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
LOCK TABLES `project` WRITE;
INSERT INTO `project` VALUES ('001','house','寧波','2020-04-11','2020-08-11'),('002','hospital','杭州','2020-03-30','2021-04-03'),('003','store','溫州','2020-01-24','2020-06-28'),('004','park','上海','2020-01-01','2020-11-24'),('005','bigdata','東北','2020-03-15','2020-12-31');
UNLOCK TABLES;

酬金錶

DROP TABLE IF EXISTS `reward`;
CREATE TABLE `reward` (
  `pno` varchar(20) NOT NULL,
  `eno` varchar(20) NOT NULL,
  `worktime` varchar(45) NOT NULL,
  PRIMARY KEY (`pno`,`eno`),
  KEY `eno_idx` (`eno`),
  CONSTRAINT `c1` FOREIGN KEY (`pno`) REFERENCES `project` (`pno`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `c2` FOREIGN KEY (`eno`) REFERENCES `employee` (`eno`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
LOCK TABLES `reward` WRITE;
INSERT INTO `reward` VALUES ('001','CW01','5'),('001','SC02','8'),('002','SC01','6'),('002','YF01','7'),('003','RS01','4'),('003','YF01','6'),('004','CW01','6'),('004','RS01','8'),('004','SC01','3'),('005','CW01','7'),('005','SC02','4'),('005','YF01','3');
UNLOCK TABLES;
檔案表
DROP TABLE IF EXISTS `message`;
CREATE TABLE `message` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `eno` varchar(45) NOT NULL,
  `reason` varchar(45) NOT NULL,
  `olddno` varchar(45) DEFAULT NULL,
  `newdno` varchar(45) DEFAULT NULL,
  `date` varchar(45) NOT NULL,
  `who` varchar(45) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

已插入的數據如下

mysql> select * from department;
+-----+--------+
| dno | dname  |
+-----+--------+
| CW  | 財務部 |
| RS  | 人事部 |
| SC  | 市場部 |
| YF  | 研發部 |
+-----+--------+
4 rows in set (0.00 sec)

mysql> select * from employee;
+------+-------+--------+-----+
| eno  | ename | epost  | dno |
+------+-------+--------+-----+
| CW01 | 方平  | 會計   | CW  |
| RS01 | 張峯  | 主任   | RS  |
| SC01 | 楚陽  | 業務員 | SC  |
| SC02 | 寧缺  | 服務員 | SC  |
| YF01 | 君陌  | 技術員 | YF  |
+------+-------+--------+-----+
5 rows in set (0.00 sec)

mysql> select * from job;
+--------+----------+
| epost  | hourrate |
+--------+----------+
| 業務員 | 250      |
| 主任   | 500      |
| 會計   | 200      |
| 技術員 | 300      |
| 服務員 | 80       |
+--------+----------+
5 rows in set (0.00 sec)

mysql> select * from project;
+-----+----------+-------+------------+------------+
| pno | pname    | paddr | pstart     | pfinal     |
+-----+----------+-------+------------+------------+
| 001 | house    | 寧波  | 2020-04-11 | 2020-08-11 |
| 002 | hospital | 杭州  | 2020-03-30 | 2021-04-03 |
| 003 | store    | 溫州  | 2020-01-24 | 2020-06-28 |
| 004 | park     | 上海  | 2020-01-01 | 2020-11-24 |
| 005 | bigdata  | 東北  | 2020-03-15 | 2020-12-31 |
+-----+----------+-------+------------+------------+
5 rows in set (0.00 sec)

mysql> select * from reward;
+-----+------+----------+
| pno | eno  | worktime |
+-----+------+----------+
| 001 | CW01 | 5        |
| 001 | SC02 | 8        |
| 002 | SC01 | 6        |
| 002 | YF01 | 7        |
| 003 | RS01 | 4        |
| 003 | YF01 | 6        |
| 004 | CW01 | 6        |
| 004 | RS01 | 8        |
| 004 | SC01 | 3        |
| 005 | CW01 | 7        |
| 005 | SC02 | 4        |
| 005 | YF01 | 3        |
+-----+------+----------+
12 rows in set (0.00 sec)

3)存儲過程

函數function1

1.設計一個存儲過程(函數),以工程編號作爲輸入參數,實現計算某工程所支付的工人酬金。沒有該工程返回-1

代碼
delimiter //
drop procedure if exists calSalary;
create procedure calSalary(in inpno int)
begin 
	declare flag int;
	declare tmpresult int;
	select if(inpno not in (select pno from project),-1,0) into flag;
	if flag=-1 then 
		select flag;
	else 
		select sum(hourrate*worktime) result into tmpresult FROM job,employee,reward where reward.pno='001' and reward.eno=employee.eno and employee.epost=job.epost;
		select tmpresult;
	end if;
end //
delimiter ;

測試結果

mysql> call calSalary(001)
    -> ;
+-----------+
| tmpresult |
+-----------+
|      1640 |
+-----------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.01 sec)

mysql> call calSalary(111)
    -> ;
+------+
| flag |
+------+
|   -1 |
+------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

函數function2

2.實現員工變更部門的存儲過程,成功返回 1,否則返回0;變更過程計入檔案;職工號/變更類型/原先部分(新增null)/新的部門(離開null)/日期/經手人

這裏的需要用到檔案,所以我們選擇新建一個change表

change (職工號,變更類型,原先部分(新增null),新的部門(離開null),日期,經手人)

這道題有2個要求,一個是對職工表的修改,一個是記錄過程進入檔案

代碼
delimiter //
drop procedure if exists move;
create procedure move(
	in ineno varchar(20),
	in change_reason varchar(20),
	in new_dno varchar(20),
	in who varchar(20)
)
begin 	
	declare results varchar(3);
	declare flag int;
	declare date varchar(45);
	SELECT DATE_FORMAT(SYSDATE(),'%Y-%m-%d %T') into date;
	select if(ineno not in (select eno from employee),-1,0) into flag;
	if flag=-1 then 
		INSERT INTO `salary`.`employee` (`eno`, `dno`) VALUES (ineno,new_dno);
		set results = '';
	else
		UPDATE `salary`.`employee` SET `dno` = new_dno WHERE (`eno` = ineno);
		SELECT dno into results FROM employee as e where eno = ineno;
	end if;
	INSERT INTO `salary`.`message` (`eno`, `reason`, `olddno`, `newdno`, `date`, `who`) VALUES (ineno, change_reason, results, new_dno, date, who);
	select 1;
end //
delimiter ;

測試結果

這是現在的employee和message表,我們看看接下來他發生的變化

mysql> select * from message;
+----+------+----------+--------+--------+---------------------+--------+
| id | eno  | reason   | olddno | newdno | date                | who    |
+----+------+----------+--------+--------+---------------------+--------+
|  5 | RS01 | 換部門   | 人事部 | 技術部 | 2020-04-11 16:09:31 | 董事長 |
| 27 | RS02 | 新人入部 | null   | CW     | 2020-04-11 18:56:18 | 經理   |
| 28 | RS01 | 更換部門 | RS     | CW     | 2020-04-11 18:56:24 | 董事長 |
| 29 | RS03 | 新人入部 | null   | CW     | 2020-04-11 18:57:37 | 經理   |
| 30 | RS01 | 更換部門 | CW     | YF     | 2020-04-11 18:57:45 | 董事長 |
| 31 | YF01 | 更換部門 | YF     | RS     | 2020-04-11 18:59:00 | 董事長 |
| 32 | RS01 | 變更     | CW     | CW     | 2020-05-06 11:53:55 | TTY    |
+----+------+----------+--------+--------+---------------------+--------+
7 rows in set (0.00 sec)

mysql> select * from employee;
+------+-------+--------+------+
| eno  | ename | epost  | dno  |
+------+-------+--------+------+
| CW01 | 方平  | 會計   | CW   |
| RS01 | 張峯  | 主任   | CW   |
| RS02 | NULL  | NULL   | CW   |
| RS03 | NULL  | NULL   | CW   |
| SC01 | 楚陽  | 業務員 | SC   |
| SC02 | 寧缺  | 服務員 | SC   |
| YF01 | 君陌  | 技術員 | RS   |
+------+-------+--------+------+
7 rows in set (0.00 sec)
老員工變更
call move('SC01','變更','YF','ZQQ')
mysql> call move('SC01','變更','YF','ZQQ');
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.01 sec)

Query OK, 0 rows affected (0.04 sec)

mysql> select * from employee;
+------+-------+--------+------+
| eno  | ename | epost  | dno  |
+------+-------+--------+------+
| CW01 | 方平  | 會計   | CW   |
| RS01 | 張峯  | 主任   | CW   |
| RS02 | NULL  | NULL   | CW   |
| RS03 | NULL  | NULL   | CW   |
| SC01 | 楚陽  | 業務員 | YF   |
| SC02 | 寧缺  | 服務員 | SC   |
| YF01 | 君陌  | 技術員 | RS   |
+------+-------+--------+------+
7 rows in set (0.00 sec)

mysql> select * from message;
+----+------+----------+--------+--------+---------------------+--------+
| id | eno  | reason   | olddno | newdno | date                | who    |
+----+------+----------+--------+--------+---------------------+--------+
|  5 | RS01 | 換部門   | 人事部 | 技術部 | 2020-04-11 16:09:31 | 董事長 |
| 27 | RS02 | 新人入部 | null   | CW     | 2020-04-11 18:56:18 | 經理   |
| 28 | RS01 | 更換部門 | RS     | CW     | 2020-04-11 18:56:24 | 董事長 |
| 29 | RS03 | 新人入部 | null   | CW     | 2020-04-11 18:57:37 | 經理   |
| 30 | RS01 | 更換部門 | CW     | YF     | 2020-04-11 18:57:45 | 董事長 |
| 31 | YF01 | 更換部門 | YF     | RS     | 2020-04-11 18:59:00 | 董事長 |
| 32 | RS01 | 變更     | CW     | CW     | 2020-05-06 11:53:55 | TTY    |
| 33 | SC01 | 變更     | YF     | YF     | 2020-05-06 11:59:05 | ZQQ    |
+----+------+----------+--------+--------+---------------------+--------+
8 rows in set (0.00 sec)

我們可以看出,舊員工更換部門的操作也是成功的

加入新員工
call move('YF02','新人入部','YF','TTY')
mysql> call move('YF02','新人入部','YF','TTY');
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.01 sec)

Query OK, 0 rows affected (0.02 sec)

mysql> select * from employee;
+------+-------+--------+------+
| eno  | ename | epost  | dno  |
+------+-------+--------+------+
| CW01 | 方平  | 會計   | CW   |
| RS01 | 張峯  | 主任   | CW   |
| RS02 | NULL  | NULL   | CW   |
| RS03 | NULL  | NULL   | CW   |
| SC01 | 楚陽  | 業務員 | YF   |
| SC02 | 寧缺  | 服務員 | SC   |
| YF01 | 君陌  | 技術員 | RS   |
| YF02 | NULL  | NULL   | YF   |
+------+-------+--------+------+
8 rows in set (0.00 sec)

mysql> select * from message;
+----+------+----------+--------+--------+---------------------+--------+
| id | eno  | reason   | olddno | newdno | date                | who    |
+----+------+----------+--------+--------+---------------------+--------+
|  5 | RS01 | 換部門   | 人事部 | 技術部 | 2020-04-11 16:09:31 | 董事長 |
| 27 | RS02 | 新人入部 | null   | CW     | 2020-04-11 18:56:18 | 經理   |
| 28 | RS01 | 更換部門 | RS     | CW     | 2020-04-11 18:56:24 | 董事長 |
| 29 | RS03 | 新人入部 | null   | CW     | 2020-04-11 18:57:37 | 經理   |
| 30 | RS01 | 更換部門 | CW     | YF     | 2020-04-11 18:57:45 | 董事長 |
| 31 | YF01 | 更換部門 | YF     | RS     | 2020-04-11 18:59:00 | 董事長 |
| 32 | RS01 | 變更     | CW     | CW     | 2020-05-06 11:53:55 | TTY    |
| 33 | SC01 | 變更     | YF     | YF     | 2020-05-06 11:59:05 | ZQQ    |
| 34 | YF02 | 新人入部 |        | YF     | 2020-05-06 12:01:02 | TTY    |
+----+------+----------+--------+--------+---------------------+--------+
9 rows in set (0.00 sec)

上圖可以看到我們將新人加入了部門,這裏因爲不知道新人的名字和職位,如果按之前的插入會出現問題,所以在這一步的時候我修改了表的結構,讓ename和epost可以爲空值

函數function3

3.員工參加工程的上班和下班 存儲過程/函數(注意時間點 早上6:之前和晚上12點後 不允許操作,當天沒有上班的不允許下班的操作…)

這裏新建一個表 來記錄員工每天的簽到情況

status表 (id(自增長),員工號,日期 , 是否簽到,是否簽退)

Y表示已簽到/簽退

N表示未簽到/簽退

這裏我認爲題目沒有說清楚具體的簽到時間和簽退時間區間,僅僅說了24.00-6.00不允許操作,所以我加上了flag參數來表示員工的舉動,type= 1代表簽到,type= 0代表簽退

代碼
drop procedure if exists workUpDown;
delimiter //
create procedure workUpDown(
	in ineno varchar(20),
    in type int
)
begin 
	declare flag int;
	declare date varchar(45);
	declare judge varchar(5);
	declare result varchar(10);
	SELECT DATE_FORMAT(SYSDATE(),'%Y-%m-%d %T') into date;
	if type=1 then
		select if (date_format(now(),'%T')>="06:00:00",1,0) into flag;
		if flag=1 then
			INSERT INTO `salary`.`status` (`eno`, `date`, `ifup`) VALUES (ineno, date, 'Y');
			set result='簽到成功!';
		else
			set result='簽到時間錯誤!';
		end if;
		select result;
	else
		select if (date_format(now(),'%T')>"00:00:00" and  date_format(now(),'%T')<"06:00:00",1,0) into flag;
		if flag=0 then
			SELECT ifup into judge FROM salary.status where eno =ineno;
			if judge='Y' then
				UPDATE `salary`.`status` SET `ifdown` = 'Y' WHERE (`eno` = ineno);
				set result='簽退成功'
			else
				set result='抱歉,您尚未簽到';
			end if;
		else
        	set result='簽退時間錯誤!';
		end if;
		select result;
	end if;
end //
delimiter ;
測試結果
簽到
mysql> select * from status;
+----------+------+------------+------+--------+
| idstatus | eno  | date       | ifup | ifdown |
+----------+------+------------+------+--------+
|        9 | CW01 | 2020-04-11 | Y    | NULL   |
|       10 | SC02 | 2020-04-11 | Y    | Y      |
|       11 | SC01 | 2020-04-11 | Y    | Y      |
+----------+------+------------+------+--------+
3 rows in set (0.00 sec)

mysql> call workUpDown('YF01',1);
+-----------+
| result    |
+-----------+
| 簽到成功! |
+-----------+
1 row in set (0.01 sec)

Query OK, 0 rows affected (0.01 sec)

mysql> select * from status;
+----------+------+---------------------+------+--------+
| idstatus | eno  | date                | ifup | ifdown |
+----------+------+---------------------+------+--------+
|        9 | CW01 | 2020-04-11          | Y    | NULL   |
|       10 | SC02 | 2020-04-11          | Y    | Y      |
|       11 | SC01 | 2020-04-11          | Y    | Y      |
|       12 | YF01 | 2020-05-06 14:08:19 | Y    | NULL   |
+----------+------+---------------------+------+--------+
4 rows in set (0.00 sec)

可以看出現在 ifdown字段是空值,下面進行簽退操作

簽退
mysql> call workUpDown('YF01',0)
    -> ;
+--------+
| result |
+--------+
| 簽退成功 |
+--------+
1 row in set (0.01 sec)

Query OK, 0 rows affected (0.01 sec)

mysql> select * from status;
+----------+------+---------------------+------+--------+
| idstatus | eno  | date                | ifup | ifdown |
+----------+------+---------------------+------+--------+
|        9 | CW01 | 2020-04-11          | Y    | NULL   |
|       10 | SC02 | 2020-04-11          | Y    | Y      |
|       11 | SC01 | 2020-04-11          | Y    | Y      |
|       12 | YF01 | 2020-05-06 14:08:19 | Y    | Y      |
+----------+------+---------------------+------+--------+
4 rows in set (0.00 sec)

上圖可以看到 ifdown字段加上了Y

非法簽退
mysql> call workUpDown('YF02',0)
    -> ;
+------------------+
| result           |
+------------------+
| 抱歉,您尚未簽到 |
+------------------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

上圖看出,如果沒有簽到的用戶去簽退,將會給出提示

4)實驗體會

本次實驗讓我鞏固了mysql的操作,在上學期的學習中,我已經熟練的掌握了命令行對mysql的各種操作,這次實驗是可以說是一次很好的複習,從需求分析開始到建表,再到最後的編寫函數,花費了我好幾個小時的時間,但是成功的結果讓我收穫滿滿

除去上學期所學的命令行的一些操作,在這次實驗中,我結合了python操縱mysql,並且學習了mysql圖形界面工具workbench的使用,它們在一定程度上使得我對mysql的操作更加方便

附件1:salay.sql (裏面包括了建表和插入數據的操作) 下載入口點此進入

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章