简介这份 SQL Server 学习笔记面向数据库初学者、数据库管理员及需要系统梳理 SQL Server 基础知识的技术人员围绕关系数据库核心概念与常用操作展开。内容覆盖 Create、Drop、Alter 等对象操作表、列、索引、触发器、存储过程等数据库对象限制Master、Model、Tempdb、Msdb 等系统数据库作用以及数据文件 .mdf、次要文件 .ndf、日志文件 .ldf 和文件组等存储知识同时整理关系模型、实体属性码域、主外键与 check、unique、default 约束、用户角色授权和建库建表语句要点可作为课堂学习后的查漏补缺清单与面试前快速回顾材料。资源包共 1 个 doc 文件约 499KB篇幅紧凑便于检索。已有 440 人学习适合希望用较短时间建立 SQL Server 知识框架并对照复习的读者。1. 到底什么是 SQL Server先把它当成一座“有规矩的仓库”很多人第一次翻开 SQL Server 学习笔记会被“实例、表、主码、范式、日志文件”这些词拦住。通俗地说SQL Server 是一套关系数据库管理系统它把数据放进一张张有列名、有类型、有约束的表里再用一套结构化查询语句去建表、查数、改数、删数。它值得搞懂因为“数据库”不是某个软件按钮而是一套让数据不打架的规则。学习笔记的价值是把这些规则串成一条线先知道数据放在哪再知道为什么不能乱放最后知道什么时候该用哪种对象。2. 为什么要有关系数据库从“表”到“关系”的一条认知线2.1 表不是 Excel 的别名一行、一列、一个分量把数据库表想成一张更“较真”的 Excel 表会容易入门但不能停在类比上。Excel 的同一列可以今天填数字、明天填文字数据库表不行每一列的数据类型必须先定好整数列就按整数规则收数据日期列就按日期规则收数据。Excel 里可以出现两行完全一样的数据关系表通常要求有办法把每一行区分开否则更新时就不知道改的是哪一行。Excel 里还能把“姓名电话”塞进一个单元格关系表会要求这个分量尽量不可再分否则查询“电话是多少”时就得先拆字符串。在关系数据库的语境里一张表就是一个“关系”表里的每一行叫元组每一列叫属性行里某个具体值叫分量某一列允许取值的范围叫域。比如“性别”这一列的域可以限定为男、女学号这一列的域可以限定为固定长度的数字串。实体是客观存在、可以相互区分的事物属性是实体的某一项特征码是能唯一标识实体的属性集。把这些词放回一个练习场景就好懂了学生是一个实体学号、姓名、性别是属性学号可以作为码所有学生构成实体集学生和课程之间通过选课发生联系。关系之所以叫“关系”不是因为它长得像表而是因为数据与数据之间存在联系并且要满足几条硬条件每一列的数据类型相同没有完全相同的行列与列之间的字段名不能重复没有组合列也就是一列里不再套子列。条件听起来琐碎作用却很直接让查询有确定答案让修改不牵连一片让重复数据少一点。很多初学者踩坑是因为把表当成“能存就行”的容器结果同一门课程名在十张表里各写一遍改一个名字要改十处漏一处就出现前后不一致。提示把“表”理解成“有列类型、有行标识、有取值规则的数据集合”比背“关系”的定义更容易落地。2.2 主码、候选码、外码给每行发身份证再给两张表牵线一张表里能唯一标识一行的属性组叫候选码。候选码可以是一列也可以是多列组合。比如学生表里学号能唯一标识一个学生身份证号也能唯一标识一个学生这两个都可以是候选码数据库设计时从中选定一个作为主码也就是主键。被主码选中的属性叫主属性没有出现在任何候选码里的属性叫非主属性。这个区分在后面讲范式时会反复用到因为“非主属性是否完全依赖主码”决定了表拆得对不对。主码的关键不只是“唯一”还包括“不能为空”。唯一性能防重复但主码还要承担“每行都有一个确定身份”的责任。没有主码的表更新和删除会变得很难受你想改某一行只能靠“姓名叫某某且日期是某天”这类组合条件去猜一旦有重名就翻车。候选码则是“有资格当主码的备选”主码是“最终选中的那一个”。如果一张表有多个候选码选哪个做主要看稳定性和简洁性学号通常比电话号码更合适因为电话号码会换学号相对稳定。外码也叫外部码负责联系两张表。学生表和选课表之间选课表里的学号就是外码它引用学生表里的主码。外码的作用不是“多存一列”而是把参照完整性落到结构上选课表里出现的学号必须在学生表里存在否则就出现“一个不存在的学生选了课”的脏数据。外码还会影响删除和更新如果学生表里某个学生已经被选课表引用直接删学生就可能被数据库拦住。这不是数据库“找麻烦”而是它在提醒你先处理关联数据再删主数据。注意主键、候选键、外键不是三个可以随便替换的词。主键是选定的唯一标识候选键是备选身份外键是另一张表伸过来的“引用线”。2.3 关系模型为什么能站住脚约束先于操作数据模型可以粗略理解成“描述数据、操作数据和约束数据的一套规则”。常见的数据模型有层次模型、网状模型、关系模型和面向对象模型。关系模型能成为主流不是因为它名字好听而是因为它的表达接近日常表格数据放在关系里关系之间有联系查询用集合的方式描述“我要什么”而不是一步步告诉机器“先走哪条指针”。对初学者来说这种直观性降低了理解成本对系统来说关系模型有一套数学基础约束和查询可以比较清晰地分离。关系模型里还有概念模型和数据模型的分层。概念模型更接近人的理解比如“学生选课”里有学生、课程、选课三个实体学生和课程是多对多联系数据模型更接近机器落地要说明数据结构、数据操作和约束条件。把概念模型转成表结构时多对多联系通常要拆成一张中间表选课表就是这样的中间表。它把“学生”和“课程”两个主码带进来形成自己的复合主码同时用外码分别指向两张表。这样设计之后一个学生可以选多门课一门课也可以被多个学生选重复的课程信息不用在每条选课记录里再写一遍。范式是关系模型里用来控制“表拆得合不合理”的一套要求。第一范式要求每个分量不可再分不能在一列里塞集合或序列第二范式要求非主属性完全依赖候选码不能只依赖复合主码的一部分第三范式要求不存在非主属性对码的传递依赖BCNF 是对第三范式的进一步修正。用大白话讲能放在一张表里的数据最好只跟这张表的“身份证”直接相关如果某个字段其实是由另一个字段推出来的就该考虑拆出去。比如选课表里只存学号、课程号、成绩不要把学生姓名和课程名称反复塞进来学生姓名归学生表课程名称归课程表选课表负责“谁选了什么、考了多少分”。范式不是越高级越好。实际设计里还要考虑查询频率、表连接成本和历史数据留存有时会有意保留一点冗余来换查询速度。初学阶段先把第一范式到第三范式的边界搞清知道“重复存储会带来插入异常、更新异常和删除异常”比死记定义更有用。关系数据库的底气正来自“结构先约束住操作再发生”先把列类型、主码、外码、唯一性、检查条件定好后面的插入和修改才不容易把数据弄乱。3. SQL Server 的“骨架”长什么样C/S、文件与系统库3.1 客户端/服务器体系谁在点菜谁在后厨SQL Server 采用客户端/服务器体系。客户端可以是桌面工具、应用程序也可以是某种编程接口发起的连接服务器端负责解析语句、执行查询、管理事务和返回结果。打个比方客户端像在餐厅点菜服务器像后厨点菜的人不需要知道灶台怎么摆但要知道菜名和规则后厨负责把菜做出来也要保证食材不被乱拿。数据库把数据集中放在服务器端管理多个客户端可以同时连接权限、备份、日志和约束也集中在服务器端控制这比把数据文件放在共享目录里让人直接打开要可靠得多。这种体系带来的第一个好处是共享和并发。多个用户可以在各自客户端上查询同一批数据服务器负责协调锁定和事务避免两个人同时改同一行导致结果互相覆盖。第二个好处是接口丰富。ODBC 这类标准接口可以让不同语言和工具连接到数据库Web 分析、报表工具、桌面应用都可以作为客户端。输入笔记里还提到支持 Web 分析、数据仓库、XML、分布式分区视图等能力这些能力可以理解为“同一套数据管理底座向上承接不同形态的数据使用场景”。初学阶段不必一上来深挖分布式先理解“客户端发请求、服务器管数据”这条主线后面看连接串、权限和日志时才不会迷路。3.2 数据文件、日志文件、文件组数据库不是一个“大文件”数据库在逻辑上是一个整体在物理上会被映射成几个操作系统文件。主要数据文件通常以 .mdf 结尾包含数据库的启动信息并存储数据次要数据文件通常以 .ndf 结尾用来扩展数据存储数据量大或需要分散到多个磁盘时可以用事务日志文件通常以 .ldf 结尾记录用于恢复数据库的日志信息。把数据库想成一个账本数据文件是账页日志文件是操作流水。账页告诉你现在余额多少流水告诉你每一笔怎么发生。只备份账页不备份流水一旦出事就很难恢复到某个时间点。日志文件常被初学者当成“可有可无的附属品”其实它是保证事务机制和可恢复性的重要手段。事务是一组不可分割的数据库操作要么一起成功要么一起回滚日志就是这套机制的“黑匣子”。文件组则是管理文件的逻辑容器方便把多个文件归在一起做分配和管理。主文件组、用户文件组这些概念不需要一上来背全先记住一个判断看到 .mdf、.ndf、.ldf不要只问“哪个能删”而要问“它承担的是数据、扩展还是恢复职责”。删除或挪动这些文件之前先确认备份和恢复路径否则容易把可恢复性一起删掉。文件类型常见扩展名主要职责初学注意主要数据文件.mdf启动信息与核心数据通常不可缺少不要直接手工改名次要数据文件.ndf扩展数据存储可用于分散数据但不是越多越好事务日志文件.ldf事务记录与恢复不能把它当普通临时文件清理文件组逻辑分组管理数据文件的分配单元先理解“逻辑管理”再谈多文件布局3.3 系统数据库各管什么模板、临时、调度与示例SQL Server 安装后会带有系统数据库每个都有自己的职责。master 保存主数据包括登录账号、其他数据库清单和服务器级配置信息model 是创建新数据库时使用的模板里面包含新数据库要继承的系统表结构tempdb 存储临时表和临时结果连接断开或服务重启后内容通常不保留msdb 保存调度作业、警报以及操作员等信息示例库则用于练习查询和对象设计。把它们想成一个公司的基础设施master 是总档案室model 是新办公室的样板间tempdb 是公共草稿纸msdb 是值班调度表示例库是培训教室。初学者容易犯的错是把系统库当业务库用。比如把正式数据放进 tempdb觉得“反正也能查”结果服务一重启数据就没了或者直接改 model导致以后新建的数据库都带上奇怪的默认设置再或者随手动 master影响登录和配置。系统库不是不能看而是要先知道它管什么再决定能不能改。学习笔记里列系统库不是为了让人背名字而是为了建立“数据库也有分层”的意识用户数据库装业务数据系统数据库装管理数据临时库装中间结果示例库装练习素材。系统库通俗作用初学注意master记录登录账号、数据库清单、服务器级配置不要直接改先有备份意识model新数据库的模板改模板会影响后续新建库tempdb临时表、排序和中间结果重启会清空别放持久数据msdb调度作业、警报、操作员信息作业历史可查但别当业务库示例库提供练习用的表和查询场景只作样例不代表生产规范3.4 授权与角色权限不是“给个账号就完事”数据库授权通常通过“登录名、用户、角色”三层来理解。登录名是服务器级的入口用户是数据库级的身份映射角色是一组权限的集合。新建登录之后还要在目标数据库里新建对应用户再给用户或角色授予权限。输入笔记里提到新建登录、新建用户、新建角色以及 grant 授权、revoke 回收权限这条链路的核心是“先认证再授权”。认证回答“你是谁”授权回答“你能做什么”。只给登录名不给数据库用户用户连不进具体数据库只给用户不给权限用户进来了也查不了表。-- 创建服务器级登录名名称和密码按实际环境替换 CREATE LOGIN user_a WITH PASSWORD Replace_with_a_strong_password; -- 在当前数据库中创建对应用户 CREATE USER user_a FOR LOGIN user_a; -- 只授予查询学生表的权限体现最小权限 GRANT SELECT ON dbo.student TO user_a; -- 回收权限时使用 REVOKE REVOKE SELECT ON dbo.student FROM user_a;这段代码里CREATE LOGIN管服务器入口CREATE USER管数据库身份GRANT把某个对象上的某种操作授权给用户REVOKE把授权收回。参数dbo.student表示架构名加表名实际写的时候要换成目标对象SELECT是最小权限示例不要图省事直接给最高权限。角色适合把一组权限打包给多个人比如只读角色、录入角色、管理角色。权限设计的原则是最小够用能查就不给改能改一张表就不给整个库。这样即使某个账号出问题影响面也可控。4. SQL 语句家族怎么分建、改、查、删、授权各管一段4.1 Create/Drop/Alter先有结构再谈数据SQL 语句可以按动作分成几类。Create 负责创建数据库对象比如数据库、表、视图、索引、存储过程Drop 负责删除对象Alter 负责修改对象结构或属性。它们更像“改房子结构”不是“往房间里搬东西”。建数据库时常见结构是CREATE DATABASE指定数据库名再用ON定义数据文件的文件名、路径、初始大小、最大大小和增长量用LOG ON定义事务日志文件。输入笔记里特别提到一般用户建库时不必指定所有可选项关键字大小写意义相同数据库逻辑名甚至可以用中文但逻辑名可读不等于可以乱起最好让名字能看出用途。Alter 的难点不在语法而在依赖。想删一列可能要先把这一列上的约束、索引、默认值绑定清理掉否则数据库会拒绝。想改列的数据类型要先看现有数据能不能转换转换失败就会翻车。想给表加约束要先检查历史数据是否满足新约束。学习笔记里把“增加属性、删除属性、打开或关闭约束、改变列类型”分开列是在提醒初学者表结构不是随便改的文本文件它带着一串依赖关系。写ALTER TABLE之前先问三个问题有没有约束依赖有没有索引依赖有没有数据不满足新规则这三个问题问完很多错误能在执行前拦住。4.2 Select/Insert/Update/Delete数据操作的四个动作Select 负责查询Insert 负责插入Update 负责修改Delete 负责删除。它们和 Create/Drop/Alter 的最大区别是前者动数据后者动结构。Insert 时列值的个数和顺序要与表的列匹配否则插入失败如果某列允许为空暂时没有数据可以用 NULL 占位。Update 可以根据条件改一行或多行也可以借助子查询从另一张表取条件。Delete 删除的是表中的行表结构还在Drop 删除的是整个对象表都没了。很多初学者把 Delete 和 Drop 混着说结果在讨论“删数据”时把表结构也删了这是典型的语义混淆。-- 建一张学生表主键保证每行有唯一身份 CREATE TABLE student ( student_id VARCHAR(10) NOT NULL PRIMARY KEY, student_name VARCHAR(50) NOT NULL, gender CHAR(1) NOT NULL CHECK (gender IN (M,F)), birth_date DATE NULL ); -- 插入时列的顺序与值一一对应 INSERT INTO student(student_id, student_name, gender, birth_date) VALUES(S001, User A, M, 2004-05-12); -- 更新时务必带 WHERE除非确实要改全表 UPDATE student SET student_name User B WHERE student_id S001; -- 删除一行表结构仍然保留 DELETE FROM student WHERE student_id S001;这段代码里VARCHAR(10)是可变长度字符类型CHAR(1)是固定长度字符类型NOT NULL表示不能为空CHECK限制性别列只能取指定值PRIMARY KEY把学号定为主键。INSERT后面显式列出列名是为了避免表结构新增列后“值对不上列”UPDATE和DELETE都带WHERE是因为不带条件的修改和删除会影响整张表。实际练习时可以先用SELECT验证条件命中哪些行再执行修改或删除这个习惯能省下很多后悔药。4.3 视图、索引、存储过程三个常被混为一谈的对象视图是一张“虚拟表”它保存的是查询定义不直接保存一份独立数据。查询视图时数据库会展开视图定义去访问基表。视图可以用来简化多表查询、限制可见列、给列起更友好的别名。输入笔记里提到WITH CHECK OPTION作用是让通过视图进行的插入和修改必须满足视图定义里的条件WITH ENCRYPTION用于加密视图定义文本WITH SCHEMABINDING把视图绑定到基表结构上防止基表随意改动导致视图失效。视图看起来像表但不等于表能不能更新视图要看它的查询是否只引用一个基表、选择列表里有没有派生列、聚合函数、TOP、GROUP BY、UNION 或 DISTINCT 等限制。-- 建立一个只显示部分课程信息的视图 CREATE VIEW v_electronic_course AS SELECT course_id, course_name FROM course WHERE course_name LIKE %电子% WITH CHECK OPTION;这段代码里CREATE VIEW定义视图名AS后面是查询表达式WITH CHECK OPTION强制通过视图修改数据时必须满足WHERE条件。参数course_id、course_name是视图中可见的列基表里其他列不会自动出现在视图里。视图的价值在于“把常用查询固定成一个入口”但它不负责加速也不负责存储数据如果基表查询本身很慢视图查询也可能慢。索引是加速检索的一种树状结构通过某些列建立让数据库更快定位数据。簇索引的顺序与表中行的物理存储顺序一致一个表只能有一个簇索引非簇索引采用不同的结构排序先通过索引找到数据位置再去取数据一个表可以有多个非簇索引。适合建索引的地方包括经常搜索的列、经常排序的列、主键或外键列、经常出现在 WHERE 条件里的列。索引不是越多越好因为每次插入、更新、删除索引也要维护索引太多写入会变慢空间也会增加。-- 在经常按课程查询的列上建非簇索引 CREATE NONCLUSTERED INDEX ix_enrollment_course ON enrollment(course_id) INCLUDE (score);这段代码里NONCLUSTERED表示非簇索引ix_enrollment_course是索引名ON enrollment(course_id)指定表和索引列INCLUDE (score)把成绩列作为覆盖列带进索引减少回表取数据的次数。参数不是固定的列要按实际查询条件选如果查询根本不按课程号过滤这个索引就可能白建。簇索引示例则要注意如果表已经有主键簇索引再建一个簇索引会冲突所以不要看到语法就照抄。存储过程是一组预编译的 SQL 语句集合可以带参数、带逻辑、被反复调用。输入笔记里提到存储过程可以有多个参数、支持嵌套触发器可以在 INSERT、UPDATE、DELETE 时被触发。存储过程适合把一段固定的业务操作封装起来比如“插入选课记录前先检查学生是否存在”。触发器则更像“事件发生后的自动动作”它附着在表上不需要手动调用。两者都能封装 SQL但调用方式不同存储过程由用户或程序显式执行触发器由数据变更事件触发。CREATE PROCEDURE usp_add_enrollment student_id VARCHAR(10), course_id VARCHAR(10), enroll_date DATE AS BEGIN SET NOCOUNT ON; IF NOT EXISTS (SELECT 1 FROM student WHERE student_id student_id) THROW 50001, 学生不存在, 1; INSERT INTO enrollment(student_id, course_id, enroll_date, score) VALUES(student_id, course_id, enroll_date, NULL); END;这段代码里student_id、course_id、enroll_date是存储过程参数调用时按顺序或按名称传入SET NOCOUNT ON减少“影响行数”消息对结果的干扰IF NOT EXISTS做存在性检查THROW抛出错误并阻止插入。实际环境如果不支持这种错误抛出写法可以换成等价的错误处理方式。存储过程把“检查插入”包在一起调用方不用每次重复写检查逻辑但也要注意存储过程不是越多越好过度封装会让排查问题变难。4.4 约束与完整性主键、外键、默认值、检查、唯一数据完整性是数据库里常被低估的一块。它要保证存储的数据在逻辑上正确、一致、准确。域的完整性管“某一列输入是否符合要求”比如性别列只能填指定值实体完整性管“每一行有没有唯一标识”通常靠主键用户自定义完整性管“业务规则”比如成绩必须在 0 到 100 之间参照完整性管“两张表之间的主键外键关系”防止出现不存在的引用。约束是强制这些完整性的一种方式常见的有主键约束、外键约束、默认值约束、检查约束和唯一性约束。约束管什么常见写法易错点主键约束唯一标识每一行且不能为空PRIMARY KEY一个表只能有一个主键外键约束维护两张表的引用关系FOREIGN KEY ... REFERENCES被引用列要有主键或唯一约束默认值约束未指定值时自动填默认值DEFAULT默认值不等于业务规则检查约束限制列值范围或条件CHECK不能替代跨表校验唯一性约束保证列值不重复UNIQUE和主键在空值、数量上不同主键约束把实体完整性落到结构上主键列不能为空每一行的主键值必须唯一。外键约束把参照完整性落到结构上让子表里的引用值必须在父表里存在。默认值约束解决“插入时没给值”的情况但它只是填一个默认值不代表这个值一定符合业务。检查约束用来限制输入范围比如CHECK (score BETWEEN 0 AND 100)但它只看当前行不能去查另一张表。唯一性约束防止列值重复适合邮箱、身份证号这类“可以有唯一要求”的列。把这些约束和完整性类型对上号比死背“四大完整性”更有用。5. 常见误区与易混概念初学 SQL Server 最容易绕晕的五个点初学 SQL Server 时很多概念单独看都懂放在一起就混。下面五个点最典型它们不是语法错误而是“名字相近、作用相邻”造成的认知错位。把易混点拆开先承认为什么会混再给出区分标准后面看学习笔记时就不会把两个东西硬套成一个。5.1 主键与唯一约束都能防重复但不是一回事易混点主键和唯一约束都能阻止重复值看起来只是写法不同。为什么混两者都常加在“不该重复”的列上比如学号、邮箱、身份证号建表时又都出现在列定义后面初学者容易觉得“唯一就是主键的另一种叫法”。怎么区分主键的核心是“唯一标识一行”所以它必须非空而且一个表只能有一个主键唯一约束的核心是“这一列的值不许重复”它可以有多个空值处理规则也和主键不同。选哪个不看哪个词更高级而看这一列是不是承担“行身份证”的职责。学号适合主键邮箱适合唯一约束如果一个表需要多个唯一性要求就用唯一约束补不要试图建两个主键。5.2 簇索引与非簇索引一个管物理顺序一个管查找路径易混点两者都叫索引都能“加快查询”于是被当成可互换的优化手段。为什么混建索引的 SQL 长得像查询变快时又都能看到效果初学者容易只记住“加索引就快”忽略索引背后的存储顺序差异。怎么区分簇索引决定表中行的物理存储顺序一个表只能有一个非簇索引是独立于数据存储顺序的查找结构一个表可以有多个。簇索引像按学号排队进教室队伍顺序就是座位顺序非簇索引像图书后面的索引页先查到页码再去书里翻内容。主键常和簇索引搭配但不是所有主键都自动等于簇索引建之前要看表上是否已经有簇索引。索引越多写入越慢这个代价不能忽略。5.3 视图与表看起来像表能不能直接改要看条件易混点视图能SELECT有时还能INSERT、UPDATE、DELETE于是被当成“另一种表”。为什么混查询视图的写法和查询表几乎一样客户端里也显示成一张结果集初学者容易忘记它背后只是查询定义。怎么区分表存数据视图存查询定义表的结构改动会影响数据视图的查询定义改动只影响“看到的窗口”。视图能不能更新要看它是否只引用一个基表、选择列表有没有派生列、聚合函数、TOP、GROUP BY、UNION、DISTINCT 等限制。带WITH CHECK OPTION的视图还会强制修改后的数据满足视图条件。把视图当“安全窗口”和“查询简化器”可以把它当“独立数据表”就会误判。5.4 存储过程与触发器都能封装动作触发方式不同易混点两者都能写一组 SQL都能在数据变化前后做事名字又都带“过程”“触发”这类动作感。为什么混业务里经常同时出现“插入选课记录后更新库存”和“调用一个过程完成选课”看起来都是自动执行。怎么区分存储过程需要被显式调用调用方知道自己在执行一段过程触发器附着在表上由 INSERT、UPDATE、DELETE 事件自动触发调用方未必感知。存储过程适合封装可复用的业务步骤触发器适合做表级的一致性动作但触发器逻辑过重会让排查变难因为一次插入可能连带触发多段代码。初学阶段先把“谁主动调用”问清楚再决定用哪个。5.5 数据库大小、表数量、连接数容量指标不是性能承诺易混点看到“20 亿个表”“1024 列”“249 个非簇索引”“32767 个用户连接”这类数字就以为系统能轻松扛住。为什么混这些数字确实来自产品能力描述看起来像“性能参数”而初学者又容易把“支持上限”理解成“推荐配置”。怎么区分容量指标回答“最多能放多少”性能回答“在当前查询、并发、索引和硬件下跑得多快”。表数量多不等于查询快连接数多不等于并发稳索引上限高也不等于该建满。学习笔记里记录这些上限是为了让人知道边界在哪不是鼓励贴着上限用。真正影响体验的往往是查询有没有走对索引、事务有没有过长、日志有没有合理备份。容易混淆的说法更准确的理解主键就是唯一索引主键承担行标识且非空唯一约束只保证不重复簇索引一定比非簇索引快要看查询条件、数据量和维护成本视图就是虚拟表可以随便改视图可更新性受查询定义限制触发器是自动的存储过程触发方式不同排查路径也不同上限越大系统越快上限是边界性能要看实际负载6. 什么时候该翻这份 SQL Server 学习笔记边界判断与一个具体例子6.1 适合与不适合先分清“建立地图”和“替代实战”这份 SQL Server 学习笔记适合用来建立概念地图当你分不清主键和唯一约束、视图和表、簇索引和非簇索引或者想知道建库、建表、授权、约束、存储过程各自管哪一段它可以当一条索引线把零散术语串起来。它也适合在写练习语句前快速查对象边界比如视图能不能更新、删除列前要看哪些依赖、日志文件为什么不能当临时文件清掉。但它不适合替代真实建库和恢复演练也不适合直接拿来调性能性能问题要看执行计划、数据分布、索引使用和并发情况单靠概念笔记判断不了。场景适不适合翻这份笔记原因初学阶段分不清表、视图、索引适合概念边界和对象职责讲得集中写建表语句前查约束类型适合主键、外键、默认、检查、唯一能快速对照线上查询突然变慢要找原因不适合单独用需要执行计划和实际数据分布准备数据库恢复演练不适合单独用要结合备份策略和恢复步骤实操设计表结构前判断范式适合当提醒能提醒冗余和依赖问题但仍要结合业务6.2 一个具体例子删除一条出价记录不只是写 Delete假设有一个练习场景商品表里存库存数量出价记录表里存某用户对某商品的出价。现在要删除某用户的一条出价记录并把商品库存加回去。初学者容易直接写两条语句先删出价记录再改库存。但这里要先看外键和约束出价记录表如果引用商品表删除顺序和引用关系会影响执行库存更新如果中途失败删除已经生效数据就不一致。更稳的做法是先确认两张表的关联列、约束条件和业务规则再把删除与更新放在同一个事务边界里考虑执行前先用查询验证命中哪些行。这个例子说明学习笔记的价值不在于背出DELETE和UPDATE的语法而在于提醒你语句背后有结构、有约束、有先后顺序。看到“删除并恢复库存”这种需求先问“哪张表是父表、哪张是子表、失败后能不能回滚”再动手写。从那以后我每次遇到带关联表的删除或更新都强制先把外键、约束和事务边界过一遍再执行语句。希望这份学习笔记也能帮到你如果你需要把建库、建表、视图、索引、存储过程、约束和授权这些点放在手边随时翻查资料页里有完整整理。本文还有配套的精品资源点击获取