前言:
参考大佬内容
介绍SQL
(1)什么SQL
SQL,是用于管理和操作关系型数据库的标准编程语言,核心作用是实现数据的查询、插入、更新、删除等操作,几乎所有关系型数据库(如MySQL、Oracle、SQL Server)都依赖它工作。
简单来说,它就像“数据库的指令遥控器”——比如想从“用户表”里找出所有年龄小于30岁的人,用SQL写一句 SELECT * FROM 用户表 WHERE 年龄 < 30 就能快速实现,无需复杂编程。
(2)MySQL相关【+创建sql数据库】
【利用小皮面板,十分容易。。】
如果用docker搭建的话,可以看这个大佬
【SQL注入】小白手把手入门SQL注入1-数据库基础-优快云博客
小皮面板的sql搭建方式可以看这个大佬
利用小皮面板自带工具搭建数据库_phpstudy小皮数据库怎么用-优快云博客
【有一些创建和查询不太一样】
安装了个SQL,创建了数据库


MySQL默认在数据库中存放一个"information_schema"的数据库,是mysql自带的一个信息数据库,保存着关于MySQL服务器所维护的所有其他数据库的信息。
(3)MySQL查询语句
1. 不知道任何条件时如下所示
select 查询的字段名 from 库名.表名
2. 已知一条条件时如下所示
select 要查询的字段名 from 库名.表名 where 已知条件的字段名='已知条件的值'
示例:sql=select name from users where id='1';
3. show的使用命令
ⅰ. show databases;查看所有数据库

information_schema库: 是信息数据库,其中保存着关于MySQL服务器所维护的所有其他数据库的信息比如数据库名,数据库表,表字段的数据类型与访问权限等。Web渗透过程中用途很大。
mysql 库: MySQL的核心数据库,主要负责存储数据库的用户、权限设置、 关键字等mysql自己需要使用的控制和管理信息。
performance_schema 库: 内存数据库,数据放在内存中直接操作的数据库。相对于磁盘,内存的数据读写速度要高出几个数量级,将数据保存在内存中相 比从磁盘上访问能够极大地提高应用的性能。
sys 库: 通过这个数据库数据库,可以查询谁使用了最多的资源 基于IP或是用户。哪张表被访问过最多等等信息。
ⅱ. show tables from information_schema;查看表

SCHEMATA 表: 提供了当前MySQL实例中所有的数据库信息,show databases 结果取之此表
TABLES 表:提供了关于数据库中表的信息
COLUMNS 表: 提供了表中的列信息,详细描述了某张表的所有列已经每个列的信息
ⅲ. 查看你某一个数据库中有哪些表
【因为我使用的是小皮面板的,所以可以直接锁定是哪一个库,,所以use mysql;无需】
第一种:
首先使用库use mysql;
然后查看表show tables;
第二种:
show tables from mysql
4. select特殊查询用法
ⅰ. select now();:查看时间
注意:运行后出现问题,now 后面不能有空格

ⅱ. select database();:查看当前选择的是哪个数据库

ⅲ. select version();:查看版本

ⅳ. select user();:查看当前登录数据库的用户

ⅴ. select @@datadir;:查看数据路径
ⅵ. select @@basedir;:查看mysql安装路径
ⅶ. select @@version_compile_os;:查看mysql安装的系统
ⅷ. select group_concat(字段名):把数据库中的某列数据或某几列数据合并为一个字符串
group_concat函数是将查询到的每行结果以某个字段名进行合并,每一行合并的结果以逗号分隔开
ⅸ. 查询数据
查所有字段select * from mysql.user;
【*是所有~~~】

查某几个比较重要的字段select user,host from mysql.user;

5. limit 分页查询
1. 语法:limit 开始的索引,每页查询的条数;
2. 公式:开始的索引 = (当前的页码 - 1) * 每页显示的条数
3. limit 是一个MySQL"方言"
-- 每页显示3条记录
SELECT * FROM student LIMIT 0,3; -- 第1页
//从第 0 条记录开始(即第一条记录),取 3 条记录。
SELECT * FROM student LIMIT 3,3; -- 第2页
//从第 3 条记录开始(索引从 0 开始,第 3 条是第 4 条记录),取 3 条记录。
SELECT * FROM student LIMIT 6,3; -- 第3页
//从第7条记录开始,取3条记录
ⅰ. limit用法
在数据库中,当表中的数据量很大时,一次性查询所有数据可能会导致性能问题或不方便查看。因此,我们通常会将数据分成“页”,每次只查询一页的数据。
LIMIT 是实现分页查询的关键工具。
SELECT * FROM 表名 LIMIT 起始位置, 每页记录数;
//起始位置:
表示从第几条记录开始(索引从 0 开始)。
//每页记录数:
表示每页显示多少条记录。
注意事项
- 索引从 0 开始:
-
LIMIT的第一个参数是从 0 开始计数的,表示偏移量。
- 超出范围的情况:
-
- 如果起始位置超出了表中的总记录数,查询结果会为空。【是否可以利用这个来猜测记录数?】
- 例如,如果表中只有 7 条记录,执行
LIMIT 9, 3会返回空结果。
ⅱ. 分页公式
如果你希望动态计算每页的起始位置,可以使用以下公式:
起始位置 = (当前页码 - 1) * 每页记录数
如果每页显示 3 条记录:
第 1 页:(1 - 1) * 3 = 0 → LIMIT 0, 3
第 2 页:(2 - 1) * 3 = 3 → LIMIT 3, 3
第 3 页:(3 - 1) * 3 = 6 → LIMIT 6, 3
使用格式 limit m,n
例如limit 0,1表示从第一条记录开始,取一条记录,

6. where条件用法
where用于指定查询条件
select user,host from mysql.user where user = 'root';
要查询的字段名 库名和表名 已知条件的字段名=‘已知条件的值’

7. ORDER BY排序查询
用于对查询结果进行排序的关键字,可以按一个或多个列进行升序或降序排列。
-
- 默认按升序(ASC)排序,降序需要指定DESC
- 可以按一个或多个列排序
- 排序列可以是表中的实际列,也可以是select语句中的别名
- 支持数字、日期、字符串等多种数据类型排序
- NULL值通常排在最后(具体取决于数据库实现)
- 多列排序时,优先级从左到右
语法:order by 子句
order by 排序字段1 排序方式1 , 排序字段2 排序方式2...
注意:
如果有多个排序条件,则当前边的条件值一样时,才会判断第二条件。
-- 例子
SELECT * FROM person ORDER BY math; --默认升序
SELECT * FROM person ORDER BY math desc; --降序
格式
SELECT 列名1, 列名2,...
FROM 表名
ORDER BY 列名1 [ASC|DESC], 列名2 [ASC|DESC]
- SELECT :指定要查询的字段(比如“姓名”“年龄”)。
- FROM :指定要查询的表(比如“学生表”“员工表”)。
- ORDER BY :对查询结果排序,后面跟要排序的列,
ASC 是升序(默认,比如数字从小到大、文字从 A 到 Z),
DESC 是降序(比如数字从大到小、文字从 Z 到 A)。
例子来啦
假设我们有一张 student 表,结构如下:
id name age score
1 张三 18 85
2 李四 19 90
3 王五 18 80
要求:单列降序(按分数从高到低)
sql SELECT name, age, score
FROM student
ORDER BY score DESC;
结果会是:
name age score
李四 19 90
张三 18 85
王五 18 80
8. grout by 分组查询
语法:group by 分组字段;
注意:分组之后查询的字段:分组字段、聚合函数
-- 按照性别分组。分别查询男、女同学的平均分
SELECT sex , AVG(math) FROM student GROUP BY sex;
//SELECT 列名, 聚合函数1(列名), 聚合函数2(列名)
-- 按照性别分组。分别查询男、女同学的数学平均分,人数
SELECT sex , AVG(math),COUNT(id) FROM student GROUP BY sex;
-- 按照性别分组。分别查询男、女同学的数学平均分,人数 要求:分数低于70分的人,不参与分组
SELECT sex , AVG(math),COUNT(id) FROM student WHERE math > 70 GROUP BY sex;
--按照性别分组。分别查询男、女同学的平均分,人数 要求:分数低于70分的人,不参与分组,分组之后。
--人数要大于2个人
SELECT sex , AVG(math),COUNT(id) FROM student WHERE math > 70 GROUP BY sex
HAVING COUNT(id) > 2;
SELECT sex , AVG(math),COUNT(id) 人数 FROM student WHERE math > 70 GROUP BY sex
HAVING 人数 > 2;
//AVG(math)平均数学成绩
//COUNT(id)每组的人数【count】
//GROUP BY sex:按照性别(sex)对筛选后的数据进行分组。
// WHERE 条件
WHERE math > 70:
筛选出数学分数大于 70 的记录。
//HAVING 分组后条件;
HAVING COUNT(id) > 2:
过滤掉人数小于等于 2 的分组。
//第一句和第二句区别:
在 SELECT 子句中,给 COUNT(id) 起了一个别名 人数。
在 HAVING 子句中,直接使用了别名 人数。
效果:
功能完全相同,但更直观地表达了“人数”的含义。
-- 查询员工表的名称,性别。部门表的名称
SELECT emp.name,emp.gender,dept.name FROM emp,dept WHERE emp.`dept_id` = dept.`id`;
//多表查询
//WHERE emp.dept_id = dept.id:
通过条件 emp.dept_id = dept.id 将两个表关联起来。
这里假设 emp 表中的 dept_id 是外键,指向 dept 表的主键 id。
//先被结合关联形成一个新的表格,然后再查询所需信息
SELECT
t1.name, -- 员工表的姓名
t1.gender,-- 员工表的性别
t2.name -- 部门表的名称
FROM
emp t1,
dept t2
WHERE
t1.`dept_id` = t2.`id`;
//使用了表别名:
emp 表被命名为 t1。
dept 表被命名为 t2。
在 SELECT 和 WHERE 子句中,用别名代替了表名。
9. 内连接查询:
1. 从哪些表中查询数据
2.条件是什么
3. 查询哪些字段
a. 隐式内连接:使用where条件消除无用数据
SELECT 列名1, 列名2, ...
FROM 表1, 表2
WHERE 表1.关联列 = 表2.关联列;
b. 显式内连接
-- 语法:
select 字段列表 from 表名1 [inner] join 表名2 on 条件
-- 例如:
SELECT * FROM emp INNER JOIN dept ON emp.`dept_id` = dept.`id`;
SELECT * FROM emp JOIN dept ON emp.`dept_id` = dept.`id`;
//这条 SQL 语句使用了 JOIN 操作,用于从两个或多个表中基于某种关联条件(ON)
提取数据。
//是emp与dept两个表名结合
//条件中 = 即将两表格结合
ⅰ. JOIN
- 定义:
JOIN是一种 SQL 操作,用于根据某些条件将两个或多个表的数据组合在一起。 - 作用:通过关联条件(如外键关系),将分散在多个表中的相关数据整合到一个结果集中。
SELECT 字段列表
FROM 表名1 [INNER] JOIN 表名2
ON 关联条件;
- 参数说明
字段列表:
-
- 指定要查询的列,可以来自任意一个参与
JOIN的表。 - 示例:
t1.name, t2.department_name
- 指定要查询的列,可以来自任意一个参与
表名1和表名2:
-
- 参与连接操作的两张表。
[INNER] JOIN:
-
INNER JOIN是默认的连接类型,也可以省略INNER,直接写JOIN。- 它只返回两个表中满足关联条件的记录。
ON 关联条件:
-
- 指定如何将两张表的数据关联起来。
- 通常是一个等值条件(如
t1.dept_id = t2.id)。
ⅱ. 外键
- 定义:
-
- 外键是一个表中的字段(或字段组合),它的值必须出现在另一个表的主键或唯一键中。
- 作用:
-
- 确保数据的参照完整性(Referential Integrity)。
- 建立表之间的关联关系,便于多表查询。

- 在
emp表中,dept_id是一个外键,它引用了dept表的主键id。 - 这意味着:
-
emp.dept_id的值必须存在于dept.id中。- 如果
dept.id中没有某个值(如3),则emp.dept_id不能插入该值。
10. 外连接查询
a. 左外连接 -- 查询的是左表所有数据以及其交集部分。
左边为主表
LEFT JOIN 的特点
- 保留主表的所有记录:
-
- 即使某些记录在从表中没有匹配项,主表的记录仍然会被保留。
- 未匹配的从表字段显示为 NULL:
-
- 如果某条记录在从表中没有匹配项,则从表的字段值会显示为
NULL。
- 如果某条记录在从表中没有匹配项,则从表的字段值会显示为
-- 语法:select 字段列表 from 表1 left [outer] join 表2 on 条件;
-- 例子:
-- 查询所有员工信息,如果员工有部门,则查询部门名称,没有部门,则不显示
部门名称
SELECT t1.*,t2.`name` FROM emp t1 LEFT JOIN dept t2 ON t1.`dept_id` = t2.`id`;
//执行顺序
(1)FROM emp t1:
指定数据来源为主表 emp,并为其起别名 t1。
(2)LEFT JOIN dept t2:
将 dept 表作为从表,并为其起别名 t2。
使用 LEFT JOIN 确保主表(emp)的所有记录都会被保留。
//选择主表(emp)的所有列(t1.*)
ⅰ. 示例场景
假设我们有两张表:
- 学生表(students):存储学生的基本信息
- 成绩表(scores):存储学生的考试成绩
| 学生表(students) | 成绩表(scores) | ||
| id(主键) | name | student_id(外键) | score |
| 1 | 小明 | 1 | 90 |
| 2 | 小红 | 2 | 85 |
| 3 | 小刚 | 4 | 78 |
| 4 | 小丽 |
SQL语句:
SELECT students.name, scores.score
FROM students
LEFT JOIN scores
ON students.id = scores.student_id;
查询结果:
| name | score |
| 小明 | 90 |
| 小红 | 85 |
| 小刚 | NULL |
| 小丽 | NULL |
关键点:
- 左表(students)的所有4条记录都被返回。
- 右表(scores)中,只有与左表匹配的记录(小明、小红)显示了成绩,不匹配的记录(小刚、小丽)显示为
NULL。
应用场景:
- 统计所有学生的成绩情况(包括没有成绩的学生)。
- 找出未参与考试的学生(通过筛选
score IS NULL)。
对比:如果使用 INNER JOIN(内连接),则只会返回小明和小红两条记录,因为内连接只返回交集部分。
b. 右外连接 -- 查询的是右表所有数据以及其交集部分。
右边为主表
RIGHT JOIN 的特点
- 保留右侧表的所有记录:
-
- 即使某些记录在左侧表中没有匹配项,右侧表的记录仍然会被保留。
- 未匹配的左侧表字段显示为 NULL:
-
- 如果某条记录在左侧表中没有匹配项,则左侧表的字段值会显示为
NULL。
- 如果某条记录在左侧表中没有匹配项,则左侧表的字段值会显示为
-- 语法:
select 字段列表 from 表1 right [outer] join 表2 on 条件;
-- 例子:
SELECT * FROM dept t2 RIGHT JOIN emp t1 ON t1.`dept_id` = t2.`id`;
//执行顺序
FROM dept t2:
指定数据来源为 dept 表,并为其起别名 t2。
RIGHT JOIN emp t1:
将 emp 表作为主表,并为其起别名 t1。
使用 RIGHT JOIN 确保主表(emp)的所有记录都会被保留。
//SELECT *:
选择两张表中的所有列。
c. 内连接与外连接的区别[一个交集,一个并集]
ⅰ. 内连接(INNER JOIN)
定义:
只返回两个表中满足连接条件的记录。
如果某条记录在一张表中有对应的数据,但在另一张表中没有,则该记录不会出现在结果集中。
ⅱ. 外连接(OUTER JOIN)
定义:
返回两个表中满足连接条件的记录,同时还会保留某些不匹配的记录。
根据保留哪一侧的不匹配记录,外连接分为三种类型:左外连接、右外连接和全外连接。
11. 子查询:查询中嵌套查询
-- 查询工资最高的员工信息
-- 1 查询最高的工资是多少 9000
SELECT MAX(salary) FROM emp;
-- 2 查询员工信息,并且工资等于9000的
SELECT * FROM emp WHERE emp.`salary` = 9000;
-- 一条sql就完成这个操作。这就是子查询
SELECT * FROM emp WHERE emp.`salary` = (SELECT MAX(salary) FROM emp);
【将原本需要两次得到的消息,合为一次】
【就是将第一条的内容带入到里面】
a. 子查询的结果是单行单列的
子查询可以作为条件,使用运算符去判断。 运算符: > >= < <= =
-- 查询员工工资小于平均工资的人
SELECT * FROM emp WHERE emp.salary < (SELECT AVG(salary) FROM emp);
b. 子查询的结果是多行单列的:
子查询可以作为条件,使用运算符in来判断
-- 查询'财务部'和'市场部'所有的员工信息
SELECT id FROM dept WHERE NAME = '财务部' OR NAME = '市场部';
SELECT * FROM emp WHERE dept_id = 3 OR dept_id = 2;
//这种方式需要手动查找部门 ID(如 2 和 3),不够自动化,容易出错。
如果部门名称或 ID 发生变化,则需要手动调整查询语句。
-- 子查询
SELECT * FROM emp WHERE dept_id IN (SELECT id FROM dept WHERE NAME = '财务部' OR NAME = '市场部');
//使用子查询动态获取部门 ID,无需手动指定。
1.内层子查询(括号内的部分)
SELECT id FROM dept WHERE NAME = '财务部' OR NAME = '市场部'
SELECT id:从dept表中只获取部门的id字段(部门编号)。
FROM dept:指定查询的表是dept(部门表)。
WHERE NAME = '财务部' OR NAME = '市场部':筛选条件——只返回部门名称为“财务部”或“市场部”的记录。
执行结果:返回这两个部门的id值(例如:财务部id=10,市场部id=20)。
2. 外层主查询(外层的部分)
SELECT * FROM emp WHERE dept_id IN (子查询结果)
SELECT *:从emp表中获取所有字段(*代表所有列)。
FROM emp:指定查询的表是emp(员工表)。
WHERE dept_id IN (...):筛选条件——员工的dept_id(部门编号)必须是内层子查询返回的id列表中的值。
IN关键字:用于判断某个值是否在一个集合中(这里的集合就是子查询返回的部门id列表)。
3. 整体执行逻辑
先执行内层子查询,得到符合条件的部门id列表(如[10,20])。
再执行外层主查询,从员工表中筛选出dept_id属于这个列表的员工。
最终返回所有属于“财务部”或“市场部”的员工信息。
4. 等价写法(用JOIN实现)
这条语句也可以用JOIN重写,逻辑更直观:
SELECT emp.*
FROM emp
JOIN dept ON emp.dept_id = dept.id
WHERE dept.name IN ('财务部', '市场部');
区别:子查询更适合简单的过滤场景,JOIN更适合多表关联的复杂查询。
总结:这条SQL通过嵌套子查询实现了“先找部门,再找员工”的逻辑,是数据库中常用的关联查询方式。
c. 子查询的结果是多行多列的:
子查询可以作为一张虚拟表参与查询
-- 查询员工入职日期是2011-11-11日之后的员工信息和部门信息
-- 子查询
SELECT * FROM dept t1 ,(SELECT * FROM emp WHERE emp.`join_date` > '2011-11-11') t2 WHERE t1.id = t2.dept_id;
【注意:t2:给这个子查询的结果集起一个别名(临时表名),方便主查询引用。】
先执行派生表:从员工表中筛选出2011年11月11日之后入职的员工,得到临时表t2。
再执行主查询:将部门表dept(t1)与临时表t2通过dept_id关联,返回符合条件的部门和员工信息。
SELECT * FROM dept t1, t2 WHERE t1.id = t2.dept_id
-- 普通内连接
SELECT * FROM emp t1,dept t2 WHERE t1.`dept_id` = t2.`id` AND t1.`join_date` > '2011-11-11'
12. CREATE操作库、表后的相关用法
【因为本人用的小皮,有一些取自大佬内容】
a. 操作库
ⅰ. 创建库
create dabase db1;
//“db1” 是你为新创建的数据库指定的名称。
create database test charset utf8mb4;
test为表名, utf8mb4为字符编码

ⅱ. 创建库是否存在,不存在则创建
create database if not exists db1;
//如果不存在db1则创建数据库
ⅲ. 查看所有数据库
show databases;
ⅳ. 查看某个数据库的定义信息
show create database db1;
ⅴ. 修改数据库字符信息
alter database db1 character set utf8;
db1是目标数据库character set utf8这部分指定了要将数据库的默认字符集更改为“utf8”Character Set(字符集)是一组符号和编码规则,用于定义数据库如何存储和处理文本数据utf8是一种常见的字符集,支持多语言字符(如中文、英文、日文等), 广泛用于现代数据库中。- 为什么要用这条语句?
-
-
- 解决字符编码问题
-
如果数据库的默认字符集不支持某些语言(例如中文),可能会导致乱码问题。通过将字符集设置为“utf8”,可以确保数据库能够正确存储和显示多语言文本。
-
-
- 统一字符集
-
在开发过程中,为了保证数据一致性,通常会将所有数据库和表的字符集统一设置为“utf8”。
ⅵ. 删除数据库
drop database db1;
b. 操作表
ⅰ. 创建表
使用刚刚创建的数据库use test
创建一个表create table t1(id INT);
t1为表名, id为字段, INT为字段类型

create table student(
id int,
name varchar(32),
age int ,
score double(4,1),
birthday date,
insert_time timestamp
);
分析
//int在变量后面,
如id int,含义:定义了一个名为id的字段,数据类型为INT。
//VARCHAR 是一种可变长度的字符串类型。
//(32) 表示该字段最多可以存储32个字符。
如果实际存储的字符少于32个,只会占用实际需要的空间。
//DOUBLE 是一种浮点数类型,用于存储小数。
//(4,1) 表示总共可以存储4位数字,其中1位是小数部分。
例如:可以存储的值包括 99.9、10.5 等。
超出范围的值(如 100.5 或 999.9)会导致错误。【包括小数点】
//birthday DATE,,定义了一个名为birthday的字段,数据类型为DATE。
//DATE 类型专门用于存储日期,格式为 YYYY-MM-DD。
//TIMESTAMP 类型用于存储日期和时间,格式为 YYYY-MM-DD HH:MM:SS。
它会自动记录当前的日期和时间(如果未指定值)。
总结
这条语句创建了一个名为student的表,包含以下字段:
id:学生的唯一标识符(整数)。
name:学生的姓名(最多32个字符的字符串)。
age:学生的年龄(整数)。
score:学生的分数(最多4位数字,其中1位是小数)。
birthday:学生的生日(日期)。
insert_time:记录数据插入的时间(时间戳)。
额外
//id字段会被设置为主键(Primary Key),以确保每条记录的唯一性。
id INT PRIMARY KEY
//如果希望insert_time字段自动记录插入时间,可以添加默认值
insert_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
(default current_timestamp)
ⅱ. 查看表结构
desc 表名;
如:desc t1;
当你执行这条命令时,数据库会返回该表的详细结构信息,
包括以下内容:
- 字段名称 (Field):表中每一列的名字。
- 数据类型 (Type):每个字段的数据类型(如 INT、VARCHAR、DATE 等)。
- 是否允许 NULL 值 (Null):该字段是否可以存储 NULL 值。
- 主键标识 (Key):如果某个字段是主键(Primary Key),这里会显示 PRI。
- 默认值 (Default):字段的默认值(如果有)。
- 额外信息 (Extra):例如自增字段(AUTO_INCREMENT)等附加属性。
| Field | Type | Null | Key | Default | Extra |
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(50) | YES | NULL | ||
| age | int(11) | YES | NULL |
ⅲ. 修改表名
alter table 表名 rename to 新的表名;
ⅳ. 查看创建表的SQL语句
show create table 表名;
ⅴ. 添加字段【添加一列】
alter table 表名 add 列名 数据类型;
如:alter table t1 add name varchar(32);
t1为要修改的表名, name为增加的字段名, varchar(32)是字段类型
ⅵ. 删除列
alter table 表名 drop 列名;
ⅶ. 插入数据
insert into t1 value (1,"aa"),(2,"bb"),(3,"cc");
ⅷ. 删除表
drop table 表名;
drop table if exists 表名 ;
如:drop table t1;
执行完之后,再次show table此时则无内容
【drop是删除,add是添加】
ⅸ. 多条件查询—and
为了方便演示,
在数据库test中再插入一条name为aa的数据
insert into t1 value (4,"aa")
然后查询name为aa,id为1的数据
select * from test.t1 where name = "aa" and id =1;

X. 多条件查询—or(重要!!!)
and是必须两个条件都成立,
or是前后成立一个条件即可,在sql注入里经常使用or 1=1,因为1=1这个条件必然成立,就不用关其他条件是什么了
【攻击者可以通过这种方式得以侵入访问所有数据】
select * from test.t1 where name = "aa" or 1=1;
因为1=1必然成立,查询语句会直接忽略name=“aa”,因此并没有查询name为aa的数据,而是查询了所有的数据。
Xⅰ. 联合查询—union(重要!!!)
union可用于将两个sql语句联合起来,把结果合并在一个结果集里
示例:select * from test.t1 union select 1,2;

-
- 前半部分
select* from test.t1查询了t1表的全部数据【在 SQL 中, * 是通配符,代表“所有字段”。】 - 后半部分
select 1,2可以用于测试该表中有多少个字段,具体用法如下: - 例如:假设test.t1表有两个字段
- 前半部分
-
-
- 使用
select * from test.t1 union select 1;会报错,因为select 1的字段只有1个 - 而
select * from test.t1的字段有两个【就是有两列】,字段个数不匹配因此会报错。可以通过这种报错进行字段数量的探测,字段数量不一致会报错,字段数量一致则不会报错。 - 增加字段进行探测,使用
select * from test.t1 union select 1,2;探测成功,该t1表的字段暴露
- 使用
-

【就是,可以用来探测字段数量,1,2,3,4,一个个试出来,就可以知道目标有多少个列】
-
- 关键规则
- 字段数量一致:两个 SELECT 语句的字段数量必须相同,否则会报错(如示例中“ select * from test.t1 union select 1; 报错,因为字段数不匹配”)。
- 数据类型兼容(即相同或可转换):对应位置的字段数据类型需可兼容(如第一个查询的第 1 列是字符串,第二个查询的第 1 列也需是字符串或可转换的类型)。
- 去重默认规则: UNION 会自动去除结果集中的重复行;若需保留重复行,需用 UNION ALL 。
举个例子:
- 第一个查询结果是 [1, 2, 3] - 第二个查询结果是 [3, 4, 5]
- 用 UNION 合并后,结果会是 [1, 2, 3, 4, 5] (自动去掉了重复的 3 )
如果想要保留重复行,就需要使用 UNION ALL ,此时合并后的结果会是 [1, 2, 3, 3, 4, 5] 。
13. 特殊表的使用
ⅰ. information_schema.SCHEMATA表
先看下information_schema.SCHEMATA表里有哪些字段:
select * from information_schema.SCHEMATA;

可以发现show databases;等价于select SCHEMA_NAME from information_schema.SCHEMATA;
ⅱ. information_schema.TABLES表
先看下information_schema.SCHEMATA表里有哪些字段:
select * from information_schema.TABLES;

ⅲ. 查看指定数据库的表信息【TABLES】
select * from information_schema.TABLES where table_schema = "test";

ⅳ. 查看指定数据库的列信息【COLUMNS】
select * from information_schema.COLUMNS where table_schema = "test";
14. 注释符
注释是代码中用来“解释逻辑”但不会被程序执行的内容
在MySQL中,常见注释符的表达方式:#或--空格或/**/,
特殊编码(URL编码)一般使用第二种
注:%23就相当于# ,%20相当于空格,%27相当于引号。
-
#:单行注释,从 # 开始到行尾的内容都会被视为注释。
//示例: SELECT * FROM student # 查询所有学生数据
-
-- 空格(注意 -- 后必须跟空格):也是单行注释,从 -- 空格 开始到行尾生效。
//示例: SELECT name FROM student -- 只查学生姓名
-
/* */:多行注释, /* 和 */ 之间的所有内容都会被注释(可以跨多行)。
//示例:
/*
这是一个多行注释
用来解释下面的查询逻辑:查询年龄大于18的学生姓名和分数
*/
SELECT name, score FROM student WHERE age > 18;
内嵌注释(补)
形式:/*!code*/
它看似是注释,但MySQL会执行 /*!...*/ 内部的SQL语句,常用于实现SQL语法的兼容性或特殊执行逻辑(比如SQL注入场景中的语句构造)。
如果没有 /*! */ 这种内嵌注释格式,单纯的 /* */ 注释里的内容会被MySQL完全忽略,不会执行。
内联注释可以用于整个sql语句中,用来执行SQL语句
-1 /*!union*/ /*!select*/ 1,2,3
这里的 /*!union*/ 和 /*!select*/ 会被MySQL当作有效SQL执行,实际等效于 -1 union select 1,2,3 ,
常用于数据库的SQL注入测试或攻击场景,通过这种“伪装”的注释形式来绕过某些过滤规则。
15. 增加,删除,修改
ⅰ. 增加 insert into
-- 写全所有列名
insert into 表名(列名1,列名2,...列名n) values(值1,值2,...值n);
-- 不写列名(所有列全部添加)
insert into 表名 values(值1,值2,...值n);
-- 插入部分数据
insert into 表名(列名1,列名2) values(值1,值2);
//表名:要插入数据的目标表。
列名:指定要插入数据的列(字段)。如果省略列名,则需要为表中的所有列提供值。
值:对应列的具体数据值。
//INSERT 是一个非常重要的 SQL 关键字,用于向表中插入新数据
ⅱ. 删除 delete
-- 删除表中数据
delete from 表名 where 列名 = 值;
-- 删除表中所有数据
delete from 表名;
//逐行删除:DELETE 会逐行扫描并删除表中的数据
//DELETE 操作是事务性的,可以回滚(Rollback)。如果删除过程中出现问题,
可以通过事务恢复数据。
//性能较慢
-- 删除表中所有数据(高效 先删除表,然后再创建一张一样的表。)
truncate table 表名;
//直接清空表:TRUNCATE 不会逐行删除数据,而是直接释放存储数据的数据页,
从而快速清空表。
//无法条件过滤:TRUNCATE 只能清空整个表,不能指定条件删除部分数据
二者区别
特性 DELETE TRUNCATE
删除方式 逐行删除 直接释放数据页
是否支持条件过滤 支持(通过 WHERE 子句) 不支持
事务安全性 支持回滚 通常不可回滚
触发器 触发触发器 不触发触发器
性能 较慢(尤其是大数据量时) 高效
自增列重置 不重置 重置
适用场景 需要删除部分数据或事务安全时 需要快速清空整个表时
触发器(Trigger)
是数据库中一种特殊的存储过程,它与表绑定在一起,
当表发生特定事件(如插入、更新或删除数据)时,会自动触发执行一段预定义的逻辑代码。
触发器的主要作用是自动化处理某些业务规则或维护数据一致性。
CREATE TRIGGER 触发器名称
{ BEFORE | AFTER } //指定触发器在事件发生前还是后执行。
{ INSERT | UPDATE | DELETE } //指定触发器响应的事件类型。
ON 表名
FOR EACH ROW //表示触发器对每一行数据生效
BEGIN
-- 触发器逻辑代码
END;
//重置自增列是指将数据库表中自增列的计数器值重新设置为初始值或指定值。
//自增列是一种特殊的列,其值由数据库自动管理,每次插入新记录时,数据库
会自动为其分配一个唯一的、递增的数字。
常见用途:
作为主键(Primary Key),确保每行数据的唯一性。
自动生成序号或其他唯一标识符。
例子:id(自增列,主键)
插入数据时,无需手动指定 id 的值:
数据库会自动为 id 分配下一个可用的值(如 1、2、3...)。
常用方法:
使用 TRUNCATE TABLE 清空表并自动重置。
使用 ALTER TABLE 表名 AUTO_INCREMENT = 新值,,手动设置自增值。
ⅲ. 修改 update
-- 不带条件的修改(会修改所有行)
update 表名 set 列名 = 值;
-- 带条件的修改
update 表名 set 列名 = 值 where 列名=值;
//SET 列名 = 值:
指定需要修改的列以及它的新值。
//WHERE 列名 = 值:
指定更新操作的条件。只有满足条件的行才会被更新。
16. BETWEEN...AND (在什么之间)和 IN( 集合)
-- 查询年龄大于等于20 小于等于30
SELECT * FROM student WHERE age >= 20 && age <=30;
SELECT * FROM student WHERE age >= 20 AND age <=30;
SELECT * FROM student WHERE age BETWEEN 20 AND 30;
【相当于&& 与 AND , BETWEEN AND 】
//from 表名 where 列名
-- 查询年龄22岁,18岁,25岁的信息
SELECT * FROM student WHERE age = 22 OR age = 18 OR age = 25
SELECT * FROM student WHERE age IN (22,18,25);
17. is not null(不为null值) 与 like(模糊查询)、distinct(去除重复值)
1. is not null
-- 查询英语成绩不为null
SELECT * FROM student WHERE english IS NOT NULL;
2.like
-- 查询姓马的有哪些? like
SELECT * FROM student WHERE NAME LIKE '马%';
-- 查询姓名第二个字是化的人
SELECT * FROM student WHERE NAME LIKE "_化%";
-- 查询姓名是3个字的人
SELECT * FROM student WHERE NAME LIKE '___';
[有三个横线]
-- 查询姓名中包含德的人
SELECT * FROM student WHERE NAME LIKE '%德%';
// _:单个任意字符
// %:多个任意字符
3.distinct
SELECT DISTINCT NAME FROM student ;
-- 关键词 DISTINCT 用于返回唯一不同的值。【distinct】
-- 语法:SELECT DISTINCT 列名称 FROM 表名称
//从 student 表中查询出所有唯一的(不重复的)NAME 值。
//SELECT:用于从数据库表中查询数据
//DISTINCT:用于去除结果中的重复值,只返回唯一的、不同的值。
//结果:自动过滤掉重复值。只返回唯一的结果集。
18. 聚合函数:将一列数据作为一个整体,进行纵向的计算。
1.count:计算个数
2.max:计算最大值
3.min:计算最小值
4.sum:计算和
5.avg:计算平均数
数据控制语言【用户,权限】
添加用户
CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';
删除用户
DROP USER '用户名'@'主机名';
查询权限
-- 查询权限
SHOW GRANTS FOR '用户名'@'主机名';
SHOW GRANTS FOR 'lisi'@'%';
授予权限
-- 授予权限
grant 权限列表 on 数据库名.表名 to '用户名'@'主机名';
-- 给张三用户授予所有权限,在任意数据库任意表上
GRANT ALL ON *.* TO 'zhangsan'@'localhost';
撤销权限
-- 撤销权限:
revoke 权限列表 on 数据库名.表名 from '用户名'@'主机名';
REVOKE UPDATE ON db3.`account` FROM 'lisi'@'%';
6068



被折叠的 条评论
为什么被折叠?



