2020-07-03:简单的图书管理系统(Python、SQL Server)


一、课题设计的基本内容

经过对图书管理系统的分析,因图书数量、规模大,管理信息量大,建立图书管理系统是为了解决人工手动管理图书信息在实践的问题。这里把系统的层次划分为了四个部分:图书维护,人员信息管理,图书借阅管理,信息查询。通过需求分析所得的信息如下:

  1. 处理对象:
    读者信息:读者编号,姓名,性别,学号,学院,专业,年级,类型,类别编号,办证日期
    管理员信息:管理员编号,姓名,性别,电话
    馆藏图书信息:图书编号,图书名称,作者,出版社,单价,摘要,关键字,副本数,分类,出版日期,状态
    借阅信息:图书编号,读者编号,借阅日期,应还日期,罚金
    借阅历史信息:图书编号,读者编号,借阅日期,应还日期, 归还日期,罚金
    罚款信息:读者编号,图书编号,借阅日期,应还日期,归还日期,罚款金额,处理状态,管理员编号

  2. 处理功能及要求
    用户对图书管理系统的功能及要求如下:
    1)能够存储一定数量的图书信息,并方便有效的进行相应的书籍数据操作和管理,这主要包括:

     a) 进行新书入库、现有图书信息修改以及删除;
     b)能够实现对读者基本信息的查询和编辑管理;
     c)能够进行超期罚款功能;
     d)能够进行借阅信息的查询功能;
    

    2)能够对一定数量的读者、管理员进行相应的信息存储与管理,这其中包括:

     a)读者信息的登记、删除及修改。
     b)管理员信息的增加、删除及修改。
     c)读者资料的统计与查询。
    

    3)能够提供一定的安全机制,提供数据信息授权访问,防止随意删改、查询。
    4)对查询、统计的结果能够列表显示。

二、设计工具及系统运行环境

	Win10:操作系统
	Power designer:建立R-R模型
	SQL Server:建立数据库,编辑基本数据类
	Python:操作界面

三、数据库设计E-R模型

  1. 各E-R图各实体的属性如下所示:
    图书:Book(BookID,BookName,BookWriter,BookPublish,BookPrice,BookDate,BookClass,BookMain,BookPrim,BookCopy,BookState,BookRNo)
    读者:Reader(ReaID,ReaName,ReaSex,ReaNo,ReaLBID,ReaType,ReaDep,ReaGrade,ReaPref,ReaDate)
    管理员:Maneger (MID,MName,MSex,MTeleph)
    读者类别:ReaderTpye(LBID,LBName,LBnum,LBbqx,LBqx)
    馆室: Room(RoomNo,RoomMID,RoomNum,RoomAddre)
    借阅信息:Borrow(BookID,ReaderID,Outdate,Indate,YHdate,Fine,CLStaer,MID)
    罚款信息:Fine(BookID,ReaderID,Outdate,Indate,Fine)

在这里插入图片描述

四、软件主要功能设计(附上成品截图)

  1. 登录窗口:用户名为管理员id,密码为123456
在这里插入图片描述在这里插入图片描述
  1. 登录成功,进入操作界面
    在这里插入图片描述
    在这里插入图片描述

  2. 部分操作结果:
    1)增
    在这里插入图片描述
    在这里插入图片描述

    2)删
    在这里插入图片描述
    在这里插入图片描述

    3)查多

在这里插入图片描述
在这里插入图片描述

五、代码

  1. SQL Sever代码:

--数据库
create database BOOK;    --建立数据库


--表
use BOOK;

create table ReaderType     --读者类别
( 	LBID     char(5)  primarykey,--读者类别编号
	LBName  char(20)notnull,--读者类别名
	LBnum   char(5)  default(3),--允许借阅最大图书数
	LBbqx    char(4)  default(30),--持有图书最长期限
	LBqx     char(3)  notnull			--借阅证期限
)

create table Maneger   --管理员
( 
	MID   char(10)  primarykey,		--管理员编号
	MName char(10)  notnull,--姓名
	MSex  char(2) default('男'),--性别
	MTeleph char(15),					--电话
	check(MSex ='男'or MSex ='女'),
	check(len(MTeleph)=11 or len(MTeleph)=8 or len(MTeleph)=0)
)

createtable Room     --图书馆室
( 
	RoomNo    char(5)  primarykey,--馆室号
	RoomMID   char(10)notnull,--馆室管理员编号
	Roomnum   char(5),--拥有图书数
	RoomAddre  char(20),--馆室地址
	foreignkey(RoomMID)references Maneger(MID)
)


createtable Book      --馆藏图书
(  
	BookID      char(9)  primarykey,     --图书编号
	BookName  char(50)notnull,      --图书的书名
	BookWriter  char(30)notnull,    --作者
	BookPublish char(20)notnull,      --出版社
	BookPrice   char(7),     --单价
	BookDate    datetime,     --出版日期
	BookClass   char(20),  		--分类
	BookCopy   char(5),  		--副本数
	BookState   bit  notnull,  		--是否可借,1可借,0不可借
	BookRNo    char(5)  notnull,--图书所属馆室号
	foreignkey(BookRNo)references Room(RoomNo)
)


createtable Reader       --读者
( 
	ReadID       char(9)  primarykey,		--读者编号
	ReaName    char(10)notnull,--姓名
	ReaSex      char(2)default('男'),--性别
	ReaLBID     char(5)  default('l001'),--类别编号
	ReaDep      char(20),--所在学院
	foreignkey(ReaLBID)references ReaderType(LBID),check(ReaSex ='男'or ReaSex ='女'))

createtable Borrow     --借阅信息
(
	BookID		char(9),			--图书编号
	ReadID       char(9),			--读者编号
	Outdate		Datetime not null,		--借阅时间
	YHdate		Datetime not null,		--应还时间
	Indate		Datetime,		--归还时间
	Fine		char(5),		--罚款金额
	MID			char(10) not null,		--管理员编号 
	primary key(BookID,ReadID,Outdate),
	foreign key(BookID) references Book(BookID),
	foreign key(ReadID) references Reader(ReadID),
	foreign key(MID) references Maneger(MID)
)
go;



--视图
createview Bookview(图书编号, 书名, 作者, 出版社, 图书状态)--查询图书基本信息的视图
as
	select BookID,BookName,BookWriter,BookPublish,BookState 
	from Book
go


createview Readerview (读者姓名,学院)--读者基本信息查询的视图
as
	select ReaName,ReaDep
	from Reader
go


createview Borrowview (读者编号,书名,作者,借阅日期,到期日期)     --显示当前借阅基本信息的视图
asselect ReadID,BookName,BookWriter,Outdate,YHdate 
	from Borrow,Book 
	where Borrow.BookID=Book.BookID and Borrow.Indate isnull
go


createview Fineview (读者编号,书名,借阅日期,归还日期,罚款)--查询罚款信息的视图
asselect ReadID,BookName,Outdate,Indate,Fine
	from Borrow,Book 
	where Borrow.BookID=Book.BookID and Fine isnotnull
go


--触发器
--当删除Reader表中某一读者基本信息时,触发Borrow表,删除相应的记录 
createtrigger Reader_delete 
on Reader 
fordeleteas  
	begin
	delete Borrow 
	from deleted 
	where Borrow.ReadID=deleted.ReadID
	end
go


--当在Borrow中增加一条借阅记录时,使该图书的状态由“可借:0”变为“不可借:1” 
createtrigger Borrow_insert1 
on Borrow 
forinsertas  
	begin
	declare@BookIDchar(9)select@BookID=BookID 
	from inserted 

	update Book 
	set BookState=1where BookID=@BookID
	end
go

  1. Python代码:
    1)DB_TSGLXT_pypyodbc.py:对数据库的数据进行相关操作的函数包

    
    import pyodbc
    
    
    def connect(driver='{SQL Server}', server='localhost', user="sa", password="123456", database='BOOK'):
        try:
            # 连接数据库
            conn = pyodbc.connect(
                'DRIVER=' + driver + ';SERVER=' + server + ';DATABASE=' + database + ';UID=' + user + ';PWD=' + password)
            # autocommit=True,    # 如果插入数据,是否自动提交? 和conn.commit()功能一致。
            # 获得游标。
            cursor = conn.cursor()
        except Exception as e:
            print(e)
        return conn, cursor
    
    def close(conn):
        conn.close()
    
    # 返回执行execute()方法后影响的行数 
    def execute(cursor, sql):
        cursor.execute(sql)
        rowcount = cursor.rowcount
        return rowcount
    
    
    # 新增并返回新增ID
    def insert(conn, cursor, *kwarg):  # table=,  fields(键:列)=values(值:列对应的值)
        # 可变参数:*kwarg(一个元组), **kwarg(可变关键字参数,kwargs是一个dict)
    
        # dict(zip(index, values)) 将列表index和day变成一个字典
        # 将字典的key转换成列表 index=list(dict)
        # 将字典的value转换成列表 values = list(dit.values())
        kwargs = dict(zip(kwarg[0], kwarg[1]))
        table = kwargs['table']
        # kwargs.pop('table')
        del kwargs['table']  # 字典对象的删除
        sql = 'insert into %s(' % table
        fields = ""
        values = ""
        for k, v in kwargs.items():  # items()  返回键-值对
            fields += "%s," % k  # 键:列
            values += "'%s'," % v  # 值:列对应的值
        fields = fields.rstrip(',')  # 去除后面的空白字符
        values = values.rstrip(',')
        sql = sql + fields + ")values(" + values + ")"
        print(sql)
        # insert into 表名(列名)
        # values(列对应的值)
    
        res = 0
        try:
            # 首次获取id
            res = cursor.lastrowid
            # 执行SQL语句
            cursor.execute(sql)
            # 提交到数据库执行
            conn.commit()
            # 二次获取id
            res -= cursor.lastrowid
        except:
            # 发生错误时回滚
            conn.rollback()
        return res
    
    
    # 删除并返回影响行数
    def delete(conn, cursor, *kwarg):  # table=,where=
        kwargs = dict(zip(kwarg[0], kwarg[1]))
    
        table = kwargs['table']
        where = kwargs['where']
    
        sql = 'DELETE FROM %s where %s' % (table, where)
        print(sql)
    
        rowcount = 0
        try:
            # 执行SQL语句
            cursor.execute(sql)
            # 提交到数据库执行
            conn.commit()
            # 影响的行数
            rowcount = cursor.rowcount
        except:
            # 发生错误时回滚
            conn.rollback()
        return rowcount
    
    
    # 修改数据并返回影响的行数
    def update(conn, cursor, *kwarg):  # table=,  fields(键:列)=values(值:列对应的值)  ,where=
        kwargs = dict(zip(kwarg[0], kwarg[1]))
        table = kwargs['table']
        kwargs.pop('table')
        where = kwargs['where']
        kwargs.pop('where')
        sql = 'update %s set ' % table
        for k, v in kwargs.items():
            sql += "%s='%s'," % (k, v)
        sql = sql.rstrip(',')
        sql += ' where %s' % where
        print(sql)
        # update 表名
        # set 列名=x
        # where 条件
    
        rowcount = 0
        try:
            # 执行SQL语句
            cursor.execute(sql)
            # 提交到数据库执行
            conn.commit()
            # 影响的行数
            rowcount = cursor.rowcount
        except:
            # 发生错误时回滚
            conn.rollback()
        return rowcount
    
    
    # 查-一条条数据   res = dbObject.fetchone(table='user',where="name='cccc'")
    def selectTopone(conn, cursor, *kwarg):  # table=,fields(列)=null(*),where="x='y'",order='x asc/desc'
        kwargs = dict(zip(kwarg[0], kwarg[1]))
        table = kwargs['table']
        field = 'field' in kwargs and kwargs['field'] or '*'  # 如果kwargs(键)中有field,则field=kwargs['field'],否则field='*'
        where = 'where' in kwargs and 'where ' + kwargs['where'] or ''  # where,group by,order by不一定有
        group = 'group' in kwargs and 'group by ' + kwargs['group'] or '' \
                + 'group' in kwargs and ('having' in kwargs and ' having ' + kwargs['having'] or '')
        # having是在group存在的前提下存在
    
        order = 'order' in kwargs and 'order by ' + kwargs['order'] or ''
        sql = 'select top 1 %s from %s %s %s %s %s ' % (field, table, where, group, order)
        print(sql)
        # select top 1 [列名]|[*]
        # from 表名
        # [where 条件]
        # [order by ]
    
        data = []
        try:
            # 执行SQL语句
            cursor.execute(sql)
            # 使用 fetchone() 方法获取单条数据.
            data = cursor.fetchone()
        except:
            # 发生错误时回滚
            conn.rollback()
        return data
    
    
    # order by field(str,str1,str2,str3,str4……),str与str1,str2,str3,str4比较,其中str指的是字段名字,
    # 意为:字段str按照字符串str1,str2,str3,str4的顺序返回查询到的结果集。
    #       如果表中str字段值不存在于str1,str2,str3,str4中的记录,放在结果集最前面返回。
    
    # 查所有数据    res = dbObject.fetchall(table='user',order="id desc")
    def selectAll(conn, cursor, *kwarg):
        # print(kwarg)
        kwargs = dict(zip(kwarg[0], kwarg[1]))
        table = kwargs['table']
        field = 'field' in kwargs and kwargs['field'] or '*'
        where = 'where' in kwargs and 'where ' + kwargs['where'] or ''
        group = 'group' in kwargs and 'group by ' + kwargs['group'] or '' \
                + 'having' in kwargs and 'having ' + kwargs['having'] or ''
        order = 'order' in kwargs and 'order by ' + kwargs['order'] or ''
        sql = 'select %s from %s %s %s %s ' % (field, table, where, group, order)
        print(sql)
        # select [列名]|[*]
        # from 表名
        # [where 条件]
        # [order by ]
    
        try:
            # 执行SQL语句
            cursor.execute(sql)
            # 使用 fetchone() 方法获取单条数据.
            data = cursor.fetchall()
    
        except:
            # 发生错误时回滚
            conn.rollback()
        # print(22, data)
        return data
    
    

    上面代码的链接:DB_TSGLXT_pypyodbc文件完整代码的链接
    参考了文章:Python操作SQL Server类封装

    2)DB_GUI.py:界面代码

    DB_GUI文件完整代码的链接


版权声明:本文为qq_45913057原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。