数据库期末复习
绪论
数据库系统
基本概念
- 数据Data:描述事物的符号,记录数据库存储的基本对象
- 数据库DB:长期 储存在计算机内、有组织的、可共享 的大量数据的集合
- 数据库管理系统DBMS:位于用户与操作系统之间的一层数据管理软件,是计算机的基础软件
- 主要功能:数据定义功能DDL、数据操纵功能DML、数据库的运行管理、数据库的建立和维护
- 数据库系统DBS:在计算机系统引入数据库后的系统构成
- 构成:数据库、数据库管理系统、应用程序、数据库管理员DBA
数据库系统的基本特征
- 数据结构化
- 共享性高、冗余度低、易扩充
- 独立性高:物理独立性/逻辑独立性
- 数据由DBMS统一管理和控制
数据管理技术发展过程
- 人工管理→文件系统→数据库系统
- 核心区别
- 人工管理:数据不保存、不共享、不独立,完全依赖于应用程序
- 文件系统:数据可长期保存,但共享性差、冗余度高、独立性弱
- 数据库系统:答基本特征即可。数据冗余 是导致数据不一致的根本原因
数据库技术的发展历史
- 层次、网状→关系数据库→面向新一代应用的数据库技术
- 结构化/半结构化/非结构化数据
数据模型
数据模型是数据库系统的核心和基础
概念模型、逻辑模型、物理模型
数据模型组成要素
- 数据结构、数据操作、数据的完整性约束条件
- 数据结构:静态特征→组成对象和对象之间的联系
- 数据操作:动态特征→对对象的实例允许执行的操作和操作规则
- 类型:查询和更新(增删改)
- 数据完整性约束条件:一组完整性规则的集合,用以保证数据的正确、有效和相容
- 完整性规则:限定符合数据模型的数据库状态以及状态的变化
概念模型(用户观点建模)
独立于具体机器和DBMS,主要用于数据库设计阶段
- 实体
- 属性:实体具有的某一特性
- 码:唯一标识实体的属性集
- 域:属性的取值范围
- 实体型:用实体名及属性名集合来抽象和刻画同类实体
- 实体集:同一类型实体的集合
- 联系:1:1、1:n、n:m
表示方法
实体-联系方法(E-R)
逻辑模型(计算机观点建模)
逻辑模型:层次模型、网状模型、关系模型、面向对象模型
逻辑模型对比
层次模型:
- 结构:树,结点只有一个双亲
- 优点:查找效率高,数据结构简单
- 缺点:表示多对多不自然,对插入删除限制多,查询子女必须通过双亲
网状模型:
- 结构:结点可以有多个双亲
- 优点:更直接描述现实世界,存取效率高
- 缺点:结构复杂,记录变动难维护,用户难上手
关系模型:
- 结构:规范化的二维表
- 优点:概念单一,存取路径对用户透明,更高的数据独立性
- 缺点:查询效率低
关系模型的数据语言(SQL等)是非过程化 的,层次和网状模型是过程化 的
格式化模型(层次、网状)
层次模型(树状结构)
多对多分解为一对多:冗余结点法、虚拟结点法
存储结构:邻接法、链接法(子女兄弟链接法、层次序列链接法)
网状模型
存储结构:单向链接、环向链接、环状链接
关系模型
关系数据库系统采用关系模型作为数据的组织方式
数据操作是集合操作,操作对象和结果都是关系
存储结构:实体及实体间的联系都用表来表示
物理模型
物理模型:数据在系统内部的表示方式和存取方法(最底层)
数据库系统外部结构
从最终用户角度:单用户结构、主从式结构、客户/服务器、分布式结构、浏览器/应用服务器/数据库服务器多层结构
从管理系统角度:通常采用三级模式结构
数据库系统模式
型:对某一类数据的结构和属性的说明
值:型的一个具体赋值
模式:数据库逻辑结构和特征的描述
实例:模式的一个具体值
三级模式结构
- 外模式(用户模式/子模式):数据库用户使用的局部数据 的逻辑结构和特征的描述;一个数据库可以有多个 外模式
- 模式(逻辑模式):数据库中全体数据 的逻辑结构和特征的描述;一个数据库只能有一个 模式
- 内模式(存储模式):数据物理结构 和存储方式 的描述;一个数据库只有一个 内模式
二级映象功能与数据独立性
外模式/模式映象:
- 定义外模式与模式之间的对应关系
- 保证数据的逻辑独立性
- 模式改变时可保持外模式不变
模式/内模式映象:
- 定义数据库全局的逻辑结构与存储结构之间的对应关系
- 保证数据的物理独立性
- 物理存储结构改变时保持模式不变
填空
- 数据管理技术经历了人工管理、文件系统、数据库系统三个阶段
- 数据库系统一般由数据库、数据库管理系统或DBMS、应用系统、数据库管理员DBA 和用户构成
- 数据模型 通常由数据结构、数据操作和完整性约束三部分组成
- 最经常使用的概念模型是实体-联系模型
- 用树型结构表示实体类型及实体间联系的数据模型称为层次模型
- 数据库系统的逻辑模型按照计算机的观点对数据建模,主要包括层次模型、网状 模型,关系 模型、面向对象模型、对象关系模型和半结构化数据模型等
- 数据库系统的三级模式结构是指数据库系统是由外模式、模式和内模式 三级构成
- 数据独立性是数据库领域的重要概念,包括数据的逻辑 独立性,和数据的物理 独立性
其他知识点自查
- 四个核心概念(数据、数据库、DBMS、DBS)的区别
- 数据模型的三要素(结构、操作、完整性)
- 层次、网状、关系模型 各自的特点和优缺点,尤其是关系模型的优势
- 三级模式(外、模式、内)和二级映像,以及它们如何保证物理和逻辑独立性
关系数据库
关系代数:用关系运算表达查询操作
关系完整性约束:对关系更新操作的限制条件
域
一组具有相同数据类型的值的集合
笛卡尔积
元组、分量、基数
关系
笛卡尔积的某个子集
- 关系:一个关系对应一张表
- 元组:表中一行为一个元组
- 属性:表中一列为一个属性;n 目关系必有 n 个属性
- 域:属性的取值范围
- 分量:元组中的一个属性值
- 关系模式:对关系的描述
- 码
- 候选码:某关系中的某一属性组的值能唯一标识一个元组,且其任何真子集都不能唯一标识元组,是最小的超码
- 超码:包含能唯一标识元组的属性的集合(包含候选码即可)
- 主码:多个候选码中选定一个为主码
- 全码:所有属性组是这个关系模式的候选码
- 主/非主属性:任何候选码中包含的属性为主属性,不包含在任何候选码中的属性为非主属性或非码属性
- 三类关系:基本关系、查询表、视图表
关系模式
是型,是对关系的静态、稳定描述
包括:元组集合的结构、元组的语义及完整性约束条件、属性间的数据依赖关系集合
关系操作与代数
操作的对象和结果都是关系
查询:选择、投影、连接、除、交、差
更新:插入、删除、修改
传统集合运算
(并交差的前提:属性个数相同、属性数据类型相同)
并:合并,去掉重复元组
交:取两个关系中都存在的元组
差:从第一个关系中去掉同时存在于第二个关系的元组
笛卡尔积:将两个关系的元组进行所有可能的组合
专门关系运算
选择:选特定行,
投影:选特定列,(会自动去掉结果中的重复行 )
连接:
- 等值连接:条件为 = 的连接
- 自然连接:自动去掉 重复属性列
- 外连接(左外连接、右外连接):缺失的属性填 NULL
除:应用场景:查询“全部”
重命名:
查询至少选修了一门其先修课为5号课程的学生姓名
查询刘晨同学没选的课程号
查询卖所有型号的PC的制造商
查询比1002型号便宜的PC型号
π PC2.model (ρ PC1(PC)⨝ PC1.model = 1002 ∧ PC1.price > PC2.price ρ PC2(PC))
查询至少生产两款不同速度PC的制造商
π PC1.maker(ρ PC1(PC ⨝ Product)⨝((PC1.maker)=PC2.maker∧PC1.speed≠PC2.speed) ρ PC2(Product ⨝ PC))
关系的完整性约束条件
- 实体完整性:主属性不能取空值
- 参照完整性:
- 外码:F不是R的主码,但是S的主码,则F是R的外码;R是参照关系,S是被参照关系
- 外码必须取空值 或等于S中某个主码值
- 用户定义的完整性:语义要求
填空
- 在关系模型中,关系操作包括查询、插入、删除 和 修改 等
- 在关系代数中,从两个关系的笛卡尔积中选取它们的属性或属性组间满足一定条件的元组得到新的关系,该操作称为 连接
- 设有关系:职工(职工号, 姓名, 部门号)和部门(部门号, 部门名称)。在这两个关系中,部门 是被参照关系,职工 是参照关系,职工关系中的 部门号 是外码
Sql
SQL功能 | 动词 |
---|---|
数据查询 | SELECT |
数据定义 | CREATE/DROP/ALTER |
数据操纵 | INSERT/UPDATE/DELETE |
数据控制 | GRANT/REVOKE |
数据定义DDL、数据操纵DML、数据控制DCL、数据查询DQL
数据查询
基本结构与执行逻辑
SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY;
- DBMS内部的逻辑处理顺序通常是
FROM
->WHERE
->GROUP BY
->HAVING
->SELECT
->ORDER BY
单表查询
DISTINCT
去除重复行AS
给列起别名WHERE
子句
- 范围
BETWEEN...AND...
- 集合
IN(...)
- 模糊查询
LIKE
,配合通配符%
任意长度字符和_
单个字符- 空值判断
IS NULL
/IS NOT NULL
,不能用=NULL
GROUP BY
与HAVING
- 聚集函数:计数
COUNT()
、求和SUM()
、平均值AVG()
、最大最小MAX()/MIN()
GROUP BY
:结果按指定列分组,聚集函数作用于每个分组HAVING
:对分组后的结果进行筛选- 核心区别:
WHERE
在分组前 筛选行 ,HAVING
在分组后 筛选组 。WHERE
子句中不能 使用聚集函数,而HAVING
子句中可以ORDER BY
:对最终结果排序,ASC
升序默认,DESC
降序- 使用聚合函数的时候要注意是否应该去除重复行
如COUNT(DISTINCT 列名)
查询列
查询指定列
1 | SELECT Sno,Sname FROM Student |
查询全部列
1 | SELECT * FROM Student |
查询计算的值
1 | SELECT Sname,YEAR(CURDATE())-Sage FROM Student |
列别名
1 | SELECT 'Year of Birth:' BIRTH,YEAR(CURDATE())-Sage BIRTHDAY,LOWER(Sdept) DEPARTMENT FROM Student |
消除取值重复的行:DISTINCT
1 | SELECT DISTINCT Sno FROM SC |
查询行
比较大小
1 | SELECT Sname FROM Student WHERE Sdept='CS' |
确定范围:(NOT) BETWEEN...AND...
1 | SELECT Sname,Sdept,Sage FROM Student WHERE Sage BETWEEN 20 AND 23 |
确定集合:(NOT) IN<值表>
1 | SELECT Sname,Ssex FROM Student WHERE Sdept IN('IS','MA','CS') |
字符匹配:(NOT) LIKE<匹配串>[ESCAPE]<换码字符>
1 | -- 匹配固定字符串 |
字符串比较
1 | SELECT * FROM Student WHERE Sno<'200215200' |
日期和时间:DATEADD(操作单位,对当前日期进行加法操作数,返回值)
1 | SELECT * FROM Student WHERE DATEADD(YEAR,-Sage,GETDATE())>'2005-01-01' |
涉及空值的查询:IS (NOT) NULL
1 | SELECT Sno,Cno FROM SC WHERE Grade IS NULL |
多重条件查询 AND/OR(AND优先级高)
1 | SELECT Sname FROM Student WHERE Sdept='CS' AND Sage<20 |
ORDER BY子句
升序(默认):ASC,空值最后显示
降序:DESC,空值最先显示
1 | SELECT Sno,Grade FROM SC WHERE Cno='3' ORDER BY Grade DESC |
LIMIT a OFFSET b
:插降序排列的第3-10位
1 | SELECT Sno,Grade FROM SC WHERE Cno='2' ORDER BY Grade DESC LIMIT 8 OFFSET 2 |
随机排序:NEWID
1 | SELECT * FROM Student ORDER BY NEWID() |
浏览
ls数据库
1 | use master; |
ls基本表
1 | select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_TYPE='BASE TABLE' |
查看表的定义
1 | sp_help Student; |
ls随机k行
1 | select top k * from SC order by NEWID(); |
聚集函数
计数:COUNT([DISTINCT|ALL]<列名>)
1 | SELECT COUNT(*) FROM Student |
总和:SUM([DISTINCT|ALL]<列名>)
1 | SELECT SUM(Ccredit) FROM SC,Course WHERE Sno='200215012' AND SC.Cno=Course.Cno |
平均值:AVG([DISTINCT|ALL]<列名>)
1 | SELECT AVG(Grade) FROM SC WHERE Cno='2' |
最大最小值:MAX/MIN([DISTINCT|ALL]<列名>)
1 | SELECT MAX(Grade) FROM SC WHERE Cno='1' |
GROUP BY子句
GROUP BY column_name(s) HAVING condition
WHERE子句中是不能用聚集函数作为条件表达式,要用HAVING
1 | SELECT Sdept,COUNT(*) FROM Student GROUP BY Sdept |
SELECT子句中非聚合函数的列必须出现在GROUP BY列表中
1 | -- 以下语句错误,Grade非聚合函数且未包含在GROUP BY |
集合查询
并操作UNION
UNION
:去掉重复元组
UNION ALL
:保留重复元组
可以用OR替代
1 | SELECT * FROM Student WHERE Sdept='CS' UNION SELECT * FROM Student WHERE Sage<=19 |
交操作INTERSECT
一般不能用AND替代
1 | SELECT Sno FROM SC WHERE Cno='1' INTERSECT SELECT Sno FROM SC WHERE Cno='2' |
差操作EXCEPT
1 | SELECT * FROM Student WHERE Sdept='CS' EXCEPT SELECT * FROM Student WHERE Sage<=19 |
连接查询
- 内连接
INNER JOIN
:返回两个表中连接条件匹配的行- 外连接
OUTER JOIN
:除了返回匹配的行,还会返回不匹配的行
LEFT JOIN
:保留左表的所有行RIGHT JOIN
:保留右表的所有行FULL JOIN
: 保留左右两表的所有行- 自身连接:一个表与它自己进行连接,通常需要为表起别名
等值与非等值连接查询
等值连接:会出现重复的列Sno
1 | SELECT Student.*,SC.* FROM Student,SC WHERE Student.Sno=SC.Sno |
自然连接:去除重复列Sno,只留一个
1 | SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade FROM Student,SC WHERE Student.Sno = SC.Sno |
自身连接
1 | SELECT FIRST.Cno,SECOND.Cpno FROM Course FIRST,Course SECOND WHERE FIRST.Cpno=SECOND.Cno |
外连接
左外连接:LEFT OUTER JOIN ... ON
右外连接:RIGHT OUTER JOIN ... ON
外连接:FULL OUTER JOIN ... ON
内连接(等值连接):INNER JOIN ... ON
1 | SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade FROM Student LEFT OUTER JOIN SC ON (Student.Sno=SC.Sno) |
复合条件连接
WHERE子句中含多个连接条件
1 | SELECT Student.Sno, Sname FROM Student, SC WHERE Student.Sno = SC.Sno AND SC.Cno= '2' AND SC.Grade > 90 |
嵌套查询
不相关子查询:子查询条件不依赖于父查询
相关子查询:子查询条件依赖于父查询
- 带
IN
的子查询:判断一个值是否存在于子查询的结果集中。子查询通常不依赖于父查询(非相关子查询)- 带比较运算符 (
>
,<
,=
) 的子查询
- 当子查询返回单值时,可直接用比较运算符
- 当子查询返回多值时,必须配合
ANY
或ALL
使用。>ANY
意为“大于集合中的某个值”(即大于最小值),>ALL
意为“大于集合中所有的值”(即大于最大值)- 带
EXISTS
的子查询
- 不为空则返回
TRUE
,为空则返回FALSE
- 通常用于相关子查询,即子查询的执行依赖于父查询的当前行
- 核心考点: 用
NOT EXISTS
实现全称量词(“查询…所有…”)
带IN谓词的子查询
1 | SELECT Sno,Sname |
尽量直接用AND连接,不要用复杂的IN谓词嵌套
带比较运算符的子查询
确切知道内层查询返回单值,可用比较运算符
子查询一定要跟在比较符之后(不能写成WHERE (SELECT...)=Sdept
)
1 | SELECT Sno,Sname,Sdept FROM Student |
带ANY(SOME)或ALL谓词的子查询
查询 | 功能 |
---|---|
>ANY | 大于子查询结果中的某个值 |
>ALL | 大于子查询结果中的所有值 |
<ANY | 小于子查询结果中的某个值 |
<ALL | 小于子查询结果中的所有值 |
>=ANY | 大于等于子查询结果中的某个值 |
>=ALL | 大于等于子查询结果中的所有值 |
<=ANY | 小于等于子查询结果中的某个值 |
<=ALL | 小于等于子查询结果中的所有值 |
=ANY | 等于子查询结果中的某个值 |
=ALL | 等于子查询结果中的所有值(通常没有实际意义) |
!=(或<>)ANY | 不等于子查询结果中的某个值 |
!=(或<>)ALL | 不等于子查询结果中的任何一个值 |
1 | SELECT Sname,Sage FROM Student WHERE Sage<ANY(SELECT Sage FROM Student WHERE Sdept='CS') AND Sdept <> 'CS' |
ANY、ALL谓词与聚集函数、IN谓词转换关系
= | <> | < | <= | > | >= | |
---|---|---|---|---|---|---|
ANY | IN | <MAX | <=MAX | >MIN | >=MIN | |
ALL | NOT IN | <MIN | <=MIN | >MAX | >=MAX |
带EXISTS谓词的子查询
不返回数据,只产生逻辑真值,目标列表达式通常都用*
1 | SELECT Sname FROM Student WHERE NOT EXISTS(SELECT * FROM SC WHERE Sno=Student.Sno AND Cno='1') |
用EXISTS/NOT EXISTS实现全称量词
基于派生表的查询
定义了一个名为Avg_sc
的公用表表达式
1 | WITH Avg_sc AS |
数据定义
模式
定义模式
CREATE SCHEMA <模式名> AUTHORIZATION <用户名>
1 | CREATE SCHEMA [S-T] AUTHORIZATION WANG |
删除模式
DROP SCHEMA <模式名> <CASCADE | RESTRICT>
CASCADE
级联 :删除模式的同时把该模式中的所有数据库对象全部删除RESTRICT
限制 :若该模式定义下属的数据库对象(表、视图),则拒绝该删除语句的执行
1 | DROP SCHEMA ZHANG CASCADE |
基本表
定义基本表
1 | CREATE TABLE Student |
数据类型
定义基本表所属模式
显式指定模式名
1 | CREATE TABLE "S-T".Student (...); |
创建模式时同时建表
1 | CREATE SCHEMA "S-T" |
设置默认模式
1 | USE `S-T`; |
修改基本表
ALTER TABLE <表名>[ADD <新列名> <数据类型> [ 完整性约束 ]][DROP <完整性约束名>][ALTER COLUMN<列名> <数据类型>]
增加列
1 | ALTER TABLE Student ADD S_entrance DATE |
更改列类型
1 | ALTER TABLE Student ALTER COLUMN Sage INT |
增加/删除完整性约束
1 | ALTER TABLE Course ADD UNIQUE(Cname); |
删除基本表
DROP TABLE <表名>[RESTRICT| CASCADE]
RESTRICT
:若存在依赖该表的对象,则此表不能被删除
CASCADE
:删除该表没有限制
索引的建立与删除
CREATE/DROP [UNIQUE] [CLUSTER] INDEX <索引名> ON <表名>(<列名>[<次序>][,<列名>[<次序>] ]…),
聚簇索引 :一个基本表上最多只能建立一个聚簇索引
1 | CREATE CLUSTER INDEX Stusname ON Student(Sname) |
唯一索引 :
1 | -- SC表按学号升序和课程号降序建唯一索引 |
数据更新
完整性规则
- 实体完整性
- 主码不允许修改
- 用户定义的完整性:NOT NULL约束、UNIQUE约束、值域约束
插入数据INSERT
插入元组
1 | INSERT INTO Student(Sno,Sname,Ssex,Sdept,Sage) |
插入子查询结果
1 | INSERT INTO Dept_age(Sdept,Avg_age) |
修改数据UPDATE
1 | UPDATE Student SET Sage=22 WHERE Sno='200215121' |
忘记写 WHERE
条件会更新整张表的数据
删除数据DELETE
1 | DELETE FROM Student WHERE Sno='200215128'; |
忘记写 WHERE
条件会删除整张表的数据
视图
定义: 视图是一张虚表,是基于 SELECT
语句结果集的可视化的表。数据库只存储视图的定义,不存储其数据
作用:简化查询、安全性(实现数据访问控制)
- 查询
- 删除
- 受限更新
- 定义基于该视图的新视图
建立视图
子查询不允许含有ORDER BY子句和DISTINCT短语
视图的属性列名:全部省略或全部指定
1 | CREATE VIEW IS_Student AS SELECT Sno,Sname,Sage FROM Student WHERE Sdept='IS'; |
基于多个基表的视图
1 | CREATE VIEW IS_S1(Sno,Sname,Grade) AS SELECT Student.Sno,Sname,Grade FROM Student,SC WHERE Sdept= 'IS' AND Student.Sno=SC.Sno AND SC.Cno= '1' |
不指定属性列
1 | CREATE VIEW F_Student(F_Sno,name,sex,age,dept) AS |
查询视图
1 | CREATE VIEW IS_Student AS SELECT Sno,Sname,Sage FROM Student WHERE Sdept='IS'; |
更新视图
不是所有视图都可以更新(INSERT, UPDATE, DELETE)
不允许更新的视图
- 视图的
SELECT
语句中包含DISTINCT
、聚集函数、GROUP BY
子句。 - 视图来自于多个表 的连接查询
- 视图的列是基于表达式 或常数
- 有嵌套查询
1 | UPDATE IS_Student SET Sname='刘辰' WHERE Sno='200215122' |
填空
- 聚簇(CLUSTER) 索引是指索引项的顺序与表中记录的物理顺序一致的索引组织
- 视图是一种虚表,是从一个或几个基本表(或视图)导出的表,数据库中只存放视图的 定义
- 在
SELECT
语句中,如果需要去掉查询结果中的重复行,应使用关键词 DISTINCT - 在
WHERE
子句中,判断空值的谓词是 IS NULL - 在集合查询中,UNION 会自动去重,而 UNION ALL 会保留所有重复行
数据库安全
数据库安全性
不安全因素
- 非授权用户对数据库的恶意存取和破坏
- 数据库中重要或敏感的数据被泄露
- 安全环境的脆弱性
用户身份鉴别
第一道 防线
实现方式:
- 静态口令:用户名+密码
- 动态口令:验证码、动态令牌
- 生物特征:指纹
- 智能卡
存取控制
- 定义用户权限
- 合法权限检查
常用存取控制方法
- 自主存取控制DAC:用
GRANT
/REVOKE
实现 - 强制存取控制MAC:用安全级别实现
自主存取控制
最小特权原则
GRANT
子句
- 基本语法:
GRANT <权限> ON <对象> TO <用户>
- 权限:
SELECT
、INSERT
、UPDATE
、DELETE
、ALL PRIVILEGES
等- 对象:
TABLE Student
,VIEW IS_Student
等- 用户: 具体用户名或
PUBLIC
(所有用户)- 重要子句
WITH GRANT OPTION
: 如果授权时加上这个子句,被授权的用户就可以再把这个权限授予其他用户,这是权限传播的关键
REVOKE
子句
- 基本语法:
REVOKE <权限> ON <对象> FROM <用户>
- 重要子句
CASCADE
: 如果收回用户U1的权限时使用了CASCADE
,那么由U1授予出去的所有相关权限也会被级联收回 ,这是权限回收的关键
授权GRANT
1 | GRANT SELECT ON TABLE Student TO PUBLIC; |
全部权限:ALL PRIVILEGES
传播:WITH GRANT OPTION
1 | GRANT ALL PRIVILEGES ON TABLE Student, Course TO U2, U3; |
回收REVOKE
CASCADE
级联
RESTRICT
受限
1 | REVOKE UPDATE(Sno) ON TABLE Student FROM U4; |
创建数据库模式的权限
CREATE USER <username>[WITH][SUPERUSER | CREATEDB | CONNECT]
数据库角色
被命名的一组与数据库操作相关的权限
角色是权限的集合
创建角色
CREATE ROLE <角色名>
给角色授权
GRANT 权限 ON 对象类型 对象名 TO 角色
1 | GRANT SELECT,UPDATE,INSERT ON TABLE Student TO R1; |
将一个角色授予其他的角色或用户
1 | GRANT R1 TO 王平,张明,赵玲; |
角色权限的收回
1 | REVOKE SELECT ON TABLE Student FROM R1; |
强制存取控制
敏感度标记
- 绝密、机密、可信、公开
主体:系统中的活动实体,如用户、进程
客体:系统中的被动实体,如表、行、列
敏感度标记
- 主体的标记:许可证级别
- 客体的标记:密级
基本规则:向下读,向上写
- 读权限:仅当主体的许可证级别 大于等于 客体的密级时,主体才能读客体。 (只能向下读 或平级读 )
- 写权限: 仅当主体的许可证级别 小于等于 客体的密级时,主体才能写客体。(只允许向上写或平级写,防止高密级信息泄露到低密级客体中)
SQL安全性管理
用户认证
权限管理
权限分类
- 对象权限
- 语句权限
用户管理
dbo用户:数据库拥有者或创建者
guest用户
角色管理
用角色统一授予和管理权限
作用: 为了简化权限管理,可以将一组相同的权限打包成一个“角色”,然后将角色授予用户,而不是一个个地给用户授予权限
操作: CREATE ROLE 角色名;
-> GRANT 权限 ON 对象 TO 角色名;
-> GRANT 角色名 TO 用户;
选择与综合题
- 在数据库系统中,允许用户定义和撤销其他用户对数据的存取权限,这属于数据库的 C 功能。 A. 完整性控制 B. 并发控制 C. 安全性控制 D. 恢复控制
- 假设数据库管理员(DBA)执行了以下SQL语句:
GRANT SELECT ON TABLE Student TO U1 WITH GRANT OPTION;
这条语句执行后,下列说法不正确的是?D
A. 用户U1拥有了查询Student表的权限。
B. 用户U1可以将查询Student表的权限授予其他用户。
C. DBA可以收回用户U1的SELECT
权限。
D. 其他用户自动拥有了查询Student表的权限。
假设你是数据库管理员(DBA),请针对“学生选课”数据库中的Student
(学生表)和SC
(选课表),为以下几位用户进行授权管理。
已知用户:
- 王老师 (W_Teacher)
- 李助教 (L_Assistant)
- 张同学 (Z_Student)
请写出完成以下需求的SQL语句:
- 授予王老师对
Student
表和SC
表的全部操作权限,并允许他将这些权限再授予他人。
GRANT ALL PRIVILEGES ON TABLE Student,SC TO W_Teacher WITH GRANT OPTION;
- 授予李助教对
SC
表的查询权限,以及修改其中Grade
(成绩)列的权限。
GRANT SELECT,UPDATE(Grade) ON TABLE SC TO L_Assistant;
- 现在李助教需要一位同学帮忙录入成绩,请将对
SC
表的插入权限授予张同学。注意:该授权应由李助教完成,但李助教本身并没有INSERT
权限,请先写出DBA如何使李助教能够完成此项授权。
第一步:DBA授权给李助教GRANT INSERT ON TABLE SC TO L_Assistant WITH GRANT OPTION;
第二步:李助教授权给张同学GRANT INSERT ON TABLE SC TO Z_Student;
- 由于张同学完成了成绩录入工作,请李助教收回其对
SC
表的INSERT
权限。
REVOKE INSERT ON SC FROM Z_Student;
- 王老师由于工作调动,不再负责学生管理。请收回之前授予王老师的所有权限,并同时收回由他授予出去的所有相关权限。
REVOKE ALL PRIVILEGES ON Student,SC FROM W_Teacher CASCADE;
- 创建一个名为
Student_Admin
的角色,该角色拥有对Student
表的查询、插入和修改权限,并将该角色授予给所有助教(假设只有李助教一人)。
第一步:创建角色CREATE ROLE Student_Admin;
第二步:给角色授权GRANT SELECT,INSERT,UPDATE ON Student TO Student_Admin;
第三步:将角色授予用户GRANT Student_Admin TO L_Assistant;
数据库完整性
-
正确性、相容性
-
实体完整性、参照完整性、用户定义的完整性
-
高级完整性控制:触发器Trigger
- 当对一个表执行
INSERT
、UPDATE
或DELETE
操作时,会自动触发预先定义好的一段SQL程序
维护完整性需要实现的功能
- 当对一个表执行
-
提供定义完整性约束条件的机制
-
提供完整性检查的方法
-
违约处理
实体完整性
主码唯一且非空
- 单属性主码:列级/表级
- 多属性主码:表级
PRIMARY KEY
定义主码
1 | -- 列级 |
参照完整性
目标:表间引用正确
外码的值要么取空值(NULL),要么必须等于其所参照关系中某个元组的主码值
FOREIGN KEY (外码列) REFERENCES 被参照表(主码列)
违约处理
当删除/更新被参照表的元组,可能破坏参照完整性时,系统有以下几种处理方式:
NO ACTION
或RESTRICT
(默认): 拒绝执行该删除或更新操作CASCADE
(级联): 删除/更新被参照表的元组时,自动删除/更新参照表中所有匹配的元组。SET NULL
(设置为空): 删除/更新被参照表的元组时,将参照表中所有匹配元组的外码值设置为NULL
1 | CREATE TABLE SC( |
显式说明违约处理
1 | CREATE TABLE SC ( |
用户定义的完整性
目标: 满足具体应用场景中,对数据提出的特定语义要求
- 属性上的约束:
NOT NULL
: 限制该列的值不能为空。UNIQUE
: 限制该列的值必须是唯一的。CHECK (布尔表达式)
: 限制该列的取值必须满足某个条件。
- 元组上的约束:
- 在表级定义
CHECK
约束,可以对元组中的多个属性值之间的关系进行限制。
- 在表级定义
完整性约束命名子句
CONSTRAINT <完整性约束条件名>[PRIMARY KEY短语|FOREIGN KEY短语|CHECK短语]
完整性约束命名子句 (CONSTRAINT
): 可以为每个约束条件命名,方便后续的修改和删除。 CONSTRAINT 约束名 CHECK (布尔表达式)
1 | CREATE TABLE Student ( |
修改约束条件
1 | ALTER TABLE Student |
大题
现有部门表Department(DeptNo, DeptName)
和员工表Employee(EmpNo, EmpName, DeptNo)
。请为Employee
表编写CREATE TABLE
的SQL语句,要求满足以下完整性约束:
EmpNo
是主码。EmpName
不能为空。DeptNo
是外码,参照Department
表的DeptNo
列,当部门被删除时,该部门所有员工的部门编号自动设为空值
1 | CREATE TABLE Employee( |
数据类型选择技巧:
数据类型 | 适用场景 | 例子 | 备注 |
---|---|---|---|
CHAR(n) |
定长字符串 | 性别(‘男’/‘女’), 身份证号, 学号 | 长度固定时用它,效率略高。 |
VARCHAR(n) |
变长字符串 | 姓名, 地址, 备注, 课程名 | 长度不固定时用它,节约空间,最常用。 |
INT, SMALLINT |
整数 | 年龄, 数量, ID号 | 根据取值范围选最小的类型,如年龄用SMALLINT 。 |
NUMERIC(p,d) |
精确小数 | 金额, 工资, 成绩 | 凡是和钱有关,或要求精确计算的,别用FLOAT 。 |
DATE, DATETIME |
日期/时间 | 出生日期, 订单时间 | 只要是日期时间就用它,方便计算和校验。 |
数据库恢复技术
一句话概括本章:事务 是基本单位,日志 是恢复依据,检查点 是提高恢复效率的手段。恢复操作无非就是对未提交的事务进行UNDO,对已提交的事务进行REDO
事务
用户定义的数据库操作序列,不可分割,恢复 和并发控制 的基本单位
定义事务
- 显式定义:
BEGIN TRANSACTION
开始,COMMIT
(提交)或ROLLBACK
(回滚)结束 - 隐式定义:没有显式定义时,DBMS会按默认规则自动划分事务
1 | BEGIN TRANSACTION |
事务的ACID特性
- (Atomicity)原子性:不可分割
- (Consistency)一致性:事务前后数据库处于一致状态
- (Isolation)隔离性:并发执行的事务不能相互干扰
- (Durability)持续性:事务提交,对数据库的改变是永久的
故障
分类
- 事务内部故障
- 恢复:撤销事务UNDO
- 系统故障(软故障):导致内存数据丢失
- 恢复
- 事务未提交:强行撤销UNDO
- 事务已提交:重做REDO
- 恢复
- 介质故障(硬故障):导致磁盘数据丢失
- 计算机病毒(人为)
影响
- 数据库本身被破坏
- 数据不正确
两大核心恢复操作
UNDO (撤销)
- 目标:撤销未提交(COMMIT) 的事务,保证原子性。
- 方法:反向扫描日志,用日志中的【更新前的值】(旧值)去覆盖数据库中的值
REDO (重做)
- 目标:重做已提交(COMMIT) 的事务,保证持续性。
- 方法:正向扫描日志,用日志中的【更新后的值】(新值)去覆盖数据库中的值
恢复的实现技术
核心思想:数据冗余
两大技术:数据转储、登记日志文件
数据转储
定期备份数据库
静态转储与动态转储
- 静态:系统中无运行事务时进行;降低数据库可用性
- 动态:转储操作与用户事务并发进行;需要配合日志文件才能恢复
海量转储与增量转储
- 海量(完全转储):每次转储全部数据库
- 增量:只转储上次转储后更新过的数据
登记日志文件
日志文件:用来记录事务对数据库的所有更新操作
日志文件的作用
- 进行事务故障恢复
- 进行系统故障恢复
- 协助后备副本进行介质故障恢复
以记录为单位
- 事务的开始标记(BEGIN TRANSACTION)
- 事务的结束标记(COMMIT或ROLLBACK)
- 事务标识、操作类型、操作对象、旧值、新值
以数据块为单位
- 事务标识
- 被更新的数据块
登记日志的基本原则:先写日志文件,后写数据库
为什么要先写日志文件
- 写数据库和写日志文件是两个不同的操作,在这两个操作之间可能发生故障
- 如果先写了数据库修改,而在日志文件中没有登记下这个修改,则以后就无法恢复这个修改了
- 如果先写日志,但没有修改数据库,按日志文件恢复时只不过是多执行一次不必要的UNDO操作,并不会影响数据库的正确性
恢复策略(重点)
事务故障恢复
策略:UNDO
步骤:系统利用日志文件,反向扫描 该事务的所有更新操作,并执行其逆操作
- INSERT的逆操作是DELETE,UPDATE的逆操作是用“更新前的值”写回
系统故障的恢复
策略:UNDO+REDO
步骤:
- 正向扫描日志,建立两个列表
- UNDO-LIST:故障发生时,已开始但未提交 的事务
- REDO-LIST:故障发生前,已经提交 的事务
- 对 UNDO-LIST 中的所有事务执行 UNDO 操作
- 对 REDO-LIST 中的所有事务执行 REDO 操作,确保它们对数据库的修改已全部写入磁盘
具有检查点的恢复技术
目的:解决系统故障恢复时,需要扫描整个日志文件导致效率低下的问题
检查点(Checkpoint):是在日志文件中增加的一种记录,它代表在这个时间点之前,所有已提交事务 的修改都已经从内存缓冲区写入磁盘数据库
恢复步骤:(看后面的大题理解着背)
- 从日志文件末尾反向 找到最后一个检查点 记录
- 根据检查点记录,确定在检查点时刻所有正在执行的事务,将它们放入 UNDO-LIST
- 从检查点开始,正向扫描 日志文件直至末尾:
- 如果发现新的事务
Ti
开始,则将其加入UNDO-LIST
- 如果发现事务
Tj
提交,则将其从UNDO-LIST
移到REDO-LIST
- 如果发现新的事务
- 扫描结束后,对最终的
UNDO-LIST
中的所有事务执行UNDO
对REDO-LIST
中的所有事务执行REDO
结果
- 在检查点前提交的不用管
- 在检查点后提交REDO
- 故障时还没提交UNDO
介质故障的恢复
最严重的故障,需要DBA介入
步骤
- 重装最新的数据库后备副本,将数据库恢复到最近一次转储时的一致状态
- 重做(REDO)所有已完成的事务。即装入转储后的所有日志文件,对所有已提交的事务进行REDO操作
数据库镜像
提高数据库可用性
DBMS会自动把整个数据库或者关键数据复制到另一个磁盘上,形成一个镜像
用途
- 出现介质故障时:由镜像磁盘继续提供使用
- 没有出现故障时:用于并发操作
实际应用中往往只对关键数据 和日志文件 镜像
大题
假设一个数据库系统在运行过程中,其日志文件(部分)按时间顺序记录如下。系统在 Tf
时刻突然崩溃。
日志记录:
[BEGIN T1]
[BEGIN T2]
[T1, X, 10, 20]
[COMMIT T1]
[CHECKPOINT]
(活跃事务列表:{T2}
)[T2, Y, 50, 60]
[BEGIN T3]
[T3, Z, 80, 90]
[BEGIN T4]
[T2, Y, 60, 70]
[ROLLBACK T4]
[COMMIT T3]
[T2, W, 30, 40]
(Tf) <-- 系统在此刻崩溃
请回答:
- 系统恢复时,需要被 UNDO 的事务有哪些?需要被 REDO 的事务有哪些?
- 请简述完整的恢复过程。
第一步:定位检查点和初始化列表
- 从后往前找到最后一个检查点,是记录5
[CHECKPOINT]
。 - 检查点指出,当时的活跃事务是
{T2}
。 - 因此,初始化两个列表:
UNDO-LIST = {T2}
REDO-LIST = {}
第二步:从检查点开始正向扫描日志
- 从记录6
[T2, Y, 50, 60]
开始向后扫描:- 记录7
[BEGIN T3]
:T3
开始,加入UNDO-LIST
。UNDO-LIST
变为{T2, T3}
。
- 记录9
[BEGIN T4]
:T4
开始,加入UNDO-LIST
。UNDO-LIST
变为{T2, T3, T4}
。
- 记录11
[ROLLBACK T4]
:(陷阱来了!)T4
事务自己回滚。T4
的所有操作已经被它自己撤销。将T4
从UNDO-LIST
中移除。UNDO-LIST
变为{T2, T3}
。
- 记录12
[COMMIT T3]
:T3
提交,将T3
从UNDO-LIST
移动到REDO-LIST
。UNDO-LIST
变为{T2}
。REDO-LIST
变为{T3}
。
- 记录14
(Tf)
:到达故障点,扫描结束。
- 记录7
第三步:执行恢复操作
- 检查扫描结束后最终的列表:
UNDO-LIST = {T2}
REDO-LIST = {T3}
- 执行 UNDO:对
UNDO-LIST
中的事务T2
执行 UNDO 操作- 系统反向查找
T2
的所有操作(记录13、记录6),将W恢复为30,Y恢复为50
- 系统反向查找
- 执行 REDO:对
REDO-LIST
中的事务T3
执行 REDO 操作- 系统正向查找
T3
的所有操作(记录8),确保Z的值为90
- 系统正向查找
第四步:得出结论
- 需要 UNDO 的事务是:T2
- 因为它在系统故障时,尚未提交
- 需要 REDO 的事务是:T3
- 因为它在检查点之后、故障点之前提交了
- 不需要处理的事务是:T1、T4
T1
(在检查点前已提交)T4
(在故障前已由自身ROLLBACK
)
可能考的点
- 为什么执行UNDO/REDO:结合前面的“两大核心恢复操作”的内容回答,根据事务的ACID性质。(原子性/持续性)
- 日志中出现
ROLLBACK
:
- 事务自己已经完成了回滚,不需要再执行UNDO
关系数据理论
规范化
目的:尽量消除
- 插入、删除异常
- 修改复杂(更新异常)
- 数据冗余
根本原因:属性间的函数依赖 关系不合理
模式分解:通过模式分解,消除不合理的函数依赖
一般讨论的是非平凡函数依赖
码:候选码、主码、超码、全码、主属性与非主属性
函数依赖
- 完全依赖和部分依赖
- 传递函数依赖
- 多值依赖:平凡多值依赖和非平凡的多值依赖
范式
==低一级范式的关系模式,通过模式分解 可以转换为若干个高一级范式的关系模式的集合,这种过程就叫规范化 ==
4NF和BCNF等价的情况:所有存在的非平凡多值依赖,都同时是函数依赖
模式分解
- 分解具有无损连接性:分解后的关系可以通过自然连接 恢复为原来的关系,那么这种分解就没有丢失信息
- 分解要保持函数依赖(减轻或解决异常情况)
- 若仅要求分解是无损连接,那么模式分解一定能够达到BCNF
- 若要求分解既具有无损连接性,又保持函数依赖,则模式分解一定能够达到3NF,但不一定能够达到BCNF
范式判断与模式分解大题
这四步都可能单独考
第一步:求候选码
- 属性分类:
- 只出现在函数依赖左边 的,肯定是 候选码
- 只出现在函数依赖右边 的,肯定不是 候选码
- 两边都没出现的,肯定是 候选码
- 两边都出现的,可能是 候选码
- 求闭包验证:
- 将肯定是候选码 的属性作为一个集合,求闭包(这些属性能确定的所有属性 )
- 如果闭包包含所有属性,则该集合为候选码
- 如果闭包不能包含所有属性,在集合中分别 加入可能 是候选码的属性,再求闭包,直到包含所有属性(可能会出现很多个满足的候选码集合)
第二步:逐级判断范式
- 1NF:肯定满足,写所有属性是不可分割的原子值
- 2NF
- 写出非主属性和候选码
- 若候选码为单个属性,一定通过
- 若候选码为复合属性,检查非主属性是否依赖部分的候选码(依赖非主属性的不管),若不存在则通过
- 通过写不包含非主属性对码的部分函数依赖
- 3NF
- 检查是否不存在非主属性依赖于非主属性
- 通过写 不包含非主属性对码的传递函数依赖
- BCNF
- 前面的检查了非主属性的函数依赖,这步检查候选码的函数依赖
- 简单来说,出现在箭头左边 的部分必须全都包含候选码
- 通过写 每一个决定属性因素都包含码
- 4NF(一般不考)
- 前面对函数依赖进行了检查,这一步检查多值依赖
- 没有多值依赖的当然通过
- 找到 型依赖关系,检查左边是否包含 候选码
- 通过写 不存在非平凡且非函数依赖的多值依赖
第三步:模式分解
- 不满足2NF:解决部分依赖
- 将导致部分依赖的函数依赖单独拿出来创建一个新关系R1
- 从原关系R中去掉拿出的函数依赖的右边的非主属性得到R2
- 由此将R分解为R1和R2
- 一直分解直到没有部分依赖
- 不满足3NF:解决传递依赖
- 将导致传递依赖的函数依赖单独拿出来创建一个新关系R1
- 从原关系R中去掉拿出的函数依赖的右边的属性得到R2
- 由此将R分解为R1和R2
- 一直分解直到没有传递依赖
- 此时达成满足无损连接性 和保持函数依赖 的3NF
- 分解到BCNF:
- 出现在箭头左边 的部分必须全都包含候选码,将反例拿出来
- 把这个函数依赖单独拿出来形成新关系R1
- 从原关系R中去掉拿出的函数依赖的右边部分得到R2
- 由此将R分解为R1和R2
- 一直分解直到没有反例出现
- 此时达成满足无损连接性 的BCNF,但不一定 保持函数依赖
第四步:判断分解无损连接性和保持函数依赖性(大概是不考)
- 判定分解的无损连接性
- 公式:和为的分解,该分解是无损分解只要原关系R 中有如下函数依赖中的一个:
- 通俗解释:公共决定独有 是否成立
- 公共属性是否能决定R1的独有属性?
- 公共属性是否能决定R2的独有属性?
- 以上两条满足一个即可
- 以上公式只能用于一分为二 的情况,不能用于一分为多
- 公式:和为的分解,该分解是无损分解只要原关系R 中有如下函数依赖中的一个:
- 判定分解是否保持函数依赖
- 原关系中的每一个函数依赖,左边和右边必须包含在分解后的其中一个中(如果是 的函数依赖要拆成 和 看)
数据库设计
对于一个给定的应用环境,构造(设计)优化的数据库逻辑模式和物理结构,并据此建立数据库及其应用系统
基本步骤
- 需求分析
- 概念结构设计
- 逻辑结构设计
- 物理结构设计
- 数据库实施
- 数据库运行和维护
需求分析 和概念设计 独立于任何数据库管理系统
逻辑设计 和物理设计 与选用的DBMS密切相关
自顶向下地进行需求分析、自底向上地设计概念结构
概念结构设计(E-R图)
- 抽象数据并设计局部视图
- 抽象:对实际的人、物、事和概念中抽取共同特征,并用概念描述
- 提取数据→参照数据流图标定局部中的实体、属性、码→确定实体之间的联系及类型
- 集成局部视图,得到全局概念结构
常用抽象
- 分类:抽象对象值与型的语义
- 聚集:抽象对象内部类型和成分的语义
实体和关系都可以拥有自己的属性
进阶考点:分E-R图的合并与冲突解决
- 属性冲突:不同分E-R图中,某个属性的类型、长度、取值范围不一致;合并时必须统一
- 命名冲突:同名异义、异名同义
- 结构冲突:同一个对象,在不同的分E-R图中,抽象的类型不一样
- 在A视图中为属性,在B视图中为实体…
- 合并需统一,通常选更精细的实体
逻辑结构设计
E-R图向关系模型转换:
- 实体转换规则
- 每一个实体(E-R图中的矩形)都转换为一个独立的表
- 实体的属性(椭圆形)就是表的字段,实体的码 就是表的主码
- 联系转换规则
- 1:1联系:在任意一方 的表中,加入另一方的主码作为外码,并把联系本身的属性 也加到这个表中
- 1:n联系:在“n”的那一方的表中,加入“1”那一方的主码作为外码,并把联系本身的属性也加到“n”这一方的表中
- m:n联系:为这个联系单独建立一张新表,这张新表的主码是原来两方实体主码的组合,同时也要把联系本身的属性加入到这张新表中
优化:有相同码的关系模式可以合并
- 选择一个关系模式(表)作为基础
- 将另一个关系模式的所有属性(除了主码)加入到这个基础表中
- 去掉多余的同义属性
实验题
数据控制(安全性与完整性)
安全性控制 (授权与回收)
这部分的核心是GRANT
和REVOKE
语句
完整性控制 (约束)
这部分的核心是确保数据的正确性和相容性,主要通过定义表时加入各种约束来实现
考点:三个完整性的定义、创建表时如何增加完整性语句
数据库备份与恢复
这部分是从实验报告里摘的
“如何进行一次完整的数据库备份?请写出关键步骤和SQL命令。”
- 将数据库的恢复模式设置为
FULL
,这样才能进行事务日志备份。然后使用BACKUP DATABASE
命令 - 核心语句:
ALTER DATABASE [Student-Course] SET RECOVERY FULL;
BACKUP DATABASE [Student-Course] TO sql_backup;
“在进行了一次完整备份后,数据库发生了一些写操作(如INSERT),如何只备份这些新增的操作?”
- 备份事务日志
- 核心语句:
BACKUP LOG [Student-Course] TO sql_backup;
“假设数据库崩溃,如何利用最近的完整备份和事务日志备份,将数据库恢复到最新的状态?简述步骤并写出关键命令。”
- 先用
NORECOVERY
选项恢复完整备份,使数据库进入一个中间状态,不允许访问,但可以继续接受后续日志的恢复 - 再用
RECOVERY
选项恢复事务日志备份,完成恢复过程并使数据库可用 - 核心语句:
RESTORE DATABASE [Student-Course] FROM sql_backup WITH NORECOVERY;
RESTORE LOG [Student-Course] FROM sql_backup WITH RECOVERY;
数据库编程
“在数据库编程中,若使用字符串拼接的方式构造SQL查询语句,会存在什么安全风险?请举例说明。”
- 风险:SQL注入攻击
当程序直接将用户输入拼接到SQL语句中时,恶意用户可以构造特殊的输入,改变SQL语句的原有逻辑 - 举例:当原始查询是
SELECT * FROM 教师表 WHERE (登陆帐号='
+ 用户输入 +')
时,如果用户输入' OR 1=1 --
,最终执行的语句就变成了SELECT * FROM 教师表 WHERE (登陆帐号='' OR 1=1)
,WHERE
条件恒为真,从而绕过了密码验证
“针对SQL注入风险,应如何改进程序以实现安全防护?”
- 核心思想 :永远不要信任用户的输入,不要直接拼接SQL字符串
- 使用参数化查询或预编译语句
- 这样,用户输入的内容就只会被当作参数值来处理,而不会被当作SQL代码执行,从而杜绝了SQL注入的可能
“请简述使用JDBC连接并查询数据库的主要步骤。”
- 加载JDBC驱动(SQL Server 或 MySQL)
- 实现方式:通过
Class.forName()
方法加载驱动类。
- 实现方式:通过
- 建立数据库连接
- 实现方式:使用
DriverManager.getConnection()
方法
需要提供:数据库的URL、用户名和密码
- 实现方式:使用
- 创建并执行SQL语句
- 执行查询 (
SELECT
)- 实现方式:通过
Connection
创建Statement
对象,调用executeQuery(String sql)
方法,返回一个ResultSet
对象
- 实现方式:通过
- 执行更新 (
INSERT
、UPDATE
、DELETE
)- 实现方式:通过
Connection
创建Statement
对象,调用executeUpdate(String sql)
方法,返回一个整数,表示受影响的行数
- 实现方式:通过
- 执行查询 (
- 处理结果集
ResultSet
ResultSet
对象是一个指向查询结果数据行的游标- 实现方式:
- 使用
while (rs.next()) { ... }
循环来遍历每一行数据,rs.next()
会将游标移动到下一行,如果成功则返回true
。 - 在循环内部,使用
rs.getString("列名")
、rs.getInt("列名")
等方法获取当前行指定列的数据
- 使用
- 关闭资源
- 实现方式:按照“后开先关”的顺序,依次关闭
ResultSet
、Statement
和Connection
对象
- 实现方式:按照“后开先关”的顺序,依次关闭