SQL Server 快速入门学习笔记
1. 安装(开发版)
下载步骤:
- 下载离线安装包
SQL2022-SSEI-Dev.exe- 链接 1:
https://go.microsoft.com/fwlink/?LinkID=2214968 - 链接 2:
https://download.microsoft.com/.../SQL2022-SSEI-Dev.exe - 链接 3:
https://www.microsoft.com/en-us/sql-server/sql-server-downloads
- 链接 1:
- 通过离线安装包下载完整的离线镜像文件
SQLServer2022-x64-CHS-Dev.iso。
安装 SQL Server 核心引擎:
- 右键点击
SQLServer2022-x64-CHS-Dev.iso文件,选择"装载",运行根目录下的setup.exe。 - 进入安装中心,选择"全新 SQL Server 独立安装"。
- 一路配置:选 Developer 版 -> 取消勾选 Azure -> 只勾选"数据库引擎服务" -> 选择"默认实例"。
- 在"数据库引擎配置"页面:选择**"混合模式"**,设置 sa 密码;去"数据目录"把路径全部改到 D 盘。
- 点击安装,等待完成,重启电脑。
安装官方管理工具:
- 安装 SSMS (SQL Server Management Studio)。
- 账号:
sa,密码:Sqlserver@022
2. 数据库基础认知
数据库包含的核心对象:表、索引、视图、存储过程、触发器等。
3. 数据表与数据类型
建表时注意数据类型(字段类型)的选择,以下是常用类型与 Java 类型的对应关系:
一、字符串类型(存文字、编号、密码等)
nvarchar(n)☆最常用。存包含中文的文本,n 代表最大字符数(如nvarchar(50)存姓名)。对应 Java:Stringnvarchar(max):存超长文本(如文章内容、长备注),最大能存 2GB。对应 Java:Stringvarchar(n):存纯英文、数字或符号(如手机号、QQ号、加密后的密码)。比 nvarchar 省一半空间。对应 Java:Stringchar(n) / nchar(n):定长字符串。比如身份证号固定 18 位,用nchar(18)效率最高;性别固定 1 位,用nchar(1)。对应 Java:String
二、数字类型(存年龄、数量、金额、状态)
int☆最常用。标准的整数,范围约 ±21 亿。常用来做主键 ID、年龄、数量。对应 Java:Integerbigint☆最常用。超大整数。如果数据量极大(如淘宝订单号、雪花算法 ID),必须用这个。对应 Java:Longdecimal(p, s)☆存钱必用。精确小数。p 是总位数,s 是小数位数。金额通常用decimal(18, 2)。对应 Java:BigDecimalbit:布尔值。只能存 0 或 1(代表 false/true)。比如"是否删除"、"是否启用"。对应 Java:Booleantinyint:极小整数(0-255)。常用来存状态码(如:0待支付,1已支付,2已发货)。对应 Java:Integer/Bytefloat / real:近似浮点数。用来做科学计算。绝对不要用来存金额 (会丢失精度)。对应 Java:Double/float
三、日期与时间类型(存生日、创建时间)
datetime2☆最推荐。存年月日时分秒,精度极高(可到微秒)。通常用来做"创建时间"、"更新时间"。对应 Java:LocalDateTimedate:只存年月日。对应 Java:LocalDatetime:只存时分秒。对应 Java:LocalTimedatetime:老版本类型。精度较低,且占用空间大,建议全面用datetime2替代。对应 Java:Date
4. SQL 增、删、改、查(CRUD)
当前测试表结构 :[myDB].[dbo].[user]
表结构:
CREATE TABLE [dbo].[Untitled] (
[id] int NOT NULL,
[name] nvarchar(8) COLLATE Chinese_PRC_CI_AS NULL,
[gender] nchar(1) COLLATE Chinese_PRC_CI_AS NULL,
[birthday] datetime NULL,
PRIMARY KEY CLUSTERED ([id])
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
ON [PRIMARY]
)
ON [PRIMARY]
GO
ALTER TABLE [dbo].[Untitled] SET (LOCK_ESCALATION = TABLE)
⚠️ 注意 :
user是 SQL Server 的系统保留字,所以在写 SQL 时必须加上方括号[]。
4.1 增(INSERT)
向表中插入新数据。列名和值的顺序必须一一对应。
sql
-- 插入单条数据
INSERT INTO [myDB].[dbo].[user] (id, name, gender, birthday)
VALUES (1, '张三', '1', '2000-01-01 08:00:00');
-- 批量插入多条数据(企业开发中常用于初始化数据)
INSERT INTO [myDB].[dbo].[user] (id, name, gender, birthday)
VALUES
(2, '李四', '0', '1999-05-20 12:00:00'),
(3, '王五', '1', '2001-11-11 23:59:59');
4.2 改(UPDATE)
修改表中已存在的数据。
🚨 致命警告 :
UPDATE必须配合WHERE条件使用,否则会更新整张表的数据!
sql
-- 修改 id 为 1 的用户的姓名和生日
UPDATE [myDB].[dbo].[user]
SET name = '张三丰', birthday = '1990-01-01 00:00:00'
WHERE id = 1;
4.3 删(DELETE)
删除表中的数据。
🚨 致命警告 :
DELETE同样必须带WHERE,否则就是"删库跑路"(清空全表)。如果不带 WHERE 且想清空全表,建议用TRUNCATE TABLE [表名](效率更高且不记日志)。
sql
-- 删除 id 为 3 的用户
DELETE FROM [myDB].[dbo].[user]
WHERE id = 3;
4.4 查(SELECT)- 基础与进阶语法
查询是开发中最核心、最复杂的操作。
1. 基础查询与条件过滤 (WHERE)
sql
-- 查询所有男性用户
SELECT * FROM [myDB].[dbo].[user] WHERE gender = '1';
-- 模糊查询:查询名字里带"张"的用户 (% 代表任意字符)
SELECT * FROM [myDB].[dbo].[user] WHERE name LIKE '%张%';
-- 范围查询:查询 id 在 1 到 5 之间的用户
SELECT * FROM [myDB].[dbo].[user] WHERE id IN (1, 2, 5);
2. 排序 (ORDER BY) 与 去重 (DISTINCT)
sql
-- 按生日倒序排列 (DESC 降序,ASC 升序默认)
SELECT id, name, birthday FROM [myDB].[dbo].[user] ORDER BY birthday DESC;
-- 查询当前表里都有哪些性别(去重)
SELECT DISTINCT gender FROM [myDB].[dbo].[user];
3. 分页查询 (SQL Server 专用)
企业开发中,绝不能一次性查出几万条数据,必须分页(配合前端页面的上一页/下一页)。
sql
-- 按 id 排序后,跳过前 0 条,取接下来的 10 条数据 (即第一页,每页10条)
SELECT * FROM [myDB].[dbo].[user]
ORDER BY id ASC
OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;
🚀 4.5 企业级开发必知:SELECT 的高阶必备知识
以上是基础语法,但在真实的 Java + Spring Boot 企业级项目中,SELECT 还要掌握以下内容:
① 聚合函数与分组(做后台报表统计必用)
不要查出一堆数据在 Java 里用 for 循环算,要用数据库算。
COUNT():统计数量。GROUP BY:分组。
sql
-- 统计男女性别各有多少人
SELECT gender, COUNT(*) AS total_count
FROM [myDB].[dbo].[user]
GROUP BY gender;
② 多表连接查询(JOIN)⭐ 核心中的核心
真实的业务数据分散在多张表里。比如你还有一个 orders(订单表)。查数据时一般不用 SELECT *,只查你需要的字段 (减少网络传输,避免列名冲突)。并在多表连接时使用 别名 (如 u, o)。
LEFT JOIN(左连接):以左表(用户表)为主,哪怕这个用户没下过单,也要查出用户,订单字段显示为空(NULL)。这是后端开发最常用的连接方式。
sql
-- 假设有个订单表 orders (id, user_id, amount)
SELECT u.id, u.name, o.amount
FROM [myDB].[dbo].[user] u
LEFT JOIN [myDB].[dbo].[orders] o ON u.id = o.user_id;
③ 动态参数与防 SQL 注入(MyBatis 必考)
在 Spring Boot 的 MyBatis 中,坚决禁止用 ${} 拼接 SQL 字符串,这会导致 SQL 注入漏洞。
-
必须用
#{}(预编译机制),MyBatis 底层会自动将其转化为 JDBC 的?占位符。xml
<!-- 正确写法:MyBatis XML 中的查询 --> <select id="getUserByName" resultType="User"> SELECT id, name, gender FROM [myDB].[dbo].[user] WHERE name = #{name} </select>
④ 避免使用 SELECT *
在企业中,SELECT * 被视为"开发恶习"。原因有三:
- 会把不需要的字段查出来(比如大文本字段),拖慢网络和内存。
- 如果表结构变更(加字段、删字段),可能会让 Java 代码的实体类映射报错。
- 无法有效利用"覆盖索引"优化查询速度。
正确姿势 :按需写明列名,如SELECT id, name, gender FROM ...。
5. T-SQL 编程语言
5.1 IF 判断
sql
IF NOT EXISTS (SELECT * FROM [myDB].[dbo].[user] WHERE name = '刘')
BEGIN
INSERT INTO [myDB].[dbo].[user] (id, name, gender, birthday)
VALUES (2, '刘', '0', '2000-08-23 11:58:59');
END
ELSE
BEGIN
-- 其他逻辑
END;
SELECT * FROM [myDB].[dbo].[user];
5.2 WHILE 循环 (含 CONTINUE 和 BREAK)
修正了原笔记中缺失的变量名 @i 和拼写错误 Itrim -> LTRIM
sql
DECLARE @i INT = 21;
WHILE (SELECT COUNT(*) FROM [myDB].[dbo].[user]) < 25
BEGIN
INSERT INTO [myDB].[dbo].[user] (id, name, gender, birthday)
VALUES (@i, '刘' + LTRIM(STR(@i)), '0', '2000-08-23 11:58:59');
SET @i = @i + 1;
IF @i = 23
BEGIN
CONTINUE; -- 跳过23,直接进行下一次循环
END
IF @i = 24
BEGIN
BREAK; -- 到24就彻底跳出循环
END
END;
SELECT * FROM [myDB].[dbo].[user];
6. 视图 (View)
创建视图:
sql
CREATE VIEW uv AS
SELECT id, name FROM [myDB].[dbo].[user] WHERE gender = '0';
修改视图: 把 CREATE 改成 ALTER 即可(不需要先删除)。
更优的写法(如果视图存在就修改,不存在就新增):
sql
CREATE OR ALTER VIEW uv AS
SELECT id, name FROM [myDB].[dbo].[user] WHERE gender = '1';
删除视图:
sql
DROP VIEW uv;
查看视图:
sql
SELECT * FROM uv;
⚠️ 注意 :如果用
UPDATE语句修改视图,将直接修改原表数据,慎用!
7. 存储过程 (Stored Procedure)
创建存储过程:
修正了原笔记中 like 语句漏掉的单引号
sql
CREATE PROCEDURE querylike
@key VARCHAR(20)
AS
BEGIN
SELECT * FROM [myDB].[dbo].[user]
WHERE name LIKE '%' + @key + '%';
END
GO;
修改存储过程:
sql
ALTER PROCEDURE querylike
@key VARCHAR(20)
AS
BEGIN
SELECT * FROM [myDB].[dbo].[user]
WHERE name LIKE '%' + @key + '%' OR gender = @key;
END
GO
使用存储过程:
sql
EXEC querylike '1';
-- 或者使用完整拼写 EXECUTE querylike '1';
8. 触发器 (Trigger)
创建触发器:
修正了原笔记中重复的代码块,整理了缩进
sql
CREATE TRIGGER triggerinsertUpdate
ON [myDB].[dbo].[user]
AFTER INSERT, UPDATE
AS
BEGIN
-- 检查本次插入或更新的所有数据中,是否存在 gender 为 NULL 的情况
IF EXISTS (SELECT 1 FROM inserted WHERE gender IS NULL)
BEGIN
-- 抛出明确的错误信息给调用方(比如 Spring Boot 后端)
THROW 50001, '操作失败:gender 不能为空!', 1;
-- 回滚事务
ROLLBACK TRANSACTION;
END
END
GO