【数据库实验】实验四 基于嵌入SQL的综合应用编程(基于QSqlTableModel实现)

一、实验目的

本次实验的主要目的是掌握嵌入SQL及主高级语言,学会使用嵌入SQL对数据库进行增、删、改、备份的方法。

二、实验要求

1.要求学生独立完成实验内容,画出E-R图及程序功能图;
2.按照实验步骤完成实验后,撰写报告内容,并对操作结果进行截图,写出主要关键程序代码。

三、实验内容、实验结果与主要程序代码

基于实验一的三个表采用嵌入式SQL语言及主语言编程实现数据库的录入、修改、删除和备份等管理功能,并能实现基于学号显示学生基本信息、课程名、成绩信息。
(一) 画出E-R图及程序功能分析设计图
(二)功能实现界面图及主要程序代码(要有注释)

数据准备(建表并插入数据)

在这里插入图片描述

前言:黎哥的写法

先使用QT写好.ui文件,然后使用pyuic转化为.py文件,在.py文件内,写槽函数,写连接函数写执行函数。使用pymysqlcursor游标,执行sql命令。显示数据。
备份的实现,使用了系统命令,具体实现如下所示。

name="root"
key="passwd"
path="D://xxxx/"
os.system("mysql drop -u {1} -p {2} {3} values(%,%,%)".(name,key,path))

参考

PyQt5教程 课时139 使用可视化的方式对SQLite数据库进行增、删、改、查操作
Qt数据库(5)-使用SQLModel类
qtableview add rows from a query and edit them in python

    self.model.setTable("produse")

    self.produse_view.setModel(self.model)
    self.produse_view.hideColumn(0) # hide id column
    self.addData(["a", "b", "c", "d", "e", "f"])

def addData(self, data):

    rec = self.model.record()

    for i in range(6):
        rec.setValue(rec.field(i+1).name(), data[i])
    self.model.insertRecord(-1, rec)

建表

#建立S学生表
Drop if exists S;
CREATE TABLE S(sclass int,sno int,sname char(20),ssex char(4),sage int,Sdept char(20));
#建立SC选课表
Drop if exists SC;
CREATE TABLE SC(sclass int,sno int,cno int ,grade int);
#建立C课程表
Drop if exists C;
CREATE TABLE C(cno int,cname char(20),cpno int,ccredit int);

SQL语言插入数据

S表
INSERT INTO S VALUES(1,1,'李勇','男',20,'IS');
INSERT INTO S VALUES(1,2,'刘晨','女',19,'IS');
INSERT INTO S VALUES(1,3,'刘朋','男',20,'IS');
INSERT INTO S VALUES(2,1,'王敏','女',18,'MA');
INSERT INTO S VALUES(2,2,'张锋','男',19,'MA');
INSERT INTO S VALUES(2,3,'李敏','男',20,'MA');
SC表
INSERT INTO SC VALUES(1,1,1,92);
INSERT INTO SC VALUES(1,1,2,85);
INSERT INTO SC VALUES(1,1,3,88);
INSERT INTO SC VALUES(1,2,2,90);
INSERT INTO SC VALUES(1,2,3,80);
INSERT INTO SC VALUES(2,1,1,75);
INSERT INTO SC VALUES(2,1,2,92);
INSERT INTO SC VALUES(2,2,2,87);
INSERT INTO SC VALUES(2,2,3,89);
INSERT INTO SC VALUES(2,3,1,90);
C表
INSERT INTO C VALUES(1,'数据库',5,4);
INSERT INTO C VALUES(2,'数学',NULL,2);
INSERT INTO C VALUES(3,'信息系统',1,4);
INSERT INTO C VALUES(4,'操作系统',6,3);
INSERT INTO C VALUES(5,'数据结构',7,4);
INSERT INTO C VALUES(6,'数据处理',NULL,2);
INSERT INTO C VALUES(7,'PASCAL语言',6,4);

嵌入式SQL

S表
query.exec_	("INSERT INTO S VALUES(1,1,'李勇','男',20,'IS')")
query.exec_	("INSERT INTO S VALUES(1,2,'刘晨','女',19,'IS')")
query.exec_	("INSERT INTO S VALUES(1,3,'刘朋','男',20,'IS')")
query.exec_	("INSERT INTO S VALUES(2,1,'王敏','女',18,'MA')")
query.exec_	("INSERT INTO S VALUES(2,2,'张锋','男',19,'MA')")
query.exec_	("INSERT INTO S VALUES(2,3,'李敏','男',20,'MA')")
SC表
query.exec_("INSERT INTO SC VALUES(1,1,1,92)")
query.exec_("INSERT INTO SC VALUES(1,1,2,85)")
query.exec_("INSERT INTO SC VALUES(1,1,3,88)")
query.exec_("INSERT INTO SC VALUES(1,2,2,90)")
query.exec_("INSERT INTO SC VALUES(1,2,3,80)")
query.exec_("INSERT INTO SC VALUES(2,1,1,75)")
query.exec_("INSERT INTO SC VALUES(2,1,2,92)")
query.exec_("INSERT INTO SC VALUES(2,2,2,87)")
query.exec_("INSERT INTO SC VALUES(2,2,3,89)")
query.exec_("INSERT INTO SC VALUES(2,3,1,90)")
C表
query.exec_("INSERT INTO C VALUES(1,'数据库',5,4)")
query.exec_("INSERT INTO C VALUES(2,'数学',NULL,2)")
query.exec_("INSERT INTO C VALUES(3,'信息系统',1,4)")
query.exec_("INSERT INTO C VALUES(4,'操作系统',6,3)")
query.exec_("INSERT INTO C VALUES(5,'数据结构',7,4)")
query.exec_("INSERT INTO C VALUES(6,'数据处理',NULL,2)")
query.exec_("INSERT INTO C VALUES(7,'PASCAL语言',6,4)")

程序按钮组成

按实验要求,需要有基于学号的检索数据功能,插入数据功能,删除数据功能,以及备份数据库功能。
首先建立数据库一个按钮,
然后显示一个按钮,
然后查询一个按钮,
然后删除一个按钮,
然后修改一个按钮,
然后备份一个按钮,
最后退出一个按钮。

共计7个按钮。

在这里插入代码片

备份实现

SQLITE的备份保存实现

保存的本质是把当前sqlite文件进行另存为保存。
保存图片

from tkinter import *
fname = tkinter.filedialog.asksaveasfilename(title=u'保存文件', filetypes=[("PNG", ".png")])
picture.save(str(fname) + '.png', 'PNG')

只需要在弹出对话框后选择保存位置,输入图片名字即可。
【注】如果不加以下两行代码:

root = tkinter.Tk()    # 创建一个Tkinter.Tk()实例
root.withdraw()       # 将Tkinter.Tk()实例隐藏

程序运行后将会出现一个小框。

MYSQL数据库备份

对于其他数据库,比如MYSQL数据库来说:
使用Python3编写脚本一键备份MySQL数据库

使用的是subprocess

import logging
import os
import subprocess
import pymysql
  • 备份
    logging.info('开始备份数据库 {}...'.format(database))
    # 通过调用mysqldump完成指定数据库的备份
    command = 'mysqldump -h192.168.1.4 -uroot -p666 --add-drop-database --databases {database} > {backup_path}/{database}.sql'.format(
        database=database,
        backup_path=BACKUP_PATH)
    exit_code = subprocess.call(command, shell=True)
    # 判断命令是否正常执行,异常则直接抛出
    if exit_code != 0:
        raise Exception('在备份数据库的过程中出错,请检查!')
    logging.info('数据库 {} 备份完毕!'.format(database))
  • 恢复
import logging
import os
import subprocess
import pymysql

# 设置日志输出格式
logging.basicConfig(format='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s',level=logging.INFO)
# MySQL数据库用户名
MYSQL_USERNAME = 'root'
# 数据库密码
MYSQL_PASSWORD = 'mypassword'
# 数据库主机地址
MYSQL_HOST = '192.168.1.4'
# 数据库端口
MYSQL_PORT = 3306
# 备份文件存放路径
BACKUP_PATH = 'backup'
logging.info('开始获取需要恢复的数据库文件...')
files = list(os.listdir(BACKUP_PATH))
logging.info('文件列表:{}'.format(files))
# 开始逐个恢复数据库
for file in files:
    logging.info('开始恢复数据库 {}...'.format(file.split('.')[0]))
    command = 'mysql -h{host} -f -u{user} -p{password} -P{port} < {path}/{file}'.format(host=MYSQL_HOST,                                                                                      user=MYSQL_USERNAME,                                                                            password=MYSQL_PASSWORD,                                                                           port=MYSQL_PORT, file=file,                                                                                path=BACKUP_PATH)
    subprocess.call(command, shell=True)
logging.info('完毕!')

主要代码

最简单的库引用的写法:

import sys 
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtSql import *

QSqlTableModel和QSqlQueryModel

QSqlQuery
可以用来执行SQL语句和获得执行结果的。
QSqlQueryModel
提供了一个sql查询结果的只读数据模型。它从查询QSqlQueryModel获取数据。
可以方便的用于在QListView, QTableView, QTreeView等各种view上展示数据。
但它是只读的,不能编辑。
QSqlTableMode
继承于QSqlQueryModel,与QSqlQueryModel功能相似。
比QSqlQueryModel的限制在于不能是任意sql语句,只是对单个数据表操作。
拓展在于在各种view上展示表格数据的同时,还允许用户进行编辑操作。

bool QSqlTableModel:: select ()
使用通过setTable ()设置的表中的数据填充模型,使用指定的过滤器(setFilter())和排序条件,true如果成功则返回;否则返回false。
注意:调用 select()将恢复任何未提交的更改并删除任何插入的列。
另请参见setTable ()setFilter ()selectStatement ()

界面

def __init__(self):
    super().__init__()
    self.initUi()

def initUi(self):
    # 设置窗口标题
    self.setWindowTitle("刘看日的数据库实验四")
    # 设置窗口大小
    self.resize(600, 400)

    # 创建一个窗口部件
    self.widget = QtWidgets.QWidget()
    # 创建一个网格布局
    self.grid_layout = QtWidgets.QGridLayout()
    # 设置窗口部件的布局为网格布局
    self.widget.setLayout(self.grid_layout)

    # 创建一个工具组
    self.group_box = QtWidgets.QGroupBox('功能按钮')
    self.group_box_layout = QtWidgets.QVBoxLayout()
    self.group_box.setLayout(self.group_box_layout)


    #设置一个LineEdit窗口
    self.text=QtWidgets.QLineEdit()
    # 设置文本框的默认浮现文本
    self.text.setPlaceholderText("输入学号/课程号")

    self.table_view = QtWidgets.QTableView()
    # 按钮控件设置
    self.btn_create=QPushButton("连接表")
    self.btn_showall=QPushButton("展示全部数据")
    self.btn_search = QPushButton("基于学号/课程号查询")
    self.btn_close = QPushButton("退出")
    self.btn_delete=QPushButton("删除")
    self.btn_edit=QPushButton("修改")
    self.btn_add=QPushButton("添加")
    self.btn_backup = QPushButton("备份")

    # 添加按钮到group_box大组件中
    self.group_box_layout.addWidget(self.text)
    self.group_box_layout.addWidget(self.btn_create)
    self.group_box_layout.addWidget(self.btn_showall)
    self.group_box_layout.addWidget(self.btn_search)
    self.group_box_layout.addWidget(self.btn_add)
    self.group_box_layout.addWidget(self.btn_delete)
    self.group_box_layout.addWidget(self.btn_edit)
    self.group_box_layout.addWidget(self.btn_backup)
    self.group_box_layout.addWidget(self.btn_close)

    # 将上述两个部件添加到网格布局中
    self.grid_layout.addWidget(self.table_view, 0, 0)  # 放置表格位置在0
    self.grid_layout.addWidget(self.group_box, 0, 1)  # 放置
    # 创建按钮功能按钮
    self.btn_create.clicked.connect(self.create_db)
    self.btn_showall.clicked.connect(self.showall_tab)
    self.btn_search.clicked.connect(self.search_data)
    self.btn_close.clicked.connect(self.close)
    self.btn_add.clicked.connect(self.add_row_data)
    self.btn_delete.clicked.connect(self.del_row_data)
    self.btn_edit.clicked.connect(self.edit_row_data)
    self.btn_backup.clicked.connect(self.backup_data)
    # 设置UI界面的核心部件
    self.setCentralWidget(self.widget)

创建数据库,插入数据表

def create_db(self):
    # 添加一个mysql数据库连接并打开
    db = QtSql.QSqlDatabase.addDatabase('QSQLITE')  # 创建Mysql数据库,可自定义
    if db.setDatabaseName('student.sqlite'):  # 设置数据库名称
        print("创建'student.sqlite'数据库文件成功")
        msgBox1 = QMessageBox()
        msgBox1.setText("创建'student.sqlite'数据库文件成功")
        msgBox1.exec()
    else:
        print("'student.sqlite'数据文件已经存在")
        msgBox2 = QMessageBox()
        msgBox2.setText("'student.sqlite'数据文件已经存在")
        msgBox2.exec()

    db.setHostName("127.0.0.1")#可以有多个连接到同一个数据库,也就是说连接名不唯一
    db.setUserName('tom')#定义用户名
    db.setPassword('tom@123')#定义密码

    # success!
    db.open()
    table_text, table_action = QtWidgets.QInputDialog.getText(self, '表名称', '请输入表名称', QtWidgets.QLineEdit.Normal)
    if (table_text.replace(' ', '') != '') and (table_action is True):
         print(table_text)
    #实例化一个查询对象
    self.tablename=table_text

    #先进行插入数据

    query = QtSql.QSqlQuery()
    if query.exec_("Drop table if exists s"):
        print("drop table s ok!")
    if query.exec_("CREATE TABLE S(sclass int,sno int,sname char(20),ssex char(4),sage int,Sdept char(20))"):
        print("create table s ok!")
    if query.exec_("Drop table if exists sc"):
        print("drop table sc ok!")
    if query.exec_("CREATE TABLE SC(sclass int,sno int,cno int ,grade int)"):
        print("create table sc ok!")
    if query.exec_("Drop table if exists c"):
        print("drop table c ok!")
    else:
        print("error:drop table c")
    if query.exec_("CREATE TABLE C(cno int,cname char(20),cpno int,ccredit int)"):
        print("create table c ok!")
    else:
        print("error:create table c")

    query.exec_("INSERT INTO S VALUES(1,1,'李勇','男',20,'IS')")
    query.exec_("INSERT INTO S VALUES(1,2,'刘晨','女',19,'IS')")
    query.exec_("INSERT INTO S VALUES(1,3,'刘朋','男',20,'IS')")
    query.exec_("INSERT INTO S VALUES(2,1,'王敏','女',18,'MA')")
    query.exec_("INSERT INTO S VALUES(2,2,'张锋','男',19,'MA')")
    query.exec_("INSERT INTO S VALUES(2,3,'李敏','男',20,'MA')")

    query.exec_("INSERT INTO SC VALUES(1,1,1,92)")
    query.exec_("INSERT INTO SC VALUES(1,1,2,85)")
    query.exec_("INSERT INTO SC VALUES(1,1,3,88)")
    query.exec_("INSERT INTO SC VALUES(1,2,2,90)")
    query.exec_("INSERT INTO SC VALUES(1,2,3,80)")
    query.exec_("INSERT INTO SC VALUES(2,1,1,75)")
    query.exec_("INSERT INTO SC VALUES(2,1,2,92)")
    query.exec_("INSERT INTO SC VALUES(2,2,2,87)")
    query.exec_("INSERT INTO SC VALUES(2,2,3,89)")
    query.exec_("INSERT INTO SC VALUES(2,3,1,90)")

    query.exec_("INSERT INTO SC VALUES(1,1,1,92)")
    query.exec_("INSERT INTO SC VALUES(1,1,2,85)")
    query.exec_("INSERT INTO SC VALUES(1,1,3,88)")
    query.exec_("INSERT INTO SC VALUES(1,2,2,90)")
    query.exec_("INSERT INTO SC VALUES(1,2,3,80)")
    query.exec_("INSERT INTO SC VALUES(2,1,1,75)")
    query.exec_("INSERT INTO SC VALUES(2,1,2,92)")
    query.exec_("INSERT INTO SC VALUES(2,2,2,87)")
    query.exec_("INSERT INTO SC VALUES(2,2,3,89)")
    query.exec_("INSERT INTO SC VALUES(2,3,1,90)")

    db.close()

展示表的全部数据

def showall_tab(self):
    query = QtSql.QSqlQuery()
    if (self.tablename == "s"):
        msgBox3 = QMessageBox()
        msgBox3.setText("展示表s")
        msgBox3.exec()

        self.model = QtSql.QSqlTableModel(
            self.table_view)  # 创建一个空的 QSqlTableModel 并将父级设置为父级,将数据库连接设置为 db。如果 db 无效,则将使用默认数据库连接。
        # model 用于装载变量
        self.model.setHeaderData(0, QtCore.Qt.Horizontal, '班号')
        self.model.setHeaderData(1, QtCore.Qt.Horizontal, '学号')
        self.model.setHeaderData(2, QtCore.Qt.Horizontal, '姓名')
        self.model.setHeaderData(3, QtCore.Qt.Horizontal, '性别')
        self.model.setHeaderData(4, QtCore.Qt.Horizontal, '年龄')
        self.model.setHeaderData(5, QtCore.Qt.Horizontal, '院系')

        self.model.setTable("s")
        self.model.select()
        self.table_view.setModel(self.model)  # 一定要写在所有设置完之后,装载数据

    elif (self.tablename == "sc"):
        msgBox4 = QMessageBox()
        msgBox4.setText("展示表sc")
        msgBox4.exec()

        self.model = QtSql.QSqlTableModel(
            self.table_view)  # 创建一个空的 QSqlTableModel 并将父级设置为父级,将数据库连接设置为 db。如果 db 无效,则将使用默认数据库连接。
        # model 用于装载变量
        self.model.setHeaderData(0, QtCore.Qt.Horizontal, '班号')
        self.model.setHeaderData(1, QtCore.Qt.Horizontal, '学号')
        self.model.setHeaderData(2, QtCore.Qt.Horizontal, '课程号')
        self.model.setHeaderData(3, QtCore.Qt.Horizontal, '成绩')


        self.model.setTable("sc")
        self.model.select()
        self.table_view.setModel(self.model)  # 一定要写在所有设置完之后,装载数据

    elif (self.tablename == "c"):
        msgBox5 = QMessageBox()
        msgBox5.setText("展示表c")
        msgBox5.exec()

        self.model = QtSql.QSqlTableModel(self.table_view)
        # onfieldchange模型的任何更改都会返回到数据库
        self.model.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange)
        self.model.setHeaderData(0, QtCore.Qt.Horizontal, '课程号')
        self.model.setHeaderData(1, QtCore.Qt.Horizontal, '课程名')
        self.model.setHeaderData(2, QtCore.Qt.Horizontal, '先修课')
        self.model.setHeaderData(3, QtCore.Qt.Horizontal, '学分')


        self.model.setTable("c")
        self.model.select()
        self.table_view.setModel(self.model)

    else:
        msgBox6 = QMessageBox()
        msgBox6.setText("表暂且不属于实验范围,请更换!")
        msgBox6.exec_()

查找,添加,删除,修改

def search_data(self):
    query = QtSql.QSqlQuery()
    # 创建一个数据库表
    if(self.tablename=="s"):
        msgBox3 = QMessageBox()
        msgBox3.setText("查询表s")
        msgBox3.exec()

        self.model = QtSql.QSqlTableModel(self.table_view)  # 创建一个空的 QSqlTableModel 并将父级设置为父级,将数据库连接设置为 db。如果 db 无效,则将使用默认数据库连接。
        #model 用于装载变量
        self.model.setHeaderData(0, QtCore.Qt.Horizontal, '班号')
        self.model.setHeaderData(1, QtCore.Qt.Horizontal, '学号')
        self.model.setHeaderData(2, QtCore.Qt.Horizontal, '姓名')
        self.model.setHeaderData(3, QtCore.Qt.Horizontal, '性别')
        self.model.setHeaderData(4, QtCore.Qt.Horizontal, '年龄')
        self.model.setHeaderData(5, QtCore.Qt.Horizontal, '院系')

        search = self.text.text()
        self.model.setTable("s")
        self.model.setFilter("sno={}".format(search))
        self.model.select()
        self.table_view.setModel(self.model)#一定要写在所有设置完之后,装载数据

    elif(self.tablename=="sc"):
        msgBox4 = QMessageBox()
        msgBox4.setText("查询表sc")
        msgBox4.exec()

        self.model = QtSql.QSqlTableModel(self.table_view) # 创建一个空的 QSqlTableModel 并将父级设置为父级,将数据库连接设置为 db。如果 db 无效,则将使用默认数据库连接。
        #model 用于装载变量
        self.model.setHeaderData(0, QtCore.Qt.Horizontal, '班号')
        self.model.setHeaderData(1, QtCore.Qt.Horizontal, '学号')
        self.model.setHeaderData(2, QtCore.Qt.Horizontal, '课程号')
        self.model.setHeaderData(3, QtCore.Qt.Horizontal, '成绩')

        search = self.text.text()
        self.model.setTable("sc")
        self.model.setFilter("sno = {}".format(search))
        self.model.select()
        self.table_view.setModel(self.model)#一定要写在所有设置完之后,装载数据

    elif(self.tablename=="c"):
        msgBox5 = QMessageBox()
        msgBox5.setText("查询表c")
        msgBox5.exec()

        self.model=QtSql.QSqlTableModel(self.table_view)
        #onfieldchange模型的任何更改都会返回到数据库
        self.model.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange)
        self.model.setHeaderData(0,QtCore.Qt.Horizontal,'课程号')
        self.model.setHeaderData(1,QtCore.Qt.Horizontal,'课程名')
        self.model.setHeaderData(2,QtCore.Qt.Horizontal,'先修课')
        self.model.setHeaderData(3,QtCore.Qt.Horizontal,'学分')

        search=self.text.text()
        self.model.setTable("c")
        self.model.setFilter("cno = {}".format(search))
        self.model.select()
        self.table_view.setModel(self.model)

    else:
        msgBox6=QMessageBox()
        msgBox6.setText("表暂且不属于实验范围,请更换!")
        msgBox6.exec_()

def add_row_data(self):
    #不是直接操作QTableView,而是对model模型进行添加
    # 如果存在实例化的数据模型对象
    # self.model.insertRow(self.model.rowCount(),1)

    if self.model:
        #rowCount()得到行数,然后添加一行
        self.model.insertRows(self.model.rowCount(), 1)
        self.model.submitAll()#提交修改
    else:
        self.create_db()

def del_row_data(self):
    if self.model:
        self.model.removeRow(self.table_view.currentIndex().row())
        self.model.submitAll()#提交修改
    else:
        self.create_db()

def edit_row_data(self):
    if self.model:
        self.model.submitAll()#提交更改
    else:
        self.create_db()

备份实现(文件函数)

def backup_data(self):
    ori_file_name = r'D:\coding_programs\PythonPrograms\database_exp4\student.sqlite'  # 输入文件路径
    if os.path.isfile(ori_file_name):  # 判断该路径的是否是文件
        # 截取文件名,重组文件名
        seek_num = ori_file_name.rfind('.')
        new_file_name = ori_file_name[:seek_num] + '.bak'
        # 打开源文件
        old_file = open(ori_file_name, 'rb')
        # 读取文件信息
        old_file_content = old_file.read()
        # 创建新文件
        new_file = open(new_file_name, 'wb')
        # 将原始文件信息写入
        new_file.write(old_file_content)
        # 关闭文件
        old_file.close()
        new_file.close()
        print("backup success!")
        msgBox7 = QMessageBox()
        msgBox7.setText("student.bak数据文件已经备份")
        msgBox7.exec()
    else:
        print('没有该文件')

演示GIF

在这里插入图片描述

完整代码

# coding:utf-8

import os,sys
from PyQt5 import QtCore, QtWidgets, QtSql
from PyQt5.QtWidgets import QApplication, QMessageBox, QPushButton

class MainUi(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUi()

    def create_db(self):
        # 添加一个mysql数据库连接并打开
        db = QtSql.QSqlDatabase.addDatabase('QSQLITE')  # 创建Mysql数据库,可自定义
        if db.setDatabaseName('student.sqlite'):  # 设置数据库名称
            print("创建'student.sqlite'数据库文件成功")
            msgBox1 = QMessageBox()
            msgBox1.setText("创建'student.sqlite'数据库文件成功")
            msgBox1.exec()
        else:
            print("'student.sqlite'数据文件已经存在")
            msgBox2 = QMessageBox()
            msgBox2.setText("'student.sqlite'数据文件已经存在")
            msgBox2.exec()

        db.setHostName("127.0.0.1")#可以有多个连接到同一个数据库,也就是说连接名不唯一
        db.setUserName('tom')#定义用户名
        db.setPassword('tom@123')

        # success!
        db.open()
        table_text, table_action = QtWidgets.QInputDialog.getText(self, '表名称', '请输入表名称', QtWidgets.QLineEdit.Normal)
        if (table_text.replace(' ', '') != '') and (table_action is True):
             print(table_text)
        #实例化一个查询对象
        self.tablename=table_text

        #先进行插入数据

        query = QtSql.QSqlQuery()
        if query.exec_("Drop table if exists s"):
            print("drop table s ok!")
        if query.exec_("CREATE TABLE S(sclass int,sno int,sname char(20),ssex char(4),sage int,Sdept char(20))"):
            print("create table s ok!")
        if query.exec_("Drop table if exists sc"):
            print("drop table sc ok!")
        if query.exec_("CREATE TABLE SC(sclass int,sno int,cno int ,grade int)"):
            print("create table sc ok!")
        if query.exec_("Drop table if exists c"):
            print("drop table c ok!")
        else:
            print("error:drop table c")
        if query.exec_("CREATE TABLE C(cno int,cname char(20),cpno int,ccredit int)"):
            print("create table c ok!")
        else:
            print("error:create table c")

        query.exec_("INSERT INTO S VALUES(1,1,'李勇','男',20,'IS')")
        query.exec_("INSERT INTO S VALUES(1,2,'刘晨','女',19,'IS')")
        query.exec_("INSERT INTO S VALUES(1,3,'刘朋','男',20,'IS')")
        query.exec_("INSERT INTO S VALUES(2,1,'王敏','女',18,'MA')")
        query.exec_("INSERT INTO S VALUES(2,2,'张锋','男',19,'MA')")
        query.exec_("INSERT INTO S VALUES(2,3,'李敏','男',20,'MA')")

        query.exec_("INSERT INTO SC VALUES(1,1,1,92)")
        query.exec_("INSERT INTO SC VALUES(1,1,2,85)")
        query.exec_("INSERT INTO SC VALUES(1,1,3,88)")
        query.exec_("INSERT INTO SC VALUES(1,2,2,90)")
        query.exec_("INSERT INTO SC VALUES(1,2,3,80)")
        query.exec_("INSERT INTO SC VALUES(2,1,1,75)")
        query.exec_("INSERT INTO SC VALUES(2,1,2,92)")
        query.exec_("INSERT INTO SC VALUES(2,2,2,87)")
        query.exec_("INSERT INTO SC VALUES(2,2,3,89)")
        query.exec_("INSERT INTO SC VALUES(2,3,1,90)")

        query.exec_("INSERT INTO SC VALUES(1,1,1,92)")
        query.exec_("INSERT INTO SC VALUES(1,1,2,85)")
        query.exec_("INSERT INTO SC VALUES(1,1,3,88)")
        query.exec_("INSERT INTO SC VALUES(1,2,2,90)")
        query.exec_("INSERT INTO SC VALUES(1,2,3,80)")
        query.exec_("INSERT INTO SC VALUES(2,1,1,75)")
        query.exec_("INSERT INTO SC VALUES(2,1,2,92)")
        query.exec_("INSERT INTO SC VALUES(2,2,2,87)")
        query.exec_("INSERT INTO SC VALUES(2,2,3,89)")
        query.exec_("INSERT INTO SC VALUES(2,3,1,90)")

        db.close()

    def showall_tab(self):
        query = QtSql.QSqlQuery()
        if (self.tablename == "s"):
            msgBox3 = QMessageBox()
            msgBox3.setText("展示表s")
            msgBox3.exec()

            self.model = QtSql.QSqlTableModel(
                self.table_view)  # 创建一个空的 QSqlTableModel 并将父级设置为父级,将数据库连接设置为 db。如果 db 无效,则将使用默认数据库连接。
            # model 用于装载变量
            self.model.setHeaderData(0, QtCore.Qt.Horizontal, '班号')
            self.model.setHeaderData(1, QtCore.Qt.Horizontal, '学号')
            self.model.setHeaderData(2, QtCore.Qt.Horizontal, '姓名')
            self.model.setHeaderData(3, QtCore.Qt.Horizontal, '性别')
            self.model.setHeaderData(4, QtCore.Qt.Horizontal, '年龄')
            self.model.setHeaderData(5, QtCore.Qt.Horizontal, '院系')

            self.model.setTable("s")
            self.model.select()
            self.table_view.setModel(self.model)  # 一定要写在所有设置完之后,装载数据

        elif (self.tablename == "sc"):
            msgBox4 = QMessageBox()
            msgBox4.setText("展示表sc")
            msgBox4.exec()

            self.model = QtSql.QSqlTableModel(
                self.table_view)  # 创建一个空的 QSqlTableModel 并将父级设置为父级,将数据库连接设置为 db。如果 db 无效,则将使用默认数据库连接。
            # model 用于装载变量
            self.model.setHeaderData(0, QtCore.Qt.Horizontal, '班号')
            self.model.setHeaderData(1, QtCore.Qt.Horizontal, '学号')
            self.model.setHeaderData(2, QtCore.Qt.Horizontal, '课程号')
            self.model.setHeaderData(3, QtCore.Qt.Horizontal, '成绩')


            self.model.setTable("sc")
            self.model.select()
            self.table_view.setModel(self.model)  # 一定要写在所有设置完之后,装载数据

        elif (self.tablename == "c"):
            msgBox5 = QMessageBox()
            msgBox5.setText("展示表c")
            msgBox5.exec()

            self.model = QtSql.QSqlTableModel(self.table_view)
            # onfieldchange模型的任何更改都会返回到数据库
            self.model.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange)
            self.model.setHeaderData(0, QtCore.Qt.Horizontal, '课程号')
            self.model.setHeaderData(1, QtCore.Qt.Horizontal, '课程名')
            self.model.setHeaderData(2, QtCore.Qt.Horizontal, '先修课')
            self.model.setHeaderData(3, QtCore.Qt.Horizontal, '学分')


            self.model.setTable("c")
            self.model.select()
            self.table_view.setModel(self.model)

        else:
            msgBox6 = QMessageBox()
            msgBox6.setText("表暂且不属于实验范围,请更换!")
            msgBox6.exec_()

    def search_data(self):
        query = QtSql.QSqlQuery()
        # 创建一个数据库表
        if(self.tablename=="s"):
            msgBox3 = QMessageBox()
            msgBox3.setText("查询表s")
            msgBox3.exec()

            self.model = QtSql.QSqlTableModel(self.table_view)  # 创建一个空的 QSqlTableModel 并将父级设置为父级,将数据库连接设置为 db。如果 db 无效,则将使用默认数据库连接。
            #model 用于装载变量
            self.model.setHeaderData(0, QtCore.Qt.Horizontal, '班号')
            self.model.setHeaderData(1, QtCore.Qt.Horizontal, '学号')
            self.model.setHeaderData(2, QtCore.Qt.Horizontal, '姓名')
            self.model.setHeaderData(3, QtCore.Qt.Horizontal, '性别')
            self.model.setHeaderData(4, QtCore.Qt.Horizontal, '年龄')
            self.model.setHeaderData(5, QtCore.Qt.Horizontal, '院系')

            search = self.text.text()
            self.model.setTable("s")
            self.model.setFilter("sno={}".format(search))
            self.model.select()
            self.table_view.setModel(self.model)#一定要写在所有设置完之后,装载数据

        elif(self.tablename=="sc"):
            msgBox4 = QMessageBox()
            msgBox4.setText("查询表sc")
            msgBox4.exec()

            self.model = QtSql.QSqlTableModel(self.table_view) # 创建一个空的 QSqlTableModel 并将父级设置为父级,将数据库连接设置为 db。如果 db 无效,则将使用默认数据库连接。
            #model 用于装载变量
            self.model.setHeaderData(0, QtCore.Qt.Horizontal, '班号')
            self.model.setHeaderData(1, QtCore.Qt.Horizontal, '学号')
            self.model.setHeaderData(2, QtCore.Qt.Horizontal, '课程号')
            self.model.setHeaderData(3, QtCore.Qt.Horizontal, '成绩')

            search = self.text.text()
            self.model.setTable("sc")
            self.model.setFilter("sno = {}".format(search))
            self.model.select()
            self.table_view.setModel(self.model)#一定要写在所有设置完之后,装载数据

        elif(self.tablename=="c"):
            msgBox5 = QMessageBox()
            msgBox5.setText("查询表c")
            msgBox5.exec()

            self.model=QtSql.QSqlTableModel(self.table_view)
            #onfieldchange模型的任何更改都会返回到数据库
            self.model.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange)
            self.model.setHeaderData(0,QtCore.Qt.Horizontal,'课程号')
            self.model.setHeaderData(1,QtCore.Qt.Horizontal,'课程名')
            self.model.setHeaderData(2,QtCore.Qt.Horizontal,'先修课')
            self.model.setHeaderData(3,QtCore.Qt.Horizontal,'学分')

            search=self.text.text()
            self.model.setTable("c")
            self.model.setFilter("cno = {}".format(search))
            self.model.select()
            self.table_view.setModel(self.model)

        else:
            msgBox6=QMessageBox()
            msgBox6.setText("表暂且不属于实验范围,请更换!")
            msgBox6.exec_()

    def add_row_data(self):
        #不是直接操作QTableView,而是对model模型进行添加
        # 如果存在实例化的数据模型对象
        # self.model.insertRow(self.model.rowCount(),1)

        if self.model:
            #rowCount()得到行数,然后添加一行
            self.model.insertRows(self.model.rowCount(), 1)
            self.model.submitAll()#提交修改
        else:
            self.create_db()

    def del_row_data(self):
        if self.model:
            self.model.removeRow(self.table_view.currentIndex().row())
            self.model.submitAll()#提交修改
        else:
            self.create_db()

    def edit_row_data(self):
        if self.model:
            self.model.submitAll()#提交更改
        else:
            self.create_db()

    def backup_data(self):
        ori_file_name = r'D:\coding_programs\PythonPrograms\database_exp4\student.sqlite'  # 输入文件路径
        if os.path.isfile(ori_file_name):  # 判断该路径的是否是文件
            # 截取文件名,重组文件名
            seek_num = ori_file_name.rfind('.')
            new_file_name = ori_file_name[:seek_num] + '.bak'
            # 打开源文件
            old_file = open(ori_file_name, 'rb')
            # 读取文件信息
            old_file_content = old_file.read()
            # 创建新文件
            new_file = open(new_file_name, 'wb')
            # 将原始文件信息写入
            new_file.write(old_file_content)
            # 关闭文件
            old_file.close()
            new_file.close()
            print("backup success!")
            msgBox7 = QMessageBox()
            msgBox7.setText("student.bak数据文件已经备份")
            msgBox7.exec()
        else:
            print('没有该文件')

    def initUi(self):
        # 设置窗口标题
        self.setWindowTitle("刘看日的数据库实验四")
        # 设置窗口大小
        self.resize(600, 400)

        # 创建一个窗口部件
        self.widget = QtWidgets.QWidget()
        # 创建一个网格布局
        self.grid_layout = QtWidgets.QGridLayout()
        # 设置窗口部件的布局为网格布局
        self.widget.setLayout(self.grid_layout)

        # 创建一个工具组
        self.group_box = QtWidgets.QGroupBox('功能按钮')
        self.group_box_layout = QtWidgets.QVBoxLayout()
        self.group_box.setLayout(self.group_box_layout)


        #设置一个LineEdit窗口
        self.text=QtWidgets.QLineEdit()
        # 设置文本框的默认浮现文本
        self.text.setPlaceholderText("输入学号/课程号")

        self.table_view = QtWidgets.QTableView()
        # 按钮控件设置
        self.btn_create=QPushButton("连接表")
        self.btn_showall=QPushButton("展示全部数据")
        self.btn_search = QPushButton("基于学号/课程号查询")
        self.btn_close = QPushButton("退出")
        self.btn_delete=QPushButton("删除")
        self.btn_edit=QPushButton("修改")
        self.btn_add=QPushButton("添加")
        self.btn_backup = QPushButton("备份")

        # 添加按钮到group_box大组件中
        self.group_box_layout.addWidget(self.text)
        self.group_box_layout.addWidget(self.btn_create)
        self.group_box_layout.addWidget(self.btn_showall)
        self.group_box_layout.addWidget(self.btn_search)
        self.group_box_layout.addWidget(self.btn_add)
        self.group_box_layout.addWidget(self.btn_delete)
        self.group_box_layout.addWidget(self.btn_edit)
        self.group_box_layout.addWidget(self.btn_backup)
        self.group_box_layout.addWidget(self.btn_close)

        # 将上述两个部件添加到网格布局中
        self.grid_layout.addWidget(self.table_view, 0, 0)  # 放置表格位置在0
        self.grid_layout.addWidget(self.group_box, 0, 1)  # 放置
        # 创建按钮功能按钮
        self.btn_create.clicked.connect(self.create_db)
        self.btn_showall.clicked.connect(self.showall_tab)
        self.btn_search.clicked.connect(self.search_data)
        self.btn_close.clicked.connect(self.close)
        self.btn_add.clicked.connect(self.add_row_data)
        self.btn_delete.clicked.connect(self.del_row_data)
        self.btn_edit.clicked.connect(self.edit_row_data)
        self.btn_backup.clicked.connect(self.backup_data)
        # 设置UI界面的核心部件
        self.setCentralWidget(self.widget)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    gui = MainUi()
    gui.show()
    sys.exit(app.exec_())
  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
第六章 嵌入SQL(E-SQL)简介 3 第一节 什么是嵌入SQL语言? 3 1.1 嵌入SQL程序的组成元素 3 1.2 什么是静态SQL和动态SQL? 4 1.3 什么是SQLCA? 4 1.4 什么是SQLDA? 5 第二节 SYBASE SQL SERVER嵌入SQL语言 5 2.1 一个嵌入SQL语言的简单例子 5 2.2 嵌入SQL的处理过程 6 2.3 嵌入SQL语句总览 7 2.3.1 宿主变量 7 2.3.2 连接数据库 12 2.3.3 数据的查询和修改 13 2.3.4 游标的使用 13 2.3.5 SQLCA 15 2.3.6 WHENEVER 16 2.3.7 批处理 18 2.3.8 事务 18 2.4动态SQL语句 18 2.4 .1 动态修改 19 2.4.2 动态游标 20 2.4.3 SQLDA 23 2.4.4 DESCRIBE语句 27 2.5 两个例子程序 27 2.5.1 TELECOM程序 27 2.5.2 ADHOC程序 29 第三节 IBM DB2嵌入SQL语言 35 3.1 一个简单示例 35 3.2 嵌入SQL语句 37 3.2.1宿主变量 37 3.2.2单行查询 39 3.2.3多行查询 39 3.2.4插入、删除和修改操作 40 3.2.5 SQLCA 43 3.2.6事务 45 3.3 DB2的嵌入SQL程序处理过程 46 3.4 DB2的动态SQL嵌入语句 53 3.4.1 基本方法 53 3.4.2 动态游标 55 3.4.3 SQLDA 55 第四节 ORACLE数据库嵌入SQL语言 66 4.1 基本的SQL语句 66 4.1.1宿主变量和指示符 66 4.1.2 查询 68 4.1.3 修改数据 68 4.1.4 游标 68 4.2 嵌入PL/SQL 71 4.3 动态SQL语句 72 4.3.1 ORACLE动态SQL语句的一些特点 72 4.3.2 使用动态SQL的四种方法 72 4.3.3 SQLDA 75 第五节INFORMIX的嵌入SQL/C语言 89 5.1 一个简单的入门例子 89 5.2 宿主变量 91 5.3 嵌入SQL的处理过程 96 5.4 动态SQL语言 96 5.4.1 SQLDA 97 第六节MICROSOFT SQL SERVER7嵌入SQL语言 105 6.1 一个嵌入SQL语言的简单例子 105 6.2 嵌入SQL的处理过程 106 6.3 嵌入SQL语句 112 6.3.1 声明嵌入SQL语句中使用的C变量 112 6.3.2 连接数据库 115 6.3.3 数据的查询和修改 115 6.3.4 游标的使用 116 6.3.5 SQLCA 117 6.3.6 WHENEVER 118 6.4动态SQL语句 119 6.4 .1 动态修改 119 6.4.2 动态游标 120 6.4.3 SQLDA 122 6.4.4 DESCRIBE语句 130 6.5 API 130
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值