简介:面向数据库管理初学者的一份 SQL Server 学习笔记,系统梳理了关系型数据库的核心概念与常见操作,可作为课堂学习、备考或日常查询的速查手册。内容覆盖数据库的创建、删除与修改(Create/Drop/Alter),表、索引、视图等对象的建立,以及 C/S 体系、编程接口、Web 分析与数据仓库支持等特性;同时整理了系统数据库(Master、Model、Tempdb、Msdb)的作用、数据文件与日志文件的存储方式,触发器与存储过程的参数限制,以及主键、外键、默认值、Check、Unique 等约束的使用要点。还涉及关系模型、候选码与主码、数据库授权和 SQL 建表语句等细节,知识点较为连贯。压缩包内共 1 个 doc 文档,大小 499KB,已有 440 人浏览学习,适合需要快速回顾 SQL Server 基础知识的入门者和数据库管理人员。
1. sql server 学习笔记:从会用 SSMS 到能排查生产问题的关键一步
我把 SQL Server 学习笔记从“抄语法”改成“记现象和排查顺序”之后,才觉得自己真的入了门。很多人装好 SSMS,跑通几条 SELECT 就以为会 SQL Server 了;等到线上报“已成功与服务器建立连接,但是在登录前发生错误”,或者日志磁盘每秒几 MB 往上涨时,才知道笔记里全是语法,没有一条能指下一步看哪。这篇笔记按从业者实际会碰到的路径重写一遍:先装对版本,再从 sys 目录视图入手学 T-SQL,接着用存储过程练事务边界,最后把登录失败、密码过期、恢复停在 RESTORING 这类高频坑的排查顺序记下来。适合刚装好数据库、准备系统学一遍的人,也适合被生产问题赶着补课的应用开发。
2. 学习环境要先装对:版本选型、安装顺序和最小连接验证
网上搜“sql server 下载”“sql server 2019 安装教程”回来的版本列表对新人非常劝退:有 SQL Server 2008 R2 的旧包,有 Developer、Express、Standard 一堆名字,还有从 Visual Studio Installer 里勾出来的组件。我的经验是,学习环境装错版本带来的坑比语法错误更隐蔽,你会花大量时间在“为什么我的行为和生产不一样”上。这一章把版本选型、安装里最常点错的两个选项,以及装完怎么用命令行验证服务在线,一次说清楚。
2.1 版本选型:Developer、Express 与 Standard,学习期最怕哪种限制
先看对比:
| 版本 | 许可 | 主要限制 | 学习用途 |
|---|---|---|---|
| Developer | 官方免费开发版 | 不能用于生产环境 | 首选,功能与 Enterprise 对齐 |
| Express | 免费 | 单库大小上限 10GB,内存受限 | 做“小数据量怪现象”对照实验 |
| Standard | 付费 | 缺少 Enterprise 高级功能 | 生产常见,行为与 Developer 接近 |
对于写 SQL Server 学习笔记来说,首选 Developer。它是免费下载,功能上不阉割在线索引重建这类性能手段,学完的东西拿到 Standard 生产环境基本通用。Express 最大的坑不是单库 10GB,而是内存限制导致大表排序或查询慢很多,容易让你误判成 SQL 写法问题,实际上换到生产环境同样的语句快得离谱。
把 Express 装来对照是值得的。我见过不少人在 Express 上练索引调优,发现加不加索引没差别,其实是数据量小到全表扫描都比索引快。所以我建议主力环境装 Developer,顺手再装一个 Express。笔记里已经有固定的一句话:“数据量上不去,很多性能结论都是错的”,这条就是被 Express 教育出来的。
2.2 安装界面里两个容易顺手点错的选项:实例名与服务账户
安装 SQL Server 引擎时,第一个容易顺手点错的是实例名。默认实例名是 MSSQLSERVER,之后连接字符串写 localhost 或服务器 IP 就行;如果装了命名实例,比如 Express 默认叫 SQLEXPRESS,连接时就得写 localhost\sqlexpress。一台物理机装多个版本做对照实验,一定要用命名实例,否则后装的会要求升级或卸载旧实例。这个“默认实例 vs 命名实例”的选择直接决定你后面所有 sqlcmd、连接串、SSMS 登录的写法。
第二个容易坑人的选项是服务账户。安装向导默认给数据库引擎用虚拟账户 NT Service\MSSQLSERVER,这个账户没有密码,不受系统密码过期策略影响,官方默认推荐。很多老教程让你改成 Local System 或指定域账户,结果某天那个账户密码被运维轮换,SQL Server 服务就起不来了。我装学习环境从不碰这个选项,保持默认。还有一处是身份验证模式,学习建议选“混合模式”,因为后面要练 SQL 账号登录、密码策略这些,只用 Windows 认证很多事情没法模拟。sa 密码一栏先设一个满足复杂度的强密码,装完再关策略,安装阶段绕不过去。
我遇到过一个更绕的安装顺序坑:先装引擎,再通过 Visual Studio Installer 勾选 SQL Server 相关组件,看起来是补工具,结果它把 LocalDB 或一个命名实例装了进来,原来写 localhost 的代码全部连错库。顺序上我习惯引擎 → SSMS → 再碰 VS 里的组件,每装一个就跑一回后面那节的最小连接验证,绝不让下一步建立在未知状态上。
2.3 最小连接验证:绕过 SSMS 用 sqlcmd 确认服务真的在线
装好之后先别急着打开 SQL Server Management Studio。图形客户端能连上,说明图形客户端自己那套配置是通的,不代表命令行工具或应用服务器能连。我见过 Navicat for SQL Server 连不上、SSMS 却正常的例子,反过来也见过,所以我的最小验证永远走命令行。
sqlcmd -S localhost -E -Q "SELECT @@VERSION"如果实例是命名实例,连接串要带上实例名:
sqlcmd -S localhost\sqlexpress -E -Q "SELECT @@VERSION"-S指定服务器和实例名,-E表示 Windows 身份验证,-Q表示执行完语句立即退出。返回版本号,说明引擎、服务、身份验证三层都是通的。如果连接失败,先别猜,直接查服务状态:
Get-Service -Name 'MSSQL*' | Select-Object Name, Status从 SQL Server 2000 时代 Desktop Engine 的命令行工具一路到现在的 sqlcmd,“先服务后命令”这个排查顺序就没变过。看服务名是 MSSQLSERVER 还是 MSSQL$SQLEXPRESS,能直接判断机器上装了什么实例。服务状态是 Running,sqlcmd 还连不上,再去 SQL Server 配置管理器里看 TCP/IP 协议有没有启用,以及客户端协议是不是被改成了只看 Named Pipes。
提示:报错“已成功与服务器建立连接,但是在登录前发生错误”不属于这个阶段,它意味着 TCP 握手成功,但在登录安全层挂了,这个放到第 5 章专门说,别在服务没起来这条路上反复查。
3. 笔记从哪记起:先学 sys 目录视图和示例库,再多语法都是排错工具
有人把 SQL Server 学习笔记记成一本“语法大全”,从 SELECT 讲到 MERGE,结果是真到查问题时一页都用不上。我更建议反过来:先学会怎么“问”数据库,查它自己存了哪些表、哪些索引、哪些过程引用了某张表,语法用到时再查。这一章给三个能直接抄进笔记的起点:sys 目录视图、AdventureWorks 示例库、带注释头的 SQL 片段库。
3.1 先学会查 sys 目录视图,而不是背语法
打开 SSMS,左侧“数据库 → 系统数据库 → master → 视图 → 系统视图”,看到的 sys 开头的视图就是目录视图。新人第一反应是翻业务表里的数据,但生产环境里出问题时的第一反应应该是翻这些元数据视图。下面这段“体检”脚本我在每台服务器上都会跑一遍,找出当前库里所有没有主键的表:
SELECT t.name AS TableName FROM sys.tables t LEFT JOIN sys.indexes i ON i.object_id = t.object_id AND i.is_primary_key = 1 WHERE i.object_id IS NULL;LEFT JOIN 条件里带is_primary_key = 1是关键。如果把这个条件直接写进 WHERE,JOIN 不到主键索引的表就会被整体过滤掉,查不出任何问题。跑出来如果有十几张表没主键,说明这个库基本靠运维人肉兜底。改表结构前,我常查“有哪些存储过程或视图引用了某张表”:
SELECT s.name AS SchemaName, o.name AS ObjectName, o.type_desc FROM sys.sql_modules m JOIN sys.objects o ON m.object_id = o.object_id JOIN sys.schemas s ON o.schema_id = s.schema_id WHERE m.definition LIKE '%Orders%' ORDER BY s.name, o.name;sys.sql_modules 存的是每个模块的定义文本,LIKE '%Orders%'是把引用 Orders 这张表的对象全部捞出来。这个查询的坑是定义文本里的注释也可能被捞到,真正动手前我会人工再核一遍,但作为影响面扫描完全够用。这类目录视图查询的收益在初期不明显,等你要改一个被十几处存储过程引用的字段时,才知道它比任何语法书都值钱。
3.2 用 AdventureWorks 示例库练窗口函数,顺手记执行顺序
AdventureWorks 是官方示例库,表结构做关联练习很合适,我第一次认真学窗口函数就靠它。窗口函数的难点不是语法,而是 SQL 的执行顺序:FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY。窗口函数在 SELECT 阶段计算,所以 WHERE 里不能用窗口函数的结果,但 ORDER BY 里可以用。这个顺序不记牢,写复杂报表时很容易陷入“为什么这个条件不能写在这里”的困惑。
下面这段是“每个产品分类里销售额前三的产品”:
SELECT pc.Name AS CategoryName, p.Name AS ProductName, SUM(so.LineTotal) AS SalesAmount, ROW_NUMBER() OVER ( PARTITION BY pc.Name ORDER BY SUM(so.LineTotal) DESC ) AS Rn FROM Sales.SalesOrderDetail so JOIN Production.Product p ON so.ProductID = p.ProductID JOIN Production.ProductSubcategory psc ON p.ProductSubcategoryID = psc.ProductSubcategoryID JOIN Production.ProductCategory pc ON psc.ProductCategoryID = pc.ProductCategoryID GROUP BY pc.Name, p.Name ORDER BY CategoryName, Rn;PARTITION BY pc.Name意思是按产品大类分组编号,ORDER BY SUM(so.LineTotal) DESC让销售额大的排前。写了 GROUP BY 之后,窗口函数里用的 SUM 就是分组后的聚合值,不是明细行的值。最容易翻车的点是漏掉 GROUP BY 里某个列,或者想在 WHERE 里对 Rn 过滤。这两条我都写在笔记的片段开头,提醒自己:窗口函数只能在 SELECT 阶段出现,想过滤排名结果,就得包一层子查询或 CTE。
3.3 把笔记沉淀成带注释头的 SQL 片段库
笔记记到后期,我发现最有价值的不是长篇教程,而是可以直接粘贴的 SQL 片段。每个片段开头用注释把用途、适用场景、坑写清楚。下面这段是我磁盘告警时第一个跑的命令——查当前库占用空间最大的前 10 张表:
/* 用途:找出当前库中占用页数最多的前 10 张表 * 适用:磁盘快满或某表查询明显变慢时 * 坑:不含日志文件;删除大量数据后这个统计会虚高,先重建索引再对比 */ SELECT TOP 10 t.name AS TableName, p.rows AS RowCounts, SUM(a.total_pages) * 8 AS TotalSizeKB, SUM(a.used_pages) * 8 AS UsedSizeKB FROM sys.tables t JOIN sys.indexes i ON t.object_id = i.object_id JOIN sys.partitions p ON i.object_id = p.object_id AND i.index_id = p.index_id JOIN sys.allocation_units a ON p.partition_id = a.container_id WHERE t.is_ms_shipped = 0 GROUP BY t.name, p.rows ORDER BY TotalSizeKB DESC;页是 SQL Server 存储的最小单位,每页 8KB,所以total_pages * 8得到 KB。这段脚本里容易写错的是关联条件漏掉i.index_id = p.index_id,一旦漏掉,分区统计会对同一张表重复计算。把这种带注释头的片段按“备份恢复”“性能排查”“日常体检”分文件夹存,就是最实用的 SQL Server 学习笔记。三个月后翻回来,注释头比正文还能说明当时为什么写它。
4. 存储过程与事务边界:学习笔记里必须记录的执行顺序和错误处理
学习 SQL Server 到中段,很多人会绕开存储过程,觉得那是老古董,应用代码里写 SQL 就够了。但存储过程强制你把参数、返回值、错误处理放在同一个代码包里,这是练习事务边界最便宜的方式。这章讲怎么用 TRY...CATCH 包事务,NOLOCK 提示什么时候能省,以及游标怎么写才不给自己埋坑。
4.1 为什么入门要写存储过程:参数化、返回码与 TRY...CATCH
存储过程不是一个高深对象,它就是一个可复用的 T-SQL 代码包。写的过程会逼你做三个决定:输入参数有哪些、调用方怎么知道成功失败、出错了数据会变成什么样。这三件事直接写 SQL 时很容易含糊,放到存储过程里含糊不了。最经典的练习是转账:
CREATE PROCEDURE dbo.usp_TransferMoney @FromAccountId INT, @ToAccountId INT, @Amount DECIMAL(18,2) AS BEGIN SET NOCOUNT ON; BEGIN TRY BEGIN TRANSACTION; UPDATE dbo.Accounts SET Balance = Balance - @Amount WHERE AccountId = @FromAccountId; UPDATE dbo.Accounts SET Balance = Balance + @Amount WHERE AccountId = @ToAccountId; COMMIT TRANSACTION; END TRY BEGIN CATCH IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION; THROW; END CATCH END;BEGIN TRY 和 BEGIN CATCH 是 SQL Server 2005 之后的两段式错误处理。这里最容易翻车的是 COMMIT 的位置:事务一旦进入 CATCH,说明数据变更还没定型,必须回滚,COMMIT 只能放在 TRY 块的正常路径里。THROW 把原始错误原样抛给调用方,比返回一个错误码再翻文档好排查得多。参数用 DECIMAL(18,2) 而不是 FLOAT,金额计算不能用浮点数,这条我写了整段笔记。没有事务的存储过程也能写,但前几个练习过程建议都带事务,养成边界意识。
4.2 事务里最容易翻车的隔离级别:NOLOCK 什么时候能省
网上抄来的笔记里,NOLOCK 几乎被写成“查询不卡顿的万能药”,但没人写代价。SQL Server 默认隔离级别是 READ COMMITTED,读和写会互相阻塞。NOLOCK 对应的是 READ UNCOMMITTED,读不加共享锁,不阻塞别人写,同时也会读到未提交的数据,甚至因为页拆分读到重复行。
-- 报表查询加 NOLOCK 的典型写法,笔记里必须注明代价 SELECT COUNT(*), SUM(Amount) FROM dbo.Orders WITH (NOLOCK) WHERE OrderDate >= '2024-01-01';这段在“能容忍读到一半数据”的汇总场景里能用,比如大致看单量。但金额汇总如果对精度有要求,就不能加。正确姿势是开快照隔离:数据库层面打开 ALLOW_SNAPSHOT_ISOLATION,连接里设置SET TRANSACTION ISOLATION LEVEL SNAPSHOT,读不会阻塞写,也不会读到未提交的数据,代价是 tempdb 压力变大。我笔记里记成一句口诀:NOLOCK 不是不能用,是你要说得清“这笔汇总差多少数据可以接受”。生产环境里用 NOLOCK 至少要在代码注释里写清楚为什么容忍脏读。
4.3 游标的三种写法:最小游标也要记得释放
游标在 SQL Server 里名声不好,但做索引碎片整理、批量归档、遍历库里的表做体检,不用游标就是和自己过不去。我总结的最小游标写法是 LOCAL FAST_FORWARD READ_ONLY:LOCAL 让游标只在当前批处理可见,FAST_FORWARD 是单向只进,READ_ONLY 不能通过游标改数据。这三个组合能避开大部分游标性能事故。
DECLARE @TableName NVARCHAR(128); DECLARE cur CURSOR LOCAL FAST_FORWARD READ_ONLY FOR SELECT name FROM sys.tables WHERE is_ms_shipped = 0; OPEN cur; FETCH NEXT FROM cur INTO @TableName; WHILE @@FETCH_STATUS = 0 BEGIN PRINT @TableName; FETCH NEXT FROM cur INTO @TableName; END; CLOSE cur; DEALLOCATE cur;WHILE @@FETCH_STATUS = 0 表示还有行可取,循环体里取下一行要放最后,否则会跳过一行。这段代码里最容易翻车的不是语法,而是不写 CLOSE 和 DEALLOCATE。第一次跑完游标没释放,第二次跑直接报“游标已存在”。CLOSE 关掉游标,DEALLOCATE 释放游标占用的资源,两个都得写。我在生产环境见过只 CLOSE 不 DEALLOCATE 的写法,时间长了就是游标资源泄漏。学习笔记里我给游标的定位是:能不用就不用,但管理脚本里用游标比递归 CTE 更容易读懂,关键是边界要封闭。
5. 高频问题排查:登录握手失败、密码到期等 4 条血泪记录
学习笔记里最值钱的部分是“现象 → 原因 → 解决”的排查记录。这一章写 4 个常见的 SQL Server 问题,全部按真实排查顺序来:先确认现象,再找原因,最后给命令。这 4 个问题覆盖了“连接建立了但登录失败”“密码过期”“还原卡住”“密码策略关不掉”四类,学习期和生产期都会碰到。
5.1 已与服务器建立连接但在登录前报错:多数是加密协议不匹配
现象:用 SSMS 或应用连接 SQL Server,提示“已成功与服务器建立连接,但是在登录过程中发生错误”,后面常跟着 SSL Provider 相关字样。很多人看到“已成功建立连接”就以为网络是好的,于是反复重装客户端,方向一开始就错了。
原因:这个报错的本质是 TCP 层面握手成功,但在登录安全协商阶段两侧协议不一致。最典型的是老版本 SQL Server(比如 SQL Server 2008 R2、SQL Server 2012)跑在较新的 Windows 上,实例只开 TLS 1.0,而新系统的 Schannel 默认禁用了 TLS 1.0;或者客户端驱动太老,只支持旧协议,服务器只允许新协议。
解决:先看 Windows 事件日志里 SQL Server 有没有记录加密协商失败。测试环境最快的是连接字符串加TrustServerCertificate=True,跳过自签名证书校验再试。加完还是失败,大概率就是 TLS 版本问题:给 SQL Server 实例打上支持 TLS 1.2 的补丁,或在服务器注册表里启用对应协议后重启实例。客户端这边,把老驱动换成新版 ODBC Driver,比在注册表里折腾更省事。这个报错不代表服务离线,不要先重启实例,先看协议配置。
5.2 SQL Server 2012 密码到期导致应用连环报错
现象:应用日志里连续出现“用户登录失败,原因是密码过期”“Login failed”,状态码 18488。数据库服务正常,资源占用也正常,就是一个登录报错把应用拖垮了。
原因:SQL Server 登录默认继承 Windows 密码策略,包括密码过期时间。装完数据库没人管,90 天后就到期。这里容易漏一点:不只是 sa,任何用 SQL 身份验证的账号都可能到期。应用连接池里的旧连接不会自动感知新密码,表现就是某天早晨所有新请求一起失败。
解决:用管理员账号连进去,把应用账号的过期和策略检查关掉:
ALTER LOGIN [app_user] WITH CHECK_EXPIRATION = OFF; ALTER LOGIN [app_user] WITH CHECK_POLICY = OFF;CHECK_EXPIRATION 控制是否强制密码过期,CHECK_POLICY 控制是否应用 Windows 密码复杂度策略。学习环境两个都关掉最省心。生产环境建议只关过期,不关复杂度,密码定期改。如果你连 sa 都到期了,必须先能连上实例才能改名,那就用 Windows 认证登录再执行。这个案例里最惨的学习是:永远不要在应用里用 sa 做连接账号,sa 出事影响的是整个实例,不是单个库。
5.3 恢复备份后库一直停在“正在恢复”,日志还不涨
现象:RESTORE DATABASE 命令执行完,SSMS 里库名后面跟着“(正在恢复)”,状态是 RESTORING,刷新半天不动。错误日志也没报错,数据文件、日志文件都在。
原因:最常见的是还原语句带了 WITH NORECOVERY。NORECOVERY 本来就是为“继续追加后续备份”设计的,没加后续备份或最后没收尾,库就永远留在还原状态。另一种情况是还原日志备份时备份链断了,比如中间日志被截断过,SQL Serve 不允许直接变 ONLINE。
解决:如果只是还原单次全量备份,确认不再追加日志后执行:
RESTORE DATABASE [MyDB] WITH RECOVERY;这一句把数据库拉回在线状态。如果是完整还原链,记住:每一步都用 NORECOVERY,最后一步换 RECOVERY。在 RESTORING 状态下不要直接删库重来,先试上面这条,很多时候一秒钟就解决。备份恢复相关的笔记务必记录备份链的起点和时间,否则等你从一大堆文件里找日志备份时,才是真麻烦。
5.4 SQL Server 2022 Express 装完关掉密码策略:两个开关别漏
现象:装 SQL Server 2022 Express 时,安装向导要求 sa 密码必须带大小写、数字、符号,设简单的不让过。装完再用 SQL 账号登录,过一段时间又提示密码过期。
原因:SQL Server 安装界面没有直接的“关闭密码策略”开关,安装阶段绕不过强密码。装完要手动改登录属性,同时注意 Express 的实例名往往是 MSSQL$SQLEXPRESS,连接串写错成 localhost 就白排查一场。
解决:安装阶段先设临时强密码,装完立即执行 5.2 的两条 ALTER LOGIN。GUI 安装就手动处理;命令行部署的话,常见做法是安装完成后统一执行策略调整。顺手把 sa 禁掉,新建一个自己的登录,以后所有连接验证都用这个账号。sa 在实例里是超级管理员,上来就用 sa 写应用连接串,等于把整个数据库的钥匙挂在门口。
6. 进阶用法:把学习笔记改造成五分钟诊断脚本集
笔记积累到一定量,下一步值得做的是把常用片段串成几个固定脚本:当前正在跑的请求、最近最长查询、库健康速览。出问题时按脚本跑一遍,基本能在五分钟内定位“是慢查询还是资源问题还是磁盘问题”。我用得最多的是第一板斧,当前正在跑的请求:
SELECT r.session_id, r.status, t.text, r.start_time, r.wait_type, r.blocking_session_id FROM sys.dm_exec_requests r CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t WHERE r.session_id <> @@SPID;wait_type 出现 PAGEIOLATCH_SH 或 PAGEIOLATCH_EX,基本指向磁盘读慢;出现 WRITELOG,说明日志写入卡住,通常要查日志文件所在盘的 IO。这个查询把正在执行的 SQL 文本直接列出来,比活动监视器更直观。我习惯再加一个输出去重的小版本,只显示重复次数最多的前 5 条 SQL,用来找“谁在疯狂请求同一个查询”。
笔记变成诊断脚本集的诀窍不是命令多,而是每条后面都带“看到什么现象 → 下一步查哪里”的注释。我有一次栽在死锁上:笔记里记录了死锁的语法,却没写死锁后先查哪个视图、怎么拿死锁图,现场只能翻官方文档。那次之后,我要求每条笔记最后都补一个“落地检查”:建完索引后怎么看碎片,加完 NOLOCK 后怎么确认结果可接受。现在翻笔记的感觉像翻自己的排错手册,遇到新问题顺着脚本集走,大部分都能落到一个具体等待类型或一条具体 SQL 上。希望这个路径对你有用,也帮到你。
本文还有配套的精品资源,点击获取