必备mysql技能(资料来自韩顺平哔哩哔哩)

1、创建数据库

在这里插入图片描述

#创建一个名称为hsp_db01的数据库
create database hsp_db01;
#创建一个使用utf8字符集的hsp_db02数据库
create database hsp_db02 character set utf8;
drop database db01;
#创建一个使用utf8字符集的hsp_db02数据库,并带校对规则的hsp_db03数据库
create database hsp_db03 character set utf8 collate utf8_bin;   # 区分大小写,且创建的表的字符集和校对规则如果没有指定,默认和数据库一样

2、查询、删除数据库

在这里插入图片描述

#显示所有数据库
show databases;
#显示数据库创建语句,在创建数据库,表的时候,为了规避关键字,可以使用反引号解决
show create database `hsp_db03`;
#删除数据库
drop database hsp_db01;

3、备份数据库

在这里插入图片描述

mysqldump备份是一种逻辑备份,它的原理是通过连接到数据库,将需要备份的数据差询出来,转化成相应的sql语句,还原数据时,只要执行这些SQL语句就可以还原,我们甚至可以借助一些连接数据库的文本工具,直接将生成的文件内容拷贝到工具内执行。
mysqldump对innodb存储引擎支持热备,对myisam只支持温备。

3.1 全量备份

#备份hsp_db02和hsp_db03这两个数据库,并恢复
mysqldump -u root -p -B hsp_db02 hsp_db03 > D:\\bakup.sql  #进入mysql管理员界面执行
mysqldump -u root -p --databases lxr > D:\\lxrbak.sql  #此种方式也可以
mysqldump -u root -p --all-databases > D:\\lxrbak3.sql #全量备份所有库
mysqldump -u root -p hsp_db03 user > D:\\lxrbak4.sql   #备份库中的某一张表
drop database hsp_db02;
drop database hsp_db03;
create database lxr;
drop database lxr;
source D:\\bakup.sql #恢复,进入mysql命令行执行

3.2 增量备份

#在mysql配置文件my.cnf(Linux)或者my.ini(wiindows)开启log-bin二进制日志
log-bin=/mysql_log/mysql-bin  #二进制日志的位置和名称可自行指定

二进制日志记录了修改数据库的相关语句,不会记录查询相关的语句,主要用于增量备份恢复和差异备份恢复。

二进制日志记录的三种方式
通过在配置文件设置如下参数来生效:
binlog_format=row

  • statement:记录对数据库做出修改的语句,只简单的记录语句,不会记录因为语句的修改具体影响了哪些行,因此,使用statement模式,bin-log日志量较少,IO压力小。
  • row:记录对数据库做出修改的语句所影响到的数据行以及这些行的修改,记录比较详细,bin-log日志量较大,IO压力大,性能消耗比较大。
  • mixed:混合使用上述两种模式,一般的语句使用statment方式进行保存,如果遇到一些特殊的函数,则使用row模式进行记录,生产环境推荐使用row模式
show variables like "%log_bin%";
+---------------------------------+--------------------------------+
| Variable_name                   | Value                          |
+---------------------------------+--------------------------------+
| log_bin                         | ON                             | 
| log_bin_basename                | /var/lib/mysql/mysql-bin       |
| log_bin_compress                | OFF                            |
| log_bin_compress_min_len        | 256                            |
| log_bin_index                   | /var/lib/mysql/mysql-bin.index |
| log_bin_trust_function_creators | OFF                            |
| sql_log_bin                     | ON                             |
+---------------------------------+--------------------------------+
log_bin:log-bin是否开启
log_bin_basename :log-bin的位置以及名字
log_bin_index:log-bin的索引文件,没生成一个log-bin都会在此记录
sql_log_bin:用来决定是否将数据库的修改操作记录到log-bin中,通过set sql_log_bin on;进行开启或者关闭
max_binlog_size :设置单个log-bin日志的大小,以字节为单位,超过设置的值,自动更新一个新的日志
[root@localhost ~]# ll /var/lib/mysql/mysql-bin*
-rw-rw---- 1 mysql mysql 328 1125 10:20 /var/lib/mysql/mysql-bin.000001
-rw-rw---- 1 mysql mysql  19 1125 10:20 /var/lib/mysql/mysql-bin.index

#查看log-bin日志可用以下两条命令
MariaDB [(none)]> show master logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |       328 |
+------------------+-----------+
1 row in set (0.000 sec)

MariaDB [(none)]> show binary logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |       328 |
+------------------+-----------+

#查看当前正在使用的log-bin
MariaDB [(none)]> show master status;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 |      328 |              |                  |
+------------------+----------+--------------+------------------+

#查看log-bin记录的模式
MariaDB [(none)]> show variables like "%binlog_format%";
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| binlog_format              | MIXED |
| wsrep_forced_binlog_format | NONE  |
+----------------------------+-------+

#查看二进制日志内容 
show binlog events in "mysql-bin.000002";   #可以指定位置,分页查询等等
+------------------+-----+-------------------+-----------+-------------+------------------------------------------------+
| Log_name         | Pos | Event_type        | Server_id | End_log_pos | Info                  |
+------------------+-----+-------------------+-----------+-------------+------------------------------------------------+
| mysql-bin.000002 |   4 | Format_desc       |         1 |         256 | Server ver: 10.3.28-MariaDB-log, Binlog ver: 4 |
| mysql-bin.000002 | 256 | Gtid_list         |         1 |         299 | [0-1-1]                  |
| mysql-bin.000002 | 299 | Binlog_checkpoint |         1 |         342 | mysql-bin.000002                  |
| mysql-bin.000002 | 342 | Gtid              |         1 |         384 | GTID 0-1-2                  |
| mysql-bin.000002 | 384 | Query             |         1 |         472 | DELETE FROM `lxr`.`t6`                  |
+------------------+-----+-------------------+-----------+-------------+------------------------------------------------+

#手动刷新二进制日志
MariaDB [lxr]> flush logs;

#查看二进制日志的内容也可以使用mysqlbinlog命令
mysqlbinlog 二进制日志名字
同时也可以指定位置,相关参数如下:
mysqlbinlog –start-position 256 mysql-bin.000002
mysqlbinlog –start-position 256 –stop-position 472 mysql-bin.000002
mysqlbinlog –start-datetime “2022-11-4 10:40:00” mysql-bin.000002
mysqlbinlog –start-datetime “2022-11-4 10:40:00” –stop-datetime “2022-11-6 10:55:00” mysql-bin.000002

以上是增量备份和差异备份一定会用到的二进制日志,以下介绍如何使用二进制日志增量备份

增量备份的使用场景: 假如一周做一次全量备份,在做过一次全量备份后,在此期间新增了相关数据,某一天误删或者其它误操作使得数据丢失,这个时候就可以通过二进制日志来进行时间节点恢复,先恢复全量备份,再逐一恢复二进制日志记录的内容。

#先做一次全量备份,在备份的时候通过相关参数做好标记,目的是为了后面增量恢复时,知道从哪儿开始恢复
mysqldump -u root -p --master-data=2 --single-transaction --all-databases --flush-logs > 20221125.sql

--master-data=2  
#数值为0,不记录对应二进制日志文件位置;
#数值为1,记录对应二进制日志文件位置;
#数值为2,记录对应二进制日值文件的位置,
#则会在备份文件中生成对应的”CHANGE MASTER TO”语句,
#此语句中标明了备份开始时二进制日志的前缀名以及其所处的position(位置),
#但是”CHANGE MASTER TO”语句将会被注释,与此值为1时不同,
#此选项值为1时,”CHANGE MASTER TO”语句不会被注释,
#此选项值为2时,”CHANGE MASTER TO”语句会被注释,
#所以,如果只是单纯的为了记录备份时的二进制日志文件位置,那么将此选项值设置为2即可。

--single-transaction   
#此参数只对 innodb 存储类型的数据有用,
#对数据库进行热备时,加上此参数,
#mysqldump会自动开启一个”可重复读”的事务,
#基于这个独立的”事务”,备份出一个满足一致性的数据备份。

#全量备份以后到下一次全量备份期间如果有误操作,先恢复全量备份,
#再通过全量备份标记的二进制位置往后进行增量恢复,
#恢复时过滤掉误操作的位置,比如drop,delete等字段
mysqlbinlog –start-position 256 –stop-position 472 mysql-bin.000002 | mysql -uroot -p
#恢复的时候会执行大量的数据库修改语句,
#建议先将 set sql_log_bin=OFF; 
#等恢复完成之后再开启,这样可以避免二进制日志做无效的记录

全量备份 master-data=2 就是如下效果:
此句会被注释
在这里插入图片描述

全量备份 master-data=1 就是如下效果:
主要用于mysql主从

在这里插入图片描述

4、创建表

在这里插入图片描述

# 创建一张user表
create table `user`(
    id int,
    `name` varchar(255),
    `password` varchar(255),
    `birthday` date)
    character set utf8 collate utf8_bin engine innodb;

4.1 修改表

在这里插入图片描述
在这里插入图片描述

-- 员工表emp的上增加一个image列,varchar类型(要求在resume后面)。
alter table employ add image varchar(25) not null default '' after resume;
desc employ;
-- 修改job列,使其长度为60。
alter table employ modify job varchar(60);
-- 删除sex列。
alter table employ drop sex;
-- 表名改为employee。
rename table employ to employee;
-- 修改表的字符集为utf-8
alter table employee charset utf8;
desc employee;
-- 列名name修改为user_name
alter table employee change column name user_name varchar(20);

5、数据类型(列类型、字段类型)

5.1 数值型

  • 整数型
    • tinyint(1个字节)
    • smallint(2个字节)
    • mediumint(3个字节)
    • int(4个字节)
    • bigint(8个字节)
  • 小数型
    • float(单精度4个字节),大约6到9位的数字
    • double(双精度8个字节),大约15到17位的数字
    • decimal[M,D],大小不确定;插入精度较高的数据,M是小数位数(精度)的总数,D是小数点(标度)后面的位数;如果D是0,则值没有小数点或分数部分。M最大65,D最大是30,如果D省略,默认是0,M省略,默认是10。

5.2 字符串类型

  • char(0~255字符),固定长度字符串
  • varchar(0-65535字节),(utf8编码最大21844字符,1~3个字节用于记录大小,65535-3除以3=21844;gbk编码除以2=32766字符)
  • text(0~65535),2^16-1
  • longtext(0~2^32-1)

5.3 二进制数据类型

  • blob(0~65535)
  • longblob(0-2^32-1)

5.4 日期类型

  • date(年月日)
  • time(时分秒)
  • datetime(年月日时分秒)
  • timestamp(时间戳,自动配置)
  • year

在这里插入图片描述
在这里插入图片描述

整型演示

# 整型演示
# tinyint,如果没有指定 unsigned,则tinyint就是有符号
create table t3 (
    id tinyint);

insert into t3 values (-129);  # 超出范围
insert into t3 values (-128);
insert into t3 values (128);  # 超出范围
insert into t3 values (127);

create table t4 (
    id tinyint unsigned);

insert into t4 values (-88); # 超出范围
insert into t4 values (0);
insert into t4 values (256); # 超出范围
insert into t4 values (255);

bit类型演示,使用场景较少

# 演示bit类型使用
# bit(m) m在 1~64位
# 添加数据 范围 按照你给的位数来确定,例如m=8,表示一个字节 0~255
# 显示按照bit,即多少位
create table t5 (num bit(8));
insert into t5 values (1);
insert into t5 values (255);
select * from t5;

在这里插入图片描述

小数型演示

# 小数型演示
create table t6 (
    num1 float,
    num2 double,
    num3 decimal(30,20));
    
insert into t6 values (88.12345678912345,88.12345678912345,88.12345678912345);
insert into t6 values (88.12345678912345789,88.12345678912345789123456,88.12345678912345789);
select * from t6;

在这里插入图片描述

字符串类型演示

# 演示字符串类型的使用
-- char(size),固定长度字符串,最大255字符
-- varchar(size) 0~65535,可变长度字符串,utf8编码最大21844字符,gbk编码最大32766字符
-- char(4)或者varchar(4)"abcd"或者"a你好吗"能插入,"abcde"或者"a你好吗b"则不能插入
create table t7 (
    `name` CHAR(255));
    
create table t8 (
    `name` varchar(65535));  # 会报错
   
create table t8 (
    `name` varchar(21844));  # utf8编码最大21844字符
   
create table t9 (
    `name` varchar(32767) character set gbk);  # 会报错
    
create table t9 (
    `name` varchar(32766) character set gbk);  # gbk编码最大32766字符,character set 可以简写成 charset

在这里插入图片描述
在这里插入图片描述

日期类型演示

# 演示日期类型
create table t10 (
    birthday date,
    job_time datetime,
    login_time timestamp 
    not null default current_timestamp 
    on update current_timestamp);  # 如果更新这张表中的记录,login_time也会根据当前时间更新

# 只插入birthday,job_time,login_time会自动插入    
insert into t10 (birthday,job_time) VALUES('2022-5-11','2022-5-11 11:32:40');
select * from t10;
update t10 set birthday='2022-08-08' where birthday='2022-05-11';  #更新之后按当前时间插入

在这里插入图片描述

所有数据类型加在一起混合练习

# 创建一张表,用各种数据类型创建
create table employ (
    `id` int,
    `name` varchar(15),
    `sex` CHAR(1),
    `birthday` date,
    `entry_date` datetime,
    `job` varchar(25),
    `salary` double,
    `resume` text) 
    charset utf8 collate utf8_bin engine innodb;
    
insert into employ 
    VALUES(1,'tom','男','1995-08-18','2001-12-13 13:48:50',
    '运维工程师',18000,'精通Linux,熟悉k8s');

select * from employ;

在这里插入图片描述

6、数据库的CRUD语句

6.1 insert

在这里插入图片描述

#演练insert语句
-- 1.创建一张商品表goods (id int , goods name varchar(10), price double );
create table `goods` (
    id int,
    goods_name varchar(10),
    price double);
-- 2.添加2条记录
insert into `goods` (id,goods_name,price) 
    values (10,"华为手机",4800),(20,"苹果手机",3200);
    
select * from goods;

在这里插入图片描述

6.2 update

在这里插入图片描述

-- 要求:在上面创建的employee表中修改表中的记录
-- 1.将所有员工薪水修改为5000元。(如果没有加上 where 条件,则会修改所有的数据,需慎用)
select * from employee;
update employee set salary = 8000;
-- 2.将姓名为tom的员工薪水修改为3000元。
update employee set salary = 3000 where user_name = 'tom';
-- 3.将tom的薪水在原有基础上增加1000元。
update employee set salary = salary + 1000 where user_name = 'tom';

在这里插入图片描述

6.3 delete

在这里插入图片描述

-- 删除表中名称为’jack'的记录。
insert into employee VALUES(2,'jack',
    '1992-02-03','2002-08-09 12:50:35',
    'java工程师',16000,'精通java语言','D:\\');
desc employee;
select * from employee;
delete from employee where user_name = 'jack';
-- 删除表中所有记录。不加where条件则会删除表中所有记录
delete from employee;

在这里插入图片描述

6.4 select

在这里插入图片描述

-- select语句
-- 创建一张学生表,并插入数据
create table student(
    id int not null default 1,
    `name` varchar(20) not null default '',
    chinese float not null default 0.0,
    english float not null default 0.0,
    math float not null default 0.0) 
    charset utf8 collate utf8_general_ci engine innodb;
desc student;

insert into student  values (1,"韩顺平",89,78,90);
insert into student  values (2,"张飞",67,98,56);
insert into student  values (3,"宋江",87,78,77);
insert into student  values (4,"关羽",88,98,90);
insert into student  values (5,"赵云",82,84,67);
insert into student  values (6,"欧阳锋",55,85,45);
insert into student  values (7,"黄蓉",75,65,30);
insert into student  values (8,"韩信",45,65,99);

select * from student;

-- 1.查询表中所有学生的信息。
select * from student;
-- 2.查询表中所有学生的姓名和对应的英语成绩。
select `name`,english from student;
-- 3.过滤表中英语成绩重复数据distinct。要查询的记录,每个字段都相同,才会去重
select distinct english from student;

6.4.1 对查询的列进行运算

在这里插入图片描述

-- 1.统计每个学生的总分
select `name` ,(chinese+english+math) as `Total_score` from student; 
-- 2.在所有学生总分加10分的情况
select `name` ,(chinese+english+math+10) as `Total_score` from student; 
-- 3.使用别名表示学生分数。
select `name` ,(chinese+english+math) as `Total_score` from student; 
-- 4.在赵云的总分上增加60%
select `name` ,(chinese+english+math)*1.6 as `Total_score` from student where `name` = '赵云'; 
-- 5.统计关羽的总分。
select `name` ,(chinese+english+math) as `Total_score` from student where `name` = '关羽'; 
-- 6.使用别名表示学生的数学分数。
select `name`,math as shuxue from student;

6.4.2 where(过滤)

在这里插入图片描述

between A and B 是一个闭区间,包含A和B

-- 使用where子句,进行过滤查询
-- 1.查询姓名为赵云的学生成绩
select * from student where `name` = '赵云';
-- 2.查询英语成绩大于90分的同学
select `name`,english from student where english > 90;
-- 3. 查询总分大于200分的所有同学
select `name` ,(chinese+english+math) as `Total_score` from student 
    where (chinese+english+math) > 200;
-- 4.查询math大于60并且(and) id大于5的学生成绩
select * from student
    where math > 60 and id > 5;
-- 5.查询英语成绩大于语文成绩的同学
select * from student
    where english > chinese;
-- 6.查询总分大于200分并且数学成绩小于语文成绩,的姓韩的学生
select * from student 
    where (chinese+english+math) > 200 
    and math < chinese and `name` like '韩%';  #这里的 like 是模糊查询,% 代表任意个字符
-- 7.查询英语分数在80 - 90之间的同学。
select * from student 
    where english between 80 and 90;
-- 8.查询数学分数为89,90,91的同学。
select * from student 
    where math = 89 or math = 90 or math = 91;
    # 或者
select * from student 
    where math in (89,90,91);
-- 9.查询所有姓韩的学生成绩。
select * from student
    where `name` like '韩%';
-- 10.查询数学分> 80,语文分> 80的同学。
select * from student
    where math > 80 and chinese > 80;
-- 11.查询语文分数在70 - 80之间的同学。
select * from student
    where chinese between 70 and 80;
-- 12.查询总分为257,221,170的同学。
select * from student 
    where (chinese+english+math) in (257,221,170);
-- 13.查询所有姓张或者姓宋的学生成绩。
select * from student
    where `name` like '张%' or `name` like '宋%';
-- 14.查询数学比语文多30分的同学。
select * from student
    where (math - chinese) > 30;

6.4.3 order by(排序)

在这里插入图片描述

-- 演示 order by
-- 对数学成绩排序后输出[升序]select * from student
    order by math asc;
-- 对总分按从高到低的顺序输出,使用别名排序,SQL语句执行有顺序,where子句中则不能使用别名
select `name`,(chinese + english + math) as Total_score from student
    order by Total_score desc;
-- 对姓韩的学生成绩(总分)排序输出(升序)
select `name`,(chinese + english + math) as Total_score from student
    where `name` like '韩%'
    order by Total_score asc;

6.4.4 select语句执行顺序

from
on
join
where
group by(开始使用select中的别名,后面的语句中都可以使用)
avg,sum…
having
select
distinct
order by
limit

6.4.5 统计函数 count(*)和count(列)

在这里插入图片描述

# 演示统计函数的使用
-- 统计一个班级共有多少学生?
select * from student;
select COUNT(*) from student;
-- 统计数学成绩大于90的学生有多少个?
select COUNT(*) from student where math > 90;
-- 统计总分大于250的人数有多少?
select COUNT(*) from student 
    where (chinese + english + math) > 250;
-- count(*)和count()的区别
COUNT(*):返回满足条件的行数,null也会算在其中
COUNT():返回某列满足条件的行数,会排出 null
create table tsc (`name` varchar(15));
insert into tsc VALUES('tom'),('jack'),('haden'),('blue'),(null);
select * from tsc;
select COUNT(*) from tsc;
select COUNT(`name`) from tsc;

count(*)
在这里插入图片描述
count(列)
在这里插入图片描述

6.4.6 合计函数 sum(列)、AVG(列)、max(列)、min(列)

在这里插入图片描述

# 演示sum()函数的使用
-- 统计一个班级数学总成绩
select SUM(math) from student;
-- 统计一个班级语文、英语、数学各科的总成绩
select SUM(math),SUM(chinese),SUM(english) from student;
-- 统计一个班级语文、英语、数学的成绩总和
select SUM(chinese + english + math) from student;
-- 统计一个班级语文成绩平均分
select SUM(chinese)/COUNT(*) from student;
select AVG(chinese) from student;

在这里插入图片描述
在这里插入图片描述

# 演示 avg 的使用
-- 求一个班级数学平均分
select AVG(math) from student;
-- 求一个班级总分平均分
select AVG(chinese + english + math) from student;

在这里插入图片描述

# 演示 max 和 min 的使用
# 求班级总分最高分和最低分
select MAX(chinese + english + math) from student;
select MIN(chinese + english + math) from student;

6.4.7 group by(分组查询)

在这里插入图片描述

# 演示 group by + having
# 创建一张部门表
create table dept(
    deptno mediumint unsigned not null default 0,  #部门编号
    dname varchar(20) not null default '',    #部门名称
    loc varchar(13) not null default '');    #部门所在地区
insert into dept VALUES(10,'ACCOUNTING','NEW YORK'),
    (20,'RESEARCH','DALLAS'),
    (30,'SALES','CHICAGO'),
    (40,'OPERATIONS','BOSHTON');   
select * from dept;
show create table dept;

# 创建一张员工表
create table emp(
	empno mediumint  unsigned not null default 0, #员工编号
	ename varchar(20) not null default '',  #部门名字
	job varchar(9) not null default '',   #工作
	mgr mediumint unsigned,  #上级编号
	hiredate date not null,   #入职日期
	sal decimal(7,2) not null,  #薪水
	comm decimal(7,2),   #奖金
	deptno mediumint unsigned not null default 0); #部门编号
	
insert into emp VALUES(7369,'SMITH','CLERK',7902,'1990-12-17',800.00,null,20),
    (7499,'ALLEN','SALESMAN',7698,'1991-2-20',1600.00,300.00,30),
    (7521,'WARD','SALESMAN',7968,'1991-2-22',1250.00,500.00,30),
    (7566,'JONES','MANAGER',7839,'1991-4-2',2975.00,null,20),
    (7654,'MARTIN','SALESMAN',7968,'1991-9-28',1250.00,1400.00,30),
    (7698,'BLAKE','MANAGER',7839,'1991-5-1',2850.00,null,30),
    (7782,'CLARK','MANAGER',7839,'1991-6-9',2450.00,null,10),
    (7788,'SCOTT','ANALYST',7566,'1991-4-19',3000.00,null,20),
    (7839,'KING','PRESIDENT',null,'1991-11-17',5000.00,null,10),
    (7844,'TURNER','SALESMAN',7698,'1991-9-8',1500.00,null,30),
    (7900,'JAMES','CLERK',7698,'1991-12-3',950.00,null,30),
    (7902,'FORD','ANALYST',7566,'1991-12-3',3000.00,null,20),
    (7934,'MILLER','CLERK',7782,'1991-1-23',1300.00,null,10);
select * from emp;

# 创建一张薪水表    
create table salgrade(
grade mediumint unsigned not null default 0,  # 工资级别
losal decimal(17, 2) not null,   # 该级别的最高工资
hisal decimal(17, 2) not null);  # 该级别的最低工资
insert into salgrade VALUES(1, 700, 1200),
(2,1201,1400),
(3,1401,2000),
(4,2001,3000),
(5,3001,9999);
select * from salgrade;


-- 如何显示每个部门的平均工资和最高工资
select deptno,AVG(sal),MAX(sal) from emp;  # 如果这样写则是求出的所有部门加在一起的平均工资以及最高工资
select deptno,AVG(sal),MAX(sal) from emp group by deptno; # 通过分组将相同组的数据取出来再来处理
-- 显示每个部门的每种岗位的平均工资和最低工资
select deptno,job,AVG(sal),MIN(sal) from emp group by deptno,job;
-- 显示平均工资低于2000的部门号和它的平均工资
select deptno,AVG(sal) avg_sal from emp 
    group by deptno having avg_sal < 2000;

6.4.8 字符串相关函数

在这里插入图片描述

# 字符串函数演示
select * from emp;
# 查看字符集
select CHARSET(sal) from emp;  

# 连接字符串,将多个列连接成一列
select CONCAT(ename,' 工作是 ',job) as `work` from emp; 

# instr(string,substring),返回substring在string出现的位置,没有则返回0   
select INSTR ('hello world', 'r') from dual;   # dual,亚元表,可以当作测试表使用

# 转换成大写
select UCASE(ename) from emp;
# 转换成小写  
select LCASE(ename) from emp;

# left(string,length),从string左边起取length个字符;
select LEFT(ename,2) from emp;
# right(string,length),从string右边边起取length个字符    
select RIGHT(ename,2) from emp;

#length(string),返回string长度[按照字节来算]
select LENGTH(job) from emp;
select LENGTH('韩顺平') from dual;

#replace(str,search_str,replace_str),在str这一列中用replace_str替换search_str
select job, REPLACE(job,'MANAGER','经理') from emp;

#逐个字符比较两个字符串大小
select STRCMP('lxr','mxr') from dual; 
select STRCMP('lxr','kxr') from dual;

#substring(str,position,length),从str的position开始取length个字符
select SUBSTRING(job,2,3) from emp; 

#去除左边空格
select LTRIM('   lixirong') from dual;
#去除右边空格
select RTRIM('lixirong    ') from dual;
#去除两边空格
select TRIM('     lixirong    ') from dual;


# 将emp表中的ename列的首字母改成小写
select CONCAT(LCASE(SUBSTRING(ename,1,1)),SUBSTRING(ename,2)) as new_name from emp;
select CONCAT(LCASE(LEFT(ename,1)),SUBSTRING(ename,2)) as new_name from emp;
# 将emp表中ename列除了首字母大写其余都为小写
select CONCAT(UCASE(LEFT(ename,1)),LCASE(SUBSTRING(ename,2))) as new_name from emp;   

6.4.9 数学函数

在这里插入图片描述

# 演示数学相关函数
# abs(num),绝对值
select ABS(-21) from dual;

# bin (desimal_number),十进制转二进制
select BIN(255) from dual;

# conv(number2,from_base,to_base),进制转换
select CONV(255,10,2) from dual;  #将255当成十进制的255转换成二进制

# ceiling(number),向上取整,得到比number大的最小整数
select CEILING(8.434) from dual;
# floor(number),向下取整,得到比number小的最大整数
select FLOOR(8.434) from dual;

# format(number,decimal_places),保留小数位数,按照四舍五入保留
select FORMAT(80.4343878942,2) from dual;

# least(number,number2,....),求最小值
select LEAST(0,1,-5,4) from dual;

# mod(number1,number2),求余
 select MOD(10,3) from dual;

# rand(),返回0~1之的随机数;rand(seed),如果seed固定,随机数会固定
select RAND() from dual;  # 随机数会变
select RAND(98) from dual; # 随机数会固定

6.4.10 时间日期相关函数

在这里插入图片描述

# 演示日期和时间相关的函数
# current_date()    当前日期
select CURRENT_DATE() from dual;
# current_time    当前时间
select CURRENT_TIME() from dual;
# current_timestamp    当前时间戳
select CURRENT_TIMESTAMP() from dual;
select NOW() from dual;
select DATE(datetime) from dual;

# DATE(time),只显示日期,不显示时间
create table mes(
    id int,
    content varchar(30),
    sendtime datetime) 
    character set utf8 collate utf8_bin engine innodb;
insert into mes (id,content,sendtime) values (1,"北京新闻",NOW());
select content,DATE(sendtime) from mes; #只会返回年月日,不会返回时分秒

# date_add(date2,interval time),在date2中加上多长时间
insert into mes (id,content,sendtime) values (2,"上海新闻",NOW()); 
select * from mes where DATE_ADD(sendtime,interval 5 minute) >= NOW();  # 查询5分钟之内发布的新闻
insert into mes (id,content,sendtime) values (3,"广州新闻",NOW()); 

# date_sub(date2,interval time),在date2中减去多长时间  
select * from mes;
select * from mes where sendtime <= DATE_SUB(NOW(),interval 10 minute); # 查询10分钟之前发布的新闻

# datediff(date1,date2),日期差
select DATEDIFF("2022-06-28","1991-11-11") from dual;

6.4.11 加密和系统函数

在这里插入图片描述

# 加密函数演示
# 查看登录到mysql的有哪些用户以及登录的ip
select USER() from dual; 

# database()   #查询当前所操作的数据库名称
select DATABASE() from dual;

# md5(str)   #为字符串算出一个md5  32位的字符串,常用于用户密码加密,使其不成为明文
select MD5('lxr@123') from dual;
select LENGTH(MD5('lxr@123')) from dual;
# 存放用户名和密码
create table t11(
    id int,
    user_name varchar(20),
    passwd CHAR(32) not null default '');
insert into t11 VALUES(1,'张三',MD5('lxr123@'));
select * from t11;

# password(str)    #通常用于数据库的用户密码加密
select PASSWORD('lxr') from dual;
select LENGTH(PASSWORD('lxr')) from dual;
select * from mysql.user;

6.4.12 流程控制函数

在这里插入图片描述

# 演示流程控制函数
# if(expr1,expr2,expr3)   #如果expr1为true,则返回expr2,否则返回expr3  三元运算
select IF(true,'是的','不是的') from dual;
select IF(false,'是的','不是的') from dual;
select ename,IF(comm is null,0.0,comm) from emp;

# ifnull(expr1,expr2)   #如果expr1不为空(null),则返回expr1,否则返回expr2
select IFNULL(null,'你好') from dual;
select * from emp;
select ename,IFNULL(comm,0.0) from emp;  # 如果comm为null则会显示0.0

# select case when expr1 then expr2 
# when expr3 then expr4 
# else expr5 end
# 如果expr1为true,则返回expr2,
# 如果expr3为true,则返回expr4,否则返回expr5,可以多层分支
 select ename,job,
     (select case when job ='CLERK' then '职员' 
     when job ='MANAGER' then '经理' 
     when job ='SALESMAN' then '销售人员' 
     when job ='ANALYST' then '分析师'
     else job end) as chinese_job from emp;
     

6.5 多表查询

6.5.1 like和limit

# like,模糊查询
# %:表示0或者任意个字符; _:单个任意字符
-- 如何显示员工姓名首字符为s的员工姓名和工资
select ename,sal from emp
    where ename like 'S%';
-- 如何显示员工姓名第三个字符为大写o的所有员工的姓名和工资
select ename,sal from emp
    where ename like '__O%';
-- 如何显示没有上级的雇员的情况
select * from emp
    where mgr is null;
-- 查询表结构
desc emp;
-- 先按部门升序,然后工资降序
select * from emp
    order by deptno,sal desc;
    
    
# 分页查询
-- 基本语法:select... limit start, rows
-- 表示从start+1行开始取,取出rows行, start 从0开始计算
-- 查询emp表每页显示3条记录,查询第一页,第二页,第三页
-- limit 每页显示记录数*(页数-1),每页显示记录数
select * from emp limit 0,3;
select * from emp limit 3,3;
select * from emp limit 6,3;
  
### group by 加强使用
-- (1)显示每种岗位的雇员总数、平均工资。
select * from emp;
select job,FORMAT(AVG(sal),2),COUNT(*) from emp
    group by job;
-- (2)显示雇员总数,以及获得奖金的雇员数。
select COUNT(*),COUNT(comm) from emp;
-- (3)显示管理者的总人数。
select COUNT(distinct mgr) from emp;
-- (4)显示雇员工资的最大差额。
select MAX(sal) - MIN(sal) from emp;
-- (5) 统计各个部门的平均工资,
并且是大于1000的,并且按照平均工资从高到低排序,取出前两行记录
select deptno,AVG(sal) as avg_sal from emp
    group by deptno 
    having avg_sal > 1000
    order by avg_sal desc
    limit 0,2;

6.5.2 笛卡尔积

select * from dept;
select * from emp;
select * from salgrade;
select * from dept,emp; # 笛卡尔积

-- 显示扉员名,雇员工资及所在部门的名字【笛卡尔集】
select ename,sal,dname from dept,emp 
    where dept.deptno = emp.deptno;
-- 多表查询的条件不能少于表的个数-1,否则会出现笛卡尔集

-- 如何显示部门号为10的部门名、员工名和工资
select dname,ename,sal from dept,emp
    where dept.deptno = emp.deptno and emp.deptno = 10;

-- 显示各个员工的姓名,工资,及其工资的级别
select ename,sal,grade from emp,salgrade
    where sal between losal and hisal;
    
-- 查询雇员名,雇员工资以及所在部门的名字,并按部门降序排序
select ename,sal,dname,emp.deptno from dept,emp
    where dept.deptno = emp.deptno
    order by emp.deptno desc;

6.5.3 自连接

  • 将同一张表看做两张表
  • 需要给表取别名
  • 列名想要表达的意思不明确,也可以取别名,取别名的 as 可以省略
-- 查询公司员工名字和他上级的名字
select E1.ename as '员工名',E2.ename as '上司' 
    from emp as E1,emp as E2 
    where E1.mgr = E2.empno;
    

在这里插入图片描述

6.5.4 子查询

在这里插入图片描述

# 演示子查询
-- 单行子查询
-- 查询和 SMITH 同一个部门的所有员工信息
select * from emp where deptno = 
    (select deptno from emp where ename = 'SMITH');

-- 多行子查询,使用关键字 in
-- 查询和部门号为10的工作相同的员工的名字、岗位、工资、部门号,
-- 但是不包含10号部门本身的信息
select ename,job,sal,deptno  from emp
    where job in 
    (select distinct job from emp where deptno = 10)
    and deptno != 10;
 
 -- 多列子查询
-- 查询返回多个列数据的子查询语句
-- 查询与 ALLEN 的部门和岗位完全相同的所有员工(并且不包含 ALLEN 本人)
select * from emp
    where (deptno,job) = (select deptno,job from emp where ename = 'ALLEN') 
    and ename != 'ALLEN';   

-- 查询和宋江数学,英语,语文成绩完全相同的学生
select * from student 
    where (math,english,chinese) = 
    (select math,english,chinese from student where name = '宋江');

-- 查询每个部门工资最高的人的详细资料
 select emp.*,emp2.max_sal from emp, 
     (select deptno,MAX(sal) as max_sal from emp group by deptno) emp2 
     where emp.deptno = emp2.deptno and emp.sal = emp2.max_sal;
 
-- 查询每个部门的信息(包括部门名,编号,地址)和人员数量
select dept.*,emp2.count_emp2 from dept,
 (select deptno,COUNT(*) as count_emp2 from emp group by deptno) emp2
 where dept.deptno = emp2.deptno;
 

在这里插入图片描述

-- 查询每个部门工资高于本部门平均工资的人的信息
-- 先查询部门号和部门的平均工资(作为临时表) emp2;
-- 把结果当做子查询,和 emp 表进行多表查询
 select ename,sal,emp2.avg_sal,emp.deptno from emp, 
     (select deptno,AVG(sal) as avg_sal from emp group by deptno) emp2 
     where emp.deptno = emp2.deptno 
     and emp.sal > emp2.avg_sal;

6.5.5 all(所有)和any(任意)操作符

-- 演示all和any
-- all,所有的
# 查询员工工资比30号部门的所有员工的工资高的员工姓名、工资和部门号
select ename,sal,deptno from emp
    where sal > all(select sal from emp where deptno = 30); 
# 或者
select ename, sal,deptno from emp
    where sal > (select MAX(sal) from emp where deptno = 30);

--any,任意的其中一个    
# 查询工资比部门30其中一个员工的工资高的员工姓名、工资和部门号
select ename,sal,deptno from emp
    where sal > any(select sal from emp where deptno = 30);
# 或者
select ename, sal,deptno from emp
    where sal > (select MIN(sal) from emp where deptno = 30);

7. 表复制

在这里插入图片描述

8. 如何删掉一张表的重复记录(经典面试题)

# 假设 emp 表有重复的数据
1、创建一张临时表 my_tmp,结构和 emp 一样
create table my_tmp like emp;
2、把 emp 的记录通过 distinct 处理后将记录复制到 my_tmp (这里复制数据之后删除之前的表,然后将临时表改名也可以)
insert into my_tmp select distinct * from emp;
3、删除 emp 表的记录
delete from emp;
4、把 my_tmp 表的记录复制到 emp
insert into emp select * from my_tmp;
5、drop 掉临时表 my_tmp;
drop table my_tmp

9. 合并查询

在这里插入图片描述

# 演示合并查询
# 使用集合操作符号 union,union all
# union all 就是将两个查询结构合并,不会去重
select ename,sal,job from emp 
    where job = 'MANAGER' 
    union all 
    select ename,sal,job from emp where sal > 2500;
    
union 会去重
select ename,sal,job from emp 
    where job = 'MANAGER' 
    union 
    select ename,sal,job from emp where sal > 2500;

union all

在这里插入图片描述

union

在这里插入图片描述

10. 外连接

10.1 左外连接

左外连接:如果左侧的表完全显示就是左外连接,能匹配,正确保留,不能匹配,其它表的该字段都置空null

# 列出部门名称和这些部门的员工信息(名字和工作),同时列出那些没有员工的部门
select emp.deptno,dname,ename,job from 
    dept left join emp on dept.deptno = emp.deptno order by dname;

10.2 右外连接

右外连接:如果右侧的表完全显示就是右外连接,能匹配,正确保留,不能匹配,其它表的该字段都置空null

# 列出部门名称和这些部门的员工信息(名字和工作),同时列出那些没有员工的部门
select emp.deptno,dname,ename,job from 
    emp right join dept on dept.deptno = emp.deptno order by dname;

11. 约束

约束用于确保数据库的数据满足特定的商业规则。
mysql中有五种约束规则:not null、unique、primary key、foreign key、check

11.1 primary key

primary key:用于唯一的标示表行的数据,当定义主键约束后,该列不能有重复值且不能为空。
一张表最多只能有一个主键,但是可以是复合主键。
直接在字段名后面指定 字段名 primary key。
在表的最后面指定 primary key(列名)。

# 字段后面指定主键
create table t11
    id int primary key,
    `name` varchar(25),
    phone_number char(11));

# 表最后面指定
create table t11
    id int,
    `name` varchar(25),
    phone_number char(11),primary key(`name`));

# 复合主键,后面的 id,`name` 就是复合主键,
# 当添加的数据 id和 name 都相同的时候才会报错
create table t12(
    id int ,
    `name` varchar(25),
    phone_number CHAR(11),primary key(id,`name`));

11.2 not null

not null:当在某一列定义此字段,则表示该列必须要插入数据,不能为空

11.3 unique

unique:唯一的约束键,该列值不能重复。
如果没有指定 not null ,则 unique 字段可以有 null 值,如果指定了,类似于 primary key 。
一张表可以有多个 unique 字段。

# 演示unique
create table t13(
    id int unique,
    `name` varchar(25),
    email varchar(20));
insert into t13 VALUES(null,null,'tom@126.com');
select * from t13;
     

11.4 foreign key

在这里插入图片描述

用于定义主表和从表之间的关系:外键约束要定义在从表上,主表则必须具有主键约束或者unique约束,当定义外键约束后,要求外键列数据必须在主表的主键列存在或者是为null
注意事项:
外键指向的主表字段,要求必须设置 primary key或者 unique
表的类型必须是 innodb
外键字段的类型必须和主键字段的类型一致,长度可以不同
外键字段的值,必须在主键字段出现过,或者为null(前提是外键字段允许为null)
一旦建立主键外键关系,主表数据便不能随意删除

# 演示 foreign key
create table my_class(
    id int primary key,
    class_name varchar(25));
insert into my_class VALUES(100,'java班'),(200,'PHP班');
select * from my_class;

create table my_stu(
    id int,
    `name` varchar(25) not null default '',
    class_id int,
    foreign key (class_id) references my_class(id));
insert into my_stu VALUES(1,'tom',100),(2,'jarry',200);
insert into my_stu VALUES(3,'bob',null);   # 这样插入可以成功,因为外键字段允许 null
insert into my_stu VALUES(3,'bob',300);    # 这样插入会报错,因为主表没有 id 300
select * from my_stu;        

11.5 check

在这里插入图片描述

12. auto_increment(自动增长)

字段名 整型 primary key auto_increment
自动增长一般和 primary key 配合使用
自动增长也可以单独使用(但是需要配合一个 unique)
自动增长修饰的字段为整数型的(小数也可以,但是很少使用)
自动增长默认从1开始,你也可以修改开始的值: alter table 表名 auto_increment = 值;
自动增长也可以在插入数据时指定值,不建议使用

# 演示 auto_increment
create table t14(
    id int primary key auto_increment,
    `name` varchar(20),
    email varchar(25));
desc t14;
select * from t14;
insert into t14 VALUES(null,'tom','tom@126.com');  # 指定该字段为空,它会从1开始自动增长,下一个指定为空,则是2
insert into t14 (`name`,email) VALUES('jack','jack@126.com'); # 另外一种写法,只有在自动增长里才适用
insert into t14 VALUES(10,'jerry','jerry@126.com');  # 在插入时,指定值,以指定值为准
insert into t14 VALUES(40,'allen','allen@126.com');
delete from t14 where id = 2;     # 删除某一行之后,后面插入的也不会使用之前的数值
delete from t14;
alter table t14 auto_increment = 50;   # 可以修改默认值
insert into t14 VALUES(null,'smith','smith@126.com');  

在这里插入图片描述

13. 索引

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

# 演示索引
create table t15 (
    id int,
    `name` varchar(20));

# 查询某张表是否有索引
show index from t15;
show indexes from t15;
show keys from t15;
# 添加索引
# 添加唯一索引
create unique index id_index on t15 (id);
# 添加普通索引
create index id_index on t15 (id);
alter table t15 add index id_index (id);
# 如何选择?
# 如果某列的值是不会重复的,则优先选择 unique 索引,否则选择普通索引

# 删除索引
drop index id_index on t15;
# 删除主键索引
alter table t15 drop  primary key;

14. 事务

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

# 演示事务
create table t16 (
    id int,
    `name` varchar(25),
    phone CHAR(11))
    engine innodb;
select * from t16;
-- 开启事务并设置一个保存点
start transaction;
savepoint a;
-- 插入数据
insert into t16 VALUES(1,'张三',13245789823);

-- 再设置一个保存点
savepoint b;
-- 添加数据
insert into t16 VALUES(2,'李四',13698275689);

-- 回退到保存点b
rollback to b;
-- 回退到保存点a
rollback to a;

-- 不指定回退点,则回退全部事务
rollback

-- 提交事务
commit;

14.1 事务隔离级别

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

14.1.1 读未提交(read uncommitted)

读未提交脏读演示,左边终端开启一个事务,右边终端开启一个事务(右边终端的隔离级别是 read uncommitted ),当右边的终端能读取到左边没有提交的事务所做的修改时,就产生了脏读。

在这里插入图片描述

读未提交不可重复读和幻读演示,当右边的终端能读取到左边已经提交事务的修改删除操作,就产生了不可重复读;当右边的终端能读取到左边已经提交事务的插入操作,就产生了幻读。

在这里插入图片描述

14.1.2 读已提交(read commited)

读已提交脏读演示,左边终端开启一个事务,右边终端开启一个事务(右边终端的隔离级别是 read committed ),当右边的终端未读取到左边没有提交的事务时,不会产生脏读。

可以看到右边的终端并没有看到左边终端插入的数据。
在这里插入图片描述

读已提交不可重复读和幻读演示,当右边的终端能读取到左边已经提交事务的修改删除操作,就产生了不可重复读;当右边的终端能读取到左边已经提交事务的插入操作,就产生了幻读。

可以看到,当左边的终端事务提交以后,右边的终端能够获取到左边事务进行的修改和插入操作。
在这里插入图片描述

14.1.3 可重复读(repeatable read)

可重复读这个隔离级别不会产生脏读、不可重复读、幻读。

不会产生脏读
在这里插入图片描述
也不会产生不可重复读和幻读
在这里插入图片描述

14.1.4 可串行化(serializable)

可串行化这个隔离级别不会产生脏读、不可重复读、幻读,会对表加锁。

当左边的事务没有提交的时候,右边的终端查询的时候会卡主,会报错。
在这里插入图片描述
在这里插入图片描述

14.2 事务的ACID

在这里插入图片描述

15. 表类型和存储引擎

mysql的表类型由存储引擎(storage engines)决定,主要包括 myisam,innodb,memory
mysql数据表主要支持六种类型,分别是:csv、memory、archive、mrg_myisam、myisam、innodb
这六种又分为两类:
一类是“事务安全型”(transaction-safe),比如:innodb;
其余属于第二类,称为“非事务安全型”(non-transaction-safe),比如:myisam 和 memory

myisam 不支持事务,也不支持外键,但其访问速度快,对事务完整性没有要求。
innodb 提供了具有提交、回滚和崩溃恢复能力的事务安全。但是比起 myisam,innodb写的处理效率差一些并且会占用更多的磁盘空间以保留数据和索引。
memory 存储引擎使用存在内存中的内容来创建表,每个 memory 表只实际对应一个磁盘文件,memory 类型的表访问非常快,因为它的数据是放在内存中的(没有IO读写),并且默认使用 hash 索引。但是一旦 mysql 服务关闭,表中的数据就会丢失掉,表的结构还在。

在这里插入图片描述

# 查看所有的引擎类型
show engines;

在这里插入图片描述

修改表的引擎指令
alter table 表名 engine = 存储引擎

如何选择表的存储引擎?
1、如果你的应用不需要事务,处理的只是基本的 crud 操作,选择 myisam
2、如果需要支持事务,选择 innodb
3、需要速度极快,临时数据选择 memory,例如,用户的在线状态

16. 视图

在这里插入图片描述

视图是一个虚拟表,其内容由查询定义。同真实的表一样,视图包含列,其数据来自对应的真实表(基表)。
通过视图可以修改基表的数据。
基表的改变,也会影响到视图的数据。
视图中可以再使用视图。

# 创建视图
create view 视图名 as select语句
create view emp_view as select empno,ename,job,deptno from emp;
select * from emp_view;

# 修改视图
alter view 视图名 as select语句

# 查看视图创建的命令
show create view 视图名

# 删除视图
drop view 视图名1,视图名2

在这里插入图片描述

# 多表联合创建视图
# 针对emp , dept ,和salgrade张三表.创建一个视图,
# 可以显示雇员编号,雇员名,雇员部门名称和薪水级别[即使用三张表,构建一个视图
create view emp_view03 as
    select empno,ename,dname,grade from dept,emp,salgrade
    where dept.deptno = emp.deptno and
    emp.sal between losal and hisal;
select * from emp_view03;

17. 用户管理和权限管理

17.1 用户管理

在这里插入图片描述

# mysql用户管理
# 使用场景
# 根据岗位职责,给不同的人赋予可以操作数据库的部分权限
# 创建的用户会存放到 mysql 库中的 user 表

# 创建用户并可以指定登录地址以及密码
# '用户名'@'登录地址':登录地址本地 localhost,任意地址用 % 表示,
# 也可以是某个ip或者某个网段 192.168.1.%
create user '用户名'@'登录地址' identified by '密码';
# 创建的用户存入 mysql 库的 user 表
# 默认只能查看 information_schema 库

# 用户自己修改自己的密码
set password = password('密码');
# 修改别人的密码,需要权限
set password for '用户名'@'登录地址' = password('密码');
# 
删除用户
drop user '用户名'@'登录地址'


# 示例
select * from mysql.user;
create user 'lxr'@'localhost' identified by '123';
# 删除用户
drop user 'lxr'@'localhost';

17.2 权限管理

在这里插入图片描述
在这里插入图片描述

# 演示权限管理
# 给 lxr 用户授权 hsp_db02 库的 emp 表的查看权限
grant select on hsp_db02.emp to 'lxr'@'localhost';
# 回收权限,用 all 则是回收所有权限
revoke all on hsp_db02.emp from 'lxr'@'localhost';

在这里插入图片描述

本文笔记来自韩顺平B站视频,非个人原创,以下链接点击跳转原视频。
韩顺平零基础学习mysql数据库B站链接,点击跳转

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值