☰
SQL Server学习笔记:三层架构、范式约束与可编程对象梳理
2026/10/31 20:32:53 网站建设 项目流程

简介:这份SQL Server学习笔记面向数据库管理初学者及运维、开发人员,帮助读者快速了解SQL Server的主要特点与核心知识点,可作为入门复习、课堂配套和日常查阅的参考。笔记从数据库对象与结构入手,梳理Create、Drop、Alter等基本操作,C/S体系与常见编程接口,表、列、索引、触发器、存储过程的容量限制,并延伸到关系数据库模型中的实体、属性、码、域,以及层次、关系、网状和面向对象等数据模型。同时整理数据库授权、系统数据库作用、mdf/ndf/ldf文件与文件组、创建数据库和建表语句、主键/外键/默认值/check/unique约束等要点,并强调关系表中列类型一致、字段名不重复等基本规则,内容按知识模块组织,便于对照记忆和查漏补缺。压缩包共1个doc文件,约499KB,篇幅精炼,适合按主题检索。已有440人学习,适合需要系统梳理SQL Server基础概念的读者。

1. 一张三层地图:这份 SQL Server 学习笔记该从哪儿读起

SQL Server 学习笔记最容易读成一本语法字典:先记 CREATE 怎么拼,再背 INSERT 后面跟什么,最后发现一到判断题还是发懵。问题不在语法,而在这门知识本身是三层结构,缺少哪一层都对不上号。底层是架构与存储——C/S 体系、六个系统数据库、mdf/ndf/ldf 三类文件、一张动不动就被考到的容量参数表;中间是关系模型与范式——实体、属性、码、域,以及 1NF 到 BCNF 的判断顺序;上层是可编程对象与完整性控制——五类约束、视图、簇索引与非簇索引、存储过程、游标、授权链。这三层之间的对应关系,才是复习时真正该盯住的东西。

这份梳理适合已经能写几条 SQL、正在备考或者准备面试、想要一张能查漏补缺清单的人。零基础也能看,但先把地图记住,比先背语法划算得多。

2. 架构与存储:C/S 体系、六个系统库与三类物理文件

2.1 C/S 体系与编程接口:SQL Server 站在哪一层

SQL Server 采用 C/S 体系,也就是客户端与服务器分离:客户端负责界面、业务逻辑和用户交互,服务器负责数据存储、查询解析与执行。这个划分看着简单,却决定了很多后续概念的位置——登录、用户、角色为什么是两套东西,权限为什么要先建登录再建用户,根子都在这个“两边分离”的结构上。

接口层面,它提供丰富的编程接口:ODBC、VB、VC、Access 都能接进来。接口多带来的好处是前端语言可以换,坏处是复习时容易把“接口”和“语言”混成一类东西,看到题目问“支持哪些编程接口”就把 C#、Java 也写上去。更稳妥的记法是:接口是通道,语言是通道两端的实现,通道本身只有 ODBC 这一类标准接口。

功能面上还有几条常被忽略:支持 Web,可做基于 Web 的分析;提供数据仓库功能;支持 XML(扩展标记语言);支持分布式分区视图;配有分布式管理框架。单库大小范围是 1MB 到 1TB。这几条在简答题里出现频率不低,尤其是“分布式分区视图”和“分布式管理框架”,很多人只记得“分布式”三个字,答不出具体是分区视图还是管理框架。

2.2 六个系统数据库:每个都对应一个典型故障场景

系统数据库不是“装完就忘”的东西,它们各自对应一类操作。下面这张表建议直接背,尤其是 Master 和 Model 的区别,这是最经典的一道送分题,也是最容易答反的一道。

系统数据库作用记忆抓手
Master保存主数据:登录账号、其他 SQL Server 数据库、服务器所有配置信息它出问题,整个实例起不来
Model模板库,创建新数据库时以它为模板,包含每个数据库都有的系统表改它等于改之后新建的所有库
Tempdb存储临时表的数据库用户退出或连接终止,内容自动消失
Msdb默认大小 12MB,保存调度作业、警报、接收警报的操作员信息代理、备份历史都在这
PubsSQL Server 提供的样例数据库教学演示用
NorthwindSQL Server 提供的样例数据库教学演示用

注意 Tempdb 那条“连接终止就消失”,和临时表的概念是同一件事的两面:临时表存放在临时数据库里,用户退出或与数据库的连接终止时自动消失。复习时把这两句绑在一起记,比分开背两个知识点省力。

2.3 三类物理文件与文件组:数据库在磁盘上长什么样

逻辑上的数据库,最终要映射成几个操作系统文件,这是“存储”这一块的核心结论。分三类:

文件类型扩展名职责注意点
主要数据文件.mdf包含数据库的启动信息,并存储数据一个库有且只有一个
次要数据文件.ndf存放主要文件容纳不下的数据数据要跨多个磁盘时用它延伸
日志文件.ldf记录用于恢复数据库的日志信息保证事务机制与可恢复性

日志文件的分量要单独强调:它是保证数据库事务机制和可恢复性最重要的手段,事务日志就是一个不可分割的数据库操作的日志记录。也就是说,日志不是“顺手记一下”,而是回滚和恢复的依据,删日志文件等于把后悔药扔了。

文件组则是文件之上的管理单位,作用是方便对文件进行管理,构成分配或用于数据库管理的单个单元。理解顺序是:文件 → 文件组 → 数据库,一层套一层,不要跳。

2.4 创建数据库的语句结构与容量参数表

创建数据库的语句结构是三段式:CREATE DATABASE 定名,ON 定义数据文件,LOG ON 定义事务日志文件。每个文件要写清文件名、存储路径、初始大小、可增长到的最大值、增长增量五个要素。

CREATE DATABASE ShopDB ON ( NAME = 'ShopDB_data', -- 逻辑文件名 FILENAME = 'D:\data\ShopDB.mdf', -- 主要数据文件路径 SIZE = 10MB, -- 初始大小 MAXSIZE = 500MB, -- 能增长到的上限 FILEGROWTH = 5MB -- 每次增长的增量 ) LOG ON ( NAME = 'ShopDB_log', FILENAME = 'D:\data\ShopDB.ldf', SIZE = 5MB, MAXSIZE = 200MB, FILEGROWTH = 5MB );

五个参数里最容易漏写的是 MAXSIZE 和 FILEGROWTH:前者决定磁盘会不会被一个库吃光,后者决定增长时是一次性拿一大块还是每次拿一点点。一般用户建库时不指定方括号里的可选项,语句关键字大小写意义相同,数据库的逻辑名甚至可以是中文——这几点原文特意提了,说明它们都是判断题爱考的地方。

容量参数是这一章的硬骨头,一张表扫完:

对象上限
每个数据库的表20 亿个
每行的字符8060 个字符
每个表的列1024 列
索引每表 1 个簇索引、249 个非簇索引(每个索引 16 列)
触发器每表 3 个:INSERT、UPDATE、DELETE
存储过程最多 1024 个参数,32 级嵌套
用户连接32767 个
锁定及打开对象20 亿个(按表的个数算)
可同时打开的数据库327687 个
数据库大小1MB — 1TB

这张表的价值不在于全背,而在于认出哪些数字是“成对出现”的陷阱:表的个数和锁定对象都是 20 亿,列是 1024,存储过程参数也是 1024,索引是 1 + 249。把数字按“20 亿组、1024 组、32767 组”重新归类,比按行死记牢得多。

3. 关系模型与范式:实体、码、依赖与三范式的判断链

3.1 从概念模型到数据模型:实体、属性、码、域

概念模型是对现实世界的第一次抽象,数据模型是对概念模型的第二次落地。数据模型包含三要素:数据结构、数据操作、数据的约束条件。这三条几乎每次简答都会问,答的时候别只写“有结构有操作”,要把约束条件单列出来。

往下是实体这一组定义,必须能互相区分:

  • 实体:客观存在的、可以相互区分的事物。
  • 属性:实体所具有的某一特性,例如性别。
  • 码(键):唯一标识实体的属性集,例如学号是学生实体的码。
  • 域:属性的取值范围,例如性别取值为男、女;学号是 11 位整数。
  • 实体型:对同类实体的抽象和刻画,用实体名加属性集合表示,例如顾客(编号、姓名、性别、年龄)。
  • 实体集:同型实体的集合,全体学生、全体顾客都是实体集。
  • 联系:包括实体内部的联系和实体之间的联系。

“实体型”和“实体集”是最容易混的一对:实体型是那个括号里带属性列表的模板,实体集是照这个模板填出来的一堆具体记录。一个说结构,一个说集合,含混过去就会在选择题上翻车。

常用的数据模型有四类:层次模型、关系模型、网状模型、面向对象模型。当前主流是关系模型,但“主流”不等于“唯一”,答“常用数据模型有哪些”时四类都要写全。

3.2 关系术语对照:同一件事的两套叫法

关系数据库最烦的地方是同一件事有两套名字,一套数学味,一套工程味。对照表如下:

数学叫法工程叫法说明
关系一张表每张表就代表一个关系
元组表中的一行一行就是一条记录
属性表中的一列一列就是一个字段
分量元组中的一个属性值单元格
域属性的取值范围列的取值约束
主码唯一确定一个元组的属性组可以是单列,也可以是多列组合
关系模式对关系的描述关系名 + 列名 + 域名 + 映射 + 依赖

关系模式那一条的完整表述是:关系名、列名、属性所属的域名、属性向域的映射、数据间的相互依赖关系。五个部分,少写一个就扣分。

3.3 一个关系能成立,要过五道关

关系是数据与数据之间的联系,它必须符合以下条件,这五条建议按顺序背:

  1. 每一列的数据类型都必须相同。
  2. 没有完全相同的行。
  3. 列与列之间的字段名不能重复。
  4. 没有组合列,即一列中不能有子列,也不能把一列分割成两列或更多列。
  5. 每一列都是不可再分的原子数据项(这条与第一条常被合起来描述第一范式)。

第四条是后面第一范式的直接铺垫。原文那个例子很典型:把商品所属类别做成 Goods_id(goods_type_1, goods_type_2, goods_type_3) 这种带下标的组合列,按生活用品查询商品编号时结果为空——不是数据错了,是结构本身违背了“没有组合列”。

3.4 四级范式:1NF 到 BCNF 的判定链

范式是对关系的不同数据依赖程度的要求,判断顺序必须固定,跳步就会判错。

第一范式:所设计表的每一个分量必须是不可分的数据项,即每一列不许是集合、序列等非原子属性。把非第一范式的表转成第一范式有两条路:一是把非原子属性列变为原子属性列,可以拆成多列,也可以拆成多行;二是分解表,把一张表拆成多张表。要注意的是,分量是否需要继续划分,与具体情况相关——这条备注常被忽略,它意味着 1NF 不是绝对的,取决于使用场景。

第二范式:在满足第一范式的前提下,每个非主属性完全依赖于码,即不存在部分依赖于码的非主属性。看一个经典反例:

-- 联合主键:(用户编号, 商品编号) CREATE TABLE buy_info ( 购买了商品的用户编号 VARCHAR(10), 用户购买商品编号 VARCHAR(10), 用户购买商品名称 VARCHAR(10), -- 只依赖商品编号,不依赖用户编号 PRIMARY KEY (购买了商品的用户编号, 用户购买商品编号) );

用户购买商品名称只由商品编号就能决定,只依赖联合主键的一部分,这就是部分依赖,违反 2NF。而且联合主键的任何一个属性都不能为空,一旦主键值为空就会出现插入异常,重复存入数据又会造成更新困难,两个毛病是连在一起的。

第三范式:在一组关系中若存在传递关系,即 A 能推出 B、B 能推出 C(C 不属于 B),且 B 不能推出 A,则不满足第三范式。换句话说,3NF 要求不存在非主属性对码的传递依赖。判断时先确认 1NF 和 2NF,再看有没有“非主属性决定非主属性”的链条。

BCNF:修正的第三范式,要求更严——所有决定因素都必须是候选码。3NF 允许主属性对码的部分与传递依赖,BCNF 一律不允许。两者的差别不在“更高级”三个字上,而在依赖的主语是谁:3NF 管非主属性,BCNF 连主属性一起管。

3.5 建表时的三种码:候选码、主码、外部码

候选码是此列值组唯一标识一行的属性组,可以是一列,也可以是多列的组合;主码是从候选码中选定一个作为主码,拥有候选码的全部特征;主码中的属性叫主属性,不包含在任何候选码中的属性叫非主属性;外部码用来联系不同的两张表。这一段是后面约束和参照完整性的伏笔:主键约束对应实体完整性,外键约束对应参照完整性,两种完整性在概念层就已经分好了。

4. 约束、完整性与可编程对象:五类约束到游标的落地

4.1 五类约束:各自管什么、写在哪

约束关键字管什么一句话记忆
主键约束PRIMARY KEY唯一标识每行值不能为空,且每行唯一
外键约束FOREIGN KEY ... REFERENCES两张表之间的对应连接动一张表要顾及另一张
默认值约束DEFAULT用户未指定时系统自动指派空着就按默认填
用户自定义约束CHECK限定输入的取值范围不满足就拒绝执行
唯一性约束UNIQUE列值不可重复可空但不可重

主键和唯一性的差别在“空”这一项:主键值不能为空并保证每行都有非空且唯一值;唯一性约束只强制值不重复,允许空值。这一点在选择题里出现的频率极高。

外键的作用是建立两张表之间的连接关系,使用户在一张表做增删改时要顾及与之关联的另一张表。默认值约束的完整表述是:当用户未指定时由系统自动指派的数据值、选项设置、排序规则或名称,即当用户未指定某些事件发生后要采取的操作时,自动采取的操作。CHECK 则是用户自建的一种规范,输入值不满足规范时系统拒绝执行,用来确保域的完整性。

跑一组建表与改表的语句,把上面五类约束落一遍:

CREATE TABLE employees ( employee_id VARCHAR(10), first_name VARCHAR(50) NOT NULL, last_name VARCHAR(50) NOT NULL, email VARCHAR(50), phone_number VARCHAR(10), hire_date DATETIME, job_id VARCHAR(10), salary MONEY, commission_pct VARCHAR(50), manager_id VARCHAR(10) REFERENCES employees(employee_id), -- 自引用外键 department_id VARCHAR(10), CONSTRAINT pk_employees PRIMARY KEY (employee_id), -- 主键约束 CONSTRAINT uq_email UNIQUE (email), -- 唯一性约束 CONSTRAINT ck_hire_date CHECK (hire_date < '2990-01-01') -- 检查约束 );

参数说明:manager_id 引用本表的 employee_id,是自引用外键,用来表示上下级;CONSTRAINT 后跟约束名,方便以后用 ALTER 直接定位删除。写这类语句时给每个约束起名字是个好习惯,否则后来想删约束只能靠系统生成的乱码名。

4.2 数据类型与插入数据的匹配

常用数据类型按类记:

类型含义关键参数
char(n)固定长度字符型n 介于 1—8000,实际存储长度 n,超长会被截掉
varchar(n)可变长度字符型存储大小为输入字符的实际字节长度,而不是 n
int / bigint / smallint / tinyint整型按取值范围从大到小
numeric(p, s)精确数值型p 总位数,s 小数位
money货币与现金值不需单引号,但要带适当货币符号
datetime日期和时间代表一天内的时间
table存储一组数据,作为函数结果集返回只支持主键、唯一性和空值约束

char 与 varchar 的差别是必考点:char 是定长,写进去 3 个字符也占 n 个位置;varchar 按实际长度存,省空间但略有开销。字符常量必须放在单引号或双引号中,这是语法层面的硬要求。

插入数据时有一条坑:插入的列值必须与表中列的个数和顺序相匹配,否则插入操作失败。如果建表时该列允许为空,没有数据可以用 NULL 代替。table 类型是个特殊存在,定义方式和建表差不多,包括列名、数据类型和约束条件,但只支持主键、唯一性和空值约束——这一句别记成支持全部约束。

4.3 完整性四分类与三种强制手段

数据完整性指存储在数据库中的所有数据必须保持正确状态,在逻辑上保持一致性和准确性。分四类:

  • 域完整性:输入到某一列的数据是否符合这一列的要求,即列的输入有效性,是对“列”做的规定。
  • 实体完整性:要求基本表中每一行有唯一标识符,能和其它行区分,使表中没有重复行,一般用主键定义,是对“行”做的规定。
  • 用户自定义完整性:由用户按业务规则自行约定的约束。
  • 参照完整性:维护表之间主键与外键的对应关系,在插入或删除记录时保持表之间已定义的关系。

这四类最容易错的地方是“域的完整性管列、实体完整性管行”这一句对不上号,答反了就全错。记忆抓手:列有取值范围,所以域管列;行要能区分,所以实体管行。

强制手段有三种:约束、默认、规则。约束是最主要的方式,五类约束分别对应上面的完整性;默认值用于插入时给没有数据的列赋默认值;规则是另一种强制方式,配合默认对象使用:

CREATE DEFAULT 生活用品 AS '生活用品'; -- 先建默认对象 EXEC sp_bindefault '生活用品', 'goods.goods_type_name'; -- 再绑定到指定列

这里的顺序不能反:先建对象,后绑定列。默认对象是独立存在的实体,可以被绑定到多个列上,删列前要先解绑。

4.4 ALTER TABLE 的五个动作与删列限制

修改表的语句一共五类动作,复习时按“增、删、开关、改型、改数据”记:

-- 1. 增加列或增加约束 ALTER TABLE goods ADD 商品产地 VARCHAR(50); ALTER TABLE goods ADD CONSTRAINT ck_amount CHECK (商品金额 > 0); -- 2. 删除约束,再删除列(顺序不能反) ALTER TABLE goods DROP CONSTRAINT ck_amount; ALTER TABLE goods DROP COLUMN 商品产地; -- 3. 关闭与打开约束 ALTER TABLE goods NOCHECK CONSTRAINT ALL; -- 关闭表上所有约束 ALTER TABLE goods CHECK CONSTRAINT ALL; -- 重新打开 -- 4. 修改列的数据类型或可空性 ALTER TABLE goods ALTER COLUMN 商品金额 INT NULL; -- 5. 修改表数据 UPDATE goods SET goods_number = goods_number - 1 WHERE goods_id = 'G001';

删除列有一串限制,被复制列、用在索引中的列、被 CHECK、FOREIGN KEY、UNIQUE 或 PRIMARY KEY 引用的列、有相关默认值的列、绑定到规则的列,都不能直接删。要删商品数量这一列,必须先把依赖它的约束删掉。

顺带记一个带子查询的修改语句写法:把商品信息表和拍卖信息表用商品编号关联,当某位用户的购买记录不止一条时,IN 返回的是多值查询,所以用 IN 而不是等号。

UPDATE goods SET goods_number = goods_number - 1 WHERE goods_id IN ( SELECT goods_id FROM bid_record WHERE reg_name = 'A同学' );

4.5 视图:三个 with 选项与更新限制

视图是从一个或多个基本表导出的逻辑表,本身不存数据。建立视图的基本结构是 CREATE VIEW 视图名(列名列表)AS 查询表达式,后面可挂选项:

  • WITH CHECK OPTION:规定对视图进行插入、修改等操作时,必须遵循视图定义中查询语句设置的条件。
  • WITH ENCRYPTION:要求在存储视图语句文本时对其进行加密。
  • WITH SCHEMABINDING:将视图绑定到架构上。
  • WITH VIEW_METADATA:用该选项创建的视图,描述结果集中视图内的元数据时,浏览模式的元数据返回与基表名相对的视图名。

定义视图的查询表达式有三条限制:定义视图的用户必须有对派生此视图的基本表或视图进行 SELECT 的权限;查询语句中不能含有 INTO、ORDER BY、COMPUTE、COMPUTE BY 这些关键字;不能引用临时表或表变量。临时表存在临时数据库里,用户退出或连接终止就自动消失,所以不能作为视图的基础。

更新视图数据要满足四个条件:查询语句的 FROM 子句至少引用一个表;选择列表中没有派生列;没有聚合函数;不包含 TOP、GROUP BY、UNION 或 DISTINCT。删除时同理,DELETE 中的视图必须是可更新且正确引用一个基表的视图,涉及两张表的删除会不成功。

CREATE VIEW goods_view_5 AS SELECT goods_name, goods_type_name FROM goods_1 WHERE goods_type_name = '电子产品' WITH CHECK OPTION; -- 通过该视图插入非电子产品会被拒绝

4.6 索引:簇索引与非簇索引的物理差别

索引是加速检索表中记录的一种由关键字组成的树状结构,建立目的是提高数据库的访问速度。按索引顺序与物理存储顺序是否相同,分两类:

类型与物理顺序的关系数量限制检索路径
簇索引相同,表中每一行按索引值排序每表只能有一个直接定位到数据
非簇索引完全不同,数据按另一顺序存储每表最多 249 个(每个 16 列)先找位置,再去取数据

“一个表只能有一个簇索引”是高频考点,因为物理顺序只有一种排法。需要建索引的地方一般有四类:经常搜索的列、需要排序的列、主键或外键、经常出现在 WHERE 语句中的列。

-- 唯一簇索引:按商品编号排序,物理顺序与索引一致 CREATE UNIQUE CLUSTERED INDEX goods_index ON goods_1 (goods_id); -- 复合索引:先按编号升序,再按类别降序 CREATE INDEX goods_index2 ON goods_1 (goods_id ASC, goods_type_id DESC);

参数含义:UNIQUE 表示唯一性索引,不允许存在索引值相同的两行;CLUSTERED 表示簇索引;ASC 升序,DESC 降序。索引建多了会拖慢增删改,所以“经常用在 WHERE 里”只是候选条件,不等于必须建。

4.7 存储过程与游标:封装与逐行处理

存储过程里包含一系列 SQL 语句,包括查询、插入、删除或更新操作,这些操作在调用本存储过程时同时执行。可以被触发器触发的操作有三种:UPDATE、DELETE、INSERT,正好对应每表三个触发器的上限。

CREATE PROCEDURE modify_process @bid_user VARCHAR(10), @bid_date DATETIME, @bid_number INT, @bid_goods_id VARCHAR(10), @goods_price MONEY AS UPDATE goods SET goods_number = goods_number - @bid_number -- 扣减库存 WHERE goods_id = @bid_goods_id; INSERT INTO user_history -- 写入历史记录 VALUES (@bid_user, @goods_price * @bid_number, @bid_date); GO

参数以 @ 开头,调用时按位置或按名传入。要注意的是:存储过程中的 SQL 语句已被封装,所以无法对其所引用的表进行存在性验证——也就是说建过程时表不在也能建成功,运行到才报错,这是排错时的一个盲区。

游标用于逐行处理,五步固定:DECLARE 声明、OPEN 打开、FETCH 取值、CLOSE 关闭、DEALLOCATE 释放。

DECLARE @goods_name VARCHAR(10), @goods_number VARCHAR(10); DECLARE shop_info CURSOR FOR SELECT goods_name, goods_number FROM goods WHERE goods_name LIKE 'S%' ORDER BY goods_name, goods_number; OPEN shop_info; FETCH NEXT FROM shop_info INTO @goods_name, @goods_number; WHILE @@FETCH_STATUS = 0 -- 0 表示取到了数据 BEGIN PRINT @goods_name + ' ' + @goods_number; FETCH NEXT FROM shop_info INTO @goods_name, @goods_number; END CLOSE shop_info; DEALLOCATE shop_info;

@@FETCH_STATUS 是循环的开关,取不到数据时变为非 0,循环结束。少写一次 FETCH 就会死循环,这是游标最经典的踩坑点。

4.8 授权链:登录、用户、角色三层

数据库的授权通过新建用户来实现,目的是对此用户指定基于本登录所拥有的数据库操作权限。顺序是新建登录 → 新建用户 → 新建角色:

EXEC sp_addlogin 'login_a', 'pwd_a', 'ShopDB'; -- 自定义登录名、密码、默认数据库 EXEC sp_adduser 'login_a', 'user_a'; -- 登录名映射为数据库用户 EXEC sp_addrole 'role_sales', 'dbo'; -- 新角色名、角色拥有者 GRANT SELECT ON goods TO user_a; -- 授权 REVOKE SELECT ON goods FROM user_a; -- 回收权限

登录是服务器级别的,用户是数据库级别的,角色是权限的集合。DCL 只有三个关键字要记:GRANT 授权、REVOKE 回收权限,加上前面 DDL 里的 CREATE、DROP、ALTER 和 DML 里的 SELECT、INSERT、UPDATE、DELETE,SQL 语句的分类就齐了。DELETE 的特点是删除数据但保持原来数据的有序性,这点常和 DROP 对比着考:DROP 删对象,DELETE 删行。

5. 易漏点:五处一考就翻车的地方

5.1 容量参数记混:20 亿、1024、32767 三组数

易漏点:把“每个数据库 20 亿个表”记成 20 亿行,把“每表 1024 列”记成 8060 列,把“32767 个用户连接”和“327687 个可同时打开的数据库”互换。

为什么漏:这些数字单个记没有逻辑,只能硬背,背到后面就开始互相污染。

怎么补:按“谁是谁的容器”重新归类。20 亿这一组说的都是“个数上限”——表、锁定及打开对象;1024 这一组说的是“结构内部容量”——列数、存储过程参数;32767 说的是“并发连接”,327687 说的是“同时打开的库”。重新分组后,每组内部有共同的语义,就不容易串。

5.2 索引数量记反:1 个簇索引、249 个非簇索引

易漏点:把 249 记到簇索引头上,或者以为一个表可以建多个簇索引。

为什么漏:簇索引用得少,平时建表默认主键就自动生成簇索引,很少有人主动 CREATE CLUSTERED,导致这个“只能有一个”的限制缺乏体感。

怎么补:从物理顺序理解。簇索引要求行的物理排序与索引排序相同,一张表的数据在磁盘上只可能有一种物理顺序,所以只能有一个;非簇索引另建一套结构,通过它先找到位置再去取数据,所以可以有很多个。记住“物理顺序唯一”这五个字,1 和 249 就不会反。

5.3 范式判定跳步:直接看 3NF 忘了 2NF

易漏点:拿到一个关系直接找传递依赖,漏掉前面的部分依赖判断,结果把 2NF 的反例判成 3NF。

为什么漏:教材讲 3NF 时篇幅通常最多,复习时注意力自然偏向后面,前面的 2NF 只当过渡。

怎么补:强制自己写三步判断链。第一步看列是不是原子项(1NF);第二步看非主属性是否完全依赖于码,重点是联合主键场景下有没有只依赖其中一个属性的列(2NF);第三步看非主属性之间有没有决定关系(3NF);最后看所有决定因素是不是候选码(BCNF)。联合主键是 2NF 的高危区,只要看到两个字段一起做 PRIMARY KEY,就先查部分依赖。

5.4 视图更新的四个条件记不全

易漏点:只记得“不能有聚合函数”,漏掉派生列、TOP/GROUP BY/UNION/DISTINCT、FROM 子句至少引用一个表这三条。

为什么漏:这四条散在不同段落里,不像五类约束那样有明确的表格形式。

怎么补:按“查询表达式的组成”倒推——SELECT 列表里不能有派生列和聚合函数,FROM 里必须至少有一个表,整体不能出现 TOP、GROUP BY、UNION、DISTINCT。也就是从 SELECT、FROM、整体修饰三个位置各取一条,四条自然就齐了,不需要额外背顺序。

5.5 删除列前忘了先删约束

易漏点:直接 ALTER TABLE ... DROP COLUMN 删列,报错后才发现列上有约束、索引或默认值绑定。

为什么漏:建表时顺手加的约束没记名字,删除时不知道删哪个。

怎么补:养成两个习惯。一是建约束时用 CONSTRAINT 显式命名,别让系统生成随机名;二是删列前先查依赖,涉及 CHECK、FOREIGN KEY、UNIQUE、PRIMARY KEY、索引、默认值、规则的列,一律先解绑再删。顺序永远是先删约束、再删列,反过来必然失败。

6. 复习清单:把三层地图压缩成一张自测表

复习到最后一轮,我的做法是把整份笔记压成一张自测表,每一行对应一个“能不能不看书讲出来”的判断点。讲不出来的那一行,就是当天要补的洞。下面这张表是我自己用的版本,按三层结构排:

层级自测点过关标准
架构六个系统数据库各自的作用能说出 Master 与 Model 的区别,Tempdb 为什么内容会消失
架构三类文件的扩展名与职责能解释日志文件为什么是“后悔药”
架构容量参数三组数能按 20 亿 / 1024 / 32767 分组复述
模型实体、属性、码、域、实体型、实体集能各举一例且不混用
模型关系术语对照关系/表、元组/行、属性/列能双向翻译
模型关系成立的五条条件能说出“没有组合列”对应哪个范式
模型1NF 到 BCNF 判定链拿到一个联合主键的表能判出违反哪一范式
对象五类约束能说出主键与唯一性在“空值”上的差别
对象完整性四分类与三种强制手段域管列、实体管行,不能答反
对象ALTER TABLE 五个动作能默写删列的正确顺序
对象视图更新的四个条件能从 SELECT / FROM / 整体修饰三处倒推
对象簇索引与非簇索引能解释 1 与 249 的来源
对象游标五步能写出 @@FETCH_STATUS 的循环骨架
对象授权链登录 → 用户 → 角色,能说出各自级别

表之外还有两个自查动作。第一个是“关书默写建库语句”,ON 和 LOG ON 两段,五个参数一个不落,写完对照检查 MAXSIZE 和 FILEGROWTH 有没有漏。第二个是“给一段带子查询的 UPDATE 挑错”,重点看 WHERE 里用的是 IN 还是等号——多值查询用等号必错,这是最容易在考场上一秒钟丢分的地方。

还有一条血泪经验:范式和约束这两块,光看会觉得自己懂了,一动笔就露馅。我后来的习惯是每复习完一个范式,随手编一张三列的小表,自己判断它违反第几范式、怎么拆。拆完再回头看分解后的表有没有引入新的传递依赖。这个动作花不了五分钟,但比反复读定义有效得多。

从那以后我每次复习数据库,都强制先画那张三层地图,再逐层填自测表,填不出来的当天补完。这份 SQL Server 学习笔记我也是按这个路子重新理了一遍,从架构存储到范式约束,再到可编程对象和易漏点,一层层压下来,比按章节顺序硬读省力不少。需要这份完整整理的话,按平时的获取方式拿就行。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询