这一章主要是记录的操作,之前已经学过记录的插入、查找、删除,下面进行更加详细的讲解。
1. 插入记录
1)第一种方法
INSERT [INTO] tbl_name [(col_name,…)] {VALUES|VALUE} ({expr | DEFAULT},…),(…),…
打开mysql服务器,连接客户端,使用test数据库:
1 | C:\Windows\system32>net start mysql |
为节省空间这里只给出指令,没有运行结果。
下面来看一个test数据库里面都有哪些数据表啦,当然你的可能和我不太一样。
1 | mysql> SHOW TABLES; |
可以看到上一个章节创建的数据表都还在。
如果存在users数据表的话,先把它删除,待会重新创建一下:
1 | mysql> DROP TABLE users; |
重新创建users数据表:
1 | mysql> CREATE TABLE users( |
在这就省略查看是否真正创建成功啦,自行查看。
接下来我们往表里插入几条记录:
1 | mysql> INSERT users VALUES(NULL,'hua','123',18,true); |
我们对id这个自增量赋值为NULL,其值为1。
1 | mysql> INSERT users VALUES(NULL,'hao','123',18,true); |
还有一种方式:
1 | mysql> INSERT users VALUES(DEFAULT,'yue','123',18,true); |
以上说明:如果想对自动递增的字段赋值,可以输入NULL或者DEFAULT.
另外上面三个记录我们都对每个字段进行了赋值,如果缺少则会出现错误:
1 | mysql> INSERT users VALUES(NULL,'chun','123',18); |
说明如果省略列名的话,所有的列必须依次赋值。
除了可以书写确切的数字以外,还可以书写表达式:
1 | mysql> INSERT users VALUES(DEFAULT,'yuan','123',20*2-20,true); |
说明对整型字段赋值,可以使用数学表达式。当然也可以是字符表达式,或者某个函数。
再来看下DEFAULT,除了可以对自动赋值的字段赋值,还可以对设置了默认约束的字段赋值:
1 | mysql> INSERT users VALUES(DEFAULT,'yue','123',DEFAULT,true); |
第五条记录的age被赋值为默认值10。
以上都是插入一条记录,下面如何一次性插入多条记录呢?
1 | mysql> INSERT users VALUES(DEFAULT,'ye','123',20*2-20,true),(DEFAULT,'chun',md5(123),DEFAULT,0); |
md5(‘123’)表示计算字符串的哈希值
2)第二种方法
INSERT [INTO] tbl_name SET col_name={expr | DEFAULT},..
与第一种方式区别在于,此方法可以使用子查询(SubQuery) ,而且只能一次性插入一条记录
1 | mysql> INSERT users SET username = 'tian',password = '1233'; |
因为age有默认值,sex允许为空,所以可以只对username和password赋值。
3)第三种方法
INSERT SELECT语句:
INSERT [INTO] tbl_name [(col_name,….)] SELECT …
此方法可以将查询结果插入到指定数据表。
由于对于SELECT语句理解较少,暂时先放这。(本章第9小节进行了讲解)
2. 单表更新记录
当我们书写记录的过程中,字段值可能出现错误,或者说我们想要更改字段值,就需要使用UPDATE语句,下面这种方式是单表更新,还有一种方式是多表更新,这种方式等学到连接时再讲。
UPDATE [LOW_PRIORITY] [IGNORE] table_reference SET col_name1={expr|DEFAULT}[,col_name2={expr|DEFAULT}]…[WHERE where_condition]
如果省略WHERE条件,将对所有的记录更新。
下面来看一个示例:
1 | mysql> UPDATE users SET age=age+10; |
第一个语句的意思就是,将所有记录的age字段的值加10。
上面的例子是更新了一列,当然我也可以更新俩列:
1 | mysql> UPDATE users SET age=age-id,sex=0; |
我更新age为age减去id的值,并且将sex全部设置为了0;
上面都是对全部的记录更新,下面就让我们使用WHERE对特定的记录进行更新吧!
将所有id为偶数的user的age加上10:
1 | mysql> UPDATE users SET age=age+10 WHERE id%2=0; |
可以看到有四条记录被修改。
3. 单表删除记录
如果数据表中的记录不想要啦,还可以进行删除操作,同样也有两种方式:单表删除和多表删除,也只看单表删除。
DELETE FROM tbl_name [WHERE where_condition]
当省略WHERE时将删除所有记录
下面我们删除id=5的记录:
1 | mysql> DELETE FROM users WHERE id = 5; |
那么当我们再增加一条记录时,它的id是5呢还是9呢?
试试:
1 | mysql> INSERT users VALUES(NULL,'hui','345',18,0); |
答案是9。可见当增加记录时,即使前面id号不连续,它仍然为当前最大的id加一。
4. SELECT查询表达式解析
曾有人说过select语句占数据表操作的百分之八十以上,嗯。。。还没有体会到
select select_expr
[
from table_references 表的参照
[where where_condition] 条件
[group by {col_name|position} [asc|sesc],…记录的分组
[having where_condition] 分组时对分组的条件进行设定
[order by {col_name|expr|position} [asc|desc]…]对于结果进行排序
[limit {[offset,]row_count|row_count OFFSET offset}]限制返回结果的数量
]
(下面几节依次讲解)
每一个表达式表示想要的一列,必须有至少一个
多个列之间英文逗号分隔
星号()表示所有列。tbl_name.可以表示命名表的所有列
之前我们最常使用的:
1 | mysql> SELECT * FROM users; |
这是对所有列的查看,如果我只想看特定的几个列呢?
1 | mysql> SELECT id,username FROM users; |
只显示了id和username两个列,查询的顺序和数据表中列的顺序可以不一致,下面看看当我把id和username的查询顺序倒过来以后的情形:
1 | mysql> SELECT username,id FROM users; |
显示的结果也倒过来啦,根据select的顺序显示。
tbl_name.*可以表示命名表的所有列,也就是可以在列的前面加上数据表的名字:
1 | mysql> SELECT users.username,users.id FROM users; |
和上面结果一样,当然,当我们只对一个表进行操作时,没有这个必要。在对多表进行操作时,可以清晰辨认列属于哪张数据表。
有些字段的名字比较复杂,不太容易记忆,这时可以赋予别名。
查询表达式可以使用[AS] alias_name为其赋予别名
别名可用于GROUP BY,ORDER BY或HAVING子句
1 | mysql> SELECT id AS username,username AS uname FROM users; |
将id命名为username,将username命名为uname。
AS可以省略,当然不推荐,有时可能与显示多条字段混淆。
5. where语句进行条件查询
对记录进行过滤,如果没有指定WHERE子句,则显示所有记录
在WHERE表达式中,可以使用MySQL支持的函数或运算符
6. 查询结果分组
[GROUP BY {col_name | position} [ASC | DESC], …]
ASC:升序,默认
DESC:降序
position:SELECT语句中列的序号
1 | mysql> SELECT password FROM users GROUP BY password; |
根据password进行分组,分成了四个组
除了写名字还可以写位置:
1 | mysql> SELECT password FROM users GROUP BY 1; |
这里1是指select字段中第一个出现的字段,这里明显是password ,所以尽量指定名称,直观一点
如果把sex放第一个位置,那么只有一个分组啦
1 | mysql> SELECT sex,password FROM users GROUP BY 1; |
7. 分组条件
[ HAVING where_condition ]
这时我们可以对符合一定条件的记录进行分组
1 | mysql> SELECT password FROM users GROUP BY 1 HAVING age>10; |
想对age>10的password进行分组,居然出现错误。
原因有两个:
第一个:HAVING 后面可以使用聚合函数(MAX最大值, MIN最小值,AVG平均值,SUM求和)
第二个:不使用聚合函数的话,HAVING 后出现的字段也必须在SELECT后面出现
来试一下:
1 | mysql> SELECT password,age FROM users GROUP BY 1 HAVING age>10; |
在SELECT后面加上age后,成功分类
再试一下聚合函数:
1 | mysql> SELECT password FROM users GROUP BY 1 HAVING AVG(age)>10; |
8. 查询结果排序
除了可以对查询结果条件进行指定,还可以对查询结果进行排序
[ORDER BY { col_name | expr | position }[ ASC | DESC ], … ]
可以按照某一字段进行排序,也可以按照位置进行排序,和GROUP BY完全相同的,ASC为升序,并且是默认的,DESC为降序,也可以同时以两个或者两个以上字段进行排序。
将查询结果按id降序排列
1 | mysql> SELECT * FROM users ORDER BY id DESC; |
当然,也可以对两个字段进行排序
先对age进行升序排列:
1 | mysql> SELECT * FROM users ORDER BY age; |
可以看到age有相同的,比如36,再按照id降序排列:
1 | mysql> SELECT * FROM users ORDER BY age,id DESC; |
可以看到最后两条age相同的记录,又按照id进行了降序排列。
9. 限制查询数量
1)限制查询结果返回的数量
[ LIMIT { [ offset, ] row_count OFFSET offset } ]
默认使用SELECT,返回所有的记录:
1 | mysql> SELECT * FROM users; |
使用limit语句就可以限制返回的数量:
1 | mysql> SELECT * FROM users LIMIT 2; |
可以看出只返回了两条数据。
如果我想返回某个位置到另一个位置的记录呢?
1 | mysql> SELECT * FROM users LIMIT 3,5; |
注意:select 语句记录从0开始编号(0,1,2,3,4···)为第1、2、3、4、5···条记录,并且与id号无关,也就是说查询的id号和结果集没有任何的联系,只要排在结果集中第一个位置,那么它就是0,排在第二个位置就是1。
如果只添加一个数字,它表示从第一条记录开始返回,返回这个数字的数据数,如果返回第三条和第四条数据,就需要告诉从第几条返回,返回几条。拓展:在以后PHP当中,进行分页的时候,就会利用LIMIT语句来进行分页效果的实现,在分页效果实现当中,偏移值的计算公式是已经计算好的,计算公式就是当前括号中的页码减1*每一页显示的记录数。
2)将查询结果插入另一个数据表
INSERT [INTO] tb1_name [(col_name, …)] SELECT col_name FROM tb2_name …
它可以将查找的结果,存储到指定的数据表。
首先再创建一个新的数据表:
1 | mysql> CREATE TABLE test( |
下面我们将users表中age大于30的username写入到新建的test表中的username
1 | mysql> INSERT test SELECT username FROM users WHERE age>30; |
出现错误
注意:因为test表中需要插入的只有一个字段,所以SELECT结果集中也只有一个字段,在插入时要指定test表中指定字段,因为test表中有两个字段,即使是主键自增也不可以。
下面我们知道test表中的username:
1 | mysql> INSERT test(username) SELECT username FROM users WHERE age>30; |
查看一下:
1 | mysql> SELECT * FROM test; |
将age大于30的username插入到了test表中。
小结
数据记录的操作:增:INSERT 更:UPDATE 删:DELETE 查:SELECT
1. 增 INSERT:可以通过三种方法进行记录的插入,分别为
普通INSERT
INSERT SET
INSERT SELECT语句
(1) INSERT [INTO] tb1_name [(col_name,…)] {VALUES | VALUE} ({expr | DEFUALT},…),(…),…
注意:如果col_name被省略,意味着所有的列都要依次被赋值,不可以省略;
对于默认编号(AUTO_INCREMENT)的字段,使用NULL/DEFUALT进行插入;
而且插入的记录是识别算术,函数和字符表达式的
(2)INSERT [INTO] tb1_name SET col1_name={expr | DEFAULT}, …
如:INSERT users2 SET username=’xxx’,password=’xxx’;
说明与第一种不同之处在于:此方法可以使用子查询(SubQuery)
(3)INSERT [INTO] tb1_name [(col_name, …)] SELECT …
此方法可以将查询结果插入到指定数据表中
2. 更 UPDATE:实际有两种更新语句,单表更新和多表更新(详见第五章)
3. 删 DELETE:存在两种语法结构,单表删除、多表删除。
单表删除:
DELETE FROM tb1_name [WHERE where_condition]
如:删除第五条记录:DELETE FROM users WHERE id = 5; 而后再添加记录,那么该条记录不会填充到第六条,而是以顺序填到最后一个
条件表达式
对记录进行过滤,如果没有指定WHERE子句,则显示所有记录。
在WHERE表达式中,可以使用MySQL支持的函数或运算符。
4. 查 select select_expr
[
from table_references 表的参照
[where where_condition] 条件
[group by {col_name|position} [asc|sesc],…记录的分组
[having where_condition] 分组时对分组的条件进行设定
[order by {col_name|expr|position} [asc|desc]…]对于结果进行排序
[limit {[offset,]row_count|row_count OFFSET offset}]限制返回结果的数量
]
(1)常规
SELECT后面可以省略:如SELECT VERSION();/SELECT NOW();/SELECT 3+5;/SELECT id,username FROM users;/SELECT username,id FROM users;
所以查询顺序影响结果的输出顺序!!!
- 表示所有的列
可以在查询的列前面加上表名+. 如:SELECT users.id,user2.password FROM users;
当列名称复杂时可以用别名:如 SELECT users.id AS usersid, users.username AS uname FROM users;(注意一下AS)
所以查询的别名也影响输出结果的列名!!!
(2)分组
查询结果分组:[GROUP BY {col_name | position} [ASC | DESC], … ]
ASC 升序;DESC 降序;
如:SELECT sex FROM users GROUP BY sex/“位置”; 查看性别的分组结果。(一般指定名称就行)
在GROUP BY 进行分组的时候,还可以进行设置分组条件:[HAVING where_condition]
如:SELECT sex FROM users GROUP BY 1 HAVING age > 35; 这个语句错误,原因是sex里面没有age,所以更正为:SELECT sex,age FROM users GROUP BY 1 HAVING age > 35;或者采用聚合函数(max,min,sum等) 如
SELECT password FROM users GROUP BY 1 HAVING AVG(age)>10;
GROUP BY的规定:
1、GROUP BY 后面可以包含多个列,这就是嵌套。
2、如果GROUP BY进行了嵌套,数据将在最后一个分组上进行汇总。
3、GROUP BY子句中列出来的每个列必须是检索列或有效的表达式(但不能是聚集函数),如果在SELECT中使用了表达式,则必须在GROUP BY子句中指定相同的表达式。不能使用别名。
4、除了聚集语句外,SELECT语句中的每一个列都必须在GROUP BY子句中给出。
5、如果分组列中具有NULL值,则NULL将作为一个分组返回。如果列中有多个NULL,它们将作为一个分组返回。
6、GROUP BY子句必须在WHERE 子句之后,ORDER BY 子句之前。
(3)排序
还可以对查询分组的结果进行排序:
[ORDER BY {col_name | expr | position} [ASC | DESC], …]
如:SELECT * FROM users ORDER BY id, age DESC; 默认是升序。
除了返回记录的排序还可以对记录进行限制查询结果的数量:
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
如:SELECT * FROM users LIMIT 2; 返回两条记录;
SELECT * FROM users LIMIT 2,2;返回的是偏移值(索引号)为2的记录开始的两条记录(不管升序还是降序,第一条记录的索引号都是0);
(4)插入记录
INSERT [INTO] tb1_name [(col_name, …)] SELECT col_name FROM tb2_name …
说明:将查询结果插入到指定数据表的列
如:INSERT test(username) SELECT username FROM users WHERE age >= 30; 查找username表里的age>=30的username,插入到test表中的username列————综合一点的