文章目錄
任務
接上篇:數據庫課設項目(上) 醫院。本篇完成需求中的醫護人員與患者信息與活動。
最終會將完整項目代碼上傳至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
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( 身份證)
)
python代碼打印SQL語句
爲了方便插入數據,我們一方面通過循環獲取多條隨機身份信息;另一方面直接以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]))
打印結果如下:
此外,爲符合醫療場景,我們將單位性質生成函數作如下修改,把原本爲其他的一些條目改爲醫護工作者:
實現結果
最終導入數據庫中執行語句如下:
醫生信息
CREATE TABLE Doctor
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
最終結果
患者信息
CREATE TABLE Patient
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
)
消費記錄
CREATE TABLE Tally
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)存儲過程
註冊
CREATE PROC proc_register
/**************註冊******************/
--提供個人姓名與身份證號與所在醫院即可註冊(選取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
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
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
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
總結
就此,基本的需求完成。接下來可以做的:
- 將代碼整合起來統一運行,之前看到的一篇文章會有幫助:使用SQLCMD在SQLServer執行多個腳本
- 通過ODBC接口將SQL語句與編程語言(python等)關聯,實現仿真交互