本文正在参加「技术专题19期 漫谈数据库技术」活动
一直觉得自己的MySQL能力不好,所以想学习一下,可是,没有一个规范来约束自己,所以借着掘金本月的活动来约束一下自己,总结一下自己数据库部分的知识点,这篇文章作为自己数据库学习专栏的打底文章,来总结一下学过的SQL语句,并且会一直维护下去,有兴趣的小伙伴可以把问题提出来。
表结构操作
在开始数据库的CRUD之前,首先先聊一聊基本的MySQL数据库结构,MySQL是由 库,表,字段,值构成的,如果进行图形化和Excel的结构类似:
MySQL库可以看作是一个Excel文件
MySQL表可以看作Excel文件当中的具体的表(sheet)
MySQL字段可以看作表头
MySQL当中的值可以看作是excel表当中具体的数据。
学习MySQL肯定需要明白这些对象之间的关系,那么基于这些,面向MySQL用户操作,我们需要知道的命令:
进入Mysql
当安装完成MySQL数据库之后,就可以尝试使用命令行进入MySQL数据库,当然会有一些好用的工具,比如navcate等等,我们这里不做讨论,但是至少需要明白,MySQL数据库连接需要的几个关键的参数:
| 参数 | 描述 |
|---|---|
| host | mysql服务器的地址 |
| user | mysql用户 |
| password | mysql用户对应的密码 |
| port | 端口,mysql默认的端口是3306 |
连接命令如下:
mysql -u 用户 -p密码
创建用户
mysql创建用户需要指定用户和服务器地址,就是服务器允许用户通过那个地址访问MySQL服务器
create user '用户名'@'服务器地址' identified by '密码';
用户授权
mysql对不同的用户设置了不同的权限,所以创建用户之后可以设置权限,也可以通过设置权限来创建用户。
grant 权限 on 库.表 to '用户名'@'localhost' identified by '密码';
这里的权限指的是增(create,insert)删(drop,delete)改(update)查(select)
修改密码
set password for '用户名'@'服务器地址' = password(密码);
创建数据库
create database 数据库名称 charset=utf-8;
创建数据库命令一定注意加上编码,否则中文容易出现乱码。
使用数据库
use 数据库名称;
创建数据表
create table 表名(字段名称 字段类型[补充描述], 字段名称1 字段类型[补充描述]);
常用的字段类型
| 字段类型 | 描述 |
|---|---|
| Char | 保存固定长度的字符串(可包含字母,数字以及特殊字符)。在括号中指定字符串的长度,最多255个字符。 |
| varchar | 保存可变的字符串(可包含字母,数字以及特殊字符),在括号中指定字符串最大长度,最多255个字符。如果值得长度大于255,则被转换为 TEXT 类型。(M个字节) |
| text | 存放最大长度为 65,535 个字符的字符串。 |
| int | -2147483648 到 2147483647 常规。0 到 4294967295 无符号。在括号中规定最大数。 |
| TinyInt | -128 到 127 常规。0 到 255 无符号,在括号中规定最大位数。 |
| BigInt | -9223372036854775808 到 9223372036854775807 常规。0 到18446744073709551616 无符号,在括号中规定最大数。 |
| Float | 单精度浮点数。天缘博客提醒这里的D是精度,如果D<=24则为默认的FLOAT,如果D>24则会自动被转换为DOUBLE型。 |
| Double | 双精度浮点。 |
| Date | 格式YYYY-MM-DD,从1000-01-01 到 9999-12-31。 |
| Datetime | 格式YYYY-MM-DD HH:MM:SS,从1000-01-01 00:00:00到 9999-12-31 23:59:59。 |
举例子:
create table student(id int primary key auto_increment, name varchar(32));
primary key 主键(感觉可以熟练的写出来是一件很酷的事情)
auto_increment 自增长
数据查询
查询单个列:
select 字段 from 表;
查询多个字段:
select 字段1,字段2 from 表;
查询所有字段:
select * from 表;
检索不同值,去重。
select distinct 字段 from 表;
限制查询条数
select * from browse_log limit 5;
select * from browse_log limit 5 offset 5;
limit 可以设置查询返回的条数,在有时候可以防止全文检索。
offset 可以设置从第几条开始查询
数据排序
order_by 排序
select * from browse_log order by id; #结果按照id从小到大排序
select * from browse_log order by id desc; #结果按照id从大到小排序
select * from browse_log order by username,age; #结果按照用户名排序,用户名相同的时候再使用age进行排序
select * from browse_log order by username desc,age; #结果按照用户名倒序,用户名相同的时候再使用age进行排序
select * from browse_log order by 2,3; #结果按照第二第三列排序
条件过滤
在mysql当中可以使用where进行条件过滤
比较查询
select * from browser where id = 3; #查询id为3的数据
select * from browser where id > 3; #查询id大于3的数据
select * from browser where id < 3; #查询id小于3的数据
select * from browser where id >= 3; #查询id大等于3的数据
select * from browser where id <= 3; #查询id小等于3的数据
select * from browser where id != 3; #查询id不等于3的数据
select * from browser where id !> 3; #查询id不大于3的数据
select * from browser where id !< 3; #查询id不小于3的数据
select * from browser where id between 3,6; #查询id在3到6之间
select * from browser where id is null; #查询id为null的数据
select * from browser where id in [3,2,4,5]; #查询id在[3,2,4,5]范围内的数据
逻辑查询
select * from browser where username = "admin" and password = "123456"; #查询用户名为admin并且密码为123456的数据
select * from browser where username = "admin" or password = "123456"; #查询用户名为admin或者密码为123456的数据
select * from browser where username not in ["admin"]; #查询用户名不在[admin]范围之内的数据
模糊查询
select * from browser where username like "刘%"; #查询刘姓用户
select * from browser where username like "%刘%"; #查询名字当中含有刘的用户
select * from browser where username like "刘_"; #查询名字当中含有刘,后面还有一个字符的用户,但是注意_只能匹配一个字符
字段计算
拼接字段
concat 进行字段拼接
select concat(store_name,"(",goods_name,")") from browse_log limit 10;
#展示一下结果吧
+---------------------------------------+
| concat(store_name,"(",goods_name,")") |
+---------------------------------------+
| 老边超市(小饼干) |
| 小卖部(棒棒糖) |
| 小卖部(小锤锤) |
| 超市(甜甜圈) |
| 小卖部(泡泡机) |
| 小卖部(棒棒糖) |
| 超市(甜甜圈) |
| 小卖部(小锤锤) |
| 小卖部(跳跳糖) |
| 小卖部(泡泡机) |
+---------------------------------------+
10 rows in set (0.03 sec)
#as 别名,使用频率巨高
mysql> select concat(store_name,"(",goods_name,")") as field from browse_log limit 10;
+------------------+
| field |
+------------------+
| 老边超市(小饼干) |
| 小卖部(棒棒糖) |
| 小卖部(小锤锤) |
| 超市(甜甜圈) |
| 小卖部(泡泡机) |
| 小卖部(棒棒糖) |
| 超市(甜甜圈) |
| 小卖部(小锤锤) |
| 小卖部(跳跳糖) |
| 小卖部(泡泡机) |
+------------------+
10 rows in set (0.00 sec)
#数值计算
select (price * 3) as value from browse_log limit 10; #查询3倍价格结果
select (price / 3) as value from browse_log limit 10; #查询1/3价格结果
select (price + yf_money) as value from browse_log limit 10; #查询价格+运费的结果
select (price - yh_price) as value from browse_log limit 10; #查询价格-优惠结果的结果
MySQL函数
文本处理
select upper(username) from browse_log; #返回用户名大写数据
select length(username) from browse_log; #返回用户名长度数据
select lower(username) from browse_log; #返回用户名小写数据
select ltrim(username) from browse_log; #返回取消左边的空格的数据
select right(username,3) from browse_log; #返回用户名从右第三个字符截取的内容数据
select left(username,3) from browse_log; #返回用户名从左第三个字符截取的内容数据
select rtrim(username) from browse_log; #返回取消右边的空格的数据
时间处理
select now(); #返回当前时间
select curdate(); #返回当前日期 年月日
select curtime();#返回当前时间 时分秒
select unix_timestamp("2022-01-01"); #时间转换为时间戳
select unix_timestamp("2022-01-01"); #时间转换为时间戳
select unix_timestamp("2022-01-01"); #时间转换为时间戳
select date("2022-11-12 19:00:01"); #截取年月日
select year("2022-11-12 19:00:01"); #截取年
select month("2022-11-12 19:00:01"); #截取月
select day("2022-11-12 19:00:01"); #截取日
select time("2022-11-12 19:00:01"); #截取时间
select hour("2022-11-12 19:00:01"); #截取小时
select minute("2022-11-12 19:00:01"); #截取分钟
select second("2022-11-12 19:00:01"); #截取秒
select date_format("%Y-%m-%d", "2022-11-12 19:00:01"); #按照%Y-%m-%d格式获取年月日
select time_format("%H:%M:%S", "2022-11-12 19:00:01"); #按照%H:%M:%S格式获取时间
select unix_timestamp("2022-11-12 19:00:01"); #时间转换为时间戳
select from_unixtime("123123123"); #时间戳转换为时间
数值处理函数
select abs(-1); #返回绝对值数据
select cos(30); #返回角度的余弦
select exp(3); #返回指数值
select pi(); #返回圆周率
select sin(30); #返回角度正弦
select sqtr(4); #返回数的平方根
select tan(30); #返回角度的正切
聚合查询
select avg(age) from user; #返回平均年龄
select count(id) from user; #返回id的数据
select max(age) from user; #返回最大年龄
select min(age) from user; #返回最小年龄
select sum(money) from user; #返回钱的总和
select avg(distinct age) from user; #返回去重后的年龄的平均值
分组查询
#分组查询
select store_name,count(*) as store_number from browse_log group by store_name;
+------------+--------------+
| store_name | store_number |
+------------+--------------+
| 供销社 | 3303 |
| 小卖部 | 3372 |
| 老边超市 | 1 |
| 超市 | 3326 |
+------------+--------------+
4 rows in set (0.01 sec)
#分组条件过滤查询
mysql> select store_name,count(*) as store_number from browse_log group by store_name having store_name like "%超%"; ;
+------------+--------------+
| store_name | store_number |
+------------+--------------+
| 老边超市 | 1 |
| 超市 | 3326 |
+------------+--------------+
2 rows in set (0.01 sec)
#having和where 都可以作为过滤条件,但是where在分组之前条件过滤,having在分组后过滤,最重要的是where排除的行不会包括在分组当中。
#分组排序,条件过滤完进行排序
mysql> select store_name,count(*) as store_number from browse_log group by store_name having store_name like "%超%" order by store_number desc;
+------------+--------------+
| store_name | store_number |
+------------+--------------+
| 超市 | 3326 |
| 老边超市 | 1 |
+------------+--------------+
2 rows in set (0.02 sec)
这里强调一下,执行优先级:
select > from > where > group by > having > order by
嵌套查询
# 作为下个查询的条件
select * from browse_log where id in (select id from browse_log where store_name="超市");
#作为下个查询的数据源,这里注意必须要设置别名才可以
select * from (select id,store_name from browse_log where store_name="超市") as tb1;
#作为字段,统计每个店铺的订单数量
select store_name,(select count(*) from orders where orders.store_id = browse_log.id) as orders from browse_log;
关联查询
这里应该考虑数据表之间的关系了,一对一,一对多,多对多关系,比如:
用户和用户详情的关系 是一对一关系
头像和用户 是一对多关系
角色和权限 是多对多权限
简单关联
也就是内连接
两个表的交集数据
mysql> select `user`.username,orders.order_number from `user`,orders where `user`.id = orders.user_id;
+----------+--------------+
| username | order_number |
+----------+--------------+
| laobian | 00000001 |
| laobian | 00000002 |
| laoli | 00000003 |
+----------+--------------+
3 rows in set (0.00 sec)
inner join
两个表的交集数据
mysql> select `user`.username,orders.order_number from `user` inner join orders on `user`.id = orders.user_id;
+----------+--------------+
| username | order_number |
+----------+--------------+
| laobian | 00000001 |
| laobian | 00000002 |
| laoli | 00000003 |
+----------+--------------+
3 rows in set (0.00 sec)
left join
以左表为主查询,如果右表没有数据返回null
select `user`.username,orders.order_number from `user` left join orders on `user`.id = orders.user_id;
+----------+--------------+
| username | order_number |
+----------+--------------+
| laobian | 00000001 |
| laobian | 00000002 |
| laoli | 00000003 |
| laowang | NULL |
| laoliu | NULL |
| laozhang | NULL |
+----------+--------------+
6 rows in set (0.00 sec)
right join
以右表为主查询,如果左表没有数据返回null
mysql> select `user`.username,orders.order_number from `user` right join orders on `user`.id = orders.user_id;
+----------+--------------+
| username | order_number |
+----------+--------------+
| laobian | 00000001 |
| laobian | 00000002 |
| laoli | 00000003 |
| NULL | 00000004 |
+----------+--------------+
4 rows in set (0.00 sec)
union表拼接
这个多用在不同表的相同数据拼接,比如:从用户和员工表里查询所有人的姓名和年龄:
mysql> select username from user union select username from customer;
+----------+
| username |
+----------+
| laobian |
| laoli |
| laowang |
| laoliu |
| laozhang |
| 老王 |
+----------+
6 rows in set (0.00 sec)
插入数据
#插入一条数据
insert into customer(字段1,字段2) values(字段1对应值,字段2对应值);
Query OK, 1 row affected (0.04 sec)
#将查询的数据插入到另外一个表当中,这个在小规模导出数据或者创建测试表超级好用
mysql> insert into customer (username) (select username from user);
Query OK, 5 rows affected (0.04 sec)
Records: 5 Duplicates: 0 Warnings: 0
修改数据
update customer set username="nice" where id = 1;
注意,这里如果不加where条件,嘿嘿嘿
删除数据
#删除库
drop database user;
#删除表
drop table user;
#删除数据
delete from user where id = 1; #同样,不加where条件的话......
#清空数据表
truncate user;
当然还有视图,索引,触发器这些东西,但是需要放到场景里才有意思,所以放到单独的篇章来分享
,这篇博客会一直升级,大家有啥好点子可以评论区留言啊。
本文正在参加「技术专题19期 漫谈数据库技术」活动