Mysql DAY1

day1

1.1 安装及登录

修改密码:set password = password(‘密码’);

授权远程访问:
grant all privileges on . to ‘root’ @’%’ identified by ‘密码’;

flush privileges; 刷新权限列表

1.2 索引

MySQL官方对索引的定义为:索引 ( index)是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护者满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据
这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。

一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储在磁盘上。索引是数据库中用来提高性能的最常用的工具

1.2.1 索引优势劣势

优势

① 类似于书籍的目录索引,提高数据检索的效率,降低数据库的IO成本。
② 通过索引列对数据进行排序,降低数据排序的成本,降低CPU消耗。

劣势

① 实际上索引也是一张表,该表中保存了主键与索引字段,并指向实体类的记录,所以索引列也是要占空间的。
② 虽然索引大大提高了查询效率,同时却也降低更新表的速度,如对表进行INSERT、UPDATE、DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件每次更新添加了索引列的字段,都会调整因为更新所带来的键值变化后的索引信息。

1.2.2 索引

索引是在MySQL的存储引擎层中实现的,而不是在服务器层实现的。所以每种存储引擎的索引都不一定完全相同,也不是所有的存储引擎都支持所有的索引类型的。MySQL目前提供了以下4钟索引:

● BTREE索引:最常见的索引类型,大部分索引都支持B树索引。
● HASH索引:只有Memory引擎支持,使用场景简单。
● R-tree索引(空间索引):空间索引是MyISAM引擎的一个特殊索引类型,主要用于地理空间数据类型,通常使用较少,不做特别介绍。
● Full-text(全文索引):全文索引也是MyISAM的一个特殊索引类型,主要用于全文索引,InnoDB从Mysql5.6版本开始支持全文索引。

MyISAM、InnoDB、Memory三种存储引擎对各种索引类型的支持

索引InnoDB引擎MyISAM引擎Memory引擎
BTREE索引支持支持支持
HASH索引不支持不支持支持
R-tree索引不支持支持不支持
Full-text5.6版本呢之后支持支持不支持

我们平常所说的索引,如果没有特别指明,都是指B+树(多路搜索树,并不一定是二叉的)结构组织的索引。其中聚集索引、复合索引、前缀索引、唯一索引默认都是使用B+tree树索引,统称为索引。

BTREE 结构

BTree又叫多路平衡搜索树,一颗m叉的BTree特性如下:

BTREE树和二叉树相比,查询数据的效率更高,因为对于相同的数据量来说,BTREE的层级结构比二叉树小,因此搜索速度快。

B+TREE结构

由于B+Tree只有叶子节点保存key信息,查询任何key都要从root走到叶子。所以B+Tree的查询效率更加稳定。

MySQL中的B+Tree

MySql索引数据结构对经典的B+Tree进行了优化。在原B+Tree的基础上,增加一个指向相邻叶子节点的链表指针,就形成了带有顺序指针的B+Tree,提高区间访问的性能。

增加指针的目的:增强范围搜索

1.2.3 索引分类

① 单值索引:即一个索引只包含单个列,一个表可以有多个单列索引
② 唯一索引:索引列的值必须唯一,但允许有空值
③ 复合索引:即一个索引包含多个列

1.2.4 索引语法

索引在创建表的时候,可以同时创建,也可以随时增加新的索引。

准备环境:


CREATE TABLE `city` (
  `city_id` int(11) NOT NULL AUTO_INCREMENT,
  `city_name` varchar(50) NOT NULL,
  `country_id` int(11) NOT NULL,
  PRIMARY KEY (`city_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8

insert  into `city`(`city_id`,`city_name`,`country_id`) values (1,'西安',1),(2,'NewYork',2),(3,'北京',1),(4,'上海',1);

CREATE TABLE `country` (
  `country_id` int(11) NOT NULL AUTO_INCREMENT,
  `country_name` varchar(100) NOT NULL,
  PRIMARY KEY (`country_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

insert  into `country`(`country_id`,`country_name`) values (1,'China'),(2,'America'),(3,'Japan'),(4,'UK');

创建索引

语法:
CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name [USING index_type] on table_name(index_col_name,...)

实例:为city表中的city_name字段创建索引:

create index idx_city_name on city(city_name);

查看索引

show index from city;

show index from city\G;

删除索引

语法:
DROP INDEX index_name ON table_name;

示例:
drop index idx_city_name on city;

ALTER命令

① alter table table_name add primary key(column_list);

该语句添加一个主键,这意味着索引值必须是唯一的,且不能为NULL

② alter table table_name add unique index_name(column_list);

这条语句创建索引的值必须是唯一的(除了NULL外,NULL可能会出现多次)

③ alter table table_name add index_name(column_list);

添加普通索引,索引值可以出现多次。

④ alter table table_name add fulltext index_name(column_list);

该语句指定了索引为FULLTEXT,用于全文索引

1.2.5 索引设计原则

索引的设计可以遵循一一些已有的原则,创建索引的时候请尽量考虑符合这些原则,便于提升索引的使用效率,更高效的使用索引。

① 对查询频次较高,且数据量比较大的表建立索引。

② 索引字段的选择,最佳候选列应当从where子句的条件中提取,如果where子句中的组合比较多,那么应当挑选最常用、过滤效果最好的列的组合。

③ 使用唯一索引,区分度越高,使用索引的效率越高。

④ 索引可以有效的提升查询数据的效率,但索引数量不是多多益善,索引越多,维护索引的代价自然也就水涨船高。对于插入、更新、删除等DML操作比较频繁的表来说,索引过多,会引入相当高的维护代价,降低DML操作的效率,增加相应操作的时间消耗。另外索引过多的话, MySQL也会犯选择困难病,虽然最终仍然会找到一个可用的索引,但无疑提高了选择的代价。

⑤ 使用短索引,索引创建之后也是使用硬盘来存储的,因此提升索引访问的I/O效率,也可以提升总体的访问效率。假如构成索引的字段总长度比较短,那么在给定大小的存储块内可以存储更多的索引值,相应的可以有效的提升MySQL访问索引的I/O效率。

⑥ 利用最左前缀, N个列组合而成的组合索引,那么相当于是创建了N个索引,如果查询时where子句中使用了组成该索引的前几个字段,那么这条查询SQL可以利用组合索引来提升查询效率。

创建复合索引:
		CREATE INDEX idx_name_email_status ON table_seller(NAME,emailm,STATUS);

就相当于 
		对name 创建索引
		对name,email 创建了索引;
		对name,email,status创建了索引;

1.3 视图

1.3.1 视图概述

视图(View)是一种虚拟存在的表。视图并不在数据库中实际存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的。通俗的讲,视图就是一条SELECT语句执行后返回的结果集。 所以我们在创建视图的时候,主要的工作就落在创建这条SQL查询语句上。

视图相对于普通的表的优势主要包括以下几项。
● 简单:使用视图的用户完全不需要关心后面对应的表的结构、关联条件和筛选条件,对用户来说已经是过滤好的复合条件的结果集。
● 安全:使用视图的用户只能访问他们被允许查询的结果集,对表的权限管理并不能限制到某个行某个列,但是通过视图就可以简单的实现。
● 数据独立:一旦视图的结构确定了,可以屏蔽表结构变化对用户的影响,源表增加列对视图没有影响;源表修改列名,则可以通过修改视图来解决,不会造成对访问者的影响。

1.3.2 创建或者修改视图

创建视图的语法为:

CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]

VIEW view_name [(colum_list)]

AS select_statement

[WITH [CASCADED | LOCAL] CHECK OPTION] 

视图也可以更新,只不过更新的是基表里的内容,不建议更新视图,因为视图只是方便查询视图

修改视图的语法为:

ALTER [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]

VIEW view_name [(column_list)]

AS select_statement

[WITH [CASCADED | LOCAL] CHECK OPTION]
选项:
		WITH [CASCADED | LOCAL] CHECK OPTION  决定了是否允许更新数据使记录不再满足视图的条件。
		LOCAL:只要满足本视图的条件就可以更新。
		CASCADED(默认值):必须满足所有针对该视图的所有视图条件才能更新。

1.3.3 查看视图

从MySQL5.1 版本开始,使用SHOW TABLES 命令的时候不仅显示表的名字,同时也会显示视图的名字,而不存在单独显示试图的SHOW VIEWS命令。

同样,在使用SHOW TABLE STATUS命令的时候,不但可以显示表的信息,同时也可以显示视图的信息。

1.3.4 删除视图

语法:

DROP VIEW [IF EXISTS] view_name [, view_name] ...[RESTRICT | CASCADE]

示例:

DROP VIEW city_country_view;

1.4 存储过程和函数

1.4.1 存储过程和函数概述

存储过程和函数是事先经过编译并存储在数据库中的一-段SQL语句的集合,调用存储过程和函数可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是有好处的。

存储过程和函数的区别在于函数必须有返回值,而存储过程没有。

函数:是一个有返回值的过程;

过程:是一个没有返回值的函数;

1.4.2 创建存储过程

CREATE PROCEDURE procedure_name ([proc_parameter[,...]])
begin
	-- SQL语句
end;

DELIMITER
该关键字用来声明SQL语句的分隔符,告诉MySQL解释器,该段命令是否已经结束了,mysql是否可以执行了。默认情况下,delimiter是分号; 。在命令行客户端中,如果有一行命令以分号结束,那么回车后,mysql将会执行该命令。

1.4.3 调用存储过程

 call procedure_name();

1.4.4 查看存储过程

-- 查询db_name数据库中的所有的存储过程
select name from mysql.proc where db='db_name';

-- 查询存储过程的状态信息
show procedure status;

-- 查询某个存储过程的定义
show create procedure test.pro_test1 \G;

1.4.5 删除存储过程

DROP PROCEDURE [IF EXISTS] sp_name;

1.4.6 语法

① 变量

DECLARE
通过DECLARE可以定义一个局部变量,该变量的作用范围只能在BEGIN…END块中。
DECLARE var_name[,...] type [DEFAULT value]

示例:

CREATE PROCEDURE pro_test1()
begin 
	declare num int default 10;
	select concat('num的值为:',num);
end$

SET
直接赋值使用SET,可以赋常量或者赋表达式,具体语法如下:
SET var_name = expr [, var_name = expr] ...

示例:

CREATE PROCEDURE `pro_test2`()
begin
	declare num int default 0;
	set num=num+10;
	select num;
end$

也可以通过select…into方式进行赋值操作:
示例:

CREATE PROCEDURE `pro_test3`()
begin
declare num int;
select count(*) into num from city;
select concat('city表中的记录数为:',num);
end

select count(*) into num from city;
这个语句获取了city表中的记录数 通过select into方式赋值给了num

② if条件判断

语法结构:

if serch_condition then statement_list
	
	[elseif search_condition then statement_list]...
	
	[else statement_list]

end if;

需求:

根据定义的身高变量,判定当前身高的所属的身材类型
	180及以上 ----------> 身材高挑
	170-180     ----------> 标准身材
	170以下     ----------> 一般身材

示例:

CREATE PROCEDURE pro_test1()
begin
	declare height int default 175;
	declare description varchar(50) default '';
	if height >= 180 then
		set description = '身材高挑';
	elseif height >=170 and height <180 then
		set description = '标准身材';
	else
		set description = '一般身材';
	end if;
select concat('身高',height,'对应的身材类型为:','description');
end$
③ 传递参数

语法格式:

create procedure procedure_name([in/out/inout] 参数名 参数类型)
...

IN:   该参数可以作为输入,也就是需要调用方传入值,默认
OUT:  该参数作为输出,也就是改啊承诺书可以作为返回值
INOUT:既可以作为输入参数,也可以作为输出参数

IN-输入
需求:
根据传递的身高变量,判定当前身高的所属的身材类型

示例:

CREATE PROCEDURE pro_test2(IN height INT)
BEGIN
	DECLARE description VARCHAR(50) DEFAULT '';
	IF height >=180 THEN
		SET description = '身材高挑';
	ELSEIF height>=170 AND height<180 THEN
		SET description = '标准身材';
	ELSE
		SET description = '一般身材';
	END IF;
SELECT CONCAT('身高',height,'对应的身材类型为:',description);
END$

OUT-输出
需求:
根据传入的身高变量,获取当前身高的所属的身材类型(返回值)

示例:

CREATE PROCEDURE pro_test3(IN height INT,out description varchar(10))
BEGIN 
	IF height >=180 THEN
		SET description = '身材高挑';
	ELSEIF height>=170 AND height<180 THEN
		SET description = '标准身材';
	ELSE
		SET description = '一般身材';
	END IF;
END$

call pro_test3(188,@description)$

select @description$

小知识
@description:这种变量要在变量名称前面加上"@"符号,叫做用户会话变量,代表整个会话过程他都是有作用的,这个类似于全局变量一样。
关闭会话窗口就会释放所有用户会话变量

@@global.sort_buffer_size:这种在变量前加上"@@"符号,叫做系统变量

④ case结构

语法结构:

方式一:
CASE case_value
	WHEN when_value THEN statement_list
	[WHEN when_value THEN statement_list] ...
	[ELSE statement_list]
END CASE;

方式二:
CASE
	WHEN search_condition THEN statement_list
	[WHEN search_condition THEN statement_list] ...
	[ELSE statement_list]
END CASE;

需求:
给定一个月份,然后计算出所在的季度

CREATE PROCEDURE `pro_test4`(in month int,out description varchar(20))
begin
	case
	when month>=1 and month<=3 then
		set description='第一季度';
	when month>=4 and month<=6 then
		set description='第二季度';
	when month>=7 and month<=9 then
		set description='第三季度';
	when month>=10 and month<=12 then
		set description='第四季度';
	end case;
end
⑤ while循环

语法结构:

while search_condition do
	sataement_list
end while;

需求:
计算从1加到n的值

create procedure pro_test05(in n int)
begin
	declare result int default 0;
	declare i int default 0;
	while i<=n do
		set result = result + i;
		set i = i+1;
	end while;
	select result;
end$
⑥ repeat结构

有条件的循环控制语句,当满足条件的时候退出循环。while是满足条件才执行,repeat是满足条件就退出循环。
语法结构:

REPEAT
	statement_lit
	UNTIL search_condition
END REPEAT;

需求:
计算从1加到n的值

create procedure pro_test6(in n int)
begin
	declare result int default 0;
	declare i int default 0;
	repeat
		set result = result + i; 
		set i = i+1;
		until i>n             //注意 until后面没有分号
	END REPEAT;
	select result;
end$
⑦ loop语句

LOOP实现简单的循环,退出循环的条件需要使用其他的语句定义,通常可以使用LEAVE语句实现,具体语法如下:

[begin_label:] LOOP
	statement_list
END LOOP [end_label]

如果不在statement_list中增加退出循环的语句,那么LOOP语句可以用来实现简单的死循环。

⑧ leave语句

用来从标注的流程构造中退出,通常和BEGIN…END或者循环一起使用。下面是一个使用LOOP和LEAVE的简单例子,退出循环:

create procedure pro_test7(in n int)
begin
	declare result int default 0;
	c:loop
		set result = result + n;
		set n = n - 1;
		if n<=0 then
			leave c;
		end if;
	END loop c;
	select result;
end$
⑨ 游标/光标

游标是用来存储查询结果集的数据类型,在存储过程和函数中可以使用光标对结果集进行循环的处理。光标的使用包括光标的声明、OPEN、FETCH和CLOSE,其语法分别如下。

声明光标:DECLARE cursor_name CURSOR FOR select_statement;

OPEN光标:OPEN cursor_name;

FETCH光标:FETCH cursor_name INTO var_name [, var_name] ...

CLOSE光标:CLOSE cursor_name;

示例:
初始化脚本:

create table emp(
	id int(11) not null auto_increment ,
	name varchar(50) not null comment '姓名',
	age int(11) comment '年龄',
	salary int(11) comment '薪水',
	primary key('id')
)engine = innodb default charset=utf8;

insert into emp(id,name,age,salary) values(null,'Rarity',15,5000),(null,'Twilight',14,4500),(null,'FlutterShy',16,4000),(null,'Pinkie',15,4700);

查询emp表中数据,并逐行获取进行展示

create procedure pro_test8()
begin
	declare e_id int(11);
	declare e_name varchar(50);
	declare e_age int(11);
	declare e_salary int(11);
	declare emp_result cursor for select * from emp;
	
	open emp_result;
	
	fetch emp_result into e_id,e_name,e_age,e_salary;
	select concat('id=',e_id,',name=',e_name,',age=',age,',薪资为:',e_salary);
		fetch emp_result into e_id,e_name,e_age,e_salary;
	select concat('id=',e_id,',name=',e_name,',age=',age,',薪资为:',e_salary);
		fetch emp_result into e_id,e_name,e_age,e_salary;
	select concat('id=',e_id,',name=',e_name,',age=',age,',薪资为:',e_salary);
		fetch emp_result into e_id,e_name,e_age,e_salary;
	select concat('id=',e_id,',name=',e_name,',age=',age,',薪资为:',e_salary);
		fetch emp_result into e_id,e_name,e_age,e_salary;
	select concat('id=',e_id,',name=',e_name,',age=',age,',薪资为:',e_salary);
	
	
	close emp_result;
end$

通过多次fetch,可以取得表中数据,但这样的操作显然麻烦且不知道何时结束。
为此,我们使用循环改进

思路1:
获取表中记录数,从而建立循环
select count(*) into num from city;

create procedure pro_test9()
begin
	declare i int default 0;		//循环用的
	declare num int;            //表中记录数
	declare e_id int(11);
	declare e_name varchar(50);
	declare e_age int(11);
	declare e_salary int(11);
	declare emp_result cursor for select * from emp;
	select count(*) into num from emp;
	open emp_result;
	repeat
		set i = i+1;
		fetch emp_result into e_id,e_name,e_age,e_salary;
		select concat('id=',e_id , ', name=',e_name , ',age=',e_age , ', 薪资为:',e_salary);
		until i>=num
	end repeat;	
	close emp_result;
end$

思路2:
定义一个边界变量,通过控制边界变量来中止循环

create procedure pro_test10()
begin
	declare has_data int default 1;
	declare e_id int(11);
	declare e_name varchar(50);
	declare e_age int(11);
	declare e_salary int(11);
	declare emp_result cursor for select * from emp;
	DECLARE EXIT HANDLER FOR NOT FOUND set has_data=0;   //声明退出必须写在游标之后
	open emp_result;
	repeat
		fetch emp_result into e_id,e_name,e_age,e_salary;
		select concat('id=',e_id , ', name=',e_name , ',age=',e_age , ', 薪资为:',e_salary);
		until has_data=0
	end repeat;	
	close emp_result;
end$

1.4.7 存储函数

语法结构:

CREATE FUNCTION function_nam([param type ...])
RETURNS type
BEGIN
	...
END;

案例:
定义一个存储过程,请求满足条件的总记录数;

create function count_city(countryId int)
returns int
begin
	declare cnum int;
	
	select count(*) into cnum from city where country_id = countryId;

	return cnum;
end$

select count_city(1)$

删除:
drop function count_city;

1.5 触发器

1.5.1 介绍

触发器是与表有关的数据库对象,指在insert/update/delete之前或之后,触发并执行触发器中定义的SQL语句集合。触发器的这种特性可以协助应用在数据库端确保数据的完整性,日志记录,数据校验等操作。
使用别名 OLD 和 NEW 来引用触发器中发生变化的记录内容,这与其他的数据库是相似的。现在触发器还只支持行级触发,不支持语句级触发。

触发器类型NEW和OLD的使用
INSERT型触发器NEW表示将要或者已经新增的数据
UPDATE型触发器OLD表示修改之前的数据,NEW表示将要或已经修改后的数据
DELETE型触发器OLD表示将要或者已经删除的数据

1.5.2 创建触发器

语法结构:

create trigger trigger_name
before/after insert/update/delete
on tbl_name
[ for each row]    -- 行级触发器
begin
	trigger_stmt;
end;

示例:

需求: 通过触发器记录emp表的数据变更日志,包含增加,修改,删除;

首先创建一张日志表:

create table emp_logs(
	id int(11) not null auto_increment,
	operation varchar(20) not null comment '操作类型, inset/update/delete',
	operate_time datetime not null comment '操作时间',
	operate_id int(11) not null comment '操作表的ID',
	operate_params varchar(500) comment '操作参数',
	primary key(`id`)
)engine=innodb default charset=utf8;
create trigger emp_insert
after insert
on emp
for each row
begin
	insert into emp_logs(id,operation,operate_time,operate_id,operate_params) values(null,'insert',now(),new.id,concat('插入后(id:',new.id,', name:',new.name,', age:',new.age,', salary:',new.salary,'('));
end$
create trigger emp_update
after update
on emp
for each row
begin
	insert into emp_logs(id,operation,operate_time,operate_id,operate_params) values(null,'update',now(),new.id,concat( '更新前(id: ' , old.id , ', name: ' , old.name , ', age: ' , old.age,', salary: ', old.salary , ') 更新后( id: ',new.id,', name: ', new.name,', age: ',new.age,', salary: ',new.salary ,')'));
end$

1.5.3 删除触发器

语法结构
drop trigger [schema_name.]trigger_name
如果没有指定 schema_name,默认当前数据库

1.5.4 查看触发器

show triggers;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: mysql interval 1 day 表示MySQL中的时间间隔函数,表示间隔1天。在MySQL中,可以使用interval函数来进行时间间隔的计算,例如interval 1 day表示间隔1天,interval 1 hour表示间隔1小时,interval 1 minute表示间隔1分钟,interval 1 second表示间隔1秒钟。这个函数可以用于日期时间的加减运算,例如可以计算出某个日期加上1天后的日期。 ### 回答2: mysql interval 1 day是MySQL数据库中的一个时间函数,表示在日期或时间中添加1天的时间间隔。它可以在查询中用来计算日期或者时间的差异,或在WHERE子句中过滤出指定时间段内的数据。 mysql interval 1 day函数可以用于日期或时间类型的字段,比如DATETIME、DATE、TIMESTAMP等。它的语法如下: SELECT * FROM table_name WHERE date_field >= DATE_ADD(NOW(), INTERVAL 1 DAY) 以上语法意思是,查询table_name表中日期字段date_field大于等于当前时间(NOW())加上1天(INTERVAL 1 DAY)的所有记录。 除此之外,mysql interval函数还支持其他的时间单位,例如:YEAR、MONTH、HOUR、MINUTE、SECOND等。它们可以用来计算时间差值,例如: SELECT DATEDIFF('2022-12-31', '2022-11-01') 以上语句用于计算2022年12月31日和2022年11月01日之间相差的天数(即两个日期之间的时间间隔)。 总的来说,mysql interval 1 day函数非常方便实用,可用于各种应用场景中,如日常的数据处理、数据统计、时间计算等等。 ### 回答3: MySQL中的interval指定时间间隔的语法是interval [value] [unit],其中value表示时间间隔的数值,unit表示时间间隔的单位,比如day表示天,hour表示小时,minute表示分钟,以此类推。 当使用interval 1 day时,表示时间间隔为1天。在MySQL中,可以将interval应用于一些查询中,例如SELECT语句,用于计算日期或时间的增量或减量。具体来说,使用interval 1 day可以在日期上加上1天,也可以在日期上减去1天。比如: SELECT NOW() + INTERVAL 1 DAY; // 现在时间加1天 SELECT CURDATE() - INTERVAL 1 DAY; // 今天日期减1天 此外,在MySQL中还有其他常用的interval用法,例如: - interval 1 minute :表示时间间隔为1分钟 - interval 1 week :表示时间间隔为1周 - interval -1 month :表示时间间隔为-1个月(即往前推1个月) - interval 2 hour 30 minute :表示时间间隔为2小时30分钟 总之,interval在MySQL中是常用的一个时间间隔单位,通过合理运用interval,可以更加灵活地处理时间和日期相关的操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值