T-SQL 变量赋值、全局变量、流程控制+T-SQL WHILE循环、表创建与数据修改+T-SQL 视图(View)

📅 2026/7/26 8:50:02 👁️ 阅读次数 📝 编程学习
T-SQL 变量赋值、全局变量、流程控制+T-SQL WHILE循环、表创建与数据修改+T-SQL 视图(View)

核心考点:局部变量与全局变量区别、SET与SELECT赋值差异、流程控制(IF-ELSE、CASE WHEN)、游标循环遍历数据、常用全局变量用法

适配表结构:Students(StudentId, Name, Age, ClassId)、ScoreList(StudentId, Score, DB)

--定义局部变量:同时定义两个变量,类型为int declare @age int,@stuId int; --方式1:SET赋值(单变量赋值,常用) set @age = 10; print @age; --输出:10 --方式2:SELECT赋值(可同时为多个变量赋值) select @age=Age,@stuId=StudentId from Students where StudentId = 1001; print @age; --输出查询到的学生年龄 print @stuId;--输出查询到的学生ID

1.2 SET与SELECT赋值差异(核心考点)

--场景1:查询结果为多条数据时 --SELECT赋值:返回多条结果时,取最后一条数据赋值给变量 select @stuId=StudentId from Students where ClassId =2; print @stuId; --输出:ClassId=2的最后一个学生ID --SET赋值:子查询返回多条结果时,直接报错(SET不支持多结果赋值) --set @stuId= (select StudentId from Students where ClassId =3); --执行报错 --print @stuId; --场景2:查询结果不存在时 set @stuId=100; --先给变量赋值100 --SET赋值:查询无结果,变量被赋值为NULL set @stuId= (select StudentId from Students where ClassId =100); --无匹配数据 print @stuId; --输出:NULL --SELECT赋值:查询无结果,变量保留原有值(不改变) select @stuId=StudentId from Students where ClassId =100; --无匹配数据 print @stuId; --输出:100(保留之前赋值的100)

1.3 SET与SELECT赋值核心区别(必背)

  • 赋值数量:SET 一次只能给一个变量赋值;SELECT 可同时给多个变量赋值。

  • 多结果处理:SET 子查询返回多条结果时报错;SELECT 返回多条结果时取最后一条赋值。

  • 无结果处理:SET 无结果时变量赋值为 NULL;SELECT 无结果时变量保留原有值。

二、全局变量(@@开头)

全局变量由SQL Server系统定义,以@@开头,用于获取系统状态、操作结果等信息,用户只能读取,不能修改。

--1. @@ERROR:返回上一条语句的错误码(0表示无错误,非0表示有错误) --delete from Students where StudentId = 1000; --假设该ID不存在,执行无错误 print @@error; --输出:0(无错误) --2. @@IDENTITY:返回上一条插入语句生成的自增标识列值(主键自增时常用) insert into Students values('1',29,'1','1','1','2020-10-1'); print @@identity; --输出:新插入数据的StudentId(自增列值) --3. @@ROWCOUNT:返回上一条语句受影响的行数 select * from Students; print @@rowcount; --输出:查询到的学生总条数(如10条) --4. @@MAX_CONNECTIONS:返回当前数据库允许的最大连接数 print @@Max_connections; --输出:系统配置的最大连接数(如32767) --5. @@SERVICENAME:返回当前SQL Server服务的实例名 print '当前服务器实例:' + @@servicename; --输出:当前服务器实例名称(如MSSQLSERVER) --6. @@FETCH_STATUS:游标专用,返回游标读取数据的状态(0=成功,-1=失败,-2=行不存在) --后续游标部分详细使用

三、流程控制语句

流程控制用于控制SQL语句的执行顺序,核心包括 IF-ELSE 条件判断、CASE WHEN 条件分支,适配不同业务场景的逻辑处理。

3.1 IF-ELSE 条件判断

用于单条件或多条件分支判断,满足条件执行对应语句块,支持嵌套,适用于简单逻辑判断。

--示例:查询2班C#平均分,根据平均分输出评价 declare @c# int; --定义变量,存储平均分 --计算2班C#平均分,赋值给变量 select @c# = AVG(Score) from ScoreList inner join Students on ScoreList.StudentId=Students.StudentId where ClassId = 2; select @c# as 平均值; --显示平均分 --IF-ELSE条件判断 if @c# is Null --判断平均分是否为NULL(无成绩) begin print '该班无成绩'; --执行语句块1 end else if(@c#>80) --判断平均分是否大于80 print '该班成绩良好'; --执行语句块2 else --其他情况 begin print '该班成绩稍差'; --执行语句块3 end

3.2 CASE WHEN 条件分支(行级判断)

用于查询语句中,对每一行数据进行条件判断,返回对应结果,适用于批量数据的分支处理(区别于IF-ELSE的批处理判断)。

--示例:根据成绩(Score+DB)平均分,为每个学生评级 select Students.StudentId, --学生ID Name, --学生姓名 --CASE WHEN 条件分支,每行数据单独判断 case when(Score+DB)/2>=90 then 'A' --平均分≥90,评级A when(Score+DB)/2 between 80 and 90 then 'B' --80≤平均分<90,评级B when(Score+DB)/2 between 70 and 80 then 'C' --70≤平均分<80,评级C when(Score+DB)/2 between 60 and 70 then 'D' --60≤平均分<70,评级D else '不及格' --其他情况,评级不及格(相当于default) end as '评级' --给分支结果起别名 from ScoreList inner join Students on ScoreList.StudentId=Students.StudentId;

四、游标(Cursor)循环遍历数据

游标用于逐行读取查询结果集,适用于需要对每行数据单独处理的场景(如逐行打印、逐行判断),核心分为6个步骤:定义→打开→初始化→循环→关闭→释放。

4.1 游标完整示例(逐行打印成绩大于50的学生信息)

--定义变量,接收游标读取的数据 declare @a int; --成绩 declare @b nvarchar(10);--姓名 declare @c int; --学号 --1. 定义游标:指定游标名称和关联的查询结果集 declare Curesor_my cursor for select Score , Name ,Students.StudentId from Students inner join ScoreList on ScoreList.StudentId=Students.StudentId; --2. 打开游标:启动游标,准备读取数据 open Curesor_my; --3. 初始化游标:指向结果集第一行,将数据赋值给变量 fetch next From Curesor_my into @a,@b,@c; --4. 循环遍历:根据@@FETCH_STATUS判断是否读取成功(0=成功) while @@FETCH_STATUS = 0 begin --逐行判断:成绩大于50,打印学生信息 if(@a>50) print '学号:'+ convert(varchar(10),@c)+ ' 姓名:'+@b+' 成绩:'+convert(varchar(10),@a); --5. 拉取下一行数据,为下一次循环做准备(必须写,否则死循环) fetch next From Curesor_my into @a,@b,@c; end --6. 关闭游标:释放游标占用的资源 close Curesor_my; --7. 释放游标:彻底销毁游标,释放所有相关资源 deallocate Curesor_my;

4.2 游标核心说明(必背)

  • @@FETCH_STATUS:游标专用全局变量,0表示读取成功,-1表示读取失败/无更多行,-2表示读取的行不存在。

  • 循环关键:循环体内必须写fetch next,否则会出现死循环(一直读取第一行数据)。

  • 适用场景:需要逐行处理数据(如逐行判断、逐行修改),普通批量查询优先使用CASE WHEN或聚合函数。

五、核心考点汇总(必背)

  1. 变量区分:@开头为局部变量(用户自定义),@@开头为全局变量(系统定义,仅可读取)。

  2. 赋值差异:SET单变量赋值、不支持多结果、无结果赋值NULL;SELECT多变量赋值、多结果取最后一条、无结果保留原值。

  3. 流程控制:IF-ELSE用于批处理级条件判断,CASE WHEN用于行级条件分支(查询中使用)。

  4. 常用全局变量:@@ERROR(错误码)、@@IDENTITY(自增列值)、@@ROWCOUNT(受影响行数)、@@FETCH_STATUS(游标状态)。

  5. 游标六步骤:定义→打开→初始化→循环(含fetch next)→关闭→释放,避免死循环。

六、易错踩坑点

  • 使用SET赋值时,子查询返回多条结果,导致语法报错,应改用SELECT赋值。

  • 游标循环中忘记写fetch next,导致死循环,一直重复处理第一行数据。

  • 混淆IF-ELSE和CASE WHEN的使用场景,在查询语句中用IF-ELSE做行级判断(应改用CASE WHEN)。

  • 局部变量未赋值直接使用,导致查询结果异常(局部变量默认值为NULL)。

  • 游标使用后未关闭和释放,导致资源占用,影响数据库性能。

七、语法速记模板

--1. 局部变量定义与赋值模板 declare @变量1 类型, @变量2 类型; set @变量1 = 值; --单变量赋值 select @变量1=字段1,@变量2=字段2 from 表 where 条件; --多变量赋值 --2. IF-ELSE模板 if 条件1 begin 语句块1 end else if 条件2 语句块2 else begin 语句块3 end --3. CASE WHEN模板(查询中使用) select 字段1, case when 条件1 then 结果1 when 条件2 then 结果2 else 结果3 end as 别名 from 表; --4. 游标使用模板 declare @变量1 类型, @变量2 类型; declare 游标名称 cursor for select 字段1,字段2 from 表 where 条件; open 游标名称; fetch next from 游标名称 into @变量1,@变量2; while @@FETCH_STATUS=0 begin 数据处理逻辑 fetch next from 游标名称 into @变量1,@变量2; end close 游标名称; deallocate 游标名称;

T-SQL WHILE循环、表创建与数据修改

核心考点:WHILE循环语法、自增列(identity)使用、默认值约束、批量插入数据、循环修改数据(避免死循环)、TOP 1查询用法

适配表结构:S2(id, name)、ScoreList(StudentId, Score)

一、创建表并批量插入数据(WHILE循环应用)

通过WHILE循环批量插入数据,结合自增列、默认值约束,实现快速生成测试数据,适用于批量造数场景。

1.1 创建表S2(含自增列、非空约束、默认值)

--创建表S2,包含自增主键和默认值约束 create table S2 ( id int not null primary key identity(1,1), --自增主键:identity(起始值,步长),此处从1开始,每次加1 name nvarchar(10) not null default(' ') --非空约束,默认值为空格 )

关键说明:

  • identity(1,1):自增列属性,第一个参数是起始值,第二个参数是步长,插入数据时无需手动赋值,系统自动生成唯一值。

  • default(' '):默认值约束,插入数据时若未指定name字段值,自动赋值为空格。

  • primary key:主键约束,保证id字段值唯一且非空。

1.2 WHILE循环批量插入数据(生成10条测试数据)

--定义局部变量,用于控制循环次数 declare @count int set @count = 0 --初始化变量为0 --WHILE循环:条件为@count < 10,循环执行10次 while (@count < 10) begin set @count = @count + 1 --循环体:变量自增1(避免死循环) --插入数据:name字段值为“亚马尔+循环次数+号” insert into S2(name) values('亚马尔'+convert(nvarchar(10),@count)+'号') end --查询表中数据,验证插入结果 select * from S2

关键说明:

  • WHILE循环语法:while(循环条件) begin 循环体 end,循环条件为真时,持续执行循环体。

  • 循环控制:必须在循环体内修改循环变量(如@count = @count + 1),否则会出现死循环。

  • 数据拼接:'亚马尔'+convert(nvarchar(10),@count)+'号',将整数@count转为字符串,与固定文本拼接。

二、WHILE循环批量修改数据(将低于70分的成绩改为70)

通过WHILE循环结合TOP 1查询,逐行修改成绩表中低于70分的记录,直到所有成绩都不低于70分为止。

--定义局部变量,接收学生ID和成绩 declare @stuid int,@score int --WHILE循环:条件为1=1(恒成立),通过循环体内的break跳出循环 while(1=1) begin --TOP 1:只查询第一条成绩小于70的记录,赋值给变量 select top 1 @stuid = StudentId,@score = Score from ScoreList where Score <70 --判断是否还有成绩小于70的记录(核心:控制循环退出) if((select count(*) from ScoreList where Score < 70)>0) --更新操作:将当前查询到的学生成绩改为70 update ScoreList set Score = 70 where StudentId = @stuid else break --无符合条件的记录,跳出循环(避免死循环) end --查询成绩表,验证修改结果 select * from ScoreList

关键说明:

  • while(1=1):恒成立条件,循环会一直执行,必须通过break语句手动跳出,否则会出现死循环。

  • TOP 1:每次只查询一条符合条件的记录,避免一次性修改所有记录,实现逐行修改(也可直接用UPDATE批量修改,此处为循环演示)。

  • 循环退出条件:通过count(*)判断是否还有成绩小于70的记录,无则执行break跳出循环。

  • 优化建议:批量修改可直接使用update ScoreList set Score=70 where Score<70,无需循环,效率更高;循环仅适用于需要逐行处理的场景。

三、核心考点汇总(必背)

  1. 自增列identity(起始值,步长),插入数据时无需赋值,系统自动生成,常用于主键。

  2. WHILE循环语法while(条件) begin 循环体 end,必须包含循环变量修改或break语句,避免死循环。

  3. 循环退出方式:① 修改循环变量,让循环条件不成立;② 使用break语句强制跳出。

  4. TOP 1用法:限制查询结果为第一条,适用于逐行处理数据的场景。

  5. 数据拼接:不同类型数据拼接时,需用convert函数转换类型(如整数转字符串)。

四、易错踩坑点

  • WHILE循环中未修改循环变量(如未写@count = @count + 1),或未写break语句,导致死循环。

  • 自增列插入数据时,手动赋值id字段,导致语法报错(自增列无需手动赋值)。

  • 数据拼接时,未转换数据类型(如整数直接与字符串拼接),导致报错。

  • 批量修改数据时,使用循环逐行修改,效率低下(优先使用UPDATE批量修改)。

  • 循环条件判断错误(如将>0写成<0),导致循环提前退出或无法退出。

五、语法速记模板

--1. 自增表创建模板 create table 表名 ( 自增字段 int not null primary key identity(起始值,步长), 其他字段 类型 约束 default(默认值) ) --2. WHILE循环批量插入模板 declare @循环变量 类型 set @循环变量 = 初始值 while(循环条件) begin set @循环变量 = @循环变量 + 步长 insert into 表名(字段) values(值+convert(类型, @循环变量)) end --3. WHILE循环批量修改模板(逐行修改) declare @变量1 类型,@变量2 类型 while(1=1) begin select top 1 @变量1=字段1,@变量2=字段2 from 表名 where 条件 if((select count(*) from 表名 where 条件)>0) update 表名 set 字段=新值 where 字段1=@变量1 else break end --4. 批量修改优化模板(替代循环,效率更高) update 表名 set 字段=新值 where 条件

T-SQL 视图(View)

核心考点:视图的概念与特点、视图的创建与删除、视图的使用场景、视图与普通表的区别、创建视图的语法规范

适配表结构:Students(StudentId, StudentName, Gender, Birthday)、ScoreList(StudentId, CSharp, SqlserverDB)

一、视图的核心概念(必背)

视图是 SQL 中一种重要的数据库对象,本质是存储在服务器端的查询语句(查询块),并非真实存在的物理表,而是一张虚拟表,其数据和结构都基于对一张或多张物理表的查询结果。

1.1 视图的核心特点

  • 虚拟性:视图本身不存储实际数据,数据来源于底层的物理表(基表),查询视图时,系统会执行视图对应的查询语句,从基表中获取数据。

  • 简化查询:将复杂的多表连接、筛选、排序等操作封装到视图中,后续使用时只需查询视图,无需重复编写复杂 SQL。

  • 数据安全:可通过视图暴露基表的部分字段和数据,隐藏敏感信息(如学生的身份证号、联系方式),提升数据安全性。

  • 使用便捷:视图的查询语法与普通物理表完全一致,支持筛选、排序、分页等所有普通表的查询操作。

1.2 视图的基本使用示例

-- 1. 直接查询视图,语法与查询普通表完全一致 select * from View_1; -- 2. 对视图进行条件筛选,与普通表筛选语法一致 select * from View_1 where Gender='男';

关键说明:使用视图时,无需关注其底层的查询逻辑(如多表连接),只需将其当作普通表操作即可,简化了开发和查询流程。

二、视图的创建与删除(核心语法)

创建视图前,需先判断视图是否存在,若存在则删除,避免重复创建报错;创建视图的核心是定义视图对应的查询语句。

2.1 视图创建与删除的完整示例

-- 第一步:判断视图是否存在,存在则删除(规范写法,避免重复创建报错) -- sysobjects:系统表,存储数据库中所有对象(表、视图、存储过程等)的信息 -- name = 'View_2':判断是否存在名为View_2的视图 if exists (select * from sysobjects where name ='View_2') drop view View_2; -- 删除视图 go -- 批处理结束,分隔 SQL 语句块,避免语法冲突 -- 第二步:创建视图 -- 语法:create view 视图名 as 对应的查询语句 create view View_2 as -- 视图对应的查询语句(多表连接+排序+限制条数) SELECT top 100 -- 限制视图只显示前100条数据 dbo.Students.StudentName, -- 学生姓名 dbo.Students.Gender, -- 学生性别 dbo.Students.Birthday, -- 学生生日 dbo.ScoreList.CSharp, -- C#成绩 dbo.ScoreList.SqlserverDB -- SQL Server成绩 FROM dbo.ScoreList INNER JOIN dbo.Students ON dbo.ScoreList.StudentId = dbo.Students.StudentId -- 多表连接 order by CSharp; -- 按C#成绩排序 go -- 批处理结束 -- 第三步:使用视图(查询视图数据) select * from View_2;

2.2 关键语法说明(必背)

  • 判断视图是否存在if exists (select * from sysobjects where name ='视图名'),sysobjects 是系统内置表,用于查询数据库对象信息。

  • 删除视图drop view 视图名,删除后视图对应的查询逻辑也会被清除,不影响底层基表数据。

  • 创建视图语法create view 视图名 as 查询语句,查询语句可以是单表查询、多表连接查询、带筛选/排序/聚合的复杂查询。

  • go 关键字:用于分隔 SQL 批处理语句,确保“删除视图”和“创建视图”作为独立的批处理执行,避免语法报错。

  • top 100:限制视图返回的记录条数,可根据需求调整,也可省略(返回所有符合条件的数据)。

三、视图与普通物理表的区别(核心考点)

对比项

视图(View)

普通物理表

数据存储

不存储实际数据,数据来源于基表,查询时动态获取

存储实际数据,占用数据库存储空间

本质

存储的查询语句(查询块),虚拟表

物理存在的数据库对象,真实表

创建语法

create view 视图名 as 查询语句

create table 表名 (字段 类型 约束)

使用场景

简化复杂查询、隐藏敏感数据、统一数据查询口径

存储原始数据,是所有操作的基础

修改影响

修改视图定义(重写查询语句),不影响基表数据

修改表结构或数据,直接影响所有依赖该表的视图

四、核心考点汇总(必背)

  1. 视图概念:虚拟表,存储查询语句,数据来源于基表,查询语法与普通表一致。

  2. 创建视图规范:先判断是否存在,存在则删除,再创建;创建语句为create view 视图名 as 查询语句

  3. go 关键字作用:分隔批处理语句,避免“删除+创建”视图时出现语法冲突。

  4. 视图特点:不存储数据、简化查询、提升数据安全、基于基表动态生成数据。

  5. 视图与表的区别:核心区别是是否存储实际数据,视图是虚拟的,表是物理的。

五、易错踩坑点

  • 创建视图前未判断是否存在,导致重复创建报错(需先执行drop view)。

  • 视图对应的查询语句存在语法错误(如多表连接条件缺失),导致视图创建失败。

  • 混淆视图和表的本质,试图向视图中插入、修改数据(部分视图支持修改,但会同步修改基表数据,需谨慎)。

  • 创建视图时,查询语句中使用了不支持的语法(如变量、临时表),导致创建失败(视图查询语句需为普通查询语句)。

  • 删除视图时,误删了普通表(需区分drop viewdrop table)。

六.语法速记模板

-- 1. 视图删除与创建模板(规范写法) if exists (select * from sysobjects where name ='视图名') drop view 视图名; go create view 视图名 as -- 视图对应的查询语句(单表/多表查询、筛选、排序等) select 字段1,字段2 from 表1 inner join 表2 on 表1.关联字段=表2.关联字段 where 筛选条件 order by 排序字段; go -- 2. 视图使用模板(与普通表一致) select * from 视图名; -- 全量查询 select * from 视图名 where 筛选条件; -- 条件查询 select 字段1,字段2 from 视图名 order by 排序字段; -- 自定义字段+排序