目录:
- 前言
- 一、CREATE -- 创建
- 二、INSERT INTO + VALUES -- 插入数据
- 三、SELECT + FROM -- 查找数据
- 四、UPDATE + SET -- 更改数据
- 五、ALTER -- 修改属性
- 六、JOIN + ON-- 链接多个表
- 七、分支语句
- 八、循环语句
- 九、CURSOR-- 游标
- 十、EXEC -- 执行
- 十一、小小示例
- 总结
前言
打怪升级:第81天 |
---|
![]() |
提前声明:
- SQL中的语法不区分大小写,下方博主为了书写方便,并没有刻意去将关键字大写,希望不会对大家带来干扰。
- 本篇文章为博主为了期末考试,考前一周临时学习时进行的自我总结,由于时间精力有限,并没有写的足够全面,如果各位在学习过程中发现问题或有所疑问都可以在评论区提出,
会及时查看,感激不尽。
希望本篇文章可以为有需要的朋友提供帮助。
一、CREATE – 创建
创建数据库与表
CREATE DATABASE testdb-- 创建 数据库 数据库名称
use testdb
CREATE TABLE T1(
CID INT NOT NULL PRIMARY KEY,
CNAME VARCHAR(20) ,
CAGE INT
);
CREATE TABLE T2(...);
CREATE TABLE T3(...);
go
创建一个名为TEST14的数据库,创建三个表T1、T2、T3,
表T1有三个列,分别为 ID、NUME、AGE,且ID列为主键,非空。
二、INSERT INTO + VALUES – 插入数据
insert into 公司
values ('g010', '哪儿都通快递公司', 10)
go
插入操作可以同时插入多行数据,通过逗号分割,示例:
insert into table1
values
(data1, data1),
(data2, data2),
(data3, data3)
go
三、SELECT + FROM – 查找数据
1.SEKECT简单了解
以下为最基本的查找模板:
SELECT 属性1, 属性2, ...
FROM table1, table2, ...
WHERE 查找条件 -- 可选
查找学生表中,学号大于等于陈灵均同学的学号的同学。
select 学号, 姓名
from 学生
where 学号 >= ( select 学号 -- 小括号-子查询
from 学生
where 姓名 ='陈灵均')
2.函数的使用
目标:
统计不同毕业去向的人数。
实现:
使用group by 按照毕业去向分组,使用 count函数,统计各个分组的行数,并且给该列起一个新的列名 – 人数
SELECT 毕业去向, COUNT(*) AS 人数
FROM 学生
GROUP BY 毕业去向
3.选择列表与group by子句的对应
select cid, count(*) as scount
from sc
group by cid
在这段代码中,选择列表中的表达式是 “cid, count( * ) as scount”,而 GROUP BY 子句中的表达式是 “cid”,它们不完全相同。但是这是合法的 SQL 查询,因为 “cid” 是 GROUP BY 子句中的唯一列,而 “count( * ) as scount” 是一个聚合函数,它将对每个分组计算 “cid” 列中的唯一值数量,并将结果命名为 “scount”。
在这个查询中,“cid” 列用于确定分组,而 “count(*) as scount” 列用于显示每个分组中 “cid” 列的唯一值数量。因此,这个查询将返回每个 “cid” 值及其对应的唯一值数量。
总之,虽然选择列表和 GROUP BY 子句中的表达式不完全相同,但它们的含义是一致的,因此这个查询是合法的。
4.exists子查询
SELECT *
FROM c
WHERE EXISTS (
SELECT 1
FROM sc
WHERE sc.cid = c.cid
GROUP BY sc.cid
HAVING COUNT(*) >= 3
);
在这个查询中,子查询返回一个布尔值,指示是否存在至少 3 个学生选修了每个课程。如果子查询返回 TRUE
,则 EXISTS
子句将返回 TRUE
,否则将返回 FALSE
。因此,这个查询将返回选修人数不少于 3 人的课程信息。
[ 注 ] :select这部分写的有些混乱,在最后的《小小示例》中,有许多查找样例参考。
四、UPDATE + SET – 更改数据
下面是一些使用 UPDATE 语句的示例:
- 更新单个记录:
UPDATE 表名
SET 列名 = 新值
WHERE 条件;
例如,如果您要将公司表中一个公司的招收人数改为10,则可以使用以下语法:
use 大学生毕业去向
update 公司
set 招收人数 = 10
where 公司id = 'g090';
- 更新多个记录:
UPDATE 表名
SET 列名 = 新值
WHERE 条件;
例如,如果您要将客户表中的所有客户的邮政编码更改为新邮政编码,则可以使用以下语法:
use 大学生毕业去向
update 公司
set 招收人数 = 0
- 更新多个列:
UPDATE 表名
SET 列1 = 新值1, 列2 = 新值2, …
WHERE 条件;
例如,如果您要将客户表中的某个客户的电话号码和邮政编码同时更改,则可以使用以下语法:
UPDATE Customers
SET Phone = '123-456-7890', PostalCode = '12345'
WHERE CustomerID = 1;
五、ALTER – 修改属性
- 添加列
ALTER TABLE STU
ADD ID INT, SEX VARCHAR(10), SCH VARCHAR(50), TOTO VARCHAR(50) -- 逗号分割,创建多个列
GO
- 删除列
USE TEST14
ALTER TABLE STU
DROP COLUMN SWA
GO
- 修改列属性
USE TEST14
ALTER TABLE STU
ALTER COLUMN ID VARCHAR(50) NOT NULL ; -- 修改列属性
ADD CONSTRAINT pk_STU PRIMARY KEY(ID); -- 设置为主键 pk_表名
GO
六、JOIN + ON-- 链接多个表
1. join初始
JOIN
的语法如下:
SELECT 列1, 列2, ...
FROM 表1
JOIN 表2 ON 连接条件
[JOIN 表3 ON 连接条件 ...]
WHERE 筛选条件
示例:
USE 大学生毕业去向
select *
from 学生, 公司
where 去向id = 公司id
GO
USE 大学生毕业去向
select *
from 学生
left join 公司 on 去向id = 公司id
where 公司id is not null -- 筛选出第三个表中有对应公司的学生和公司信息
go
USE 大学生毕业去向
select *
from 学生
left join 公司 on 去向id = 公司id
go
2.inner join
七、分支语句
1.IF
IF语句的基本语法如下:
IF condition
BEGIN
-- code to be executed if condition is true
END
ELSE
BEGIN
-- code to be executed if condition is false
END
其中,condition是一个布尔表达式,如果为true,则执行第一个BEGIN和END之间的代码块,否则执行第二个BEGIN和END之间的代码块。您还可以使用ELSE IF子句来添加更多的条件分支。
以下是一个简单的示例,演示如何在SQL Server中使用IF语句:
DECLARE @score INT = 80;
IF @score >= 90
BEGIN
PRINT 'A';
END
ELSE IF @score >= 80
BEGIN
PRINT 'B';
END
ELSE IF @score >= 70
BEGIN
PRINT 'C';
END
ELSE
BEGIN
PRINT 'F';
END
在这个例子中,我们声明了一个变量@score,并使用IF语句根据不同的分数范围打印不同的成绩等级。如果@score大于或等于90,则打印’A’,否则检查下一个条件分支,以此类推。
2.CASE
它的语法如下:
CASE
WHEN condition1 THEN result1
WHEN condition2 THEN result2
...
ELSE default_result
END
其中,condition1
、condition2
等是条件表达式,result1
、result2
等是对应条件成立时返回的结果,default_result
是所有条件都不成立时返回的默认结果。在 CASE
表达式中,可以包含多个 WHEN
子句,每个子句都可以有不同的条件和返回结果。
栗子1:获取学生学号、姓名、考试科目以及考试成绩,并且根据考试成绩划分等级。
select s.sid, sname, cid, score,
case
when score >= 90 then 'a'
when score >= 80 then 'b'
else 'c'
end as grade
from s inner join sc on s.sid = sc.sid
栗子2:因为课程号不方便我们查看,要求通过课程号为各个科目命名(假设sc表没有存课程名)求各科平均成绩
select
case
when cid = 1 then 'course1'
when cid = 2 then 'course2'
else 'other_course'
end as grade,
avg(score) as course -- 求均值
from sc
group by
case
when cid = 1 then 'course1'
when cid = 2 then 'course2'
else 'other_course'
end
3.IF 与 CASE 对比
CASE
表达式和 IF
语句虽然都是用于条件判断和流程控制,但它们的语法和使用场景是不同的。
IF
语句通常用于程序中的控制流程,例如在编写存储过程或函数时,可以使用 IF
语句来判断输入参数的值,以便执行不同的逻辑。而 CASE
表达式则是用于查询语句中的条件判断,可以根据不同的条件返回不同的结果集。
八、循环语句
1.WHILE
WHILE 循环的语法如下:
WHILE condition
BEGIN
-- Code block to be executed while condition is true
END
其中,condition
是一个逻辑表达式,用于指定循环的条件。只要 condition
的值为真,就会重复执行 BEGIN
和 END
之间的代码块。
下面是一个简单的 WHILE 循环示例,用于计算 1 到 10 的和:
DECLARE @i INT = 1
DECLARE @sum INT = 0
WHILE @i <= 10
BEGIN
SET @sum = @sum + @i
SET @i = @i + 1
END
SELECT @sum -- 输出结果为 55
在这个例子中,我们首先定义了两个变量 @i
和 @sum
,分别用于存储计数器和累加器的值。然后使用 WHILE 循环重复执行累加操作,直到计数器的值达到 10。最后输出累加器的值,即 1 到 10 的和。
- 变量
在 SQL Server 中,变量可以用来存储临时数据,以便在查询或存储过程中使用。变量必须在使用之前声明,并且必须指定变量的数据类型。以下是一个声明和使用变量的示例:
DECLARE @myVariable INT;
SET @myVariable = 10;
SELECT @myVariable;
在上面的示例中,我们声明了一个名为 @myVariable 的整数类型变量,并将其设置为 10。然后,我们使用 SELECT 语句检索变量的值。
2.FOR + TO
其基本语法结构如下:
DECLARE @counter INT = 0
FOR @counter = 1 TO 10
BEGIN
-- 循环体
END
其中,@counter
变量被初始化为 0,然后在 for
循环中被设置为 1,循环条件为 @counter <= 10
,循环迭代为 @counter = @counter + 1
。在每次循环中,@counter
的值都会自动递增,直到循环条件不再满足为止。需要注意的是,for
循环仅在 SQL Server 2016 及以上版本中才支持,如果使用早期版本,则需要使用 while
循环来实现类似的功能。
九、CURSOR-- 游标
1.初识游标
2.游标的定义
最简单的游标声明语法如下:
DECLARE cursor_name CURSOR FOR
SELECT column1, column2, ...
FROM table_name
其中,cursor_name
是游标的名称,table_name
是要查询的表名,column1
、column2
等是要查询的列名。这条语句将创建一个游标,将查询结果集中的所有行放入游标中,游标的指针初始位置为第一行。
3.见见猪跑
以下是一个示例代码,用于读取 student 表中的女生信息,并将第二个女同学的年龄改为 20:
(略看即可)
DECLARE female_cursor CURSOR FOR
SELECT name, age FROM student WHERE gender='female'
OPEN female_cursor
DECLARE @name VARCHAR(50), @age INT
FETCH NEXT FROM female_cursor INTO @name, @age
WHILE @@FETCH_STATUS = 0
BEGIN
-- 处理数据
PRINT 'Name: ' + @name + ', Age: ' + CAST(@age AS VARCHAR(10))
IF @@CURSOR_ROWS = 2
BEGIN
-- 修改第二个女同学的年龄为 20
UPDATE student SET age = 20 WHERE CURRENT OF female_cursor
PRINT 'Age updated to 20'
END
FETCH NEXT FROM female_cursor INTO @name, @age
END
CLOSE female_cursor
DEALLOCATE female_cursor
在上面的示例代码中,我们使用 DECLARE
语句声明了一个名为 female_cursor
的游标,用于遍历 student
表中的女生信息。然后使用 OPEN
语句打开游标,使用 FETCH
语句读取第一行数据,并将数据存储到 @name
和 @age
变量中。在循环中,我们对每一行数据进行相应的处理,包括输出、更新等操作。在读取完所有数据后,使用 CLOSE
语句关闭游标,使用 DEALLOCATE
语句释放游标占用的内存空间。
4.吃“猪肉”
例如,以下代码声明了一个 FORWARD_ONLY
类型的游标:
DECLARE myCursor CURSOR FORWARD_ONLY FOR
SELECT column1, column2, column3
FROM myTable
5.FETCH使用细节
在 SQL Server 中,可以使用 FETCH
语句来从游标中检索数据,并且可以使用 关键字来显式地移动游标指针。
`FETCH` 语句有多种形式,可以使用 `FETCH NEXT` 语句来检索下一行数据,例如:
FETCH NEXT FROM cursor_name; -- 如不显示声明,默认为 NEXT
可以使用 `FETCH PRIOR` 语句来检索上一行数据,例如:
FETCH PRIOR FROM cursor_name;
可以使用 `FETCH FIRST` 语句来检索第一行数据,例如:
FETCH FIRST FROM cursor_name;
可以使用 `FETCH LAST` 语句来检索最后一行数据,例如:
FETCH LAST FROM cursor_name;
此外,还可以使用 `FETCH ABSOLUTE` 和 `FETCH RELATIVE` 语句来检索指定行号或相对位置的数据,例如:
FETCH ABSOLUTE 5 FROM cursor_name;
FETCH RELATIVE 2 FROM cursor_name;
需要注意的是,游标的移动是有限制的,当游标移动到结果集的第一行或最后一行时,再次移动游标将不会有任何效果。此外,在使用游标时,还应该注意游标的关闭和释放,以免占用过多的系统资源。
十、EXEC – 执行
它的语法如下:
EXEC procedure_name [parameter1, parameter2, ...]
例如:
DECLARE @sql NVARCHAR(MAX); -- 声明变量 变量名 数据类型
SET @sql = 'SELECT * FROM my_table'; -- 变量赋值
EXEC (@sql); -- 执行
这里,我们首先声明一个变量@sql
来存储SQL语句,然后使用EXEC
关键字来执行该语句。请注意,在执行动态SQL语句时,需要非常小心,以避免SQL注入等安全问题。
示例:
USE TEST14
--CREATE TABLE [STU](aaa INT); -- 创建表,一列,列名为 aaa
EXEC sp_rename 'STU.aaa', 'S', 'COLUMN'; -- 更改列明 '旧名' , '新名', '列'
存储过程
create procedure c_xf
@cid int
as
begin
select *
from c
where cid = @cid
end
exec c_xf @cid = 1
十一、小小示例
该样例从建库开始,所有操作都可以直接复制运行,并且带有部分注释,希望对大家有所帮助。
-- 1.建数据库
create database ssc
go
-- 2.建表
use ssc
create table s -- 学号,姓名,性别
(
sid int not null primary key , -- 非空 主键
sname varchar(50) ,
sex char(10),
);
create table c -- 课程号,课程名,教师
(
cid int not null primary key,
cname varchar(50) ,
teacher varchar(50)
);
create table sc -- 学号,课程号,成绩
(
sid int not null,
cid int not null,
score int,
constraint pk_sc primary key(sid, cid)
)
GO
-- 3.插入数据
use ssc
insert into s
values (202121, 's1', 'man'),
(202122, 's2', 'man'),
(202123, 's3', 'woman'),
(202153, 's4', 'man');
go
use ssc
insert into c
values
(01, 's1', 'tea1'),
(02, 's2', 'tea2'),
(07, 's7', 'tea7');
go
use ssc
insert into sc
values
(202121, 01, 91),
(202122,02, 67),
(202123, 01, 97),
(202153,01, 91);
go
-- 4.查找练习
use ssc
select s.sid , sname, score -- 查看学生成绩
from s join sc on s.sid = sc.sid
go
use ssc
select s.sid , sname, score -- 同上
from s, sc
where s.sid = sc.sid
go
use ssc
select * -- 查找学生学号中含有 212 的学生信息
from s
where sid like '%212%'
use ssc
select *
from c join sc on c.cid = sc.cid -- 筛选有学生选修的课程信息
go
use ssc
select teacher, count(*) as 报课人数
from c join sc on c.cid = sc.cid
group by teacher -- 按照老师分组,开始统计报课人数
go
use ssc
select * -- 查找有学生报名的课程的信息 -- 去重
from c
where teacher IN -- 判断 teacher是否在子查询中
(
select c.teacher -- 子查询,查找所有学生选课的信息
from sc
where sc.cid = c.cid
)
go
use ssc -- 同上
select *
from c
where exists
(
select 1
from sc
where sc.cid = c.cid
)
go
-- 查找不学习课程s7的学生
select sid, sname
from s
where sid not in -- 查找不在的
(
select sid -- 子查询:查找在的
from sc
where cid = 1
)
-- 查询选修人数不少于3人的课程信息
select *
from c
where cid in
(
select cid
from sc
group by cid
having count(*) >= 3 -- 判断人数
)
-- 查询选修人数不少于3人的课程信息 -- 同上
select *
from c
where exists -- 使用 exists子查询
(
select 1
from sc
where c.cid = sc.cid
group by cid
having count(*) >= 3 -- 判断人数
)
-- 查询选修人数不少于3人的课程信息 -- 同上 -- 返回结果略有不同,会带上子查询的结果
select *
from c inner join -- 链接子查询返回的结果集
(
select cid, count(*) as scount
from sc
group by cid
having count(*) >= 3 -- 判断人数
) as tmp -- 起个名字,便于下方使用
on c.cid = tmp.cid
-- 5. 修改数据
use ssc
update c
set cid = 06, cname = 'c6', teacher = 'newtea' -- 没有人报名的课,更换老师,跟换新课程
-- 按照教师分组,并统计各个教师所教课程的报课人数,等于0就替换
where not exists
(
select 1
from sc
where c.cid = sc.cid
)
go
-- 6.修改属性
use ssc
alter table sc
alter column score int ;
go
-- 7.while循环的使用,print函数只能打印字符串
-- 使用循环中的print语句,打印学生信息以及它的成绩
use ssc
declare @minid int = (select min(sid) from s);
declare @maxid int = (select max(sid) from s);
declare @i int = @minid;
while @i <= @maxid
begin
if exists (select 1 from s where sid = @i) -- 判断学生是否存在
begin
declare @name varchar(50) = (select sname from s where sid = @i)
declare @score int = (select score from sc where sid = @i)
print 'sname: ' + @name + ', score: ' + cast (@score as varchar(10)); -- 使用cast函数,将整形score转换为varchar,以便于字符串连接
end
set @i = @i + 1;
end
-- 8.游标
-- 使用游标,查找第二个成绩大于90分的同学的姓名与成绩
DECLARE S_CURSOR CURSOR FORWARD_ONLY FOR
SELECT SNAME, SCORE FROM SC JOIN S ON SC.SID = S.SID
WHERE SCORE >= 90
OPEN S_CURSOR
DECLARE @NAME VARCHAR(50), @SCORE INT;
FETCH FROM S_CURSOR INTO @NAME, @SCORE
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT @NAME + ': ' + CAST(@SCORE AS VARCHAR(10) );
FETCH FROM S_CURSOR INTO @NAME, @SCORE
END
CLOSE S_CURSOR
DEALLOCATE S_CURSOR
总结
- SQL关键字不区分大小写。
- 在 SQL 中,引号用于表示字符串类型的值。如果公司id是字符串类型的话,那么需要使用引号将其括起来。如果招收人数是数值类型的话,就不需要使用引号。所以,需要根据数据类型来决定是否使用引号。
- 子查询是指在一个 SQL 语句中嵌套另一个完整的 SQL 语句,用于查询嵌套查询中所需要的数据。子查询返回的是一个结果集,这个结果集可以是一个标量值、一个行或多行数据。
子查询的结果可以作为另一个 SQL 语句的一部分,用于过滤、排序、分组等操作。例如,我们可以使用子查询来查询某个表中满足某个条件的记录数,或者查询某个表中的最大或最小值等。
需要注意的是,子查询的结果集必须是单列或单行的,否则会导致语法错误。此外,子查询的性能较差,如果不是必要的,应尽量避免使用。 - 在 SQL Server 中,变量名前面必须加上 “@” 符号,这是为了区分变量名和列名或表名。