接上篇:数据库课设项目(上) 医院。本篇完成需求中的医护人员与患者信息与活动。
最终会将完整项目代码上传至GitHub仓库。
为了快速将数据导入数据库中测试代码效果,在GitHub上找到随机生成身份信息的项目:https://github.com/gh0stkey/RGPerson,是python代码,运行效果如下:
这里要推荐一下运行python代码的利器JupyterLab, 之前简单写了一下基本的使用方法:JupyterLab入门应用
我们查看一下主函数:
if __name__ == '__main__':
age = random.randint(16,60) #可调整生成的年龄范围(身份证),这边是16-60岁
gender = random.randint(0,1)
sex = u"男" if gender == 1 else u"女"
print("姓名: {0}\n年龄: {1}\n性别: {2}\n身份证: {3}\n手机号: {4} {5}\n组织机构代码: {6}\n统一社会信用代码: {7}\n单位性质: {8}".format(genName(), age, sex, genIdCard(age, gender), list(genMobile().keys())[0], list(genMobile().values())[0], genOrgCode(), list(genCreditCode().keys())[0], list(genCreditCode().values())[0]))
那我们就可以根据这个随机生成的信息建表,如下:
CREATE TABLE Resident(
姓名 nvarchar(20) NULL,
年龄 tinyint NULL CONSTRAINT cc_age CHECK( 年龄>0 and 年龄<120) ,
性别 nvarchar(4) NULL,
身份证 char(18) NOT NULL,
手机号 char(11) NULL,
运营商 varchar(20) NULL,
组织机构代码 varchar(40) NULL,
统一社会信用代码 varchar(20) NULL,
单位性质 nvarchar(20) NULL,
CONSTRAINT pk_resident PRIMARY KEY( 身份证)
)
为了方便插入数据,我们一方面通过循环获取多条随机身份信息;另一方面直接以SQL语句的格式输出,便可以直接通过复制粘贴放到SQL中执行。修改后的主函数如下:
if __name__ == '__main__':
for i in range(1000):
age = random.randint(16,60) #可调整生成的年龄范围(身份证),这边是16-60岁
gender = random.randint(0,1)
sex = u"男" if gender == 1 else u"女"
print("INSERT INTO Resident VALUES ('{0}',{1} ,'{2}','{3}','{4}','{5}','{6}','{7}','{8}')".format(genName(), age, sex, genIdCard(age, gender), list(genMobile().keys())[0], list(genMobile().values())[0], genOrgCode(), list(genCreditCode().keys())[0], list(genCreditCode().values())[0]))
打印结果如下:
此外,为符合医疗场景,我们将单位性质生成函数作如下修改,把原本为其他的一些条目改为医护工作者:
doctor (ID, position, workday,hospitalName, workDeptName,directDeptNumber)
CREATE TABLE Doctor
(
ID char(18) NOT NULL ,
position nvarchar(20) NULL,
workday nvarchar(20) NULL,
hospitalName nvarchar(40) NOT NULL ,
workDeptNumber int NOT NULL,
directDeptNumber int NULL,
CONSTRAINT pk_doctor PRIMARY KEY(ID,workDeptNumber,hospitalName),
CONSTRAINT fk_doctor_ID FOREIGN KEY(ID)
REFERENCES Resident(身份证) ON DELETE CASCADE,
CONSTRAINT fk_doctor_workDept FOREIGN KEY(workDeptNumber,hospitalName)
REFERENCES Department(number,hospitalName) ON DELETE CASCADE
)
GO
为简化过程,我们把此数据库中所有的医护工作者都分配到同一家医院。并采用随机函数rand()
将他们随机分配至不同科室。
INSERT INTO Doctor (ID ,position,hospitalName,workDeptNumber)
SELECT 身份证,substring(单位性质,4,len(单位性质)),hospitalName,number
FROM Department ,Resident
WHERE
hospitalName='河北大学附属医院' and
convert(int,substring(身份证,10,3))%11+1=number and
单位性质 like '医院%'
我们默认主任医师都是所在科室的管理者
UPDATE Doctor SET directDeptNumber=workDeptNumber
WHERE position='主任医师'
设定几个工作时间,用临时表存储,通过随机函数安排!
CREATE TABLE #workday
(
code int IDENTITY PRIMARY KEY,
workday nvarchar(20)
)
INSERT INTO #workday VALUES
( '一、三、五'),
( '二、四、六'),
('三、日'),
('四、日')
UPDATE Doctor SET workday=#workday.workday
FROM Doctor,#workday
WHERE
convert(int,substring(ID,10,3))%4+1=code
Patient( ID ,hospitalName, 卡号 ,注册时间)
CREATE TABLE Patient
(
ID char(18) NOT NULL ,
hospitalName nvarchar(40) NOT NULL,
卡号 nvarchar(40) NULL,
注册时间 datetime default getdate(),
CONSTRAINT pk_patient PRIMARY KEY(ID,hospitalName),
CONSTRAINT fk_patient_ID FOREIGN KEY(ID)
REFERENCES Resident(身份证) ON DELETE CASCADE,
CONSTRAINT fk_patient_hospital FOREIGN KEY(hospitalName)
REFERENCES Hospital(医院名称) ON DELETE CASCADE
)
Tally( hospitalName(医院) ,卡号 ,金额 ,时间, departmentNumber(柜台:充值处/科室))
CREATE TABLE Tally
(
hospitalName nvarchar(40) NOT NULL,
卡号 nvarchar(40) NOT NULL,
金额 money NULL,
时间 datetime default getdate(),
departmentNumber int NOT NULL,
CONSTRAINT pk_tally PRIMARY KEY(departmentNumber,hospitalName,卡号,时间),
CONSTRAINT fk_tally_department FOREIGN KEY(departmentNumber,hospitalName)
REFERENCES Department(number,hospitalName) ON DELETE CASCADE,
)
如之前所述,我们通过存储过程 PROCEDURE实现,其实与编程语言中的函数概念相似,一旦生成,可以反复调用。
存储过程例题分析:数据库每日一题 (4)存储过程
/**************注册******************/
--提供个人姓名与身份证号与所在医院即可注册(选取Resident表中的数据)
CREATE PROC proc_register
@name nvarchar(20),
@ID char(18),
@hospitalName nvarchar(40)
AS
SET nocount ON --不返回计数
BEGIN
if exists(SELECT * FROM Resident WHERE 身份证=@ID and 姓名=@name)
BEGIN
if exists(SELECT * FROM Patient WHERE ID=@ID)
print @ID+'already registered'
else
BEGIN
DECLARE @hospitalNumber int
SELECT @hospitalNumber=ROW_NUMBER() over(order by 医院名称 desc)
FROM Hospital
INSERT INTO Patient(ID,hospitalName,卡号)
VALUES(@ID,@hospitalName,convert(nvarchar(4),@hospitalNumber)+@ID)
END
END
END
SELECT * FROM Patient
EXECUTE proc_register '郝掂','340321196507203290','河北大学附属医院'
SELECT * FROM Patient
我们默认充值是从收费部进行,通过字符匹配找到相应的部门编号。WHERE hospitalName=@hospitalName and name like '%费%' or name like '%值%'
CREATE PROC proc_deposit
@hospitalName nvarchar(40),
@cardNumber nvarchar(40),
@money money
AS
SET nocount ON --不返回计数
BEGIN
if exists (SELECT * FROM Patient
WHERE 卡号=@cardNumber)
BEGIN
DECLARE @departmentNumber int
SELECT @departmentNumber=number FROM department
WHERE hospitalName=@hospitalName and
name like '%费%' or name like '%值%'
-- SELECT @departmentNumber
INSERT INTO Tally(hospitalName,卡号,金额,departmentNumber) VALUES
(@hospitalName,@cardNumber,@money,@departmentNumber)
END
END
SELECT * FROM TALLY
EXECUTE proc_deposit '河北大学附属医院','5340321196507203290',100
SELECT * FROM TALLY
消费与充值基本一致,只是需要提供消费的部门名称
CREATE PROC proc_charge
@hospitalName nvarchar(40),
@cardNumber nvarchar(40),
@money money,
@departmentName nvarchar(20)
AS
SET nocount ON --不返回计数
BEGIN
if exists (SELECT * FROM Patient
WHERE 卡号=@cardNumber)
BEGIN
DECLARE @departmentNumber int
SELECT @departmentNumber=number FROM department
WHERE hospitalName=@hospitalName and
name = @departmentName
-- SELECT @departmentNumber
INSERT INTO Tally(hospitalName,卡号,金额,departmentNumber) VALUES
(@hospitalName,@cardNumber,@money,@departmentNumber)
END
END
GO
注销就相对简单,提供必要的信息,删除注册记录。
CREATE PROC proc_logout
@name nvarchar(20),
@ID char(18),
@hospitalName nvarchar(40)
AS
SET nocount ON --不返回计数
BEGIN
if exists(SELECT * FROM Resident WHERE 身份证=@ID and 姓名=@name)
BEGIN
DELETE FROM Patient
WHERE ID =@ID and
hospitalName=@hospitalName
END
END
GO
SELECT * FROM PATIENT
EXECUTE proc_logout'郝掂','340321196507203290','河北大学附属医院'
SELECT * FROM PATIENT
就此,基本的需求完成。接下来可以做的: