mysql3

mysql多表查询与事务的操作

MySQL数据库中,
字段或列的注释是用属性comment来添加。

1.1dql查询

1.1.1排序使用什么子句  order by

升序 asc

降序 desc

1.1.2聚合函数

1.1.3分页查询

limit 起始值从0开始  长度

1.1.4分组查询

group by 分组列  having 过滤条件 

1.2 约束

1.2.1约束的关键字

约束名     约束关键字

主键         primary key

唯一         unique

非空         not null

默认         default

外键         foreign key

1.2.2自增长的关键字

auto_increment

1.2.3级联操作的语法

级联操作语法                       描述

on update cascade               级联更新

on delete cascade                 级联删除

1.3表与表之间的关系

表与表之间的三种关系          关系如何维护

一对多                                 通过主外键约束

多对多                                 通过中间表,中间表与两个表是多对一

一对一                               1 特殊的一对多。多方加唯一约束

                                          2从表的主键同时又是外键

1.4数据库的三大范式

范式

第一范式    原子性,每列不可再拆分

第二范式              不产生局部依赖,表中每一列完全依赖于主键

第三范式            不产生传递,表中每一列都直接依赖于主键

学习目标

能够使用内连接进行多表查询

能够使用左外连接和右外连接进行多表查询

能够使用子查询进行多表查询,能够使用多表进行查询

能够理解事务的概念

能够说出事务的特点

能够在mysql中使用事务

能够理解脏读,不可重复读,幻读的概念和解决方法

能使用DCL管理mysql用户

第三节  表连接查询 

3.1什么是多表查询

数据准备

# 创建部门表
create table dept(
 id int primary key auto_increment,
 name varchar(20)
)
insert into dept (name) values ('开发部'),('市场部'),('财务部');
# 创建员工表
create table emp (
 id int primary key auto_increment,
 name varchar(10),
 gender char(1), -- 性别
 salary double, -- 工资
 join_date date, -- 入职日期
 dept_id int,
 foreign key (dept_id) references dept(id) -- 外键,关联部门表(部门表的主键)
)
insert into emp(name,gender,salary,join_date,dept_id) values('孙悟空','男
',7200,'2013-02-24',1);
insert into emp(name,gender,salary,join_date,dept_id) values('猪八戒','男
',3600,'2010-12-02',2);
3 / 30
insert into emp(name,gender,salary,join_date,dept_id) values('唐僧','男',9000,'2008-
08-08',2);
insert into emp(name,gender,salary,join_date,dept_id) values('白骨精','女
',5000,'2015-10-07',3);
insert into emp(name,gender,salary,join_date,dept_id) values('蜘蛛精','女
',4500,'2011-03-14',1);

mysql中engine=innodb和engine=myisam的区别

1/ISAM

ISAM是一个定义明确且历经时间考验的数据表格管理方法,它在设计之时就考虑到数据库被查询的次数要远大于更新的次数。因此,ISAM执行读取操作的速度很快,而且不占用大量的内存和存储资源。ISAM的两个主要不足之处在于,它不支持事务处理,也不能够容错:如果你的硬盘崩溃了,那么数据文件就无法恢复了。如果你正在把ISAM用在关键任务应用程序里,那就必须经常备份你所有的实时数据,通过其复制特性,MySQL能够支持这样的备份应用程序。

2/InnoDB

它提供了事务控制能力功能,它确保一组命令全部执行成功,或者当任何一个命令出现错误时所有命令的结果都被回退,可以想像在电子银行中事务控制能力是非常重要的。支持COMMIT、ROLLBACK和其他事务特性。最新版本的Mysql已经计划移除对BDB的支持,转而全力发展InnoDB。

以下是一些细节和具体实现的差别:

1.InnoDB不支持FULLTEXT类型的索引。
2.InnoDB中不保存表的
具体行数,也就是说,执行select count(*) from
table时,InnoDB要扫描一遍整个表来计算有多少行,但是MyISAM只要简单的读出保存好的行数即可。注意的是,当count(*)语句包含
where条件时,两种表的操作是一样的。
3.对于AUTO_INCREMENT类型的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中,可以和其他字段一起建立联合索引。
4.DELETE
FROM table时,InnoDB不会重新建立表,而是一行一行的删除。
5.LOAD TABLE FROM
MASTER操作对InnoDB是不起作用的,解决方法是首先把InnoDB表改成MyISAM表,导入数据后再改成InnoDB表,但是对于使用的额外的InnoDB特性(例如外键)的表不适用。

另外,InnoDB表的行锁也不是绝对的,如果在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表

多表查询的作用

比如我们想查询孙悟空的名字和他所在的部门的名字,则需要多表查询

如果一条sql语句查询多张表,因为查询结果在多张不同的表中,每张表取一列或多列

3.1.1多表查询的分类

3.2 笛卡尔积现象

3.2.1 笛卡尔积现象是什么

需求查询所有员工 和所有部门

select * from emp,dept

结果分析

3.2.2如何清除笛卡尔积现象的影响

我们发现不是所有的数据组合都是有用的,只要员工表.dept_id=部门表.id的数据才是有用,所以需要 通过条件过滤掉没用的数据

-- 设置过滤条件 Column 'id' in where clause is ambiguous
select * from emp,dept where id=5;
select * from emp,dept where emp.`dept_id` = dept.`id`;
-- 查询员工和部门的名字
select emp.`name`, dept.`name` from emp,dept where emp.`dept_id` = dept.`id`;

3.3 内连接

用左边表的记录去匹配右边表的记录,如果符合条件的则显示。如:从表.外键=主表.主键

3.3.1隐式内连接

 隐式内连接:看不到 JOIN 关键字,条件使用 WHERE 指定

select * from emp,dept where emp.`dept_id` = dept.`id`;

3.3.2 显式内连接

显示内连接:使用 INNER JOIN ... ON 语句, 可以省略 INNER

SELECT 字段名 FROM 左表 [INNER] JOIN 右表 ON 条件

查询唐僧的信息,显示员工 id,姓名,性别,工资和所在的部门名称,我们发现需要联合 2 张表同时才能 查询出需要的数据,使用内连接

select * from emp inner join dept;

2) 确定表连接条件,员工表.dept_id = 部门表.id 的数据才是有效的

select * from emp e inner join dept d on e.`dept_id` = d.`id`;

3) 确定查询条件,我们查询的是唐僧的信息,员工表.name='唐僧'

select * from emp e inner join dept d on e.`dept_id` = d.`id` where e.`name`='唐僧 ';

4)确定查询字段  查询唐僧的信息,显示员工 id,姓名,性别,工资和所在的部门名称

5) 我们发现写表名有点长,可以给表取别名,显示的字段名也使用别名

3.3.3 总结内连接查询步骤:

1) 确定查询哪些表

2) 确定表连接的条件

3) 确定查询的条件

4) 确定查询的字段

3.4 左外连接

 左外连接:使用 LEFT OUTER JOIN ... ON,OUTER 可以省略

SELECT 字段名 FROM 左表 LEFT [OUTER] JOIN 右表 ON 条件

用左边表的记录去匹配右边表的记录,如果符合条件的则显示;否则,显示 NULL 可以理解为:在内连接的基础上保证左表的数据全部显示(左表是部门,右表员工)

-- 在部门表中增加一个销售部 insert into dept (name) values ('销售部');

select * from dept;

-- 使用内连接查询

select * from dept d inner join emp e on d.`id` = e.`dept_id`;

-- 使用左外连接查询

select * from dept d left join emp e on d.`id` = e.`dept_id`;

3.5右外连接

 右外连接:使用 RIGHT OUTER JOIN ... ON,OUTER 可以省略

SELECT 字段名 FROM 左表 RIGHT [OUTER ]JOIN 右表 ON 条件

用右边表的记录去匹配左边表的记录,如果符合条件的则显示;否则,显示 NULL 可以理解为:在内连接的基础上保证右表的数据全部显示

-- 在员工表中增加一个员工

-- 在员工表中增加一个员工

insert into emp values (null, '沙僧','男',6666,'2013-12-05',null); select * from emp;

-- 使用内连接查询

select * from dept inner join emp on dept.`id` = emp.`dept_id`;

-- 使用右外连接查询

select * from dept right join emp on dept.`id` = emp.`dept_id`;

4子查询

4.1什么是子查询

-- 需求:查询开发部中有哪些员工

select * from emp;

-- 通过两条语句查询

select id from dept where name='开发部' ;

select * from emp where dept_id = 1;

-- 使用子查询 select * from emp where dept_id = (select id from dept where name='市场部');

子查询的概念:

1) 一个查询的结果做为另一个查询的条件

2) 有查询的嵌套,内部的查询称为子查询

3) 子查询要使用括号

4.2 子查询结果的三种情况:

1) 子查询的结果是单行单列

2) 子查询的结果是多行单列

3) 子查询的结果是多行多列

4.3 子查询的结果是一个值的时候

 子查询结果只要是单行单列,肯定在 WHERE 后面作为条件,父查询使用:比较运算符,如:> 、、= 等

SELECT 查询字段 FROM 表 WHERE 字段=(子查询);

4.3.1 案例:查询工资最高的员工是谁?

-- 1) 查询最高工资是多少 select max(salary) from emp;

-- 2) 根据最高工资到员工表查询到对应的员工信息

select * from emp where salary = (select max(salary) from emp);

4.3.2 查询工资小于平均工资的员工有哪些?

-- 1) 查询平均工资是多少 select avg(salary) from emp;

-- 2) 到员工表查询小于平均的员工信息

select * from emp where salary < (select avg(salary) from emp);

4.4 子查询结果是多行单列的时候

子查询结果是单例多行,结果集类似于一个数组,父查询使用 IN 运算符

SELECT 查询字段 FROM 表 WHERE 字段 IN (子查询);

4.4.1 查询工资大于 5000 的员工,来自于哪些部门的名字

-- 先查询大于 5000 的员工所在的部门 id select dept_id from emp where salary > 5000; -- 再查询在这些部门 id 中部门的名字 Subquery returns more than 1 row

select name from dept where id = (select dept_id from emp where salary > 5000); select name from dept where id in (select dept_id from emp where salary > 5000);

4.4.2 查询开发部与财务部所有的员工信息

-- 先查询开发部与财务部的 id select id from dept where name in('开发部','财务部'); -- 再查询在这些部门 id 中有哪些员工 select * from emp where dept_id in (select id from dept where name in('开发部','财务 部'));

4.5 子查询的结果是多行多列

子查询结果只要是多列,肯定在 FROM 后面作为表

SELECT 查询字段 FROM (子查询) 表别名 WHERE 条件;

子查询作为表需要取别名,否则这张表没有名称则无法访问表中的字段

4.5.1 查询出 2011 年以后入职的员工信息,包括部门名称

-- 查询出 2011 年以后入职的员工信息,包括部门名称 -- 在员工表中查询 2011-1-1 以后入职的员工 select * from emp where join_date >='2011-1-1'; -- 查询所有的部门信息,与上面的虚拟表中的信息组合,找出所有部门 id 等于的 dept_id select * from dept d, (select * from emp where join_date >='2011-1-1') e where d.`id`= e.dept_id ;

-- 也可以使用表连接:

select * from emp inner join dept on emp.`dept_id` = dept.`id` where join_date >='2011-1-1'; select * from emp inner join dept on emp.`dept_id` = dept.`id` and join_date >='2011-1-1';

4.6 子查询小结

子查询结果只要是单列,则在 WHERE 后面作为条件

 子查询结果只要是多列,则在 FROM 后面作为表进行二次查询

第5节 事务

5.1 事务的应用场景说明

 什么是事务: 在实际的开发过程中,一个业务操作如:转账,往往是要多次访问数据库才能完成的。转 账是一个用户扣钱,另一个用户加钱。如果其中有一条 SQL 语句出现异常,这条 SQL 就可能执行失败。 事务执行是一个整体,所有的 SQL 语句都必须执行成功。如果其中有 1 条 SQL 语句出现异常,则所有的 SQL 语句都要回滚,整个业务执行失败。

 转账的操作

-- 创建数据表 CREATE TABLE account ( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(10), balance DOUBLE ); -- 添加数据 INSERT INTO account (NAME, balance) VALUES ('张三', 1000), ('李四', 1000);

模拟张三给李四转 500 元钱,一个转账的业务操作最少要执行下面的 2 条语句: 张三账号-500 李四账号+500

-- 张三账号-500 update account set balance = balance - 500 where name='张三'; -- 李四账号+500 update account set balance = balance + 500 where name='李四';

假设当张三账号上-500 元,服务器崩溃了。李四的账号并没有+500 元,数据就出现问题了。我们需要保证其中 一条 SQL 语句出现问题,整个转账就算失败。只有两条 SQL 都成功了转账才算成功。这个时候就需要用到事务。

5.2 手动提交事务

MYSQL 中可以有两种方式进行事务的操作:

1) 手动提交事务 2) 自动提交事务

5.2.1 手动提交事务的 SQL 语句

功能          sql语句

开启事务   start transaction

提交事务        commit;

回滚            rollback;

5.2.2 手动提交事务使用过程

1 执行成功的情况  开启事务,-》执行多条sql语句-》成功提交事务

2 执行失败情况  开启事务-》执行多条sql语句 -》事务的回滚

5.2.3

模拟张三给李四转 500 元钱(成功) 目前数据库数据如下:

1) 使用 DOS 控制台进入 MySQL 2) 执行以下 SQL 语句: 1.开启事务, 2.张三账号-500, 3.李四账号+500 3) 使用 SQLYog 查看数据库:发现数据并没有改变 4) 在控制台执行 commit 提交事务: 5) 使用 SQLYog 查看数据库:发现数据改变

5.2.4案例演示2 事务回滚

模拟张三给李四转 500 元钱(失败) 目前数据库数据如下:

1) 在控制台执行以下 SQL 语句:1.开启事务, 2.张三账号-500 2) 使用 SQLYog 查看数据库:发现数据并没有改变 3) 在控制台执行 rollback 回滚事务: 4) 使用 SQLYog 查看数据库:发现数据没有改变

总结: 如果事务中 SQL 语句没有问题,commit 提交事务,会对数据库数据的数据进行改变。 如果事务中 SQL 语句有问题,rollback 回滚事务,会回退到开启事务时的状态。

5.3自动提交事务

MySQL 默认每一条 DML(增删改)语句都是一个单独的事务,每条语句都会自动开启一个事务,语句执行完毕 自动提交事务,MySQL 默认开始自动提交事务

5.3.1 案例演示 3:自动提交事务

1. 将金额重置为 1000 2. 更新其中某一个账户 3. 使用 SQLYog 查看数据库:发现数据已经改变

5.3.2 取消自动提交 

查看 MySQL 是否开启自动提交事务

@@表示全局变量,1 表示开启,0 表示关闭

取消自动提交事务

 执行更新语句,使用 SQLYog 查看数据库,发现数据并没有改变

 在控制台执行 commit 提交任务

5.4 事务原理

事务开启之后, 所有的操作都会临时保存到事务日志中, 事务日志只有在得到 commit 命令才会同步到数据表 中,其他任何情况都会清空事务日志(rollback,断开连接)

5.4.1原理图

5.4.2 事务的步骤

1) 客户端连接数据库服务器,创建连接时创建此用户临时日志文件

2) 开启事务以后,所有的操作都会先写入到临时日志文件中

3) 所有的查询操作从表中查询,但会经过日志文件加工后才返回

4) 如果事务提交则将日志文件中的数据写到表中,否则清空日志文件。

5.5 回滚点

5.5.1 什么是回滚点

在某些成功的操作完成之后,后续的操作有可能成功有可能失败,但是不管成功还是失败,前面操作都已经成 功,可以在当前成功的位置设置一个回滚点。可以供后续失败操作返回到该位置,而不是返回所有操作,这个点称 之为回滚点。

5.5.2 回滚点的操作语句

savepoint 

rollback to

5.5.3 具体操作:

1) 将数据还原到 1000

2) 开启事务 3) 让张三账号减 3 次钱,每次 10 块 4) 设置回滚点:savepoint three_times; 5) 让张三账号减 4 次钱,每次 10 块 6) 回到回滚点:rollback to three_times; 7) 分析执行过程

 总结:设置回滚点可以让我们在失败的时候回到回滚点,而不是回到事务开启的时候

5.6 事务的隔离级别

5.6.1事务的四大特性 ACID

5.6.2 事务的隔离级别

事务在操作时的理想状态: 所有的事务之间保持隔离,互不影响。因为并发操作,多个用户同时访问同一个 数据。可能引发并发访问的问题:

脏读    一个事物读取另一个事务未提交的数据

不可重复读     一个事务中两次读取数据内容不一致,要求的是一个事务中多次读取时数据是一致的  这是事务 update时引发的问题

幻读   一个事务  中两次读取的数据数量不一致,要求在一个事务中读取数据数量是一致的  这是insert或delete时引发的问题,

5.6.3 MySQL 数据库有四种隔离级别

上面的级别最低,下面的级别最高。“是”表示会出现这种问题,“否”表示不会出现这种问题。

隔离级别越高,性能越差,安全性越高。

5.6.4 MySQL 事务隔离级别相关的命令

查询全局事务隔离级别

查询隔离级别 select @@tx_isolation;

 设置事务隔离级别,需要退出 MySQL 再重新登录才能看到隔离级别的变化

设置隔离级别 set global transaction isolation level 级别字符串;

5.6.5 脏读的演示

将数据进行恢复:UPDATE account SET balance = 1000;

1. 打开 A 窗口登录 MySQL,设置全局的隔离级别为最低

mysql -uroot -proot set global transaction isolation level read uncommitted;

2. 打开 B 窗口,AB 窗口都开启事务

use day23; start transaction;

3. A 窗口更新 2 个人的账户数据,未提交

update account set balance=balance-500 where id=1; update account set balance=balance+500 where id=2;

4. B 窗口查询账户

select * from account;

5. A 窗口回滚

rollback;

6. B 窗口查询账户,钱没了

脏读非常危险的,比如张三向李四购买商品,张三开启事务,向李四账号转入 500 块,然后打电话给李四说钱 已经转了。李四一查询钱到账了,发货给张三。张三收到货后回滚事务,李四的再查看钱没了。

解决脏读的问题:将全局的隔离级别进行提升

将数据进行恢复:

UPDATE account SET balance = 1000;

1. 在 A 窗口设置全局的隔离级别为 read committed

set global transaction isolation level read committed;

B 窗口退出 MySQL,B 窗口再进入 MySQL

2. A 更新 2 个人的账户,未提交

update account set balance=balance-500 where id=1; update account set balance=balance+500 where id=2;

3. B 窗口查询账户

A 窗口 commit 提交事务

4. B 窗口查看账户

结论:read committed 的方式可以避免脏读的发生

5.6.6 不可重复读的演示

将数据进行恢复:

UPDATE account SET balance = 1000;

1. 开启 A 窗口

set global transaction isolation level read committed;

2. 开启 B 窗口,在 B 窗口开启事务

start transaction; select * from account;

3. 在 A 窗口开启事务,并更新数据

start transaction;

update account set balance=balance+500 where id=1;

commit;

4. B 窗口查询

select * from account;

两次查询输出的结果不同,到底哪次是对的?不知道以哪次为准。 很多人认为这种情况就对了,无须困惑, 当然是后面的为准。我们可以考虑这样一种情况,比如银行程序需要将查询结果分别输出到电脑屏幕和发短信给客 户,结果在一个事务中针对不同的输出目的地进行的两次查询不一致,导致文件和屏幕中的结果不一致,银行工作人员就不知道以哪个为准了。

解决不可重复读的问题:

将全局的隔离级别进行提升为

:repeatable read

将数据进行恢复:

UPDATE account SET balance = 1000;

1. A 窗口设置隔离级别为:repeatable read

set global transaction isolation level repeatable read;

2. B 窗口退出 MySQL,B 窗口再进入 MySQL

start transaction; select * from account;

3. A 窗口更新数据

start transaction;

update account set balance=balance+500 where id=1;

commit;

4. B 窗口查询

select * from account;

结论:同一个事务中为了保证多次查询数据一致,必须使用 repeatable read 隔离级别

5.6.7 幻读的演示

在 MySQL 中无法看到幻读的效果。

但我们可以将事务隔离级别设置到最高,以挡住幻读的发生 将数据进行恢复:

UPDATE account SET balance = 1000;

select @@global_tx.isolation;

1. 开启 A 窗口

set global transaction isolation level serializable; -- 设置隔离级别为最高

2. A 窗口退出 MySQL,A 窗口重新登录 MySQL

start transaction; select count(*) from account;

3. 再开启 B 窗口,登录 MySQL

4. 在 B 窗口中开启事务,添加一条记录

start transaction; -- 开启事务 insert into account (name,balance) values ('LaoWang', 500);

5. 在 A 窗口中 commit 提交事务,B 窗口中 insert 语句会在 A 窗口事务提交后立马运行

6. 在 A 窗口中接着查询,发现数据不变

select count(*) from account;

7. B 窗口中 commit 提交当前事务

8. A 窗口就能看到最新的数据

结论:使用 serializable 隔离级别,一个事务没有执行完,其他事务的 SQL 执行不了,可以挡住幻读

第6节 DCL (Data Control Language)

 DDL: create / alter / drop

DML:insert /update/delete

DQL :select /show

 DCL :grant /revoke

我们现在默认使用的都是 root 用户,超级管理员,拥有全部的权限。但是,一个公司里面的数据库服务器上面 可能同时运行着很多个项目的数据库。所以,我们应该可以根据不同的项目建立不同的用户,分配不同的权限来管 理和维护数据库。

注:mysqld 是 MySQL 的主程序,服务器端。mysql 是 MySQL 的命令行工具,客户端。

6.1 创建用户

6.1.1 语法:

CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';

6.1.2 关键字说明:

6.1.3 具体操作:

创建 user1 用户,只能在 localhost 这个服务器登录 mysql 服务器,密码为 123

create user 'user1'@'localhost' identified by '123';

创建 user2 用户可以在任何电脑上登录 mysql 服务器,密码为 123

create user 'user2'@'%' identified by '123';

注:创建的用户名都在 mysql 数据库中的 user 表中可以查看到,密码经过了加密。

6.2 给用户授权

用户创建之后,没什么权限!需要给用户授权

6.2.1 语法:

GRANT 权限 1, 权限 2... ON 数据库名.表名 TO '用户名'@'主机名';

6.2.2 关键字说明:

6.2.3 具体操作:

1.给 user1 用户分配对 test 这个数据库操作的权限:创建表,修改表,插入记录,更新记录,查询

grant create,alter,insert,update,select on test.* to 'user1'@'localhost';

注:用户名和主机名要与上面创建的相同,要加单引号。

2. 给 user2 用户分配所有权限,对所有数据库的所有表

grant all on *.* to 'user2'@'%';

6.3 撤销授权

6.3.1 语法:

REVOKE 权限 1, 权限 2... ON 数据库.表名 revoke all on test.* from 'user1'@'localhost'; '用户名'@'主机 名';

6.3.2 具体操作:

撤销 user1 用户对 test 数据库所有表的操作的权限

revoke all on test.* from 'user1'@'localhost';

注:用户名和主机名要与创建时相同,各自要加上单引号

6.4 查看权限

6.4.1 语法:

SHOW GRANTS FOR '用户名'@'主机名';

6.4.2 具体操作:

 查看 user1 用户的权限

 注:usage 是指连接(登陆)权限,建立一个用户,就会自动授予其 usage 权限(默认授予)。

6.5 删除用户

6.5.1 语法

DROP USER '用户名'@'主机名';

6.5.2 具体操作:

 删除 user2

drop user 'user2'@'%';

6.6 修改管理员密码

6.6.1语法

mysqladmin -uroot -p password 新密码

注意:需要在未登陆 MySQL 的情况下操作,新密码不需要加上引号。

6.6.2 具体操作:

1) 将 root 管理员的新密码改成 123456 2) 要求输入旧密码 3) 使用新密码登录

6.7 修改普通用户密码

6.7.1 语法:

set password for '用户名'@'主机名' = password('新密码');

 注意:需要在登陆 MySQL 的情况下操作,新密码要加单引号。

6.7.2 具体操作:

1) 将'user1'@'localhost'的密码改成'666666'

2) 使用新密码登录,老密码登录不了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值