表的增删改查
- 1. 创建一个表 CREATE
- 2 插入数据 INSERT INTO
- 2.1 语法
- 2.2 插入单行数据+全列插入
- 2.3 插入多行数据+指定列插入
- 2.4 同步更新 ON DUPLICATE KEY UPDATE
- 2.4.1 引入
- 2.4.2 同步更新
- 2.4.3 查看被影响的行
- 2.5. 替换 REPLACE INTO
- 3. Retrieve(查询SELECT)
- 3.1 语法
- 3.2 全列查询 SELECT
- 3.3 指定列查询
- 3.4 查询字段为表达式
- 3.5 为查询结果指定别名 AS
- 3.6 查询结果去重 DISTINCT
- 4. WHERE 条件
- 4.1 运算符
- 4.2 示例
- 4.2.1 所有查询示例
- 4.2.2 易错点
- 5. 排序 ORDER BY
- 5.1 语法:
- 5.2 示例
- 6. 筛选分页 LIMIT OFFSET
- 6.1 语法
- 6.2 示例
CRUD : Create(创建), Retrieve(读取),Update(更新),Delete(删除)
1. 创建一个表 CREATE
语法:
CREATE TABLE table_name (
column1 datatype,
column2 datatype,
column3 datatype
) character set 字符集 collate 校验规则 engine 存储引擎;
示例:
create table students(
id int unsigned primary key auto_increment,
sn int not null unique comment ‘学号’,
name varchar(8) not null,
qq varchar(12) );
2 插入数据 INSERT INTO
2.1 语法
语法:
INSERT [INTO] table_name
[(column [, column] …)]
VALUES (value_list)
[, (value_list)] … value_list: value, [, value] …
注:INTO
可以省略不写,insert into
是只对表进行执行,insert into
后不跟关键字table
,而是==直接跟表名 ==。
2.2 插入单行数据+全列插入
示例:
- 全列插入, 写出插入的列。
命令:insert into students (id, sn, name, qq) values(1, 300, '李明', 888);
- 全列插入,不写出插入的列。
命令:insert into students values(2, 400, '张三', 666);
- 插入单行数据,不插入自增型的列。
命令:insert into students (sn, name, qq) values(500, '李逵', 999);
- 查看插入的数据。
命令:select * from students;
注:AUTO_INCREMENT 列会自动为每一行生成一个唯一的标识符,通常从1开始,并且每次插入新行时递增1。
2.3 插入多行数据+指定列插入
指定列插入时,插入的数据必须和指定列对应。
示例:
-
插入单行,指定
sn
和name
列
命令:insert into students (sn, name) values(600, '郭靖');
-
插入多行,指定
sn
、name
和qq
列。
命令:insert into students
(sn, name, qq)
values(700, ‘李华’, 111),
(800, ‘龙葵’, 222); -
查看插入的数据
命令:select * from students;
注:AUTO_INCREMENT 列会自动为每一行生成一个唯一的标识符,通常从1开始,并且每次插入新行时递增1。
2.4 同步更新 ON DUPLICATE KEY UPDATE
2.4.1 引入
由于 主键 或者 唯一键 对应的值已经存在而导致插入失败
- 主键存在导致失败:
命令:insert into students (id, sn, name) values(1, 900, '杨过' );
- 唯一键存在导致错误:
命令:insert into students (id, sn, name) values(100, 300, '杨过' );
2.4.2 同步更新
可以选择性进行同步更新操作:
语法:
INSERT INTO table_name ON DUPLICATE KEY UPDATE
column = value [, column = value] …
示例:
主键存在,进行更新:
-
使用
on duplicate key upfate
命令:insert into students values(1, 400, '李白', 111) on duplicate key update sn=400, name='李白', qq=1;
使用了on duplicate key update
怎么还是错误呢?
仔细观察sn = 400
,我们创建表时,sn int not null unique comment '学号'
,
所以,sn
的列是唯一的,跟新后的sn
与表中已存在的sn
冲突了。 -
正确使用
on duplicate key update
命令:insert into students values(1, 100, '李白', 111) on duplicate key update sn=100, name= '李白', qq=111;
唯一键存在,进行更新:
-
把
sn=800
的行进行更换。
命令:insert into students values(2, 800, '程咬金', 333) on duplicate key update id=2, name='程咬金, qq=333;
同学们可对比没换之前的下图,是不是出现了问题?
是不是没有把sn=800
的列进行更换,而是把id=2
的进行了更换。
结论,on duplicate key update
是按照vulues的先后顺序进行识别,再进行更换。 -
更改
sn=800
的行
命令:insert into students (sn, name, qq) values(800, '雪见', 888) on duplicate key update name='雪见', qq=888;
2.4.3 查看被影响的行
当使用on duplicate key update
时,执行后会显示 ** rows affected
:
– 0 row affected: 表中有冲突数据,但冲突数据的值和 update 的值相等。
– 1 row affected: 表中没有冲突数据,数据被插入
– 2 row affected: 表中有冲突数据,并且数据已经被更新
也可以使用命令查询被影响的行数
语法:SELECT ROW_COUNT();
2.5. 替换 REPLACE INTO
语法:
REPLACE INTO table_name ...
(和insert into 用法一样)
替换规则:
- 主键 或者 唯一键 没有冲突,则直接插入;
- 主键 或者 唯一键 如果冲突,则删除后再插入
示例:
- 命令:
replace into students values(6, 700, '小龙女', 444)
- 命令:
replace into students values(5, 700, '白居易', 555);
同学们可以看看前后对比;这里是把values中重复的键全部删除后替换了。
当使用replace into
时,执行后会显示 ** rows affected
:
- 1 row affected: 表中没有冲突数据,数据被插入
- 2 row affected: 表中有一个冲突数据,删除后重新插入
- 3 row affected: 表中有二个冲突数据,全部删除后重新插入
3. Retrieve(查询SELECT)
3.1 语法
语法:
SELECT
[DISTINCT] {* | {column [, column] …}
[FROM table_name]
[WHERE …]
[ORDER BY column [ASC | DESC], …]
LIMIT …
样例:
创建表:
create table score(
id int not null unique comment ‘学号’,
name varchar(8) not null comment ‘姓名’,
chinese tinyint default 0.0,
math tinyint default 0.0,
english tinyint default 0.0
);
插入数据:
insert into score
values(1,‘雷军’,100,100,100),
(2, ‘马化腾’,91,93,90),
(3, ‘马云’, 90,45,91),
(4, ‘李白’,90, 60, 30),
(5, ‘李华’, 72, 80, 88),
(6, ‘白居易’, 90, 75, 70
);
3.2 全列查询 SELECT
通常情况下不建议使用 * 进行全列查询,查询的列越多,意味着需要传输的数据量越大,可能会影响到索引的使用。
示例:
-
指定全列进行查询。
命令:selecte id, name, chinese, math, english from score;
-
使用
*
进行查询。
命令:select * from score;
3.3 指定列查询
指定列查询不需要按定义表的顺序来,显示的数据序列是指定的顺序。
示例:
命令:select name, id, chinese from score;
3.4 查询字段为表达式
在SQL中,查询字段可以是一个表达式,这允许你在查询结果中直接进行计算。这种功能非常有用,因为它可以在不改变表结构的情况下,动态地生成所需的计算结果。
示例:
- 表达式为 1+1
命令:select '1+1;'
- 更改表达式的列名为 ‘ 计算 ’。
命令:selecte '1+1' as '计算' ;
- 表达式为计算总成绩 ‘ chinese+math+english’
命令:select id, name, 'chinese +math + english from sacore;'
- 更改计算总成绩的列名
命令:select id, name, chinese+ math+ english as total from score;
- 给 ‘chinese’ 列 增加100, 命名为 new_chinese
命令:selecte id, name, chinese+100 as new_chinese, math, english from score;
这里的chinese+10
只是在打印的时候显示,并没有改变表中实际的chinese
值。
3.5 为查询结果指定别名 AS
在SQL查询中,使用别名(Alias)是一种常见的做法,它提供了多种好处,使查询结果更易读、更灵活。别名可以应用于列名、表名甚至子查询。
语法:
SELECT column [AS] alias_name [...] FROM table_name;
示例:
-
设置id 别名为 “学号”,设置 name 别名为 “姓名”
命令:select id, name from score;
-
设置总分为
chinese*0.4 + math*0.4 + english*0.2
,设置别名为 “成绩”
命令:select id, name, chinese*0.4 + math*0.4 + english*0.2 as '成绩' from score;
3.6 查询结果去重 DISTINCT
示例:
- 打印未去重的chinese 列
命令:select name, chinese from score;
- 用
distinct
关键字去重。
命令:select distinct chinese from score ;
显然,重复的90
只剩下一个了。
4. WHERE 条件
4.1 运算符
- 比较运算符
运算符 | 说明 |
---|---|
>,>=,<,<= | 大于,大于等于,小于,小于等于 |
= | 等于,NULL 不安全,例如 NULL=NULL的结果是NULL |
<=> | 等于,NULL 安全,例如,NULL<=>NULL 的结果是TRUE(1) |
IS NULL | 是 NULL |
IS NOT NULL | 不是 NULL |
- 逻辑运算符
运算符 | 说明 |
---|---|
AND | 多个条件必须都为TRUE(1),结果才为TRUE(1) |
OR | 任意一个条件为TRUE(1),结果才为TRUE(1) |
NOT | 条件为TRUE(1),结果为(0);相当于 ‘非’ |
- 条件运算符
运算符 | 说明 |
---|---|
BETWEEN n1 AND n2 | 范围匹配,[ n1, n2 ],如果 n1<= value <= ,返回TRUE(1) |
IN | 检查某个值是否存在于一个指定的值列表或子查询结果中 |
LIKE | 模糊匹配。%表示任意多个(包括0)个任意字符;;_表示任意一个字符 |
4.2 示例
4.2.1 所有查询示例
-
查询英语不及格的同学
命令:select id, name from score where english<60;
-
语文成绩在[ 80, 90] 分的同学,使用
and
连接
命令:select id, name, chinese from score where chinese>=80 and chinese<=90;
-
数学成绩在[ 90,100 ] 分的同学,使用
between...and..
连接
命令:select id, name, select score where chinese between 90 and 100;
-
数学成绩等于100,或则 数学成绩小于等于100的同学
命令:select id, name, math from score where math<=60 or math=100;
-
使用
in
查询 英语成绩为 (70,80,90,100)的同学
命令:select id, name, english from score where english in (70,80, 90, 100);
-
查询姓 “李” 的同学,多个字符匹配
命令:select * from score where name like "李% ;"
-
查询名字为两个字,且名为 ‘军’ 的人
命令:select * from score where name like '_军';
-
查询语文成绩好于英语成绩的同学
命令:select id, name, chinese, english from score wehere chinese>english;
-
chinese*0.4 + nmath*0.4 + english*0.2
按比例的总成绩大于80的同学
命令:select id, name, chinese*0.4+math*0.4+english).2 from score where chinese*0.4 + math *0.4+english*0.2 > 80;
-
数学成绩大于80,但是不姓雷的同学
命令:select id, name, mah from score where math>80 and name not like '雷%';
-
查询数学成绩已知的同学
命令:select id, name from score where math id not null;
-
查询数学成绩未知的同学
命令:select id, name from score where chinese is null;
表示数学成绩为空的同学 不存在。 -
NULL 和 NULL 的 比较,“=”
命令:select NULL=NULL;
在SQL中,NULL 表示一个未知或不存在的值。与其他编程语言不同,SQL中的 NULL 不能直接使用等号 = 进行比较。具体来说,NULL = NULL 的结果不是 TRUE,而是 UNKNOWN。为什么 NULL = NULL 结果是 UNKNOWN?
在SQL中,NULL 表示一个未知的值。当你尝试比较两个 NULL 值时,实际上是问“未知值是否等于另一个未知值”。由于这两个值都是未知的,因此无法确定它们是否相等,所以结果是 UNKNOWN。如何正确比较 NULL 值?
为了检查一个值是否为 NULL,应该使用 IS NULL 或 IS NOT NULL 运算符。 -
NULL 和 NULL 的 比较,“<=>”
命令:select NULL<=>NULL;
在SQL中,<=> 是一个特殊的运算符,称为==“空安全等值运算符”(null-safe equality operator)。它用于比较两个值,包括 NULL 值,并且在两个值都为 NULL 时返回 TRUE==
4.2.2 易错点
-
命令:
select id, name, chinese*0.4+math*0.4+english*0.2 from score where chinese*0.4 + math *0.4+english*0.2 > 80;
上述命令能否改成:
select id, name, chinese*0.4+math*0.4+english*.2 as total from score where total > 80;
这样写不是方便多了吗?
我们执行一下试试
为什么会报错呢?服务端执行命令的时候是后先后顺序的,先执行
from score
检索表,再执行where total > 80
执行条件,最后 执行select id, name, chinese*0.4+math*0.4+english*.2 as total
需要打印出的数据。在这个命令中,当执行
where total > 80
的时候没有total
的关键字的定义,显然会报错。那同学们是不是想到这样写了呢?
命令:select id, name, total from score where chinese*0.4+math*0.4+english*0.2 as total >80
这又为什么会发生错误呢?
因为 这里的total 只是作为chinese*0.4+math*0.4+english*0.2
结果的重命名,而不是重新生成了一个列。总之,还是要按正确的格式来写,
命令:select id, name, chinese*0.4+math*0.4+english*.2 as total from score where chinese*0.4+math*0.4+english*0.2 > 80;
查询命令的执行顺序:from table_name 从哪个表查询 --> where筛选数据内容 --> 显示表的内容
5. 排序 ORDER BY
5.1 语法:
– ASC 为升序(从小到大)
– DESC 为降序(从大到小)
– 默认为 ASC
SELECT … FROM table_name [WHERE …]
ORDER BY column [ASC|DESC], […];
注意:没有 ORDER BY 子句的查询,返回的顺序是未定义的,永远不要依赖这个顺序
5.2 示例
-
按数学成绩排序(默认是升序)。
命令:select * from score order by math;
-
按数学成绩降序排列 desc
命令:select * from score order by math desc;
如果数学中有 NULL 值,NULL值被视为最小的值,会放到最下面。 -
按语文降序排列,如果语文值相等则数学降序排列。
命令:select * from score order by math desc ,chinese desc;
-
查询学生总分,按总分的降序排列
命令:select id, name, chinese+math+english from score order by chinese+math+english desc;
-
按总分的降序排列,order by 别名
命令:select id, name, chinese+math+english as total from score order by total desc;
这里为什么可以用total 别名了呢?查询命令的执行顺序:from table_name 从哪个表查询 --> where筛选数据内容 --> 显示表的内容 --> order by 排序
这时候显示的内容是一个新表,可以用新表的列名进行操作。
-
查询姓马和姓雷的同学名字,把他们的总成绩按降序排列
命令:select id,name, chinese+math+english as total from score where name like '马%' or name like '雷%' order by total;
6. 筛选分页 LIMIT OFFSET
6.1 语法
– 起始下标为 0
1.- 从 0 开始,筛选 n 条结果
SELECT … FROM table_name [WHERE …] [ORDER BY …] LIMIT n;
2.- 从 s 开始,筛选 n 条结果
SELECT … FROM table_name [WHERE …] [ORDER BY …] LIMIT s, n
3.- 从 s 开始,筛选 n 条结果,比第二种用法更明确,建议使用
SELECT … FROM table_name [WHERE …] [ORDER BY …] LIMIT n OFFSET s;
建议:对未知表进行查询时,最好加一条 LIMIT 1,避免因为表中数据过大,查询全表数据导致数据库卡死
6.2 示例
-
查询三行。
-
查询总成绩的前三名
命令:select * from score order by chinese+math+english desc limit 3;
-
查询总成绩,从第二名开始的依次后三人。
命令:select * from score order by chinese+math+english limit 1,3;
说明:1
是行的索引,3
是页数。
-
查询总成绩,从第二名开始的一次后三人,使用
offset
命令:select * from score order by chinese+math+english desc limit 3 offset 1;
说明:limit 3
是查询三页,offset 1
是从索引1开始查。