简介:这份跟随郝斌老师学习SQL Server 2005整理的笔记,以docx文档形式收录数据库学习的核心脉络,重点围绕“数据库如何解决数据存储问题”展开,系统梳理了字段、记录、表、约束(主键、外键、唯一键、非空、CHECK、DEFAULT、触发器)等基础概念,并区分了数据存储、数据操作与数据展示三大层面。笔记同时包含创建数据库、设置登录用户、删除数据库、理解.mdf与.ldf文件等实操要点,以及T-SQL、存储过程、函数、触发器、索引等进阶特性的入门说明,并给出了CREATE TABLE构建主外键约束、CHECK、DEFAULT、UNIQUE约束的示例命令,便于读者边看边练。包内为1个docx文档,压缩包约387KB,内容紧凑、知识点密集,适合SQL Server初学者系统掌握数据库基础,也适合备考或课程复习时快速查阅。该资源目前已有132人学习,实用性较强。
1. 为什么还在学SqlServer2005:存量系统逼出来的刚需
SqlServer2005这个版本,在很多公司机房里还没有退休。我去年接手过一套内部供应链系统,数据库就是2005,报表、接口、定时任务全挂在上面,产线一刻不能停。郝斌老师的SqlServer2005课程是当年培训机构的经典讲法,这一份笔记把讲课脉络浓缩成了可翻阅的文字,正好用它来快速捡起T-SQL语法和库表、视图、存储过程的组织方式。它适合两类人:一类是想系统学数据库、能照着步骤动手的新手;另一类是维护老库遇到语法半生不熟、需要快速查证的从业者。这份笔记的价值在于把课程要点拆成了可执行的步骤,复习时不用重刷视频,直接照着做就行,前面走过的弯路都已经帮你标出来。
2. 搭好环境再谈学习:虚拟机选型与2005安装的三个前置检查
学SqlServer2005,第一件事不是敲代码,而是把环境搭对。环境搭错了,后面每一步都在跟安装程序搏斗。2005这个版本对现代操作系统不太友好,准备工作做足,能省掉八成无故翻车的时间。
2.1 为什么先装虚拟机而不是本机硬怼
SqlServer2005发布时间早,官方支持的生命周期早就结束,在Windows 10/11上直接安装经常卡在“安装程序支持文件”检查那一步。就算是运气好装完了,SSMS连接时也可能出现各种莫名其妙的兼容性问题。我一般不建议在本机硬怼,直接在VMware或者VirtualBox里装一个Windows 7 SP1虚拟机,再把SqlServer2005装进去。虚拟机的好处是快照可以当后悔药,装坏了还原一下就是一分钟的事,学习库怎么折腾都不心疼。
虚拟机配置不用高,平时我用2核CPU、4GB内存、60GB磁盘,跑2005绰绰有余。如果是想模拟生产环境,把配置提到4核8GB,装Windows Server 2008 R2也行。下面是一个对照参考配置。
| 使用场景 | CPU | 内存 | 磁盘 | 操作系统 |
|---|---|---|---|---|
| 开发/学习 | 2核 | 4GB | 60GB | Windows 7 SP1 |
| 模拟生产 | 4核 | 8GB | 120GB | Windows Server 2008 R2 |
内存不用给太大,2005本身吃不了多少资源,反而是磁盘空间要留意。SQL Server的日志和tempdb比较吃空间,磁盘建议最低预留50GB以上,别卡着30GB用,测试库日志一膨胀就报警。
2.2 安装前的三个前置检查
安装包用SqlServer2005开发版或企业版的光盘镜像,下载后先校验SHA值再解压。解压完setup.exe别急着双击,右键属性,把兼容模式设为Windows 7,勾选“以管理员身份运行”,这一步能避开大部分UAC权限拦截,是2005安装里最容易省掉的坑。
第一个前置检查是.NET Framework 3.5 SP1。Windows 7默认没有开全,安装时报缺少.NET的话,去“控制面板–程序–打开或关闭Windows功能”里勾上Microsoft .NET Framework 3.5.1,让系统自动更新补上。第二个是Windows Installer 4.5,Win7一般自带。第三个是安全软件,装数据库前尽量把杀毒软件、防火墙、Defender实时保护临时停掉,2005的老安装程序经常被误判成可疑行为,中途强制结束安装,剩下的半成品环境最难受。
安装过程中有一个选择要特别留意:身份验证模式。新手默认选“Windows身份验证”也能装完,但之后在代码里用账号密码连接时,就会遇到SA登录失败的坑。建议一开始就选“混合模式”,给SA设置一个强密码,包含大小写字母、数字和特殊符号的16位密码。这样后续讲登录、权限、连接串的时候,不用回头折腾身份验证模式的开关。
2.3 连接验证:实例名与身份验证模式
装完以后,打开安装自带的SqlServer Management Studio(SSMS)。服务器名称这一栏,默认实例填localhost或者一个点号都行;如果装的是命名实例,要写成“主机名\实例名”,比如WIN7-DB\SQLEXPRESS。漏掉斜杠后面的实例名,是最常见的连接失败原因。
用SQL Server身份验证,输入sa和刚才设置的密码,能连上树形目录就算成功了。连上之后先跑一段确认版本的语句,确认环境干净可用。
SELECT SERVERPROPERTY('ProductVersion') AS ProductVersion, SERVERPROPERTY('ProductLevel') AS ProductLevel, SERVERPROPERTY('InstanceName') AS InstanceName;ProductVersion返回数据库引擎的版本号,SqlServer2005是9.00.xxxx,见到9开头就说明没装错。ProductLevel显示SP级别,比如SP4,补丁越新越少踩坑。InstanceName如果是NULL,表示当前连的是默认实例。这段确认脚本建议每次搭新环境都跑一遍,顺便记到笔记里。以后遇到莫名其妙的性能问题,先看补丁级别,很多老库问题靠升级SP4就解决了。
2.4 笔记的使用顺序:先概念后建库
郝斌老师课程的顺序很有套路,笔记基本也是跟着这个套路来的:先讲数据库是什么、表是什么,然后是建库建表、增删改查,再往后是视图、存储过程、触发器、事务这些进阶对象。我拿到这份笔记时没有从头到尾一口气读完,而是把每一章当成一次实战任务,读一节就在SSMS里敲一节代码。
比如看到“约束”这一节,就顺手建一张Customer表,把主键、唯一约束、默认值全部加上;看到“查询”那一节,就造几十条数据,把JOIN、GROUP BY、HAVING轮着试一遍。笔记里有些说法是有时代背景的,比如对C/S架构的强调,当时的系统普遍是客户端直接连数据库,现在虽然是B/S居多,但底层T-SQL的逻辑没有变,该学的还是要学。
读笔记的窍门是:先看每一节标题,自己想一想“如果我来实现这个功能,会怎么写SQL”,再去对笔记里的答案。差异点就是你要补的盲区。
3. 建库建表到增删改查:把笔记里的T-SQL练成手感
SqlServer2005的语法和现在的新版本差别不算大,但有些细节一旦用错,行为完全不一样。这一章按笔记里的主线走:建库、建表、查询、更新,把最常用到的写法练成肌肉记忆。
3.1 建表时最容易踩的类型与约束
笔记里讨论最多的是建表,因为表结构设计决定了后面所有查询的写法。见过很多初学者在类型选择上随缘:字符串一律varchar(4000),金额用float,日期用varchar。这种写法在2005里能跑,但后期维护成本非常高。
字符串类型优先选varchar,如果确定要存中文等多字节字符,用nvarchar,长度按业务实际来定,比如客户名称nvarchar(50)就够,不用一上来就4000。这里有个2005的老坑:早期版本里varchar(8000)以上的大字段用text、ntext类型,2005已经开始用varchar(max)和nvarchar(max)替代了。笔记如果提到text类型的写法,你看个眼熟就行,新代码不要用text,因为text的操作限制多,很多函数不支持。
金额用decimal(18,2),18是总位数,2位小数,足够应付绝大多数财务场景。float是浮点数,做累计求和时会留下二进制舍入误差,月底对账差几分钱非常正常,还没法查。日期时间用datetime,2005还没有date类型,这一点和现在的新版不一样,写惯了datetime2的人要特别注意,反向移植到2005时得把语法改回来。
约束这一块,习惯给约束起标准名字:主键PK_表名,唯一约束UK_表名_列名,默认约束DF_表名_列名,外键FK_表名_列名。起名的意义在于报错时能一眼看出哪个对象坏了,而不是看一行“Unknown constraint name”。
CREATE DATABASE LearnDB; GO USE LearnDB; GO CREATE TABLE dbo.Customer ( CustomerID INT IDENTITY(1,1) NOT NULL, CustomerNo VARCHAR(20) NOT NULL CONSTRAINT UK_Customer_CustomerNo UNIQUE, Name NVARCHAR(50) NOT NULL, CreatedDate DATETIME NOT NULL CONSTRAINT DF_Customer_CreatedDate DEFAULT(GETDATE()), CONSTRAINT PK_Customer PRIMARY KEY (CustomerID) ); GOIDENTITY(1,1)的意思是自增列,种子从1开始,每次加1,这是交易流水表最常用的设计。UNIQUE约束保证CustomerNo编号不重复,默认约束让CreatedDate在插入时不传值也能自动取当前时间。建表时把约束写在CREATE TABLE里,比等表建完再补更稳妥,数据一多再补约束,还原旧数据时很容易失败。
3.2 查询逻辑:SELECT解析顺序与JOIN写法
很多新手写查询,遇到报错就在SELECT、WHERE、GROUP BY之间来回改。这时候最该做的是记住逻辑解析顺序:FROM先读表,JOIN把多张表合并,WHERE过滤行,GROUP BY分组,HAVING过滤分组,然后才是SELECT计算列,最后ORDER BY排序。牢记这个顺序,你就知道为什么WHERE里不能用SELECT的别名,SELECT还没执行呢,别名自然不存在。
笔记里JOIN的例子多,因为老系统大多都是多表关联查询。写法上推荐显式写INNER JOIN,可读性好,但2005时代的代码里大量是FROM A, B WHERE A.ID = B.ID这种旧式写法,读老库时也得能看懂。
SELECT c.Name, COUNT(o.OrderID) AS OrderCount, ISNULL(SUM(o.Amount), 0) AS TotalAmount FROM dbo.Customer c LEFT JOIN dbo.Orders o ON c.CustomerID = o.CustomerID WHERE c.CreatedDate >= '2024-01-01' GROUP BY c.Name HAVING COUNT(o.OrderID) > 0 ORDER BY TotalAmount DESC;这段查询演示了完整的解析顺序:FROM先取出Customer和Orders两张表,LEFT JOIN保证没有订单的客户也能出现在结果里,WHERE先过滤掉2024年以前的客户,GROUP BY按客户姓名分组,HAVING把没有任何订单的分组删掉,SELECT阶段做COUNT和SUM聚合,ISNULL函数把NULL金额转成0,最后ORDER BY按总额倒序。注意HAVING是在分组之后过滤,跟WHERE的行过滤是两个层级,这个区分是考试和面试都喜欢问的点。
3.3 更新删除必须带事务边界
笔记里讲DML时有一条忠告一直记着:UPDATE和DELETE操作,动手之前必须能回答“影响多少行”。回答不了就说明没写全条件,最怕的是DELETE不带WHERE,一跑就是把整张表清空。
我一般会在操作前先用SELECT把要影响的范围查出来,比如先SELECT COUNT(*)看行数,再决定要不要执行。更稳妥的做法是直接在事务里操作,影响行数不对马上回滚。
BEGIN TRAN; DELETE FROM dbo.Orders WHERE CreatedDate < '2020-01-01'; SELECT @@ROWCOUNT AS DeletedRows; -- 确认删除行数与预期一致后,再把下面的ROLLBACK换成COMMIT ROLLBACK;@@ROWCOUNT返回的是上一条语句影响的行数,这里删完历史订单立刻读取,数字对得上就说明范围没错。事务的COMMIT是唯一确认键,ROLLBACK就是后悔药。实际工作中都是先ROLLBACK,确认无误后再正式执行一次,最后提交。这个习惯能救很多次急,尤其是凌晨处理线上数据时,大脑不清晰的情况下绝不能直接COMMIT。
UPDATE的写法也是同一个道理,它本质上是“先定位行再改列”,可以理解为SELECT加写值,同样建议用事务包住,影响行数不对就回滚。
4. 视图、存储过程与索引:靠这些才敢说会SqlServer
只会在查询编辑器里写SELECT,那叫会操作,不叫会SqlServer。笔记里后半部分讲的视图、存储过程、索引,才是老系统里真正在用的东西,也是面试里区分“写手”和“工程师”的分界线。
4.1 视图:封装查询,但别套娃
笔记里视图这一节的重点是“视图不存数据,只存查询语句”。新人最容易误解的地方就在这,以为建了视图就是复制了一份数据,改了视图里的数据会有备份。实际上2005里视图在大多数情况下是不可更新的,它只是一段保存的SELECT。它的价值在于封装:把复杂的多表关联拆成一张虚拟表,让报表查询只面对简单结构;也可以用来做行级权限,比如视图里固定WHERE一个部门字段,其他人只看到某个部门的数据。
视图的坑在于嵌套。有人图省事,一个视图套另一个视图,最外层看起来就几行SQL,背后却套了五六层查询。2005的优化器面对这种多层视图嵌套,很难把谓词下推到最内层,查询性能就崩了。笔记里反复叮嘱不要在同一张基表上做多层视图,我是吃过亏的:以前接过一个报表视图套了四层,单看外层挺简单,跑一次要一分半钟,把中间层全部拆开,合并成一次基表扫描后,三秒就出结果。
如果要在视图上做聚合,也尽量把聚合控制在最外层,内层只做行过滤,这样执行计划更可控。
4.2 存储过程:参数、输出与执行计划
存储过程是2005老系统里最常见的业务载体,定时任务调它,接口层也调它。笔记里这一节的价值在于讲清了参数怎么传、输出怎么接。下面是一个典型的按客户查订单的存储过程,包含输入参数、默认值、输出参数三个要素。
CREATE PROCEDURE dbo.usp_GetCustomerOrders @CustomerID INT, @StartDate DATETIME = '2024-01-01', @TotalAmount DECIMAL(18,2) OUTPUT AS BEGIN SELECT o.OrderID, o.Amount, o.OrderDate FROM dbo.Orders o WHERE o.CustomerID = @CustomerID AND o.OrderDate >= @StartDate; SELECT @TotalAmount = SUM(Amount) FROM dbo.Orders WHERE CustomerID = @CustomerID AND OrderDate >= @StartDate; END; GO@CustomerID没有默认值,调用时必传;@StartDate给了默认值,调用方可以不传,也可以传别的日期;OUTPUT参数用来把聚合结果带出去。执行时要用EXEC,并且OUTPUT参数必须用变量接着。
DECLARE @Total DECIMAL(18,2); EXEC dbo.usp_GetCustomerOrders @CustomerID = 1, @TotalAmount = @Total OUTPUT; SELECT @Total AS TotalAmount;EXEC后面没有OUTPUT,或者变量声明漏了,结果就带不回来,这是最常见的翻车点。存储过程的另一层价值是执行计划缓存:第一次执行时生成执行计划,后续再调用,同样的参数形态就直接复用计划。代价是如果参数值分布差异很大,比如有的@CustomerID返回一行,有的返回十万行,复用的计划对两者都不合适,这就是经典的参数嗅探问题,有时候表现得很玄学,存储过程时快时慢。2005对这个问题的处理不如新版本,遇到“时快时慢”先怀疑它。
提示:参数嗅探不是一次查询的错误,是同一过程在不同参数下共用同一执行计划导致的性能波动。排查时看实际执行计划,而不是只看耗时感受。
4.3 索引:聚集与非聚集的取舍
索引这一节,笔记里把聚集索引和非聚集索引的差别讲得很直白:聚集索引决定表数据的物理顺序,一张表只能有一个,就像书的页码本身;非聚集索引是独立的目录结构,可以建很多个,每条目录都指向页码。
知道了这个差别,就知道为什么主键默认建聚集索引,也就能理解为什么不要在GUID列上建聚集索引。GUID随机分布,每次插入都会大幅调整物理顺序,导致页分裂和碎片。对2005来说,还要注意一点:2005开始支持在非聚集索引的叶子层附带额外的列,这就是INCLUDE。
CREATE NONCLUSTERED INDEX IX_Orders_CustomerID_OrderDate ON dbo.Orders (CustomerID, OrderDate) INCLUDE (Amount); GO索引键列放在CustomerID和OrderDate,INCLUDE列把Amount塞进叶子页。这样查询只需要这三列时,系统直接在索引里取数,不用回表查原数据页,IO次数明显下降。INCLUDE列的写入会增加索引维护成本,所以不要什么东西都往里塞,只加查询里最频繁使用的那一两列。
索引失效的场景在笔记里也有汇总。WHERE子句里对索引列做函数运算,比如WHERE Year(CreatedDate)=2024,会让索引基本白建,每一行都要先执行函数再比较;LIKE前面用百分号通配也一样。我想补一句:2005的查询提示和统计信息比新版本原始得多,索引建完不等于生效,跑完语句要打开实际执行计划,确认走的是Index Seek而不是Table Scan,才算数。
5. 避坑排查:SqlServer2005最常见的五个翻车场景
下面这五个坑,是不同项目里真实遇到过的,笔记里也零散提到。按现象、原因、解决三个步骤展开,遇到同款直接照着排查。
5.1 连接报“用户登录失败”:多数是身份验证模式错位
现象:SSMS用sa登录,弹出“用户‘sa’登录失败。原因:与基于SQL Server的登录名相关联的密码不正确”,密码明明刚设过。
原因:安装时选的是Windows身份验证模式,SQL Server根本不接受账号密码登录,或者SA没有启用。默认在Windows身份验证模式下,SA是禁用状态,即使密码正确也进不来。
解决:先用Windows身份验证连一次,在SSMS里右键服务器选属性,切到“安全性”,把服务器身份验证改成“SQL Server和Windows身份验证模式”。然后在“安全性–登录名–sa”上右键属性,状态里勾上“启用”,再把密码重置一遍。两个步骤都做完,重启SqlServer服务,再试sa登录。我每次装完2005都会顺手把这段记进笔记,因为隔一段时间再装,总会忘掉其中一个步骤。
5.2 安装卡在“性能计数器一致性检查”失败
现象:在安装SqlServer2005过程中,到“检查安装程序支持文件”那一步卡住,日志里报“Performance counter registry hive consistency check failed”,反复重装都过不去。
原因:这台Windows系统的性能计数器注册表项损坏了,2005的安装程序启动时会校验Perflib注册表,检测到不一致直接中止。
解决:这个坑在Windows 7虚拟机里很常见。最省事的做法是用管理员命令行执行lodctr /r,让系统重建性能计数器,重建完再重新运行安装程序。也可以把HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib键导出备份后删除,重启系统让它自动重建,但注册表操作风险高,我一般是在干净快照上先做一次系统更新,更新完再装2005,基本能绕过去。
5.3 附加数据库提示“无法打开物理文件”
现象:把一个MDF文件附加进SSMS,报“无法打开物理文件 xxx.mdf。操作系统错误5:5(拒绝访问)”,刚复制过来的文件也会这样。
原因:SQL Server服务账户对MDF和LDF文件没有读取权限。MDF从别的机器复制过来后,继承了原位置的ACL权限,SQL Server账户访问不到。
解决:在文件属性–安全里点“编辑”,给SQL Server服务账户加上完全控制权限,或者直接给Authenticated Users添加读取权限,之后再附加。很多人会顺手把MDF文件放到默认的数据目录,这样权限继承没问题,但如果放到自定义目录,权限这一关必须单独确认。
5.4 UPDATE执行后半天没反应:先查阻塞再说
现象:一条简单UPDATE语句,在测试库瞬间完成,一上生产库就卡住,十几分钟不返回。等的人急,但不敢杀进程。
原因:目标行被另一个连接持有了锁。SqlServer2005里最常见的是业务系统里有人开启了事务没有提交,占着行锁;或者是定时任务在跑大事务,正好覆盖到你更新的那批行。被阻塞的UPDATE会一直等锁,不会自动超时。
解决:先找出持有锁的会话。打开SSMS新建查询,执行sp_who2,看BlkBy列,哪个会话号出现在BlkBy字段,就是它在阻塞别人。确认是死会话后,用KILL杀掉那个会话号,比如KILL 57。注意先跟业务方确认是否为正常长事务,贸然KILL会回滚掉对方的事务,可能造成数据不一致。
5.5 从高版本备份恢复回2005:数据倒流不了
现象:从一台2008 R2服务器上备份出来的.bak文件,拿到2005上执行RESTORE,直接报“备份文件无法恢复,因为该备份文件是从服务器版本10.x创建的”。
原因:SqlServer备份文件只能恢复到版本相同或更高的实例上,2005是9.x,2008是10.x,高版本的备份文件2005不识别。这不是兼容性问题,是从设计上就不允许倒流。
解决:如果必须在2005上重建数据,只能从高版本导出脚本和数据。用“生成脚本”把表结构导出来,建到2005上,再用BCP或导出导入向导把表数据搬过去。BCP命令把一张表导出成文件,再在2005上用BCP导入,是2005时代最可靠的数据搬迁方式,流程固定,也方便定期同步。这种方式要改动的地方不少,特别是高版本用到的date、datetime2这些新类型,到2005得换成datetime才能落地。
6. 把笔记变成自检清单:用一套验证脚本收口
6.1 建一个不心疼的验证库
学习笔记最有价值的不是答案本身,是那些“原来还有这种写法”的时刻。我会在笔记旁边维护一个不心疼的验证库,专门用来试各种临时想法。名字就叫LearnDB,权限给足,随便建表、删表、清数据,所有验证脚本都以事务开始,以回滚结束,保证实验不残留数据。
6.2 把笔记条目转成幂等脚本
把笔记里的每一个结论转成一段“要么证明成立,要么证明记错”的SQL。比如验证LEFT JOIN会不会保留左表所有行。
USE LearnDB; BEGIN TRAN; SELECT COUNT(*) AS LeftRows FROM dbo.Customer; SELECT COUNT(DISTINCT c.CustomerID) AS JoinRows FROM dbo.Customer c LEFT JOIN dbo.Orders o ON c.CustomerID = o.CustomerID; ROLLBACK;两个数字一对比,JoinRows等于LeftRows,说明语义理解对了;不等,就回去翻笔记重新想。这种把知识变成可重复执行脚本的做法,比反复看视频高效得多。我后来带新人学老库,都强制让他们过一遍同样的流程:搭虚拟机、装2005、建LearnDB、把笔记每节转成验证脚本、全部ROLLBACK收尾。从那以后,再没出现过“看了三遍笔记还是不会写查询”的尴尬,自己的验证库里存着几十段能跑的脚本,比任何截图都有说服力。希望帮到你。
本文还有配套的精品资源,点击获取