待补充:S锁(Shared Lock)共享锁 X锁(Exclusive Lock)排他锁

一、单项选择题

题目1

题目:在关系数据库中,实现表与表之间的联系是通过( )
选项
A. 实体完整性规则
B. 参照完整性规则
C. 用户自定义的完整性规则
D. 值域

答案:B

解析
参照完整性规则用于维护表与表之间的关系,通过外键约束实现;
实体完整性规则保证主键的唯一性和非空性;
用户自定义完整性规则是用户根据业务需求定义的约束
值域是属性的取值范围。

题目2

题目:SQL语言中,删除一个表的命令是( )
选项
A. DELETE
B. DROP
C. CLEAR
D. REMOVE

答案:B

解析DROP用于删除数据库对象(如表、视图等),DELETE用于删除表中的数据,CLEAR和REMOVE不是标准SQL命令。

题目3

题目:下列哪个不是数据库系统的三级模式结构( )
选项
A. 外模式
B. 概念模式
C. 内模式
D. 数据模式

答案:D

解析:数据库系统的三级模式结构包括外模式(用户视图)、概念模式(全局逻辑结构)和内模式(物理存储结构),"数据模式"不是标准术语。

题目4

题目:关系数据库规范化是为了解决关系数据库中( )问题而引入的
选项
A. 插入、删除异常和数据冗余
B. 提高查询速度
C. 减少数据操作的复杂性
D. 保证数据的安全性

答案:A

解析规范化主要解决数据冗余和操作异常问题,通过分解关系模式来消除不良特性。

题目5

题目:在SQL的SELECT语句中,与关系代数中的σσσ运算符对应的是( )
选项
A. SELECT子句
B. FROM子句
C. WHERE子句
D. GROUP BY子句

答案:C

解析σσσ运算符表示选择操作,对应于SQL中的WHERE子句。SELECT子句对应于投影操作πππ

题目6

题目:事务的隔离性是指( )
选项
A. 事务一旦提交,对数据库的改变是永久的
B. 一个事务内部的操作及使用的数据对并发的其他事务是隔离的
C. 事务必须是使数据库从一个一致性状态变到另一个一致性状态
D. 事务中包括的所有操作要么都做,要么都不做

答案:B

解析:隔离性是事务ACID特性之一,确保并发事务相互隔离。A描述的是持久性,C描述的是一致性,D描述的是原子性

ACID是数据库事务的四个关键特性,确保数据库操作的可靠性

A - Atomicity (原子性)
事务是不可分割的工作单位,事务中的操作要么全部成功,要么全部失败回滚
C - Consistency (一致性)
事务执行前后,数据库从一个一致状态转变为另一个一致状态
I - Isolation (隔离性)
多个事务并发执行时,一个事务的执行不应影响其他事务
D - Durability (持久性)
一旦事务提交,其结果就是永久性的,即使系统故障也不会丢失

题目7

题目:下列哪种情况不属于数据库恢复技术( )
选项
A. 数据转储
B. 登记日志文件
C. 视图机制
D. 检查点机制

答案:C

解析:视图机制用于数据安全和简化查询,不属于恢复技术。其他选项都是数据库恢复的常用技术。

题目8

题目:在关系R(R#, RN, S#)和S(S#, SN, SD)中,R的主键是R#,S的主键是S#,则S#在R中称为( )
选项
A. 外键
B. 候选键
C. 主键
D. 超键

答案:A

解析:S#在R中引用S表的主键,因此是外键。

题目9

题目:下列哪种关系运算不要求参与运算的两个关系具有相同的属性个数( )
选项
A. 并
B. 交
C. 差
D. 笛卡尔积

答案:D

解析:并、交、差运算要求参与运算的关系具有相同的属性集,而笛卡尔积则没有此限制。

关系运算
关系运算是关系数据库中的基本操作,主要对关系(表)进行各种操作。以下是四种基本关系运算的详细说明:
并(Union)

定义:两个关系的并运算结果包含所有属于这两个关系的元组(行),去除重复项。
要求

  • 两个关系必须有相同数量的属性(列)
  • 对应属性的数据类型必须兼容

示例

R:          S:
A | B       A | B
-----       -----
1 | a       2 | b
2 | b       3 | c

R ∪ S:
A | B
-----
1 | a
2 | b
3 | c

交(Intersection)

定义:两个关系的交运算结果包含同时属于这两个关系的元组。

要求

  • 两个关系必须有相同数量的属性
  • 对应属性的数据类型必须兼容

示例

R ∩ S:
A | B
-----
2 | b

差(Difference)

定义:R - S 的结果包含属于R但不属于S的所有元组。

要求

  • 两个关系必须有相同数量的属性
  • 对应属性的数据类型必须兼容

示例

R - S:
A | B
-----
1 | a

笛卡尔积(Cartesian Product,选项D)

定义:两个关系的笛卡尔积结果是第一个关系的每个元组与第二个关系的每个元组的组合。

特点

  • 不要求两个关系有相同数量的属性
  • 结果关系的属性数是两个关系属性数之和
  • 结果关系的元组数是两个关系元组数的乘积

示例

R:        S:
A | B     C | D
-----     -----
1 | a     7 | x
2 | b     8 | y

R × S:
A | B | C | D
-----------
1 | a | 7 | x
1 | a | 8 | y
2 | b | 7 | x
2 | b | 8 | y

题目10

题目:在数据库设计中,将E-R图转换成关系数据模型的过程属于( )
选项
A. 需求分析阶段
B. 概念设计阶段
C. 逻辑设计阶段
D. 物理设计阶段

答案:C

解析E-R图转换为关系模型逻辑设计阶段的任务。概念设计阶段创建E-R图物理设计阶段考虑存储结构和存取方法

在数据库的概念设计中,最常用的数据模型是实体联系模型(E-R图)

二、应用题

第1小题

第一部分 (关系代数)

设有以下关系模式:

  • 学生(学号, 姓名, 性别, 年龄, 系别)
  • 课程(课程号, 课程名, 学分)
  • 选课(学号, 课程号, 成绩)
    用关系代数表达式表示以下查询:
    (1)查询选修了"数据库"课程的学生的学号和姓名
    (2)查询既选修了"001"号课程又选修了"002"号课程的学生的学号

答案:π_学号,姓名(σ_课程名=‘数据库’(学生⋈选课⋈课程))
解析:先自然连接三个表,然后选择课程名为"数据库"的记录,最后投影学号和姓名。

答案:π_学号(σ_课程号=‘001’(选课)) ∩ π_学号(σ_课程号=‘002’(选课))
解析:分别找出选修001和002课程的学生学号,然后取交集。

第二部分 (SQL填空)

使用SQL语言实现以下操作:

(3)查询计算机系年龄最大的学生的姓名和年龄

SELECT 姓名, 年龄
FROM 学生
WHERE 系别 = '计算机系' AND 年龄 = (
    SELECT ______(1)______
    FROM 学生
    WHERE ______(2)______
)
SELECT 姓名, 年龄
FROM 学生
WHERE 系别 = '计算机系' AND 年龄 = (
    SELECT MAX(年龄)  -- (1) 获取最大年龄
    FROM 学生
    WHERE 系别 = '计算机系'  -- (2) 限定计算机系
)

(4)将"数据库"课程的学分修改为4

______(3)______ 课程
______(4)______
WHERE 课程名 = '数据库'
UPDATE 课程  -- (3) 更新操作
SET 学分 = 4  -- (4) 设置新值
WHERE 课程名 = '数据库'

(5)删除没有人选修的课程记录

DELETE FROM 课程
WHERE 课程号 ______(5)______ (
    SELECT 课程号
    FROM ______(6)______
)
DELETE FROM 课程
WHERE 课程号 NOT IN (  -- (5) 不在选修表中的课程
    SELECT 课程号
    FROM 选课  -- (6) 从选课表中查询有选修的课程
)

(6)查询选修课程数超过3门的学生学号和姓名

SELECT S.学号, S.姓名
FROM 学生 S, 选课 SC
WHERE S.学号 = SC.学号
GROUP BY ______(7)______
HAVING ______(8)______
SELECT S.学号, S.姓名
FROM 学生 S, 选课 SC
WHERE S.学号 = SC.学号
GROUP BY S.学号, S.姓名  -- (7) 按学号和姓名分组
HAVING COUNT(*) > 3  -- (8) 统计选修课程数超过3门

(7)创建一个视图,显示每个学生的学号、姓名和平均成绩

______(9)______ V_学生平均成绩 ______(10)______
SELECT S.学号, S.姓名, ______(11)______
FROM 学生 S, 选课 SC
WHERE S.学号 = SC.学号
GROUP BY ______(12)______
CREATE VIEW V_学生平均成绩 AS  -- (9) 创建视图 (10) AS关键字
SELECT S.学号, S.姓名, AVG(SC.成绩) AS 平均成绩  -- (11) 计算平均成绩
FROM 学生 S, 选课 SC
WHERE S.学号 = SC.学号
GROUP BY S.学号, S.姓名  -- (12) 按学号和姓名分组

第2小题

在销售管理系统中,需要统计每个销售员的月销售额,如果销售额超过10000元,则给予5%的奖金。请补全以下T-SQL代码:

DECLARE @SalesPersonID int, @MonthlySales money, @Bonus money
DECLARE SalesCursor CURSOR FOR 
    SELECT SalesPersonID, SUM(Amount) 
    FROM Sales 
    WHERE MONTH(SaleDate) = MONTH(GETDATE()) 
    GROUP BY ______(13)______

OPEN SalesCursor
FETCH NEXT FROM SalesCursor INTO @SalesPersonID, @MonthlySales
WHILE @@FETCH_STATUS = 0
BEGIN
    IF @MonthlySales > 10000
        SET @Bonus = ______(14)______
    ELSE
        SET @Bonus = 0
    
    PRINT '销售员ID: ' + CAST(@SalesPersonID AS varchar) + 
          ' 月销售额: ' + CAST(@MonthlySales AS varchar) + 
          ' 奖金: ' + CAST(@Bonus AS varchar)
    
    FETCH NEXT FROM SalesCursor INTO @SalesPersonID, @MonthlySales
END

CLOSE SalesCursor
DEALLOCATE SalesCursor
DECLARE @SalesPersonID int, @MonthlySales money, @Bonus money
DECLARE SalesCursor CURSOR FOR 
    SELECT SalesPersonID, SUM(Amount) 
    FROM Sales 
    WHERE MONTH(SaleDate) = MONTH(GETDATE()) 
    GROUP BY SalesPersonID  -- (13) 按销售员分组统计

OPEN SalesCursor
FETCH NEXT FROM SalesCursor INTO @SalesPersonID, @MonthlySales
WHILE @@FETCH_STATUS = 0
BEGIN
    IF @MonthlySales > 10000
        SET @Bonus = @MonthlySales * 0.05  -- (14) 计算5%的奖金
    ELSE
        SET @Bonus = 0
    
    PRINT '销售员ID: ' + CAST(@SalesPersonID AS varchar) + 
          ' 月销售额: ' + CAST(@MonthlySales AS varchar) + 
          ' 奖金: ' + CAST(@Bonus AS varchar)
    
    FETCH NEXT FROM SalesCursor INTO @SalesPersonID, @MonthlySales
END

CLOSE SalesCursor
DEALLOCATE SalesCursor

第3小题

在银行账户管理系统中,需要实现转账操作的存储过程。请补全以下代码:

CREATE PROCEDURE TransferFunds
    @FromAccount varchar(20),
    @ToAccount varchar(20),
    @Amount money
AS
BEGIN
    BEGIN TRANSACTION
    BEGIN TRY
        -- 从转出账户扣除金额
        UPDATE Accounts
        SET Balance = Balance - @Amount
        WHERE ______(15)______
        
        -- 检查转出账户余额是否足够
        IF (SELECT Balance FROM Accounts WHERE AccountNo = @FromAccount) < 0
        BEGIN
            ______(16)______
            RAISERROR('转出账户余额不足', 16, 1)
            RETURN
        END
        
        -- 向转入账户增加金额
        UPDATE Accounts
        SET Balance = Balance + @Amount
        WHERE ______(17)______
        
        -- 记录交易
        INSERT INTO Transactions (FromAccount, ToAccount, Amount, TransactionDate)
        VALUES (@FromAccount, @ToAccount, @Amount, GETDATE())
        
        ______(18)______
    END TRY
    BEGIN CATCH
        ______(19)______
        PRINT '转账失败: ' + ERROR_MESSAGE()
    END CATCH
END
CREATE PROCEDURE TransferFunds
    @FromAccount varchar(20),
    @ToAccount varchar(20),
    @Amount money
AS
BEGIN
    BEGIN TRANSACTION
    BEGIN TRY
        -- 从转出账户扣除金额
        UPDATE Accounts
        SET Balance = Balance - @Amount
        WHERE AccountNo = @FromAccount  -- (15) 指定转出账户
        
        -- 检查转出账户余额是否足够
        IF (SELECT Balance FROM Accounts WHERE AccountNo = @FromAccount) < 0
        BEGIN
            ROLLBACK TRANSACTION  -- (16) 余额不足回滚事务
            RAISERROR('转出账户余额不足', 16, 1)
            RETURN
        END
        
        -- 向转入账户增加金额
        UPDATE Accounts
        SET Balance = Balance + @Amount
        WHERE AccountNo = @ToAccount  -- (17) 指定转入账户
        
        -- 记录交易
        INSERT INTO Transactions (FromAccount, ToAccount, Amount, TransactionDate)
        VALUES (@FromAccount, @ToAccount, @Amount, GETDATE())
        
        COMMIT TRANSACTION  -- (18) 所有操作成功提交事务
    END TRY
    BEGIN CATCH
        ROLLBACK TRANSACTION  -- (19) 发生错误回滚事务
        PRINT '转账失败: ' + ERROR_MESSAGE()
    END CATCH
END

三、SQL编程题

题目描述

  1. 创建图书馆管理系统的三个基本表:

    • 图书(书号, 书名, 作者, 出版社, 出版日期, 单价, 库存数量)
    • 读者(借书证号, 姓名, 性别, 单位, 联系电话)
    • 借阅(借书证号, 书号, 借书日期, 还书日期)

    要求:

    • 定义适当的主键和外键
    • 设置借书日期的默认值为当前日期
    • 设置单价和库存数量的约束条件(单价>0,库存数量>=0)
  2. 为图书馆管理系统创建以下对象:

    • 创建一个视图,显示当前借阅超期(超过30天未还)的图书和读者信息
    • 创建一个存储过程,实现读者借书功能,包括库存检查
    • 创建一个触发器,当图书被归还时自动更新库存数量

1. 创建基本表

-- 创建图书表
CREATE TABLE 图书 (
    书号 VARCHAR(20) PRIMARY KEY,
    书名 VARCHAR(100) NOT NULL,
    作者 VARCHAR(50),
    出版社 VARCHAR(100),
    出版日期 DATE,
    单价 DECIMAL(10,2) CHECK (单价 > 0),
    库存数量 INT CHECK (库存数量 >= 0) DEFAULT 0
);

-- 创建读者表
CREATE TABLE 读者 (
    借书证号 VARCHAR(20) PRIMARY KEY,
    姓名 VARCHAR(50) NOT NULL,
    性别 CHAR(2) CHECK (性别 IN ('男', '女')),
    单位 VARCHAR(100),
    联系电话 VARCHAR(20)
);

-- 创建借阅表
CREATE TABLE 借阅 (
    借书证号 VARCHAR(20),
    书号 VARCHAR(20),
    借书日期 DATE DEFAULT GETDATE(),
    还书日期 DATE,
    PRIMARY KEY (借书证号, 书号, 借书日期),
    FOREIGN KEY (借书证号) REFERENCES 读者(借书证号),
    FOREIGN KEY (书号) REFERENCES 图书(书号),
    CHECK (还书日期 IS NULL OR 还书日期 >= 借书日期)
);

2. 创建数据库对象

(1) 创建显示超期借阅的视图
CREATE VIEW 超期借阅视图 AS
SELECT R.借书证号, R.姓名, R.联系电话, 
       B.书号, B.书名, B.作者,
       L.借书日期, L.还书日期,
       DATEDIFF(DAY, L.借书日期, GETDATE()) AS 借阅天数
FROM 借阅 L
JOIN 读者 R ON L.借书证号 = R.借书证号
JOIN 图书 B ON L.书号 = B.书号
WHERE L.还书日期 IS NULL 
AND DATEDIFF(DAY, L.借书日期, GETDATE()) > 30;
(2) 创建借书存储过程
CREATE PROCEDURE 借书
    @借书证号 VARCHAR(20),
    @书号 VARCHAR(20)
AS
BEGIN
    DECLARE @库存数量 INT;
    
    -- 检查库存
    SELECT @库存数量 = 库存数量 FROM 图书 WHERE 书号 = @书号;
    
    IF @库存数量 IS NULL
    BEGIN
        RAISERROR('图书不存在', 16, 1);
        RETURN;
    END
    
    IF @库存数量 <= 0
    BEGIN
        RAISERROR('图书库存不足', 16, 1);
        RETURN;
    END
    
    -- 检查读者是否存在
    IF NOT EXISTS (SELECT 1 FROM 读者 WHERE 借书证号 = @借书证号)
    BEGIN
        RAISERROR('读者不存在', 16, 1);
        RETURN;
    END
    
    -- 检查是否已借未还
    IF EXISTS (SELECT 1 FROM 借阅 
              WHERE 借书证号 = @借书证号 AND 书号 = @书号 AND 还书日期 IS NULL)
    BEGIN
        RAISERROR('该读者已借阅此书且未归还', 16, 1);
        RETURN;
    END
    
    -- 执行借书操作
    BEGIN TRANSACTION;
    BEGIN TRY
        -- 插入借阅记录
        INSERT INTO 借阅 (借书证号, 书号)
        VALUES (@借书证号, @书号);
        
        -- 减少库存
        UPDATE 图书
        SET 库存数量 = 库存数量 - 1
        WHERE 书号 = @书号;
        
        COMMIT TRANSACTION;
        PRINT '借书成功';
    END TRY
    BEGIN CATCH
        ROLLBACK TRANSACTION;
        RAISERROR('借书失败: %s', 16, 1, ERROR_MESSAGE());
    END CATCH
END;
(3) 创建还书触发器
CREATE TRIGGER 还书触发器
ON 借阅
AFTER UPDATE
AS
BEGIN
    -- 只处理还书日期从NULL变为非NULL的记录
    IF UPDATE(还书日期)
    BEGIN
        -- 更新图书库存
        UPDATE 图书
        SET 库存数量 = 库存数量 + 1
        WHERE 书号 IN (
            SELECT I.书号
            FROM inserted I
            JOIN deleted D ON I.借书证号 = D.借书证号 AND I.书号 = D.书号 AND I.借书日期 = D.借书日期
            WHERE D.还书日期 IS NULL AND I.还书日期 IS NOT NULL
        );
        
        PRINT '还书成功,库存已更新';
    END
END;

四、分析题

题目描述

给定关系模式R(A,B,C,D,E),其函数依赖集F={A→BC, CD→E, B→D, E→A}

  1. 写出R的所有候选码
  2. 指出R最高已达到第几范式?为什么?
  3. 将R分解为3NF,要求分解具有无损连接性和保持函数依赖性

1. 写出R的所有候选码

步骤

  1. 找出所有可能作为候选码的属性或属性组合
  2. 计算各属性闭包看是否包含所有属性(A,B,C,D,E)

计算过程

  • 计算单个属性的闭包:
    • A⁺ = A→BC→BCD(B→D)→BCDE(CD→E) = ABCDE
    • B⁺ = B→D = BD
    • C⁺ = C
    • D⁺ = D
    • E⁺ = E→A→ABC→ABCD(B→D)→ABCDE(CD→E) = ABCDE

A和E的闭包都包含所有属性,所以{A}和{E}都是候选码。

  • 检查是否有其他组合候选码:
    由于A和E单独已经是候选码,不需要更大的组合。但需要检查是否有其他最小组合也是候选码。

    例如检查{CD}:
    CD⁺ = CD→E→A→ABC→ABCD→ABCDE = ABCDE
    所以{CD}也是候选码。

结论:R的所有候选码为{A}, {E}, {CD}

2. 指出R最高已达到第几范式?为什么?

分析

  1. 首先R显然满足1NF(所有属性都是原子的)
  2. 检查2NF:
    • 候选码有{A}, {E}, {CD}
    • 对于候选码{A}:非主属性为D,E
      • A→BC是完全函数依赖
      • B→D是部分函数依赖(因为B是A决定的BC的一部分)
      • 存在部分函数依赖,所以不满足2NF
    • 对于候选码{E}:非主属性为B,C,D
      • E→A→BC→D,存在部分函数依赖
    • 对于候选码{CD}:非主属性为A,B
      • CD→E→A→B,存在传递函数依赖

结论:R最高只达到1NF,因为存在部分函数依赖(对于候选码{A}和{E})和传递函数依赖(对于候选码{CD})。

3. 将R分解为3NF,要求分解具有无损连接性和保持函数依赖性

步骤

  1. 首先求最小函数依赖集

    • F={A→BC, CD→E, B→D, E→A}
      已经是极小集,无法进一步简化。
  2. 为每个函数依赖创建一个关系模式:

    • R1(A,B,C) (来自A→BC)
    • R2(C,D,E) (来自CD→E)
    • R3(B,D) (来自B→D)
    • R4(E,A) (来自E→A)
  3. 检查是否包含候选码:

    • 候选码有{A}, {E}, {CD}
    • R1包含{A}, R4包含{E}, R2包含{CD}
      所以已经包含所有候选码。
  4. 检查是否可以合并

    • R4(E,A)和R1(A,B,C)可以合并为R14(A,B,C,E)
    • 最终分解:
      • R14(A,B,C,E)
      • R2(C,D,E)
      • R3(B,D)

验证

  • 无损连接性:满足,因为包含候选码
  • 保持函数依赖:
    • A→BC在R14中
    • CD→E在R2中
    • B→D在R3中
    • E→A在R14中

最终3NF分解
R1(A,B,C,E)
R2(C,D,E)
R3(B,D)

五、设计题

设计一个医院门诊管理系统的数据库,要求包括以下实体和联系:

  • 医生(医生编号, 姓名, 职称, 科室, 专长, 出诊时间)
  • 病人(病历号, 姓名, 性别, 出生日期, 联系电话, 住址)
  • 药品(药品编号, 名称, 规格, 单价, 生产厂家, 库存量)
  • 每个病人可以预约多位医生,每次预约有预约日期和时间段
  • 医生为病人诊断后可以开处方,处方包括开方日期和诊断结果
  • 处方可以包含多种药品,每种药品有用法用量

要求:

  1. 画出该系统的E-R图,注明属性、联系类型、实体标识符等(9分)
  2. 将E-R图转换成关系模型,并说明主键和外键(7分)
Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐