☰
SQL Server 学习笔记(详细整理版)
2026/9/30 6:52:04 网站建设 项目流程

涵盖:数据库基础概念、数据类型、五大约束、DDL 库表结构操作、DML 增删改查、多表 JOIN、分组聚合、分页、子查询、结果集合并,附带练习案例与避坑要点

一、数据库基础必学概念

核心学习清单:数据库、架构 (schema)、表、字段、数据类型、约束、视图、存储过程、函数、触发器、临时表、表变量。

1. 常用重点数据类型

分类类型说明与注意事项
字符类型varchar(n)非 Unicode 字符串,存中文容易乱码,适合纯英文数字
nvarchar(n)Unicode 类型,中文优先使用,n 代表最多字符数量
char / nchar定长字符,长度不足自动补空格,一般很少使用
数值类型int整型,普通数字
bigint长整型,用于自增主键 Id,数据量大时使用
decimal(精度,小数位)定点小数,金额、价格必须用这个,避免精度丢失
float浮点数,存在精度误差,禁止用于金额计算
时间类型datetime旧版时间类型,精度较低
datetime2推荐使用,时间范围更大、精度更高

💡坑点总结:存储中文,字符字段一律选用nvarchar,避免中文乱码

2. 五大约束(保证数据完整性,防止脏数据)

约束作用:对表中数据做限制,从数据库层面拦截非法数据。

缩写约束名称关键字作用说明
PK主键约束PRIMARY KEY唯一标识一行数据;不能为 NULL,不能重复;一张表仅能设置 1 个主键,支持多个字段组成复合主键
UK唯一约束UNIQUE字段值不能重复;SQL Server 允许最多 1 行 NULL,不能多条 NULL;一张表可设置多个唯一约束
FK外键约束FOREIGN KEY引用另一张表的主键,保障关联数据一致性;例:订单表UserId必须在用户表中真实存在
CHECK检查约束CHECK()限制字段取值范围;例:价格≥0、年龄 > 0
DEFAULT默认值约束DEFAULT 值插入数据不填写该字段时,自动填充预设值;例:IsDelete bit DEFAULT 0默认未删除

示例 1:创建用户表 UserInfo

CREATE TABLE UserInfo ( Id bigint PRIMARY KEY IDENTITY(1,1), -- PK主键,自增从1开始,步长1 UserName nvarchar(50) NOT NULL, Phone nvarchar(11) UNIQUE, -- UK唯一约束:手机号不能重复 Age int CHECK(Age>0), -- CHECK约束:年龄必须大于0 Balance decimal(18,2) DEFAULT 0, -- DEFAULT 默认值 IsDelete bit DEFAULT 0 )

示例 2:创建订单表 OrderInfo,外键关联用户表

CREATE TABLE OrderInfo( OrderId bigint PRIMARY KEY IDENTITY(1,1), UserId bigint, OrderMoney decimal(18,2), -- FK外键,关联UserInfo的Id主键 FOREIGN KEY(UserId) REFERENCES UserInfo(Id) );

📝课堂练习:新建 Product 产品表 需求:主键 Id、产品名称(唯一)、价格大于等于 0、默认库存 100

CREATE TABLE Product( Id bigint PRIMARY KEY IDENTITY(1,1), ProductName nvarchar(50) UNIQUE, Price decimal(18,2) CHECK(Price>=0), Inventory int DEFAULT 100 );

二、DDL 数据定义语言(操作库、表结构,不操作表内数据)

核心关键字:CREATE创建、ALTER修改、DROP删除

⚠️警告:DROP直接销毁对象,没有回收站,生产环境谨慎执行!

1. 数据库操作

CREATE DATABASE StudyDB; -- 创建数据库StudyDB USE StudyDB; -- 切换当前操作的数据库 DROP DATABASE StudyDB; -- 删除数据库

练习任务:

  1. 创建数据库BlogDB
  2. USE BlogDB;切换库
  3. 新建 Article 文章表:主键 Id,标题 nvarchar,阅读量 int 默认 0
  4. 使用 ALTER 新增创建时间字段 datetime2
CREATE DATABASE BlogDB; GO USE BlogDB; CREATE TABLE Article( Id bigint PRIMARY KEY IDENTITY(1,1), Title nvarchar(100) NOT NULL, ReadNum int DEFAULT 0 ); -- ALTER新增创建时间 ALTER TABLE Article ADD CreateTime datetime2 DEFAULT SYSDATETIME();

2.ALTER 修改表结构

-- 新增字段 ALTER TABLE UserInfo ADD Email nvarchar(100); -- 修改字段类型 ALTER TABLE UserInfo ALTER COLUMN Email nvarchar(200); -- 删除字段 ALTER TABLE UserInfo DROP COLUMN Email;

3.DROP 删除表

DROP TABLE UserInfo; -- 删除整张表,表结构+数据全部消失

三、DML 数据操作语言(重点!操作表里的数据行)

关键字:SELECT查询、INSERT新增、UPDATE修改、DELETE删除

✅ SELECT 完整书写顺序(牢记)

SELECT 字段列表 FROM 表 别名 JOIN 关联表 ON 关联条件 WHERE 行过滤条件 GROUP BY 分组字段 HAVING 分组后过滤 ORDER BY 排序字段 OFFSET ... FETCH NEXT 分页

1. 多表连接 JOIN

连接类型说明
INNER JOIN内连接只返回两边表可以匹配上的数据,相当于交集
LEFT JOIN左连接左表所有数据全部保留;右表匹配不到,右表字段填充 NULL
RIGHT JOIN右连接右表全部保留,左表匹配不到为 NULL
CROSS JOIN交叉连接笛卡尔积,大部分业务场景不使用

2.WHERE

  • 在分组之前过滤原始数据行
  • ❌不能使用聚合函数SUM、COUNT、MAX等

3.GROUP BY 分组 + 聚合函数

常用聚合函数SUM()求和、COUNT()计数、AVG()求平均值、MAX()最大值、MIN()最小值

规则:SELECT 后面写的普通非聚合字段,需要放到 GROUP BY 中; 如果分组字段是主键,SQL Server 允许同表其他字段不写进 GROUP BY,为了兼容多数据库,建议全部写上

COUNT 补充重点
  1. COUNT(字段):统计该字段不为 NULL 的行数;左连接统计子表记录优先用这个;NULL 不会计数
  2. COUNT(*):统计行数,不管是否为 NULL,左连接统计子表不要用,会统计出来错误数据
AS 别名

WHERE:过滤原始行;HAVING:过滤分组后的结果

  • AS用来给列设置查询临时别名,不会修改原表字段,AS 可以省略
  • ORDER BY可以识别别名;GROUP BY、HAVING不能识别别名
    COUNT(o.OrderId) AS OrderCount --带AS COUNT(o.OrderId) OrderCount --省略AS,效果一样
  • 分组统计完成之后对分组结果过滤
  • ✅可以写聚合函数,这是和 WHERE 最大区别

5.ORDER BY 排序

ORDER BY CreateTime DESC; --DESC降序,最新数据放最上面;ASC升序(默认)

6. 分页两种写法

写法 1:TOP,简单取前 N 条

SELECT TOP 10 * FROM UserInfo;

写法 2:OFFSET ... FETCH NEXT(SQL Server2012 及以上推荐)

⚠️强制要求:分页必须搭配ORDER BY,否则分页结果错乱不稳定 计算公式:OFFSET = (页码-1)*每页条数

--第1页,取10条 SELECT * FROM UserInfo ORDER BY Id OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;

📝综合练习任务(LEFT JOIN + 分组 + HAVING + 排序 + 分页)

需求:

  1. LEFT JOIN 关联用户表、订单表,统计每个用户订单总数
  2. HAVING 筛选订单总数≥2 的用户
  3. ORDER BY 总金额降序
  4. OFFSET FETCH 取第 1 页,5 条数据
    SELECT u.ID,u.UserName, COUNT(o.OrderId) OrderCount , SUM(o.OrderMoney) TotalMoney FROM UserInfo u LEFT JOIN OrderInfo o ON u.Id=o.UserId GROUP BY u.Id,u.UserName HAVING COUNT(o.OrderId)>=2 ORDER BY TotalMoney DESC OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY;

    7. 子查询

    1. 标量子查询:返回单个值,可以放在 SELECT、WHERE 后使用
    2. IN 子查询:返回一组值,WHERE Id IN (1,2,3)
    3. EXISTS:判断子查询是否有返回数据;找到匹配立刻停止,性能优于 IN

示例:查询有订单的用户

SELECT * FROM UserInfo u WHERE EXISTS (SELECT 1 FROM OrderInfo o WHERE o.UserId = u.Id);

8.UNION/ UNION ALL 合并结果集

要求:前后查询列数量、数据类型必须保持一致

  • UNION:合并结果并且自动去重,性能差
  • UNION ALL:直接拼接结果,不去重,业务优先使用,速度更快
SELECT Id,UserName FROM UserInfo WHERE Id=1 UNION ALL SELECT Id,UserName FROM UserInfo WHERE Id=2

9.INSERT/ UPDATE / DELETE 增删改

-- INSERT插入 INSERT INTO UserInfo(UserName,Age) VALUES(N'张三',20); -- UPDATE修改 UPDATE UserInfo SET Age=21 WHERE Id=1; -- DELETE删除 DELETE FROM UserInfo WHERE Id=1;

⚠️生产重要提醒:UPDATE和DELETE执行前,先用 SELECT 验证 WHERE 条件! 一旦忘记写 WHERE 条件,会造成全表更新、全表删除重大事故。

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

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

立即咨询