1. 图书馆管理系统

姓名 主要完成的工作 备注

2. 需求分析

1.1 基础信息管理模块 书架类型管理:通过shelf_types 表定义书架类型(如 “文学类”“科技类” 等),便于分类管理书架。 读者类型管理:利用reader_types 表区分读者类型(如 “学生”“教师”“普通读者”),可用于设定不同的借阅权限(如借阅时长、可借数量等)。 1.2 资源与设施管理模块 对图书馆的物理资源(书架、图书)和人力资源(工作人员)进行管理。 书架管理:shelves表记录书架编号、类型及所属类型 ID,关联书架类型表,实现书架的分类定位和状态跟踪。 图书管理:books表存储图书的核心信息,包括书名、作者、ISBN、出版年份及所在书架 ID,通过 ISBN 唯一性约束避免重复录入,通过书架 ID 关联书架表,实现图书的定位管理。 工作人员管理:staff 表记录工作人员的姓名、职位等信息,用于后续业务操作的责任追溯(如图书位置变更记录中的 changed_by 字段)。 1.3 读者管理模块 管理读者的基本信息和借阅权限。 读者档案管理:readers 表存储读者姓名、类型、联系电话等信息,通过读者类型 ID 关联读者类型表,支持差异化服务(如学生读者可借阅更多书籍)。 联系信息维护:新增的contact_phone 字段便于图书馆发送借阅通知或逾期提醒。 1.4 借阅业务管理模块 覆盖图书借阅的全流程,从借阅、续借到归还的自动化管理。 借阅管理:loans 表记录借阅记录,包含借阅图书 ID、读者 ID、借阅日期及应还日期( due_date ),通过外键关联图书和读者表,确保业务数据的一致性。 归还管理:returns 表记录归还信息,通过 loan_id 关联借阅记录,记录归还日期,用于统计借阅时长和图书流通率。 逾期管理:overdue_notifications 表自动生成逾期通知记录,包含通知日期、读者 ID 和提醒信息,支持定时触发通知机制(如短信、邮件),提升催还效率。 1.5 数据跟踪与审计模块 用于记录业务操作的历史轨迹,便于追溯和数据分析。 图书位置变更记录:book_location_history 表跟踪图书的移动记录,记录旧书架 ID、新书架 ID、变更日期及操作人(工作人员 ID),帮助管理员追溯图书位置变化,优化书架布局。 操作审计:通过历史记录表和通知记录表,可统计工作人员的操作日志(如图书移位)和读者的借阅行为(如逾期次数),为管理决策提供数据支持。。

3. 系统设计

3.1. 系统结构功能图

根据需求分析,确定系统结构功能如图2-1所示:

图2-1 系统功能结构图

3.2. 功能流程图

系统最主要的功能就是管理员登录之后对各种功能的使用。管理员登录过程流程如图4-2所示。

图2-2 借阅还书流程

3.3. 数据库设计

整体功能的E-R图如图2-3所示。

画板

图2-3 系统E-R图

本系统包含的数据表如下:

1**书架类型表** (shelf_types)

列名 数据类型 字段类型 长度 是否为空 默认值 备注
shelf_type_id NUMBER 主键 - - 书架类型ID
shelf_type_name VARCHAR2 非空 50 - 书架类型名称

2**读者类型表** (reader_types)

列名 数据类型 字段类型 长度 是否为空 默认值 备注
reader_type_id NUMBER 主键 - - 读者类型ID
reader_type_name VARCHAR2 非空 50 - 读者类型名称

3**书架表** (shelves)

列名 数据类型 字段类型 长度 是否为空 默认值 备注
shelf_id NUMBER 主键 - - 书架ID
shelf_number VARCHAR2 非空 20 - 书架编号
shelf_type_id NUMBER 外键且非空 - - 书架类型ID

4**工作人员表** (staff)

列名 数据类型 字段类型 长度 是否为空 默认值 备注
staff_id NUMBER 主键 - - 工作人员ID
staff_name VARCHAR2 非空 100 - 工作人员姓名
staff_position VARCHAR2 非空 50 - 工作人员职位

5**图书表** (books)

列名 数据类型 字段类型 长度 是否为空 默认值 备注
book_id NUMBER 主键 - - 图书ID
title VARCHAR2 非空 200 - 图书标题
author VARCHAR2 非空 100 - 图书作者
isbn VARCHAR2 唯一且非空 20 - 图书国际标准书号
publication_year NUMBER 可空 - - 出版年份
shelf_id NUMBER 外键且非空 - - 书架ID

6**读者表** (readers)

列名 数据类型 字段类型 长度 是否为空 默认值 备注
reader_id NUMBER 主键 - - 读者ID
reader_name VARCHAR2 非空 100 - 读者姓名
reader_type_id NUMBER 外键且非空 - - 读者类型ID
contact_phone VARCHAR2 可空 15 - 联系电话

7**正借阅表** (loans)

列名 数据类型 字段类型 长度 是否为空 默认值 备注
loan_id NUMBER 主键 - - 借阅记录ID
book_id NUMBER 外键且非空 - - 图书ID
reader_id NUMBER 外键且非空 - - 读者ID
loan_date DATE 非空 - - 借书日期
due_date DATE 非空 - - 应还日期

8**已还书籍表** (returns)

列名 数据类型 字段类型 长度 是否为空 默认值 备注
return_id NUMBER 主键 - - 还书记录ID
loan_id NUMBER 外键 - - 借阅记录ID
return_date DATE 非空 - - 还书日期

9**通知记录表(overdue_notifications)**

列名 数据类型 字段类型 长度 是否为空 默认值 备注
notification_id NUMBER 主键 - - 通知记录
loan_id NUMBER 外键 - - 借阅记录 ID
reader_id NUMBER 外键 - - 读者 ID
notification_date DATE 日期 - SYSDATE 通知日期
message VARCHAR2 字符串 500 - 通知内容

10**历史记录表(book_location_history)**

列名 数据类型 字段类型 长度 是否为空 默认值 备注
history_id NUMBER 主键 - - 历史记录
book_id NUMBER 外键 - - 图书 ID
old_shelf_id NUMBER 外键 - - 旧书架 ID
new_shelf_id NUMBER 外键 - - 新书架 ID
change_date DATE 日期 - SYSDATE 变更日期
changed_by NUMBER 外键 - - 操作人 ID

4. 3 SQL**实现

4.1. 3.1创建数据库表对象

-- 书架类型表
CREATE TABLE shelf_types (
shelf_type_id NUMBER PRIMARY KEY,
shelf_type_name VARCHAR2(50) NOT NULL
);

-- 读者类型表
CREATE TABLE reader_types (
reader_type_id NUMBER PRIMARY KEY,
reader_type_name VARCHAR2(50) NOT NULL
);

-- 书架表 (添加NOT NULL约束)
CREATE TABLE shelves (
shelf_id NUMBER PRIMARY KEY,
shelf_number VARCHAR2(20) NOT NULL,
shelf_type_id NUMBER NOT NULL,
FOREIGN KEY (shelf_type_id) REFERENCES shelf_types(shelf_type_id)
);

-- 工作人员表
CREATE TABLE staff (
staff_id NUMBER PRIMARY KEY,
staff_name VARCHAR2(100) NOT NULL,
staff_position VARCHAR2(50) NOT NULL
);

-- 图书表 (添加出版年份和NOT NULL约束)
CREATE TABLE books (
book_id NUMBER PRIMARY KEY,
title VARCHAR2(200) NOT NULL,
author VARCHAR2(100) NOT NULL,
isbn VARCHAR2(20) UNIQUE NOT NULL,
publication_year NUMBER, -- 新增出版年份
shelf_id NUMBER NOT NULL, -- 添加NOT NULL约束
FOREIGN KEY (shelf_id) REFERENCES shelves(shelf_id)
);

-- 读者表 (添加联系电话和NOT NULL约束)
CREATE TABLE readers (
reader_id NUMBER PRIMARY KEY,
reader_name VARCHAR2(100) NOT NULL,
reader_type_id NUMBER NOT NULL, -- 添加NOT NULL约束
contact_phone VARCHAR2(15), -- 新增联系电话
FOREIGN KEY (reader_type_id) REFERENCES reader_types(reader_type_id)
);

-- 正借阅表 (添加应还日期)
CREATE TABLE loans (
loan_id NUMBER PRIMARY KEY,
book_id NUMBER NOT NULL,
reader_id NUMBER NOT NULL,
loan_date DATE NOT NULL,
due_date DATE NOT NULL, -- 新增应还日期
FOREIGN KEY (book_id) REFERENCES books(book_id),
FOREIGN KEY (reader_id) REFERENCES readers(reader_id)
);

-- 已还表
CREATE TABLE returns (
return_id NUMBER PRIMARY KEY,
loan_id NUMBER,
return_date DATE NOT NULL,
FOREIGN KEY (loan_id) REFERENCES loans(loan_id)
);
-- 创建通知记录表
CREATE TABLE overdue_notifications (
notification_id NUMBER PRIMARY KEY,
loan_id NUMBER NOT NULL,
reader_id NUMBER NOT NULL,
notification_date DATE DEFAULT SYSDATE,
message VARCHAR2(500),
FOREIGN KEY (loan_id) REFERENCES loans(loan_id),
FOREIGN KEY (reader_id) REFERENCES readers(reader_id)
);

-- 创建历史记录表
CREATE TABLE book_location_history (
history_id NUMBER PRIMARY KEY,
book_id NUMBER NOT NULL,
old_shelf_id NUMBER,
new_shelf_id NUMBER NOT NULL,
change_date DATE DEFAULT SYSDATE,
changed_by NUMBER, -- 工作人员ID
FOREIGN KEY (book_id) REFERENCES books(book_id),
FOREIGN KEY (old_shelf_id) REFERENCES shelves(shelf_id),
FOREIGN KEY (new_shelf_id) REFERENCES shelves(shelf_id),
FOREIGN KEY (changed_by) REFERENCES staff(staff_id)
);

4.2. 3.2**创建索引**

-- 创建索引提升查询性能
CREATE INDEX idx_books_isbn ON books(isbn);
CREATE INDEX idx_books_title ON books(title);
CREATE INDEX idx_readers_name ON readers(reader_name);
CREATE INDEX idx_loans_dates ON loans(loan_date, due_date);
CREATE INDEX idx_returns_date ON returns(return_date);

4.3. 3.3创建视图

-- 借阅详情视图:显示所有借阅记录及归还状态
CREATE VIEW loan_details AS
SELECT
l.loan_id AS 借阅ID,
b.book_id AS 图书ID,
b.title AS 图书标题,
r.reader_id AS 读者ID,
r.reader_name AS 读者姓名,
l.loan_date AS 借阅日期,
l.due_date AS 应还日期,
CASE
WHEN ret.return_id IS NOT NULL THEN '已归还'
ELSE '未归还'
END AS 归还状态,
ret.return_date AS 实际归还日期
FROM
loans l
JOIN
books b ON l.book_id = b.book_id
JOIN
readers r ON l.reader_id = r.reader_id
LEFT JOIN
returns ret ON l.loan_id = ret.loan_id;

-- 图书库存视图:按书架类型分类显示图书数量
CREATE VIEW loan_details AS
SELECT
l.loan_id AS 借阅ID,
b.book_id AS 图书ID,
b.title AS 图书标题,
r.reader_id AS 读者ID,
r.reader_name AS 读者姓名,
l.loan_date AS 借阅日期,
l.due_date AS 应还日期,
CASE
WHEN ret.return_id IS NOT NULL THEN '已归还'
ELSE '未归还'
END AS 归还状态,
ret.return_date AS 实际归还日期
FROM
loans l
JOIN
books b ON l.book_id = b.book_id
JOIN
readers r ON l.reader_id = r.reader_id
LEFT JOIN
returns ret ON l.loan_id = ret.loan_id;
3.4创建存储过程、函数

--借阅图书存储过程
CREATE OR REPLACE PROCEDURE borrow_book(
p_reader_id IN NUMBER,
p_book_id IN NUMBER,
p_loan_date IN DATE DEFAULT SYSDATE
)
IS
v_reader_exists NUMBER;
v_book_status VARCHAR2(10);
BEGIN
-- 验证读者存在性
SELECT COUNT(*) INTO v_reader_exists
FROM readers WHERE reader_id = p_reader_id;

IF v_reader_exists = 0 THEN
RAISE_APPLICATION_ERROR(-20010, '读者ID不存在');
END IF;

-- 获取图书状态
SELECT book_status INTO v_book_status
FROM books WHERE book_id = p_book_id;

-- 检查图书可借性
IF v_book_status != '在馆' THEN
RAISE_APPLICATION_ERROR(-20011, '图书当前不可借阅,状态:' || v_book_status);
END IF;

-- 创建借阅记录
INSERT INTO loans (loan_id, book_id, reader_id, loan_date, due_date)
VALUES (loan_seq.NEXTVAL, p_book_id, p_reader_id, p_loan_date, NULL);

-- 更新图书状态
UPDATE books SET book_status = '借出' WHERE book_id = p_book_id;

COMMIT;
DBMS_OUTPUT.PUT_LINE('借阅操作成功完成');
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
RAISE;
END;
/

--归还图书存储过程
CREATE OR REPLACE PROCEDURE return_book(
p_loan_id IN NUMBER,
p_return_date IN DATE DEFAULT SYSDATE
)
IS
v_book_id NUMBER;
v_due_date DATE;
v_fine_amount NUMBER := 0;
BEGIN
-- 获取借阅信息
SELECT book_id, due_date INTO v_book_id, v_due_date
FROM loans WHERE loan_id = p_loan_id;

-- 检查是否已归还
IF EXISTS (SELECT 1 FROM returns WHERE loan_id = p_loan_id) THEN
RAISE_APPLICATION_ERROR(-20020, '该借阅记录已归还');
END IF;

-- 创建归还记录
INSERT INTO returns (return_id, loan_id, return_date)
VALUES (return_seq.NEXTVAL, p_loan_id, p_return_date);

-- 更新图书状态
UPDATE books SET book_status = '在馆' WHERE book_id = v_book_id;

-- 计算逾期罚款(每天1元)
IF p_return_date > v_due_date THEN
v_fine_amount := (p_return_date - v_due_date) * 1;
INSERT INTO fines (fine_id, loan_id, amount, fine_date)
VALUES (fine_seq.NEXTVAL, p_loan_id, v_fine_amount, SYSDATE);
END IF;

COMMIT;
DBMS_OUTPUT.PUT_LINE('归还操作成功完成' ||
CASE WHEN v_fine_amount > 0 THEN ',产生逾期罚款:¥' || v_fine_amount ELSE '' END);
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR(-20021, '借阅ID不存在');
END;
/

--图书搜索函数
CREATE OR REPLACE FUNCTION search_books(
p_title IN VARCHAR2 DEFAULT NULL,
p_author IN VARCHAR2 DEFAULT NULL,
p_year_from IN NUMBER DEFAULT NULL,
p_year_to IN NUMBER DEFAULT NULL,
p_status IN VARCHAR2 DEFAULT NULL
) RETURN SYS_REFCURSOR
IS
v_result SYS_REFCURSOR;
BEGIN
OPEN v_result FOR
SELECT b.book_id, b.title, b.author, b.isbn,
b.publication_year, s.shelf_number,
st.shelf_type_name, b.book_status
FROM books b
JOIN shelves s ON b.shelf_id = s.shelf_id
JOIN shelf_types st ON s.shelf_type_id = st.shelf_type_id
WHERE (p_title IS NULL OR LOWER(b.title) LIKE '%' || LOWER(p_title) || '%')
AND (p_author IS NULL OR LOWER(b.author) LIKE '%' || LOWER(p_author) || '%')
AND (p_year_from IS NULL OR b.publication_year >= p_year_from)
AND (p_year_to IS NULL OR b.publication_year <= p_year_to)
AND (p_status IS NULL OR b.book_status = p_status)
ORDER BY b.title;

RETURN v_result;
END;
/

-- 计算逾期天数函数
CREATE OR REPLACE FUNCTION calculate_overdue_days(
p_loan_id IN NUMBER
) RETURN NUMBER
IS
v_due_date DATE;
v_return_date DATE;
BEGIN
-- 获取应还日期
SELECT due_date INTO v_due_date
FROM loans WHERE loan_id = p_loan_id;

-- 获取实际归还日期(如果已还)
BEGIN
SELECT return_date INTO v_return_date
FROM returns WHERE loan_id = p_loan_id;
EXCEPTION
WHEN NO_DATA_FOUND THEN
v_return_date := SYSDATE; -- 未归还则使用当前日期
END;

-- 计算逾期天数(只算正数)
RETURN GREATEST(v_return_date - v_due_date, 0);
END;
/

-- 生成月度借阅报告存储过程
CREATE OR REPLACE PROCEDURE generate_monthly_report(
p_year IN NUMBER,
p_month IN NUMBER
)
IS
v_report CLOB;
BEGIN
SELECT
XMLAGG(XMLELEMENT("row",
XMLFOREST(
TO_CHAR(loan_date, 'YYYY-MM-DD') AS "借阅日期",
COUNT(*) AS "借阅量",
COUNT(CASE WHEN book_status = '借出' THEN 1 END) AS "未归还量",
SUM(calculate_overdue_days(loan_id)) AS "总逾期天数"
)
).EXTRACT('//row').GETCLOBVAL()
INTO v_report
FROM loans
WHERE EXTRACT(YEAR FROM loan_date) = p_year
AND EXTRACT(MONTH FROM loan_date) = p_month
GROUP BY loan_date;

-- 实际应用中可替换为文件写入或邮件发送
DBMS_OUTPUT.PUT_LINE('月度借阅报告:');
DBMS_OUTPUT.PUT_LINE(v_report);
END;
/

--图书位置转移存储过程
CREATE OR REPLACE PROCEDURE move_book(
p_book_id IN NUMBER,
p_new_shelf_id IN NUMBER,
p_staff_id IN NUMBER
)
IS
v_old_shelf_id NUMBER;
BEGIN
-- 获取原书架ID
SELECT shelf_id INTO v_old_shelf_id
FROM books WHERE book_id = p_book_id;

-- 更新图书位置
UPDATE books
SET shelf_id = p_new_shelf_id
WHERE book_id = p_book_id;

-- 更新书架计数(通过触发器自动处理)

COMMIT;
DBMS_OUTPUT.PUT_LINE('图书转移成功');
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR(-20030, '图书或书架不存在');
END;
/

4.4. 3.5**创建触发器**

--借阅时自动设置应还日期 (基于读者类型)
CREATE OR REPLACE TRIGGER set_due_date_before_loan
BEFORE INSERT ON loans
FOR EACH ROW
DECLARE
v_loan_period NUMBER;
BEGIN
-- 获取读者类型的借阅期限
SELECT loan_period INTO v_loan_period
FROM reader_types
WHERE reader_type_id = (
SELECT reader_type_id
FROM readers
WHERE reader_id = :NEW.reader_id
);

-- 设置应还日期 = 借阅日期 + 借阅期限
:NEW.due_date := :NEW.loan_date + v_loan_period;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR(-20001, '读者类型未配置借阅期限');
END;
/

--还书时自动更新图书状态
-- 先添加图书状态字段
ALTER TABLE books ADD book_status VARCHAR2(10) DEFAULT '在馆'
CHECK (book_status IN ('在馆', '借出', '维护'));

-- 创建状态更新触发器
CREATE OR REPLACE TRIGGER update_book_status
AFTER INSERT ON returns
FOR EACH ROW
BEGIN
-- 更新图书状态为"在馆"
UPDATE books b
SET book_status = '在馆'
WHERE book_id = (
SELECT book_id
FROM loans
WHERE loan_id = :NEW.loan_id
);
END;
/

--借书时检查图书可用性
CREATE OR REPLACE TRIGGER check_book_availability
BEFORE INSERT ON loans
FOR EACH ROW
DECLARE
v_book_status VARCHAR2(10);
BEGIN
-- 获取当前图书状态
SELECT book_status INTO v_book_status
FROM books
WHERE book_id = :NEW.book_id;

-- 检查图书是否可借
IF v_book_status != '在馆' THEN
RAISE_APPLICATION_ERROR(-20002,
'图书不可借阅 - 当前状态: ' || v_book_status);
END IF;

-- 更新图书状态为"借出"
UPDATE books
SET book_status = '借出'
WHERE book_id = :NEW.book_id;
END;
/

-- 新书上架时验证书架容量
-- 添加书架容量字段
ALTER TABLE shelves ADD capacity NUMBER DEFAULT 100;
ALTER TABLE shelves ADD current_count NUMBER DEFAULT 0;

-- 创建容量检查触发器
CREATE OR REPLACE TRIGGER check_shelf_capacity
BEFORE INSERT OR UPDATE OF shelf_id ON books
FOR EACH ROW
DECLARE
v_current_count NUMBER;
v_capacity NUMBER;
BEGIN
SELECT current_count, capacity
INTO v_current_count, v_capacity
FROM shelves
WHERE shelf_id = :NEW.shelf_id;

-- 检查书架是否已满
IF v_current_count >= v_capacity THEN
RAISE_APPLICATION_ERROR(-20003,
'书架已满! 最大容量: ' || v_capacity ||
', 当前图书: ' || v_current_count);
END IF;

-- 更新书架图书计数
UPDATE shelves
SET current_count = current_count + 1
WHERE shelf_id = :NEW.shelf_id;

-- 处理图书移动情况
IF UPDATING AND :OLD.shelf_id != :NEW.shelf_id THEN
UPDATE shelves
SET current_count = current_count - 1
WHERE shelf_id = :OLD.shelf_id;
END IF;
END;
/

--逾期未还自动通知


-- 创建逾期通知触发器
CREATE OR REPLACE TRIGGER generate_overdue_notice
AFTER INSERT OR UPDATE ON loans
FOR EACH ROW
WHEN (NEW.due_date < SYSDATE) -- 只处理逾期记录
DECLARE
v_overdue_days NUMBER;
BEGIN
v_overdue_days := SYSDATE - :NEW.due_date;

INSERT INTO overdue_notifications (
notification_id,
loan_id,
reader_id,
message
) VALUES (
notification_seq.NEXTVAL, -- 需要创建序列
:NEW.loan_id,
:NEW.reader_id,
'您借阅的图书已逾期 ' || v_overdue_days || ' 天,请尽快归还!'
);
END;
/

--维护数据历史记录 (图书位置变更)


-- 创建历史记录触发器
CREATE OR REPLACE TRIGGER track_book_location
AFTER UPDATE OF shelf_id ON books
FOR EACH ROW
BEGIN
INSERT INTO book_location_history (
history_id,
book_id,
old_shelf_id,
new_shelf_id,
changed_by
) VALUES (
history_seq.NEXTVAL, -- 需要创建序列
:OLD.book_id,
:OLD.shelf_id,
:NEW.shelf_id,
USER -- 假设使用数据库用户跟踪
);
END;
/

4.5. 3.6 数据的操纵

数据插入
-- 插入书架类型
INSERT INTO shelf_types (shelf_type_id, shelf_type_name) VALUES (1, '文学类');
INSERT INTO shelf_types (shelf_type_id, shelf_type_name) VALUES (2, '科技类');
INSERT INTO shelf_types (shelf_type_id, shelf_type_name) VALUES (3, '历史类');

-- 插入书架
INSERT INTO shelves (shelf_id, shelf_number, shelf_type_id, capacity)
VALUES (101, 'A-101', 1, 150);

INSERT INTO shelves (shelf_id, shelf_number, shelf_type_id, capacity)
VALUES (102, 'B-201', 2, 200);

-- 插入读者类型
INSERT INTO reader_types (reader_type_id, reader_type_name) VALUES (1, '学生');
INSERT INTO reader_types (reader_type_id, reader_type_name) VALUES (2, '教师');

-- 插入读者
INSERT INTO readers (reader_id, reader_name, reader_type_id, contact_phone)
VALUES (1001, '张三', 1, '13800138000');

INSERT INTO readers (reader_id, reader_name, reader_type_id, contact_phone)
VALUES (1002, '李教授', 2, '13900139000');

-- 插入图书
INSERT INTO books (book_id, title, author, isbn, publication_year, shelf_id)
VALUES (5001, '数据库系统概论', '王珊', '978-7-04-019583-5', 2014, 102);

INSERT INTO books (book_id, title, author, isbn, publication_year, shelf_id, book_status)
VALUES (5002, '三体', '刘慈欣', '978-7-5366-9293-0', 2008, 101, '在馆');

-- 插入员工
INSERT INTO staff (staff_id, staff_name, staff_position)
VALUES (9001, '管理员小王', '图书管理员');

更新数据
UPDATE readers
SET contact_phone = '13800138111'
WHERE reader_id = 1001;

数据删除
-- 删除无效借阅记录(需先删除相关子表记录)
DELETE FROM returns WHERE loan_id = 5;
DELETE FROM loans WHERE loan_id = 5;

-- 删除不存在的读者类型(无关联数据时)
DELETE FROM reader_types WHERE reader_type_id = 99;

图书管理系统.zip