【數據庫】基於Qt/MySQL的學生信息管理系統

環境說明

  • 系統環境:Windows 10 專業版
  • 數據庫管理系統:MySQL
  • 設計工具:Navicat for MySQL
  • 編程工具:Qt 5.12.3 / VS

流程圖

  • 建立數據庫
    流程1
  • 建立數據表
    流程2

數據字典

  • 學生表
    1
  • 體檢表
    2
  • 成績表
    3
  • 課程表
    4
  • 用戶表
    5

ER圖

  • 學生ER圖
    1
  • 體檢ER圖
    2
  • 成績ER圖
    3
  • 課程ER圖
    4
  • 用戶ER圖
    5
  • 總體ER圖
    6

關係模式及規範化

關係模式定義

設計學生信息管理數據庫,包括學生信息、體檢信息、課程信息、成績信息、用戶信息五個關係,其關係模式中每個實體定義的屬性如下:

  • 學生信息:(學號,姓名,性別,年齡,身份證號,聯繫電話,入學時間,畢業時間,學業情況,備註);
  • 體檢信息:(學號,身高,體重,辨色,左眼視力,右眼視力,左耳聽力,右耳聽力,腿長比,血壓,病史,備註);
  • 課程信息:(課程號,課程名,備註);
  • 成績信息:(學號,課程號,上次考試時間,考試次數,分數);
  • 用戶信息:(用戶名,密碼,身份證號);

規範化(3NF)

  • 秉持最優化、最簡潔的設計原則,應選擇合理的範式規範;
  • 在最開始的設計中,我引入了地址、院系、年級、類似“XX1901”的班級命名制度;
  • 由於師生信息本身的複雜性,全部消除非主鍵的部分依賴和傳遞依賴,需要新增和刪改很多表來避免數據冗餘,具體操作如下:
  • 根據日期的可分性,可分出國家表、地區表等(1NF);
  • 根據年級對班級的部份依賴,將年級更改爲入學年份或屆數(2NF);
  • 根據班級對院系、專業的部份依賴, 學生表中分出院系表、班級表、專業表(2NF);
  • 根據班級對年級、院系、專業複雜的傳遞依賴,亦可將幾類鍵分出(3NF)。

開發流程

Qt設計界面

1
2

Navicat搭建庫

1
2

部分後端代碼

#include "mysql.h"
#include "mainwindow.h"
#include <QDebug>

My_Sql::My_Sql()
{
}

void My_Sql::initsql()
{
    QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
    db.setHostName("localhost");
    db.setUserName("root");
    db.setPassword("123456");
    db.setDatabaseName("student");
    if(db.open())
     {
         qDebug() << "database is established!";
         createtable();
         return;
     }
     else
     {
         qDebug() << "build error!";
         return;
    }
}

// 創建數據庫操作
void My_Sql::createtable()
{
    query = new QSqlQuery;

    //建表
    query->exec("create table user(name VARCHAR(30) UNIQUE NOT NULL, passward VARCHAR(30), identify VARCHAR(30) PRIMARY KEY)");
    query->exec("create table studentInfo(stuaccount VARCHAR(30) PRIMARY KEY UNIQUE NOT NULL, stuname VARCHAR(30), stusex ENUM('Male', 'Female') NOT NULL, stuage INT, identify VARCHAR(30) UNIQUE NOT NULL, tel VARCHAR(20), enroll_time DATE, leave_time DATE, scondition enum('Studying', 'Educated', 'Off'), stu_text TEXT)");
    query->exec("create table healthInfo(stuaccount VARCHAR(30) PRIMARY KEY UNIQUE NOT NULL, stuname VARCHAR(30) NOT NULL, height FLOAT, weight FLOAT, differentiate ENUM('Normal', 'Weak', 'Blind'), left_sight FLOAT, right_sight FLOAT, left_ear ENUM('Normal','Weak'), right_ear ENUM('Normal','Weak'), legs ENUM('Normal','Diff'), pressure ENUM('Normal','High','Low'), history VARCHAR(50), h_text TEXT)");
    query->exec("create table courseInfo(classid INT PRIMARY KEY UNIQUE NOT NULL AUTO_INCREMENT, classname VARCHAR(30), class_text TEXT)");
    query->exec("create table gradeInfo(stuaccount VARCHAR(30) PRIMARY KEY UNIQUE NOT NULL, classid INT NOT NULL, lasttime date, times INT default 1, grade float default 0, constraint grade_acc_fk FOREIGN KEY(stuaccount) REFERENCES studentInfo(stuaccount), constraint grade_cid_fk FOREIGN KEY(classid) REFERENCES courseInfo(classid))");

    //添加管理員
    query->exec("insert into user value('root', '123456', 'root')");

    //索引
    query->exec("create index int_name ON studentInfo(stuname)");
    query->exec("alter table studentInfo ADD INDEX ind_con(scondition)");
    query->exec("create index ind_hname ON healthInfo(stuname)");

    //視圖
    query->exec("create VIEW grade_view AS SELECT g.stuaccount, s.stuname, c.classname, g.lasttime, g.times, g.grade FROM studentinfo s, courseinfo c, gradeinfo g WHERE g.stuaccount = s.stuaccount AND g.classid = c.classid");

    //三種觸發器
    query->exec("CREATE TRIGGER license_stu AFTER INSERT ON licenseInfo  FOR EACH ROW BEGIN UPDATE studentInfo SET leave_time=NEW.recv_time, scondition = 'Educated' WHERE stuaccount = NEW.stuaccount; END");

    query->exec("CREATE TRIGGER update_name AFTER UPDATE ON studentinfo FOR EACH ROW BEGIN UPDATE healthinfo SET stuname = NEW.stuname WHERE stuaccount = NEW.stuaccount;END");

    query->exec("CREATE TRIGGER delete_stu AFTER DELETE ON studentinfo FOR EACH ROW BEGIN DELETE FROM gradeinfo WHERE stuaccount = OLD.stuaccount; DELETE FROM healthinfo WHERE stuaccount = OLD.stuaccount; DELETE FROM licenseinfo WHERE stuaccount = OLD.stuaccount;END");
}


bool My_Sql::inituser(QString name, QString identify, QString passward)
{
    query = new QSqlQuery;
    QString str = QString("insert into user value('%1', '%2', '%3')").arg(name).arg(identify).arg(passward);
    bool ret = query->exec(str);
    return ret;
}

bool My_Sql::loguser(QString name, QString passward)
{
    query = new QSqlQuery;
    QString str = QString("select * from user where name = '%1' and passward = '%2'").arg(name).arg(passward);
    query->exec(str);
    query->last();
    int record = query->at() + 1;
    if(record == 0)
    {
        return false;
    }
    MainWindow* MW = MainWindow::getIntence();
    MW->passward = query->value(1).toString();
    return true;
}

bool My_Sql::addstu(stuInfo *stu)
{
    query = new QSqlQuery;
    QString str = QString("insert into studentInfo value('%1', '%2', '%3', %4, '%5', '%6', '%7', '%8', '%9', '%10')")
            .arg(stu->account).arg(stu->name).arg(stu->sex).arg(stu->age).arg(stu->identify).arg(stu->tel).arg(stu->enroll_time)
            .arg(stu->leave_time).arg(stu->scondition).arg(stu->text);
    bool ret = query->exec(str);
    return ret;
}

bool My_Sql::deletestu(QString account)
{
    query = new QSqlQuery;
    QString str = QString("select * from studentInfo where stuaccount = '%1'").arg(account);
    query->exec(str);
    query->last();
    int record = query->at() + 1;
    if(record == 0)
    {
        return false;
    }
    str = QString("delete from studentInfo where stuaccount = '%1'").arg(account);
    query->exec(str);
    return true;
}

bool My_Sql::updatestu(my_stu *stu)
{
    query = new QSqlQuery;
    QString str = QString("select * from studentInfo where stuaccount = '%1'").arg(stu->account);
    query->exec(str);
    query->last();
    int record = query->at() + 1;
    if(record == 0)
    {
        return false;
    }
    str = QString("update studentInfo set stuname = '%1', stusex = '%2', stuage = %3, identify = '%4', tel = '%5', enroll_time = '%6', leave_time = '%7', scondition = '%8', stu_text = '%9' where stuaccount = '%10'")
            .arg(stu->name).arg(stu->sex).arg(stu->age).arg(stu->identify).arg(stu->tel).arg(stu->enroll_time).arg(stu->leave_time).arg(stu->scondition).arg(stu->text).arg(stu->account);
    qDebug()<<str;
    bool ret = query->exec(str);
    return ret;
}

bool My_Sql::addheal(my_heal *heal)
{
    query = new QSqlQuery;
    QString str = QString("insert into healthInfo value('%1', '%2', '%3', %4, '%5', '%6', '%7', '%8', '%9', '%10', '%11', '%12', '%13')")
            .arg(heal->stuaccount).arg(heal->stuname).arg(heal->height).arg(heal->weight).arg(heal->differentiate).arg(heal->left_sight).arg(heal->right_sight)
            .arg(heal->left_ear).arg(heal->right_ear).arg(heal->legs).arg(heal->pressure).arg(heal->history).arg(heal->h_text);
    bool ret = query->exec(str);
    return ret;
}

bool My_Sql::updateheal(my_heal *heal)
{
    query = new QSqlQuery;
    QString str = QString("select * from healthInfo where stuaccount = '%1'").arg(heal->stuaccount);
    query->exec(str);
    query->last();
    int record = query->at() + 1;
    if(record == 0)
    {
        return false;
    }
    str = QString("update healthInfo set stuname = '%1', height = '%2', weight = '%3', differentiate = '%4', left_sight = '%5', right_sight = '%6', left_ear = '%7', right_ear = '%8', legs = '%9', pressure = '%10', history = '%11', h_text = '%12' where stuaccount = '%13'")
            .arg(heal->stuname).arg(heal->height).arg(heal->weight).arg(heal->differentiate).arg(heal->left_sight).arg(heal->right_sight)
            .arg(heal->left_ear).arg(heal->right_ear).arg(heal->legs).arg(heal->pressure).arg(heal->history).arg(heal->h_text).arg(heal->stuaccount);
    qDebug()<<str;
    bool ret = query->exec(str);
    qDebug()<<ret;
    return ret;
}

bool My_Sql::deleteheal(QString account)
{
    query = new QSqlQuery;
    QString str = QString("select * from healthInfo where stuaccount = '%1'").arg(account);
    query->exec(str);
    query->last();
    int record = query->at() + 1;
    if(record == 0)
    {
        return false;
    }
    str = QString("delete from healthInfo where stuaccount = '%1'").arg(account);
    query->exec(str);
    return true;
}

bool My_Sql::addgrade(my_grade *grad)
{
    query = new QSqlQuery;
    QString str = QString("insert into gradeInfo value('%1', %2, %3, %4, %5)")
            .arg(grad->stuaccount).arg(grad->classid).arg(grad->lasttime).arg(grad->times).arg(grad->grade);
    qDebug()<<str;
    bool ret = query->exec(str);
    return ret;
}

bool My_Sql::updategrade(my_grade *grad)
{
    query = new QSqlQuery;
    QString str = QString("select * from gradeInfo where stuaccount = '%1'").arg(grad->stuaccount);
    query->exec(str);
    query->last();
    int record = query->at() + 1;
    if(record == 0)
    {
        return false;
    }
    str = QString("update gradeInfo set classid = '%1', lasttime = %2, times = %3, grade = %4 where stuaccount = '%5'")
            .arg(grad->classid).arg(grad->lasttime).arg(grad->times).arg(grad->grade).arg(grad->stuaccount);

    qDebug()<<str;
    bool ret = query->exec(str);
    return ret;
}

bool My_Sql::deletegrade(QString account)
{
    query = new QSqlQuery;
    QString str = QString("select * from gradeInfo where stuaccount = '%1'").arg(account);
    query->exec(str);
    query->last();
    int record = query->at() + 1;
    if(record == 0)
    {
        return false;
    }
    str = QString("delete from gradeInfo where stuaccount = '%1'").arg(account);
    query->exec(str);
    return true;
}

數據保護

防止用戶直接操作數據庫

  • 用戶在登錄時需要輸入用戶名和密碼,才能進行操作;
  • 若用戶忘記密碼,可通過登錄頁面驗證身份證號重置密碼;
  • 一般用戶(學生)只可修改密碼,僅管理員才能進行用戶的增刪查改操作;
  • 一般用戶用戶只能用賬號登錄,通過應用軟件訪問數據,而沒有其他途徑可以操作數據庫。

用戶帳號密碼的加密

  • 對用戶賬號的密碼進行加密處理,確保任何地方都不會出現明文;
  • 可增加密碼難易度檢測提醒。

角色與權限

1

數據優化

1

系統截圖

1
3
2
3

項目總結

  • 本項目捨棄了傳統的Web開發,劍走偏鋒,改用Qt接口嘗試,實際上存在一定的侷限性;在數據庫方面,目前僅實現了基本的增刪查改功能,UI方面也尚未優化;
  • 數據庫的前期設計工作較爲繁瑣,但熟練了之後還是能較快的上手;
  • 作爲數據庫課設中最簡單的項目,搭建一個XX信息管理系統對於剛入門的同學來說練手再好不過,希望本文能給一些不會Java但想動手試試搭數據庫的朋友提供幫助;
  • 完整源碼地址(僅供參考)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章