Python+MySQL图书管理系统数据库设计(分析+源码)

1 绪论

在信息化时代,图书管理工作面临着数据量激增、管理效率要求提高等挑战。传统的手工管理方式已难以满足现代图书馆的运营需求,迫切需要借助数据库技术构建高效的图书管理系统。该系统旨在实现图书信息、读者信息、借阅记录等数据的系统化管理,提升图书借阅、归还、查询等业务的处理效率,为读者提供便捷的服务,同时为图书馆管理人员提供科学的数据支持,优化资源配置和管理流程。

2 需求分析

2.1 读者需求

能够便捷地查询图书信息,包括书名、作者、出版社、ISBN 号、馆藏位置等。
可进行图书借阅、续借和归还操作,并了解借阅期限、应还日期等信息。
查看个人借阅记录,包括已借阅图书、历史借阅记录等。
接收图书到期提醒、预约到书通知等信息。

2.2 图书馆管理人员需求

对图书信息进行管理,包括图书的添加、修改、删除和更新,如录入新书信息、修改图书状态等。
管理读者信息,包括读者注册、信息更新、注销等。
处理图书借阅、归还业务,记录借阅信息,办理续借、预约等手续。
统计和分析图书借阅数据,如热门图书统计、读者借阅频率分析等,为图书采购和管理决策提供依据。
对系统数据进行备份和维护,确保数据安全和系统正常运行。

2.3 系统功能需求

图书信息管理模块:实现图书基础信息的存储和管理。
读者信息管理模块:管理读者的个人信息和借阅权限。
借阅服务模块:处理图书的借阅、归还、续借、预约等业务流程。
信息查询模块:提供多条件的图书和借阅信息查询功能。
统计分析模块:对借阅数据进行统计和分析,生成相关报表。
系统管理模块:包括用户权限管理、数据备份与恢复等功能。

3 概念与逻辑设计

3.1 用例图

3.2 数据库模型

3.2.1 图书表(Book)

主码:BookID(图书编号)
字段

BookID:varchar (20),图书唯一标识
BookName:varchar (100),图书名称
Author:varchar (50),作者
Publisher:varchar (50),出版社
PublishDate:date,出版日期
ISBN:varchar (20),国际标准书号
CategoryID:int,图书类别编号
Location:varchar (50),馆藏位置
TotalCount:int,总藏书量
AvailableCount:int,可借阅数量
Price:decimal (10,2),价格
Status:varchar (20),图书状态(如可借、已借出、损坏等)

外码:CategoryID,参照图书类别表(Category)的 CategoryID

3.2.2 读者表(Reader)

主码:ReaderID(读者编号)
字段

ReaderID:varchar (20),读者唯一标识
ReaderName:varchar (50),读者姓名
Gender:char (2),性别
Age:int,年龄
IDCard:varchar (20),身份证号
Phone:varchar (20),联系电话
Email:varchar (50),电子邮箱
Address:varchar (100),联系地址
ReaderType:varchar (20),读者类型(如学生、教师、职工等)
RegisterDate:date,注册日期
Status:varchar (20),读者状态(如正常、挂失、注销等)

外码:无

3.2.3 借阅记录表(BorrowRecord)

主码:RecordID(记录编号)
字段

RecordID:varchar (30),记录唯一标识
BookID:varchar (20),图书编号
ReaderID:varchar (20),读者编号
BorrowDate:date,借阅日期
ReturnDate:date,应还日期
ActualReturnDate:date,实际归还日期
Fine:decimal (10,2),罚款金额(如有)
Status:varchar (20),借阅状态(如借阅中、已归还、逾期等)

外码

BookID,参照图书表(Book)的 BookID
ReaderID,参照读者表(Reader)的 ReaderID

3.2.4 图书类别表(Category)

主码:CategoryID(类别编号)
字段

CategoryID:int,类别唯一标识
CategoryName:varchar (50),类别名称
Description:varchar (200),类别描述

外码:无

3.2.5 预约表(Reservation)

主码:ReservationID(预约编号)
字段

ReservationID:varchar (30),预约唯一标识
BookID:varchar (20),图书编号
ReaderID:varchar (20),读者编号
ReservationDate:date,预约日期
Status:varchar (20),预约状态(如预约中、已取消、已通知等)

外码

BookID,参照图书表(Book)的 BookID
ReaderID,参照读者表(Reader)的 ReaderID

4 物理设计(数据库设计)

4.1 图书表(Book)

字段名

数据类型

长度

允许空

主键

外键

描述

BookID

varchar

20

图书唯一编号

BookName

varchar

100

图书名称

Author

varchar

50

作者

Publisher

varchar

50

出版社

PublishDate

date

出版日期

ISBN

varchar

20

国际标准书号

CategoryID

int

图书类别编号,参照 Category 表的 CategoryID

Location

varchar

50

馆藏位置

TotalCount

int

总藏书量

AvailableCount

int

可借阅数量

Price

decimal

10,2

价格

Status

varchar

20

图书状态

4.2 读者表(Reader)

字段名

数据类型

长度

允许空

主键

外键

描述

ReaderID

varchar

20

读者唯一编号

ReaderName

varchar

50

读者姓名

Gender

char

2

性别

Age

int

年龄

IDCard

varchar

20

身份证号

Phone

varchar

20

联系电话

Email

varchar

50

电子邮箱

Address

varchar

100

联系地址

ReaderType

varchar

20

读者类型

RegisterDate

date

注册日期

Status

varchar

20

读者状态

4.3 借阅记录表(BorrowRecord)

字段名

数据类型

长度

允许空

主键

外键

描述

RecordID

varchar

30

借阅记录唯一编号

BookID

varchar

20

图书编号,参照 Book 表的 BookID

ReaderID

varchar

20

读者编号,参照 Reader 表的 ReaderID

BorrowDate

date

借阅日期

ReturnDate

date

应还日期

ActualReturnDate

date

实际归还日期

Fine

decimal

10,2

罚款金额

Status

varchar

20

借阅状态

4.4 图书类别表(Category)

字段名

数据类型

长度

允许空

主键

外键

描述

CategoryID

int

类别唯一编号

CategoryName

varchar

50

类别名称

Description

varchar

200

类别描述

4.5 预约表(Reservation)

字段名

数据类型

长度

允许空

主键

外键

描述

ReservationID

varchar

30

预约唯一编号

BookID

varchar

20

图书编号,参照 Book 表的 BookID

ReaderID

varchar

20

读者编号,参照 Reader 表的 ReaderID

ReservationDate

date

预约日期

Status

varchar

20

预约状态

5 代码链接(这里只做图书的增删改查操作)

import mysql.connector
from mysql.connector import Error
from prettytable import PrettyTable
import sys

class BookManagementSystem:
    def __init__(self, host="localhost", user="root", password="123456", database="book_management"):
        """初始化MySQL数据库连接"""
        self.conn = mysql.connector.connect(
            host=host,
            user=user,
            password=password,
            database=database
        )
        self.cursor = self.conn.cursor()
        print("成功连接到数据库")
    
    def add_book(self):
        """添加图书(交互式)"""
        print("
=== 添加图书 ===")
        book_id = input("请输入图书ID: ")
        book_name = input("请输入书名: ")
        author = input("请输入作者: ")
        publisher = input("请输入出版社: ")
        publish_date = input("请输入出版日期 (YYYY-MM-DD): ")
        isbn = input("请输入ISBN: ")
        category_id = input("请输入类别ID: ")
        location = input("请输入馆藏位置: ")
        total_count = int(input("请输入总藏书量: "))
        available_count = int(input("请输入可借数量: "))
        price = float(input("请输入价格: "))
        status = input("请输入状态 (可借/已借出): ")
        
        book_info = (book_id, book_name, author, publisher, publish_date, 
                    isbn, category_id, location, total_count, available_count, price, status)
        
        sql = '''
        INSERT INTO Book (BookID, BookName, Author, Publisher, PublishDate, 
                          ISBN, CategoryID, Location, TotalCount, AvailableCount, Price, Status)
        VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
        '''
        try:
            self.cursor.execute(sql, book_info)
            self.conn.commit()
            print("图书添加成功")
            return True
        except Error as e:
            self.conn.rollback()
            print(f"添加失败: {e}")
            return False
    
    def update_book(self):
        """更新图书信息(交互式)"""
        print("
=== 更新图书 ===")
        book_id = input("请输入要更新的图书ID: ")
        
        # 获取当前图书信息
        current_book = self.get_book(book_id)
        if not current_book:
            return False
            
        print("
当前图书信息:")
        self.display_book(current_book)
        
        print("
请输入要更新的字段(直接回车跳过)")
        update_fields = {}
        
        book_name = input(f"书名 [{current_book[1]}]: ")
        if book_name:
            update_fields["BookName"] = book_name
            
        author = input(f"作者 [{current_book[2]}]: ")
        if author:
            update_fields["Author"] = author
            
        publisher = input(f"出版社 [{current_book[3]}]: ")
        if publisher:
            update_fields["Publisher"] = publisher
            
        publish_date = input(f"出版日期 [{current_book[4]}]: ")
        if publish_date:
            update_fields["PublishDate"] = publish_date
            
        isbn = input(f"ISBN [{current_book[5]}]: ")
        if isbn:
            update_fields["ISBN"] = isbn
            
        category_id = input(f"类别ID [{current_book[6]}]: ")
        if category_id:
            update_fields["CategoryID"] = category_id
            
        location = input(f"馆藏位置 [{current_book[7]}]: ")
        if location:
            update_fields["Location"] = location
            
        total_count = input(f"总藏书量 [{current_book[8]}]: ")
        if total_count:
            update_fields["TotalCount"] = int(total_count)
            
        available_count = input(f"可借数量 [{current_book[9]}]: ")
        if available_count:
            update_fields["AvailableCount"] = int(available_count)
            
        price = input(f"价格 [{current_book[10]}]: ")
        if price:
            update_fields["Price"] = float(price)
            
        status = input(f"状态 [{current_book[11]}]: ")
        if status:
            update_fields["Status"] = status
            
        if not update_fields:
            print("未输入任何更新内容,操作取消")
            return False
            
        set_clause = ", ".join([f"{key} = %s" for key in update_fields.keys()])
        values = tuple(update_fields.values()) + (book_id,)
        sql = f"UPDATE Book SET {set_clause} WHERE BookID = %s"
        
        try:
            self.cursor.execute(sql, values)
            if self.cursor.rowcount > 0:
                self.conn.commit()
                print("图书更新成功")
                return True
            print(f"未找到ID为{book_id}的图书")
            return False
        except Error as e:
            self.conn.rollback()
            print(f"更新失败: {e}")
            return False
    
    def delete_book(self):
        """删除图书(交互式)"""
        print("
=== 删除图书 ===")
        book_id = input("请输入要删除的图书ID: ")
        
        # 检查借阅记录
        self.cursor.execute("SELECT COUNT(*) FROM BorrowRecord WHERE BookID = %s", (book_id,))
        if self.cursor.fetchone()[0] > 0:
            print(f"图书ID {book_id} 存在借阅记录,无法删除")
            return False
        
        confirm = input(f"确定要删除图书ID为 {book_id} 的记录吗?(y/n): ")
        if confirm.lower() != 'y':
            print("操作已取消")
            return False
            
        sql = "DELETE FROM Book WHERE BookID = %s"
        try:
            self.cursor.execute(sql, (book_id,))
            if self.cursor.rowcount > 0:
                self.conn.commit()
                print("图书删除成功")
                return True
            print(f"未找到ID为{book_id}的图书")
            return False
        except Error as e:
            self.conn.rollback()
            print(f"删除失败: {e}")
            return False
    
    def get_book(self, book_id=None):
        """查询图书(支持查询单本或所有图书)"""
        if book_id:
            sql = "SELECT * FROM Book WHERE BookID = %s"
            params = (book_id,)
        else:
            sql = "SELECT * FROM Book"
            params = ()
            
        try:
            self.cursor.execute(sql, params)
            if book_id:
                book = self.cursor.fetchone()
                return book
            else:
                books = self.cursor.fetchall()
                return books
        except Error as e:
            print(f"查询失败: {e}")
            return None
    
    def list_books(self):
        """列出所有图书"""
        print("
=== 图书列表 ===")
        books = self.get_book()
        if not books:
            print("图书馆暂无藏书")
            return
            
        table = PrettyTable()
        table.field_names = ["图书ID", "书名", "作者", "出版社", "出版日期", "ISBN", "类别ID", "馆藏位置", "总藏书量", "可借数量", "价格", "状态"]
        
        for book in books:
            table.add_row([book[0], book[1], book[2], book[3], book[4], book[5], book[6], book[7], book[8], book[9], f"¥{book[10]}", book[11]])
            
        print(table)
    
    def search_books(self):
        """按条件搜索图书"""
        print("
=== 搜索图书 ===")
        keyword = input("请输入搜索关键词(书名或作者): ")
        
        sql = "SELECT * FROM Book WHERE BookName LIKE %s OR Author LIKE %s"
        params = (f"%{keyword}%", f"%{keyword}%")
        
        try:
            self.cursor.execute(sql, params)
            books = self.cursor.fetchall()
            
            if books:
                table = PrettyTable()
                table.field_names = ["图书ID", "书名", "作者", "出版社", "出版日期", "ISBN", "类别ID", "馆藏位置", "总藏书量", "可借数量", "价格", "状态"]
                
                for book in books:
                    table.add_row([book[0], book[1], book[2], book[3], book[4], book[5], book[6], book[7], book[8], book[9], f"¥{book[10]}", book[11]])
                    
                print(table)
            else:
                print(f"未找到包含关键词 '{keyword}' 的图书")
                
        except Error as e:
            print(f"搜索失败: {e}")
    
    def display_book(self, book):
        """格式化显示单本图书信息"""
        if not book:
            print("未找到图书")
            return
            
        table = PrettyTable()
        table.field_names = ["字段", "值"]
        table.add_row(["图书ID", book[0]])
        table.add_row(["书名", book[1]])
        table.add_row(["作者", book[2]])
        table.add_row(["出版社", book[3]])
        table.add_row(["出版日期", book[4]])
        table.add_row(["ISBN", book[5]])
        table.add_row(["类别ID", book[6]])
        table.add_row(["馆藏位置", book[7]])
        table.add_row(["总藏书量", book[8]])
        table.add_row(["可借数量", book[9]])
        table.add_row(["价格", f"¥{book[10]}"])
        table.add_row(["状态", book[11]])
        
        print(table)
    
    def close(self):
        """关闭数据库连接"""
        if self.conn.is_connected():
            self.cursor.close()
            self.conn.close()
            print("数据库连接已关闭")


def show_menu():
    """显示主菜单"""
    print("
" + "="*30)
    print("  图书管理系统")
    print("="*30)
    print("1. 添加图书")
    print("2. 更新图书信息")
    print("3. 删除图书")
    print("4. 查看图书列表")
    print("5. 搜索图书")
    print("0. 退出系统")
    print("="*30)


if __name__ == "__main__":
    # 初始化系统
    system = BookManagementSystem(
        host="localhost",
        user="root",
        password="123456",
        database="book_management"
    )
    
    try:
        while True:
            show_menu()
            choice = input("请输入您的选择: ")
            
            if choice == "1":
                system.add_book()
            elif choice == "2":
                system.update_book()
            elif choice == "3":
                system.delete_book()
            elif choice == "4":
                system.list_books()
            elif choice == "5":
                system.search_books()
            elif choice == "0":
                print("感谢使用图书管理系统,再见!")
                break
            else:
                print("无效的选择,请重新输入")
                
    finally:
        system.close()

总结

在本次数据库综合实验中,完成了图书管理系统的设计与实现。从需求分析出发,明确了读者对图书查询、借阅等操作的需求,以及管理人员对图书和读者信息管理、数据统计的需求,据此构建了包含图书、读者、借阅记录等表的数据库模型,通过外键关联确保数据完整性。

在代码实现上,使用 Python 连接 MySQL 数据库,实现了图书的增删改查等功能,以交互式菜单提升操作便捷性。过程中解决了外键约束冲突、输入验证等问题,例如删除图书前检查借阅记录,避免数据不一致。

技术层面,体会到数据库设计需遵循范式原则,合理设置字段类型与约束。代码模块化设计便于维护,异常处理机制保障系统稳定性。同时,也认识到存在性能优化空间,如为高频查询字段添加索引,后续可引入连接池、存储过程等提升效率。

此次实验将理论知识与实践结合,深入理解了数据库设计的核心要点,也意识到实际开发中需兼顾功能与性能。未来可扩展权限管理、数据可视化等功能,开发 GUI 界面提升用户体验,为系统应用于实际场景奠定基础。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容