为了方便学习SQL注入,所以我打算简单的入门一下SQL,至少基础语法要会,此学习笔记记录的是b站up——PAPAYA电脑教室 的SQL14分钟速成班的视频课程。
在线练习网站:
基础语法:
SELECT * FROM "students";
SELECT 选取
” * ” 全部
FROM “students” 从students表格查询
注:“students” 是否使用引号取决于数据库,在线练习网站可以不使用。一些数据库支持省略末尾的分号,但是用分号来表示语句的结束是一个良好的编写习惯*
SELECT 姓名,班级,成绩 FROM students;
从students表格查询姓名,班级,成绩三列的信息,此处查询语句要注意使用英文的逗号
SELECT 姓名,班级,成绩 FROM students LIMIT 5;
当数据库过大时,查询所有的信息会非常影响效能,所以可以使用LIMIT来限制查询结果的笔数
从students表格中查询姓名,班级,成绩三列,返回五笔信息
SELECT 姓名,班级,成绩 FROM students LIMIT 5 OFFSET 5;
OFFSET 跳过指定的笔数
这里是指从students表格中查询姓名,班级,成绩三列的第6~10笔信息
同理,如果要看11~15笔的资料,将 OFFSET 5 改为 OFFSET 10 即可
SELECT 姓名,班级,成绩
FROM students
LIMIT 5
OFFSET 5;
这些程序码虽然可以写在一行,但是为了可读性,通常会将每个关键字做分行
这样看就很清晰明了了,选取 姓名,班级,成绩 三列 ,从 students 表格,返回5笔信息,跳过前5笔
SELECT 姓名,班级,成绩
FROM students
WHERE 班级 = '1 年 2 班';
WHERE 设定筛选条件
只显示1年2班的姓名,班级,成绩
注:我发现此处如果使用双引号会报错,查询相关内容才知道的,双引号被解释为标识符的引用,单引号才是用于字符串常量。ANSI_QUOTES 是 sql_mode 中的一个重要选项,它改变了 MySQL 对于字符串和标识符的识别方式。
什么意思呢?”students”指students这个表格,’students’指这个students的字符串。如上,’1 年 2 班’ 指查询符合1年2班的信息。上面students没有使用双引号前面说过,因为”students” 是否使用引号取决于数据库,在线练习网站可以不使用,所以这里就没有加双引号。
WHERE 班级 <> '1 年 2 班'
= 代表等于,<> 代表不等于,这样写会返回除 1 年 2 班 以外的所有信息
这里可以看到返回的内容并没有按照班级正确分隔出来,所以可以在末尾输入 ORDER BY 来对查询结果进行排序
SELECT 姓名,班级,成绩
FROM students
WHERE 班级 <> '1 年 2 班'
ORDER BY 班级;
ORDER BY 它可以针对一个或多个栏位的值进行排序,如此,返回的内容会先显示1年1班的信息,然后是1年3班的信息,如图:
当然,我们还可以加入其他的栏位来进行排序,比如同学们的考试成绩
SELECT 姓名,班级,成绩
FROM students
WHERE 班级 <> '1 年 2 班'
ORDER BY 班级,成绩;
这样,在同一个班级下,成绩就会由最低分排到最高分
当然,我们还可以将排序的方式改为从高到底,只要在语法的后面输入 DESC 即可,DESC是指降序的意思
如果要查询的不是某个班级,而是某个具体的同学就可以直接使用WHERE 姓名 = ‘xxx’ ,但是如果你不知道这个同学的全名也没关系,SQL支持万用字元的输入,譬如百分比符号 % 代表的是零个或多个任意字元
SELECT 姓名,班级,成绩
FROM students
WHERE 姓名 LIKE '张%';
如上,不过需要将 = 号换成 LIKE ,LIKE 代表符合,这样系统就会将所有姓张的同学列出来了
SELECT 姓名,班级,成绩
FROM students
WHERE 姓名 LIKE '张_';
另一个常用的万用字元是底下,也叫下划线,它代表的是一个字元,因此用这个条件去做检索的话SQL就只会传回名字只有两个字的张静同学了
SELECT 姓名,班级,成绩
FROM students
WHERE 成绩 >= 80 AND 成绩 < 90;
-- 精简写法
SELECT 姓名,班级,成绩
FROM students
WHERE 成绩 BETWEEN 80 AND 成绩 90;
AND 且
BETWEEN 在….之间
WHERE语法除了能进行文字的比对之外,它也做数字大小的判断,比如我们可以列出所有成绩在80分以上的同学,也可以配合AND语法来查询一个分数的区间
当然这一行成绩大于等于80,且成绩小于90有个比较精简的写法,就是使用 BETWEEN
SELECT 姓名,班级,成绩
FROM students
WHERE 成绩 BETWEEN 80 AND 成绩 90 AND 班级 = '1 年 1 班';
那我们可以用AND来加入更多的筛选条件,比如班级为1 年 1 班,这样只会显示1 年 1 班且成绩在80~90之间的同学
如果我们想要同时列出1 年 2 班的同学就可以使用 OR ,OR 是指 符合任一条件即可
WHERE 成绩 BETWEEN 80 AND 成绩 90 AND 班级 = '1 年 1 班' OR 班级 = '1 年 2 班';
不过,如果你直接这样运行,会发现1年2班中有些同学的分数不在80~90之间仍然列了出来
这是因为在SQL中 AND 语法的优先层级比 OR 来得高,因此SQL会优先处理这个条件:
WHERE 成绩 BETWEEN 80 AND 成绩 90 AND 班级 = '1 年 1 班'
来找出1年1班分数介于80~90之间的同学,接着才会处理后面的 OR 班级 = ‘1 年 2 班’ ,如此就导致1年2班的同学无论成绩好坏都会被筛选出来
如果想要解决这个问题可以想乘除运算那样添加圆括号来调整逻辑的顺序
SELECT 姓名,班级,成绩
FROM students
WHERE 成绩 BETWEEN 80 AND 成绩 90 AND (班级 = '1 年 1 班' OR 班级 = '1 年 2 班');
这样SQL就会先处理后面的OR,再处理前面的AND,这样系统就能列出正确的查询结果了,同样的,这段语法也有一个比较精简的表达方式,就是改用 IN 关键字来简化多个 OR 条件的使用,这样能让查询结果变得更容易阅读和管理
SELECT 姓名,班级,成绩
FROM students
WHERE 成绩 BETWEEN 80 AND 成绩 90 AND (班级 IN ('1 年 1 班','1 年 2 班'));
函数:
SQL和Excel有个很类似的地方,就是它们都能用一些函数针对多笔资料进行汇总和计算
SELECT AVG(成绩)
FROM students;
AVG (Average 平均)函数
如上,会返回此次测验全部同学的平均分数,除了 AVG 外,还有其他的函数如: SUM(加总) MAX(求最大值) MIN(求最小值) COUNT(计算数量)
SELECT AVG(成绩) AS 成绩平均, MAX(成绩) AS 最高分
FROM students;
在使用这些函数时,如果觉得这些栏位(列名)名称看起来不够直观,你也可以为这些栏位设定所谓的别名,比如将AVG 改命名为 成绩平均,MAX 命名为最高分等,这样查询结果的可读性就会比较高了
SELECT ROUND(AVG(成绩),1) AS 成绩平均
FROM students;
ROUND 将数值四舍五入,能指定要保留的小数位数,整数省略后面的数字即可
目前查询的结果平均分为80.66666666666667,如果想要把这个数值做个四舍五入的话,可以在前面加入 ROUND 语法
SELECT ROUND(AVG(成绩),1) AS 成绩平均
FROM students
GROUP BY 班级
ORDER BY 成绩平均 DESC;
GROUP BY 将资料进行分组
这些汇总函数经常和 GROUP BY (分组)的语法配合使用,例如你想要知道的不是全班同学的平均成绩,而是各班的平均成绩,那么就可以在最后一行输入GROUP BY 班级
有需要的话,还可以应用刚才学到的 ORDER BY 语法 把成绩列表改成由最高分排到最低分
SELECT ROUND(AVG(成绩),1) AS 成绩平均
FROM students
GROUP BY 班级
ORDER BY 成绩平均 DESC
HAVING 成绩 >= 80;
HAVING 筛选已分组的资料
之前也提到使用WHERE语法可以为资料进行筛选,不过对于经过 GROUP BY 分组后的资料 要做筛选的话必须改用 HAVING 这个关键字,例如列出平均分数大于等于80分的班级
但是直接使用上面这种写法,你会发现SQL报错了,这是因为我们在撰写SQL语法时,关键字的顺序不对,关键字之间是有一个特定的顺序,这个顺序会影响到SQL语法是否能正确的执行,譬如 ORDER BY 要排在 LIMIT 之前,因为资料必须在完成排序之后才能限制回传的笔数。
而 GROUP BY 必须排在 HAVING 之前,因为 HAVING 是用来筛选分组的结果
SELECT 选取 FROM 来源 WHERE 条件 GROUP BY 分组 HAVING 条件 ORDER BY 顺序 LIMIT 笔数限制
SELECT ROUND(AVG(成绩),1) AS 成绩平均
FROM students
GROUP BY 班级
HAVING 成绩 >= 80
ORDER BY 成绩平均 DESC;
所以按照前面那个顺序调整成如上代码后才能够正常查询结果
SELECT COUNT(*)
FROM students;
除了使用 AVG 来求平均值, COUNT 计数也是一个很常用的函数,比如我在 COUNT 里面输入一个 * 号,SQL会去计算整个表格的总行数——18
当然,也可以在圆括号中输入栏位的名称,例如——社团,你会发现社团的行数跟表格的总行数数字并不一样,这是因为 COUNT 在针对单一栏位进行计数时会自动忽略空白的储存格,因此总行数18在减去两个空格之后就会得到16这个数值了
SELECT COUNT(DISTINCT 社团)
FROM students;
DISTINCT 移除重复的结果
此外 COUNT 函数也常常会配合 DISTINCT 这个关键字来检索,DISTINCT 可用来排除表格中重复的资料,执行后会显示结果为4,代表这间学校总共个有4个不同的社团
SELECT COUNT(DISTINCT 社团)
FROM students
WHERE 社团 IS NOT NULL
ORDER BY 社团;
如果想要知道具体是那四个,可以把 COUNT 函数去掉仅保留 DISTINCT ,但是要注意 DISTINCT 不会自动排除 NULL(空值),如果想要把空值隐藏起来的话只要另外加上一行 WHERE 的语法指定社团栏位中不要有 NULL 即可
建立表格:
CREATE TABLE clubs (
社团编号 INT PRIMARY KEY,
社团名称 VARCHAR(15)
);
-- 建立一个新的表格(clubs) 指定栏位名称和类型,int为整数,varchar为文字字符串,字数上限为15
-- 最后我们还要在表格内指定一个栏位为主键 (Primary Key)
-- 主键的功能是用来识别每一笔资料,因此主键不能有重复的数值,也不能是空值
删除表格:
DROP TABLE clubs2;
-- 删除表格clubs2
插入数据:
INSERT INTO clubs (社团编号,社团名称)
VALUES (101,'吉他社'),(102,'篮球社'),(103,'美术社'),(104,NULL);
-- 往clubs表插入数据,如果不确定名称可以先设为空值,空值用NULL表示
SELECT * FROM clubs;
-- 如果不确定数据是否插入,可以在后面在加一段查询语法查看结果
更新数据:
UPDATE clubs
SET 社团名称 = '舞蹈社'
WHERE 社团编号 = 104;
-- 一定要用WHERE指定要更新的是哪一笔数据,不然会更新全部数据
SELECT * FROM clubs;
-- 如果不确定数据是否更新,可以在后面在加一段查询语法查看结果
删除数据:
DELETE
FROM clubs
WHERE 社团编号 = 104;
-- 一定要用WHERE指定要删除的是哪一笔数据,不然会删除全部数据
SELECT * FROM clubs;
-- 如果不确定数据是否删除,可以在后面在加一段查询语法查看结果
联合查询:
SELECT students.姓名,students.社团,clubs.社团名称
FROM students
LEFT JOIN clubs
On students.社团 = clubs.社团编号
WHERE 班级 = '1 年 1 班';
LEFT JOIN 结合表格并显示左侧表格的所有资料
也就是跨表格查询,由于不同的表格可能会有相同名称的栏位,因此这里我们要在栏位名称前另外标注表格的名称,查询的主要资料来源是 students 表格,然后我们会用到一个叫做 LEFT JOIN 的语法来吧 clubs 表格加入进来。
在结合这两个表格的时候,我们必须要说明这两个表格是如何进行连接的,以此例子来说,我们是用 students 表格中的社团连接到 clubs 表格中的社团编号
使用 LEFT JOIN 的方式来连接表格时系统会列出左侧表格的所有记录,也就是1年1班的所有同学,尽管有的同学可能没有报名社团或时填写的社团编号找不到对应的名称,但是都会列出来。如果你想要把这些没对应上的记录隐藏起来,你可以把 JOIN 的方式改为 INNER (内部联结),这样就只有成功对应到社团名称的同学才会被列出来
SELECT students.姓名,students.社团,clubs.社团名称 FROM students INNER JOIN clubs On students.社团 = clubs.社团编号 WHERE 班级 = '1 年 1 班';