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("\n=== 添加图书 ===")
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("\n=== 更新图书 ===")
book_id = input("请输入要更新的图书ID: ")
# 获取当前图书信息
current_book = self.get_book(book_id)
if not current_book:
return False
print("\n当前图书信息:")
self.display_book(current_book)
print("\n请输入要更新的字段(直接回车跳过)")
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("\n=== 删除图书 ===")
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("\n=== 图书列表 ===")
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("\n=== 搜索图书 ===")
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("\n" + "="*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()
字段名 |
数据类型 |
长度 |
允许空 |
主键 |
外键 |
描述 |
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 |
否 |
否 |
否 |
图书状态 |
字段名 |
数据类型 |
长度 |
允许空 |
主键 |
外键 |
描述 |
ReaderID |
varchar |
20 |
否 |
是 |
否 |
读者唯一编号 |
ReaderName |
varchar |
50 |
否 |
否 |
否 |
读者姓名 |
Gender |
char |
2 |
否 |
否 |
否 |
性别 |
Age |
int |
- |
是 |
否 |
否 |
年龄 |
IDCard |
varchar |
20 |
否 |
否 |
否 |
身份证号 |
Phone |
varchar |
20 |
是 |
否 |
否 |
联系电话 |
|
varchar |
50 |
是 |
否 |
否 |
电子邮箱 |
Address |
varchar |
100 |
是 |
否 |
否 |
联系地址 |
ReaderType |
varchar |
20 |
否 |
否 |
否 |
读者类型 |
RegisterDate |
date |
- |
否 |
否 |
否 |
注册日期 |
Status |
varchar |
20 |
否 |
否 |
否 |
读者状态 |
字段名 |
数据类型 |
长度 |
允许空 |
主键 |
外键 |
描述 |
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 |
否 |
否 |
否 |
借阅状态 |
字段名 |
数据类型 |
长度 |
允许空 |
主键 |
外键 |
描述 |
CategoryID |
int |
- |
否 |
是 |
否 |
类别唯一编号 |
CategoryName |
varchar |
50 |
否 |
否 |
否 |
类别名称 |
Description |
varchar |
200 |
是 |
否 |
否 |
类别描述 |
字段名 |
数据类型 |
长度 |
允许空 |
主键 |
外键 |
描述 |
ReservationID |
varchar |
30 |
否 |
是 |
否 |
预约唯一编号 |
BookID |
varchar |
20 |
否 |
否 |
是 |
图书编号,参照 Book 表的 BookID |
ReaderID |
varchar |
20 |
否 |
否 |
是 |
读者编号,参照 Reader 表的 ReaderID |
ReservationDate |
date |
- |
否 |
否 |
否 |
预约日期 |
Status |
varchar |
20 |
否 |
否 |
否 |
预约状态 |