
1. 从零开始为什么选择SQL Server作为你的第一个数据库如果你刚接触后端开发、数据分析或者想从Excel进阶到更强大的数据处理工具那么“数据库”这个词对你来说可能既熟悉又陌生。熟悉是因为它无处不在从你手机里的购物APP到公司的财务系统背后都离不开数据库陌生是因为它听起来像是一个需要深厚计算机背景才能驾驭的黑盒子。今天我想和你聊聊SQL Server特别是它为什么能成为许多开发者和数据分析师入门数据库的首选以及我们如何用最接地气的方式迈出坚实的第一步。我见过太多新手一上来就被各种数据库概念淹没关系型、非关系型、ACID、事务、索引……还没开始操作热情就被浇灭了一半。我的建议是先别管那么多理论我们从一个最朴素的需求开始如何安全、可靠、方便地存储和管理一堆有结构的数据比如一个简单的员工花名册里面有工号、姓名、部门和入职日期。用Excel当然可以但当数据量上千、需要多人同时修改、或者要频繁进行复杂查询比如“找出技术部所有在2020年前入职的员工”时Excel就会变得笨拙且容易出错。这时你就需要一个像SQL Server这样的关系型数据库管理系统RDBMS。SQL Server是微软出品的一款重量级商业数据库。选择它入门有几个非常实在的理由。首先它的图形化管理工具SQL Server Management Studio, SSMS做得极其友好你几乎可以通过点击完成大部分基础操作这大大降低了初学者的心理门槛。其次它和Windows生态、.NET开发体系结合紧密如果你身处这个技术栈学习SQL Server几乎是必然选择。再者它的T-SQLTransact-SQL语言在标准SQL的基础上增加了许多实用功能语法丰富且强大。最后微软提供了功能完整的免费版本——SQL Server Express对于学习和构建中小型应用完全够用。我们这篇基础篇就将以SQL Server Express和SSMS为环境带你亲手搭建起第一个数据库并理解最核心的几个概念。2. 环境搭建与初识SSMS亲手安装你的第一个数据库实例理论说再多不如动手装一遍。安装数据库环境是许多新手的第一个“拦路虎”但其实步骤很清晰。我们这里以安装免费的SQL Server 2019 Express版为例因为它轻量、免费且包含了我们学习所需的核心功能。2.1 下载与安装避开典型配置陷阱首先访问微软官网的SQL Server下载页面找到SQL Server 2019 Express。下载那个叫做“SQLServer2019-SSEI-Expr.exe”的安装引导程序。运行它选择“下载介质”或“基本”安装类型。对于纯粹的学习环境“基本”安装是最省心的它会自动安装数据库引擎和一个最小化的管理工具。安装过程中有几个关键点需要你特别注意这也是第一个实操心得注意在“实例配置”步骤如果你电脑上没有其他SQL Server版本通常选择“默认实例”即可。但如果未来你可能安装多个版本比如同时有2017和2019就需要命名实例如SQLEXPRESS。我们学习时用默认实例最简单。在“服务器配置”步骤请务必记下你为SQL Server Database Engine这个服务设置的“身份验证模式”。这里会引出我们第一个核心概念身份验证模式。SQL Server支持两种方式登录Windows身份验证直接用你登录Windows的账号密码来连接数据库无需额外记忆。这种方式最安全方便适合个人开发环境。混合模式SQL Server身份验证除了Windows账号你还可以为数据库创建一个专门的“sa”系统管理员账号并设置密码。一些第三方工具或远程连接可能需要这种方式。我强烈建议初学者在安装时直接选择“混合模式”并为sa用户设置一个强密码并牢记它。为什么因为这会让你在后续使用各种客户端工具时拥有最大的灵活性避免出现“只能用Windows登录其他工具连不上”的尴尬。这是一个非常典型的踩坑点很多教程只教Windows验证结果学员在用其他软件连接时卡住。安装完成后我们还需要一个“方向盘”来驾驶这个数据库引擎那就是SQL Server Management Studio (SSMS)。它是一个独立的免费工具需要单独下载安装。安装SSMS的过程很简单一路下一步即可。2.2 第一次连接理解“服务器”与“对象资源管理器”安装好SSMS后打开它。你会看到一个“连接到服务器”的对话框。这是你作为“驾驶员”与数据库“引擎”建立连接的握手环节。服务器类型选择“数据库引擎”。服务器名称这里填写你要连接的SQL Server实例所在的位置。对于本机安装的默认实例最简单就是一个小数点“.”或者“(local)”也可以写本机计算机名。如果你安装的是命名实例如SQLEXPRESS则需要写成计算机名\SQLEXPRESS或.\SQLEXPRESS。身份验证根据你安装时的选择来定。如果选了混合模式这里就可以选择“SQL Server身份验证”登录名填“sa”密码填你安装时设的那个。记住密码在学习环境可以勾选方便下次登录。点击“连接”如果一切顺利你就成功进入了SSMS的主界面。左侧那个树状结构的窗口叫做“对象资源管理器”它是你管理整个数据库服务器的控制台。在这里你可以看到“数据库”、“安全性”、“服务器对象”等文件夹。展开“数据库”文件夹你会看到一些系统自带的数据库如master,model,tempdb等这些是SQL Server自己用来管理的先不要动它们。我们的操作将从创建自己的第一个用户数据库开始。这个连接过程看似简单但已经蕴含了几个重要概念服务器实例一个安装好的SQL Server引擎、身份验证证明你是谁、连接建立会话通道。理解这些是后续所有操作的基础。3. 核心概念实战创建数据库、表与理解数据类型现在我们来到了最激动人心的环节创建属于自己的数据库和表。我将通过一个具体的例子——创建一个“公司员工管理系统”的数据库——来带你理解每一步背后的逻辑。3.1 创建第一个用户数据库不仅仅是点一下“新建”在“对象资源管理器”中右键点击“数据库”文件夹选择“新建数据库”。会弹出一个对话框。在“数据库名称”里我们输入CompanyDB。其他选项可以先保持默认直接点击“确定”。瞬间一个名为CompanyDB的数据库就创建好了。但这个过程背后发生了什么SSMS帮你执行了一条标准的SQL语句。你可以点击工具栏上的“新建查询”按钮打开一个查询编辑器窗口然后右键点击CompanyDB选择“编写数据库脚本为” - “CREATE到” - “新查询编辑器窗口”就能看到生成的SQL代码CREATE DATABASE [CompanyDB] CONTAINMENT NONE ON PRIMARY ( NAME NCompanyDB, FILENAME NC:\Program Files\...\CompanyDB.mdf , SIZE 8192KB , FILEGROWTH 65536KB ) LOG ON ( NAME NCompanyDB_log, FILENAME NC:\Program Files\...\CompanyDB_log.ldf , SIZE 8192KB , FILEGROWTH 65536KB )我来解释一下关键部分CREATE DATABASE [CompanyDB]这是核心命令创建名为CompanyDB的数据库。ON PRIMARY指定数据文件存储在“主”文件组上。FILENAME指出了数据库文件.mdf和日志文件.ldf在硬盘上的具体存储路径和文件名。.mdf是主要数据文件存储表、索引等实际数据.ldf是事务日志文件记录所有对数据库的修改操作用于数据恢复和保证事务完整性。SIZE和FILEGROWTH定义了文件的初始大小和增长方式。对于初学者你不需要记住这些语法但必须理解一个核心思想在SQL Server中创建一个数据库本质是在磁盘上分配和初始化一组文件数据文件和日志文件并建立一个逻辑名称来管理这些文件。图形化操作帮你隐藏了细节但了解底层有助于你未来处理数据库迁移、磁盘空间不足等问题。3.2 设计并创建第一张表数据类型的艺术数据库是仓库表就是仓库里一个个结构化的货架。现在我们要在CompanyDB里创建一个Employees员工表。右键点击CompanyDB下的“表”文件夹选择“新建” - “表”。右侧会打开表设计器。设计表就是定义这个“货架”有多少列字段每列放什么类型的数据。这步极其关键糟糕的表设计是后续所有数据混乱的根源。我们来定义几个字段EmployeeID (员工ID)数据类型int整数。这是最常用的整数类型。是否允许Null值取消勾选不允许为空。主键绝对不能为空。设计右键该列选择“设置主键”。主键是表中每一行数据的唯一标识就像每个人的身份证号。我们还将它设置为“标识规范”为“是”标识增量为1。这意味着EmployeeID会从1开始每新增一条记录自动加1我们无需手动输入避免了重复和错误。这是设计自增主键的标准做法。FirstName (名) LastName (姓)数据类型nvarchar(50)。varchar是可变长度字符串n前缀表示支持Unicode可以存储中文等字符。(50)表示最大允许50个字符。对于名字50个字符长度通常足够且能节省存储空间varchar只占用实际字符长度少量开销。是否允许Null这里根据业务决定。如果业务要求姓名必填就取消勾选不允许Null。我们假设名和姓都是必填项。DepartmentID (部门ID)数据类型int。为什么不用nvarchar直接存部门名称这里引入了关系型数据库的核心思想通过ID关联避免数据冗余。我们计划另建一张Departments表存放部门信息部门ID、部门名称这里只存一个指向Departments表的ID。这保证了数据一致性部门名只在Departments表里存一次。允许Null暂时允许因为员工可能未分配部门。HireDate (入职日期)数据类型date。专门用于存储日期年-月-日没有时间部分。比用datetime日期时间更精确存储空间也更小。允许Null通常不允许入职日期应是必填信息。Salary (薪资)数据类型decimal(10, 2)。decimal是精确数值类型适用于货币等需要精确计算的场景。(10, 2)表示总共10位数字其中小数点后占2位。这意味着最大可以存储99999999.99。允许Null允许可能有些实习生薪资未定。设计完所有列后点击工具栏的“保存”按钮或CtrlS输入表名Employees。至此你的第一张表就创建完成了。这个过程中关于数据类型选择和主键设计的决策是每个数据库设计者必须掌握的基本功。选错了类型比如用varchar存日期后续的查询、排序、计算都会异常痛苦。4. 数据的增删改查用T-SQL与你的数据对话表建好了空荡荡的。现在我们来学习如何与数据互动即经典的CRUD操作创建Create、读取Read、更新Update、删除Delete。这些操作通过T-SQL语句完成。在SSMS中我们通常在“新建查询”窗口里编写并执行这些语句。4.1 插入数据INSERT INTO语句我们要向Employees表添加几条员工记录。在查询窗口输入以下语句USE CompanyDB; -- 这条语句指定后续操作在哪个数据库中进行 GO -- GO是一个批处理分隔符告诉SSMS可以执行前面的语句了 INSERT INTO Employees (FirstName, LastName, DepartmentID, HireDate, Salary) VALUES (张, 伟, 1, 2020-05-10, 8500.00), (李, 娜, 2, 2019-11-23, 12000.50), (王, 磊, NULL, 2022-08-01, NULL);逐行解析USE CompanyDB;切换当前数据库上下文到CompanyDB。非常重要否则你可能会把数据插到别的数据库里。INSERT INTO 表名 (列1, 列2, ...)指定要向哪张表的哪些列插入数据。注意自增主键EmployeeID不需要出现在这里数据库会自动生成。VALUES (...), (...), ...提供要插入的具体值顺序必须和前面列的声明顺序一致。每个括号()代表一行数据。这里我们插入了三行。注意第三行数据DepartmentID和Salary我们插入了NULL值因为建表时允许它们为空。NULL在数据库里表示“未知”或“不适用”它不是空字符串也不是数字0。执行这段语句按F5或点击“执行”按钮下方消息窗口会显示“3行受影响”。恭喜数据已经入库了4.2 查询数据SELECT语句的千变万化查询是数据库最常用、也最灵活的操作。最基本的查询是查看所有数据SELECT * FROM Employees;*表示所有列。但实际工作中很少直接用*因为它会返回所有列可能包含你不关心的数据影响查询效率。更好的做法是指定需要的列SELECT EmployeeID, FirstName, LastName, HireDate FROM Employees;现在我们来点更有趣的查询条件查询使用WHERE子句。-- 查找薪资超过10000的员工 SELECT * FROM Employees WHERE Salary 10000; -- 查找姓‘张’的员工 SELECT * FROM Employees WHERE LastName 张; -- 查找部门ID为1或2并且在2020年之后入职的员工 SELECT * FROM Employees WHERE DepartmentID IN (1, 2) AND HireDate 2020-01-01;排序使用ORDER BY子句。-- 按入职日期从晚到早排序DESC表示降序 SELECT * FROM Employees ORDER BY HireDate DESC; -- 先按部门ID升序部门相同的再按薪资降序排 SELECT * FROM Employees ORDER BY DepartmentID ASC, Salary DESC;模糊查询使用LIKE运算符和通配符。-- 查找名字中带‘伟’字的员工%代表任意多个字符 SELECT * FROM Employees WHERE FirstName LIKE %伟%; -- 查找姓‘李’且名字只有两个字的员工_代表一个字符 SELECT * FROM Employees WHERE LastName 李 AND FirstName LIKE __;实操心得SELECT语句的WHERE条件中如果对列进行了函数操作如WHERE YEAR(HireDate) 2020可能会导致数据库无法使用该列上的索引从而在大数据量时严重拖慢查询速度。这是一个常见的性能陷阱。尽量保持WHERE条件中列的原貌如WHERE HireDate 2020-01-01 AND HireDate 2021-01-01。4.3 更新与删除数据务必慎之又慎更新和删除操作会直接修改磁盘上的数据因此必须格外小心最好先使用SELECT语句确认要操作的目标数据。更新数据使用UPDATE语句。-- 将员工ID为2的员工李娜的薪资调整为13000 UPDATE Employees SET Salary 13000.00 WHERE EmployeeID 2;关键点WHERE子句在这里至关重要如果没有WHERE条件UPDATE语句会更新表中的所有行这通常是一场灾难。所以在执行UPDATE或DELETE前养成先用SELECT ... WHERE ...验证结果集的习惯。删除数据使用DELETE语句。-- 删除员工ID为3的员工记录王磊 DELETE FROM Employees WHERE EmployeeID 3;同样WHERE子句是生命线。没有它的DELETE FROM Employees会清空整张表对于重要的数据在删除前进行备份是铁律。5. 建立表间关系理解关系型数据库的“关系”之前我们提到Employees表中的DepartmentID是一个指向另一张表的ID。现在我们来创建那张Departments表并建立它们之间的“关系”。5.1 创建从表并插入数据首先创建Departments表CREATE TABLE Departments ( DepartmentID int PRIMARY KEY IDENTITY(1,1), -- 部门ID主键自增 DepartmentName nvarchar(50) NOT NULL, -- 部门名称不允许为空 Location nvarchar(100) NULL -- 办公地点允许为空 );然后插入一些部门数据INSERT INTO Departments (DepartmentName, Location) VALUES (技术部, A座3楼), (市场部, B座2楼), (人事部, A座1楼);5.2 建立外键约束数据完整性的守护者目前Employees表中的DepartmentID值为1, 2等只是一个普通的整数。我们可以随意插入一个不存在的部门ID如999这会导致数据不一致一个员工属于一个不存在的部门。为了防止这种情况我们需要建立外键约束。外键约束定义了表与表之间的一种引用关系。Employees表中的DepartmentID列是外键它引用指向Departments表中的DepartmentID主键列。在SSMS中建立外键在对象资源管理器中展开CompanyDB- “表” -Employees。右键点击“键”选择“新建外键”。在“外键关系”对话框中点击“表和列规范”右侧的“...”按钮。在主键表下拉框中选择Departments并在下方网格中将主键表列选择为DepartmentID外键表列选择为DepartmentID。点击“确定”保存。现在外键约束已经建立。它的作用是阻止插入你无法在Employees表中插入一个DepartmentID值除非这个值在Departments表的DepartmentID列中存在。阻止更新你不能随意更新Departments表中已被Employees表引用的DepartmentID值除非设置级联操作。阻止删除你不能直接删除Departments表中被Employees表引用的行除非设置级联操作。这就是关系型数据库维护数据参照完整性的核心机制。它确保了“员工所属部门”这个信息的真实有效。5.3 使用JOIN进行关联查询让数据“活”起来有了关系我们就可以通过JOIN连接查询将分散在多张表中的数据按逻辑关系组合起来呈现完整的信息。最基本的连接是INNER JOIN内连接它只返回两个表中匹配的行。SELECT e.EmployeeID, e.FirstName e.LastName AS FullName, -- 拼接姓名并起别名FullName d.DepartmentName, e.HireDate, e.Salary FROM Employees e -- 给Employees表起别名e INNER JOIN Departments d ON e.DepartmentID d.DepartmentID; -- 通过DepartmentID连接这条语句会列出所有有明确部门的员工及其部门名称。如果某个员工的DepartmentID是NULL或者是一个不存在于Departments表中的值那么这条记录就不会出现在结果里。如果你想列出所有员工即使他没有部门DepartmentID为NULL就需要用到LEFT JOIN左连接SELECT e.EmployeeID, e.FirstName e.LastName AS FullName, ISNULL(d.DepartmentName, 未分配) AS DepartmentName, -- 如果部门名为NULL显示‘未分配’ e.HireDate, e.Salary FROM Employees e LEFT JOIN Departments d ON e.DepartmentID d.DepartmentID;LEFT JOIN会返回左表Employees的所有行即使右表Departments中没有匹配的行。对于不匹配的行右表的列将显示为NULL。我们使用ISNULL函数将这些NULL值替换为更友好的“未分配”字样。理解并熟练运用JOIN是你从“会写单表查询”到“能处理真实业务数据关系”的关键飞跃。在实际项目中一个复杂的报表查询可能涉及五六张甚至更多表的连接。6. 基础篇的总结与避坑指南走到这里你已经完成了SQL Server入门最核心的一环从安装环境、理解核心概念实例、数据库、表、数据类型、主键到进行最基本的CRUD操作再到建立表间关系并进行关联查询。你已经拥有了操作一个关系型数据库所需的全套基础工具。回顾一下我们构建的简单系统一个CompanyDB数据库里面有两张表Employees和Departments通过DepartmentID建立了外键关系。你可以插入员工和部门数据可以查询、更新、删除还可以通过JOIN看到完整的员工部门信息。这已经是一个微型应用的数据层雏形。在结束之前我想分享几个我早期学习时踩过的坑希望能帮你绕开关于NULL的陷阱NULL与任何值包括NULL本身进行比较结果都是UNKNOWN而不是TRUE或FALSE。因此查询条件WHERE Salary NULL是错误的它永远查不到数据。正确的写法是WHERE Salary IS NULL。同样WHERE Salary NULL也是错的应写为WHERE Salary IS NOT NULL。字符串与日期格式在T-SQL中字符串和日期常量需要用单引号括起来。对于日期虽然2023-08-01这种YYYY-MM-DD格式兼容性最好但有时也会遇到其他格式。为了避免混淆和错误在插入或比较日期时明确使用标准格式或者使用CONVERT或CAST函数进行转换。事务的初步认知我们上面的UPDATE和DELETE操作都是直接生效的。但在实际业务中一组操作要么全部成功要么全部失败这需要“事务”来保证。一个简单的事务示例BEGIN TRANSACTION; -- 开始事务 UPDATE Accounts SET Balance Balance - 100 WHERE AccountID 1; -- A账户扣款 UPDATE Accounts SET Balance Balance 100 WHERE AccountID 2; -- B账户收款 -- 如果此时检查发现A账户余额不足可以执行 ROLLBACK TRANSACTION; 回滚所有操作 COMMIT TRANSACTION; -- 确认无误提交事务所有更改永久生效对于初学者可以先知道有BEGIN TRANSACTION、COMMIT、ROLLBACK这几个命令它们用于保证数据操作的原子性。在SSMS的查询窗口默认是“自动提交”模式每条语句自己就是一个事务。在后续的教程中我们会深入探讨事务。养成备份习惯尤其是在学习阶段当你打算进行一些不确定的、可能破坏数据的操作如修改表结构、删除大量数据前右键点击你的数据库选择“任务”-“备份”做一个完整的数据库备份。这是你的“后悔药”。学习数据库动手远比看书重要。我建议你按照本文的步骤在自己的电脑上完全重现一遍这个CompanyDB的创建和操作过程。然后尝试设计一个你自己的主题比如“个人图书管理系统”Books, Authors表或“简易博客系统”Posts, Comments表从建库、建表、插数据到查询完整地走一遍流程。遇到报错不要慌仔细阅读错误信息它通常已经告诉了你问题所在。SQL Server和SSMS的联机丛书按F1也是极好的官方文档。