MySql学习笔记

一、SQL:

1、什么是SQL:

SQL,全称 Structured Query Language,是一种结构化查询语言,数据库访问语言。自1970年代诞生到现在。

2、SQL的功能:

SQL 可用于在数据库中增加,删除,修改,查询数据;
SQL 可用于新建数据库,新建数据表;
SQL 可用于新建视图,函数;
SQL 可用于简单的数据清洗;
SQL 可用于简单的数据分析;
SQL 可搭配 Hive,Spark SQL 做大数据;
SQL 可搭配 SQLFlow 做机器学习;
SQL 可搭配一定的工具做数据报表。

3、RDBMS:

RDBMS,全称relational database management system(关系数据库管理系统),是一种数据库软件,但我们经常狭义地称呼它为数据库。RDBMS将数据及数据关系以数据库和数据表的形式存储,并提供 SQL 访问接口。

目前主流 RDBMS 有 MySQL、PostgreSQL、SQL Server 和 Oracle;其中MySQL和PostgreSQL是免费开源且使用广泛的数据库。

4、SQL的分类:

 DML(Data Manipulation Language)数据操纵语言,负责数据访问和数据操作

如:insert,delete,update,select(插入、删除、修改、检索)简称CRUD操新增Create、查询Retrieve、修改Update、删除Delete

 DDL(Data Definition Language)数据库定义语言,负责数据库结构定义和数据库对象定义

如:create table之类

 DCL(Data Control Language)数据库控制语言

如:grant、deny、revoke等,只有管理员才有相应的权限

 DQL(Data Query Language) 数据查询语言:

是由SELECT子句,FROM子句,WHERE子句组成的查询块:

 SELECT <字段名表>

 FROM <表或视图名>

 WHERE <查询条件>

二、Mysql:

1、数据库:

数据库是一个长期存储在计算机内的、有组织的、有共享的、统一管理的数据集合。是按照数据结构来组织、存储和管理数据的仓库。目前常用的数据库主要分为开源 MySQL 数据库(包括官方版 MySQL、Percona MySQL MariDB)和商业版数据库 ( 包括 SQL Server、Oracle、DB2 )。

2、数据库的分类:

(1)关系型数据(SQL)
关系型数据库,是指采用了关系模型来组织数据的数据库,从语言功能层面来讲,一般是指用 SQL 语言来进行操作管理的关系型数据库。常用的关系型数据库有 MySQL、Oracle、SQLServer、PostGreSQL。

(2)非关系型数据库(NoSQL)
NoSQL 通常指的是 non-relational ,也可以理解为 Not Only SQL,泛指非关系型数据库。常见的非关系型数据库有 MongDB、HBase、Redis。

(3)新型数据库(NewSQL)
NewSQL 是对各种新的可扩展/高性能数据库的简称,这类数据库不仅具有 NoSQL 对海量数据的存储管理能力,还保持了传统数据库支持 ACID 和 SQL 等特性。常见的 NewSQL 有 Google Spanner/F1、阿里 OceanBase、腾讯 TDSQL、TiDB、Cockroach。

3、关系型数据库:

顾名思义,关系型数据库就是一种建立在关系模型的基础上的数据库。关系模型表明了数据库中所存储的数据之间的联系(一对一、一对多、多对多)。

关系型数据库中,我们的数据都被存放在了各种表中(比如用户表),表中的每一列就存放着一条数据(比如一个用户的信息)。

4、mysql数据库:

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一。
MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。
MySQL所使用的 SQL 语言是用于访问数据库的最常用标准化语言。MySQL 软件采用了双授权政策,分为社区版和商业版,由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,一般中小型网站的开发都选择 MySQL 作为网站数据库。

三、数据库的相关操作:

建库:

create database dbname DEFAULT CHARACTER SET utf8;

删库:

drop database dbname;

查看所有数据库:

show databases;

use 命令选中数据库:


use item_name;

四、数据表:

1、设计数据表:

数据表命名是小写字母和下划线_组成,用来分割不同单词之间的含义,例如 “student_course” 表示学生选课关联表,实际命名需要根据具体功能而定,好的命名规范在实际工作中也是很重要的。

(1)确定字段:

字段名称含义
id自增主键
name学生姓名
age学生年龄
id_number身份证号

(2)确定数据类型:

字段名称数据类型
id无符号整型(UNSIGNED INT)
nameVARCHAR(50)
ageUNSIGNED INT
id_numberVARCHAR(18)

(3)新建数据表:

create table student(
id int primary key auto_increment,
name varchar(50) not null,
age int not null,
id_number varchar(20)); 

2、数据表的相关操作:

(1)创建表:

      创建tb_door表,有id,door_name,tel字段

create table tb_door(
id int primary key auto_increment,
door_name varchar(100),
tel varchar(50)
);

(2)修改表:

 添加字段:

alter table student add grade int not null;

修改表名:

alter table student rename new_student;

(3)删:

删除表:

drop table new_student;

删除字段:

alter table student drop grade;

(4)查看表结构:

desc student;

六、字段的相关操作:

1、插入:

(1)插入数据:

INSERT INTO student (name,age,id_number) VALUES ('秦小贤',18,'42011720200604088X');

(2)查询数据:

select * from student;

*表示通配符,可以换成任何字段:

select name,age,id_number from student;

使用*查询的效率较低。

(3)一次性插入多条数据:

INSERT INTO student (name,age,id_number) VALUES ('王小虎',21,'530401198704022145'),('张敏',16,'52012419991105536X'),('李雪',22,'32040519950324890X');

2、删除:

(1)删除一条数据:

delete from student where id = 4;

(2)删除所有数据:

delete from student;

3、修改:

(1)修改一条数据:

update student set age = 22 where name = '王小虎';

(2)修改多条数据:

#修改前三条数据:
update student set age = 24 limit 3;

七、数据类型:

1、整型:

类型大小SIGNED(有符号)UNSIGNED(无符号)说明
tinyint1字节-128~1270~255小整型
smallint2字节-32768~327670~65535小整型
mediumint3字节-8388608~83886070~16777215中整型
int4字节-2147483648~21474836470~49294967295整型
bigint8字节-9223372036854775808
~
9223372036854775807
0~18446744073709551615大整型

mysql没有boolean类型的数据,一般用tinyint(1)来表示boolean;

2、浮点型:

类型大小SIGNED(有符号)UNSIGNED(无符号)说明
float4字节-3.402823466E+38 ~ -1.175494351E-38,
0,
1.175494351E-38 ~ 3.402823466351E+38
0,1.175494351E-38 ~ 3.402 823 466 E+38单精度浮点型
double8字节-1.7976931348623157E+308 ~ -2.2250738585072014E-308,
0,
2.2250738585072014E-308 ~ 1.7976931348623157E+308
0,
2.2250738585072014E-308 ~ 1.797693134862315 7E+308
双精度浮点型
decimal每4个字节存储9个数字,小数点占1字节DECIMAL(M,D),取决于M和D,M是整数部分,D是小数部分DECIMAL(M,D),取决于M和D,M是整数部分,D是小数部分精确类型,常用来表示金额

3、日期和时间:

类型大小格式范围
date3字节YYYY-MM-DD1000-01-01 ~ 9999-12-31
time3-6字节HH::MM:SS[.微秒]-838:59:59 ~ 838:59:59
year1字节YYYY1901 ~ 2155
datetime5-8字节YYYY-MM-DD HH:MM:SS[.微秒值]1000-01-01 00:00:00 ~ 9999-12-31 23:59:59 UTC
timestamp4-7字节YYYY-MM-DD HH:MM:SS[.微秒值]1970-01-01 00:00:00 ~ 2038-01-19 03:14:07 UTC

4、字符串:

类型范围说明
char1~255个字节固定长度
varchar字段存储所占字节数不能超过65535字节可变长度
tinytext最大长度255字节可变长度
text最大长度65535个字节可变长度
mediumtext最大长度16777215个字节可变长度
longtext最大长度4294967295个字节可变长度

5、枚举:

类型范围说明
enum几何数最大65535

枚举值类型,只能插入列表中指定的值

6、二进制:

类型范围说明
tinyblob最大长度255字节可变长度
blob最大长度65535个字节可变长度
mediumblob最大长度16777215个字节可变长度
longblob最大长度4294967295个字节可变长度

八、约束:

1、非空约束 not null:数据不能为空。
2、唯一约束 unique:数据不能重复。
3、主键约束 primary key:主键是一条记录的唯一标识,具有唯一性,不能重复。
4、外键约束 froeign key:是能确认另一张表记录的字段,用于保持数据的一致性。 比如,A表中的一个字段,是B表的主键,那它就可以是A表的外键。
5、默认约束 default:为字段提供默认值。
6、检查约束 check:为字段的赋值提供判断功能。

一个综合的案例:

create table test_tb(
id int primary key auto_increment,
id_number varchar(20) not null unique,
name varchar(18) not null,
age int not null default 0,
CHECK(age >= 0 and age<=200));

create table test_forgrein(
user_id int primary key not null,
address varchar(50),
FOREIGN KEY(user_id) REFERENCES test_tb(id));

九、函数:

1、基本函数:

(1)lower(字段名):数据转小写。
upper(字段名):数据转大写。
length(字段名):字段长度。
substr(字段名,a,b):截取子串,从a开始到b结束。
concat(字段名,"字符串"):将字符串拼接到字段后。
replace(字段名,"a","b"):将字段中的a替换成b。
ifnull(字段名,a):如果字段为空,则将其替换为a。
round(字段名,保留小数位数) & ceil(字段名,保留小数位数) & floor(字段名,保留小数位数):四舍五入、向上取整、向下取整。
uuid:返回UUID。
now:

select now() -- 年与日 时分秒

select curdate() --年与日

select curtime() --时分秒
year & month & day:

--hour()时  minute()分 second()秒

select now(),hour(now()),minute(now()),second(now()) from emp ;

--year()年 month()月 day()日

select now(),year(now()),month(now()),day(now()) from emp ;
转义字符:用\将'转换为普通字符。

2、聚合函数:

1、count
select count(*) from emp --底层优化了
select count(1) from emp --效果和*一样
select count(comm) from emp  --慢,只统计非NULL的

2、max / min
select max(sal) from emp --求字段的最大值
select max(sal) sal,max(comm) comm from emp 
select min(sal) min from emp --获取最小值
select min(sal) min,max(sal) max  from emp --最小值最大值
SELECT ename,MAX(sal) FROM emp group by ename --分组

3、sum / avg 平均值
select count(*) from emp --总记录数
select sum(sal) from emp --求和
select avg(sal) from emp --平均数

十、条件查询和分组:

1、条件查询:

1、distinct
使用distinct关键字,去除重复的记录行
SELECT loc FROM dept;
SELECT DISTINCT loc FROM dept;

2、where
注意:where中不能使用列别名,不能使用聚合函数。
select * from emp
select * from emp where 1=1 --类似没条件
select * from emp where 1=0 --条件不成立
select * from emp where empno=100 --唯一条件
select * from emp where ename='tony'  and deptno=2 --相当于两个条件的&关系
select * from emp where ename='tony'  or deptno=1 --相当于两个条件的|关系
select name, sal from emp where sal=1400 or sal=1600 or sal=1800;
-- 或
select name, sal from emp where sal in(1400,1600,1800);
select name, sal from emp where sal not in(1400,1600,1800);

3、like
通配符%代表0到n个字符,通配符下划线_代表1个字符
select * from emp where ename like 'l%' --以l开头的
select * from emp where ename like '%a' --以a结束的
select * from emp where ename like '%a%' --中间包含a的
select * from emp where ename like 'l__'  --l后面有两个字符的 _代表一个字符位置

4、null
select * from emp where mgr is null --过滤字段值为空的
select * from emp where mgr is not null --过滤字段值不为空的

5、between and
SELECT * FROM emp
select * from emp where sal>3000 and sal<10000
select * from emp where sal>=3000 and sal<=10000--等效
select * from emp where sal between 3000 and  10000--等效

6、limit
分数最高的记录:按分数排序后,limit n,返回前n条。Oracle做的很笨,实现繁琐,后期有介绍,而mysql做的很棒,语法简洁高效。在mysql中,通过limit进行分页查询:
select * from emp limit 2 --列出前两条
select * from emp limit 1,2 --从第二条开始,展示2条记录
select * from emp limit 0,3 --从第一条开始,展示3条记录--前三条

7、order by
SELECT * FROM emp order by sal #默认升序
SELECT * FROM emp order by sal desc #降序

2、分组:

将查询的结果进行分组统计,group by表示如何分组,having表示过滤的条件。

(1)group by:

select count(user_level),user_level from user group by user_level;

注意:

->查询有聚合函数和普通的字段时,普通字段要作为分组的对象。

(2)having:

select count(user_level),user_level from user group by user_level
having count(user_level) >2;

十一、事务:

1、何为事务:

事务是一组原子性的SQL查询,事务内的SQL语句,要么全部执行成功,要么全部执行失败。即任何一条语句失败,都必须回滚所有的步骤。

2、事务的特点:

关系型数据库都有ACID的特性:即原子性(atomicity)、一致性(consistency)、隔离性(isolation)、持久性(durability)。

原子性(atomicity):一个事务被视为一个完整的最小工作单元,事务中的数据库操作,要么全部执行成功,要么全部执行失败回滚,不能只成功执行了其中的一部分数据库操作;

一致性(consistency):数据库总是从一个一致性的状态转换到另一个一致性的状态。在银行转账的例子中,即使执行到第四条 SQL 语句时失败,用户的支票账户也不会损失 100 元人民币,因为执行失败时,事务进行了回滚,所做的修改并没有保存到数据库中;

隔离性(isolation):通常来说,一个事物所做的修改在提交以前,对其他事务是不可见的。在银行转账的例子中,当执行完第三条 SQL 语句时,此时另外一个程序在汇总支票账户,它所查询到的用户A的支票账户,并没有减去 100 元人民币;

持久性(durability):事务提交成功,所做的修改就会永久保存到数据库中,即使系统崩溃,修改的数据也不会丢失。

在 MySQL 中,事务是在存储引擎层实现的。MySQL 是支持多种存储引擎的数据库,但并不是所有的存储引擎都支持事务,比如 MyISAM 就不支持事务。

事务增加了数据库的安全性,同时也需要数据库做很多额外的工作。相比没有实现 ACID 的数据库,实现了 ACID 的数据库需要更强的 CPU、内存、以及磁盘空间。

3、隔离级别:

在 SQL 标准中,包含了四种隔离级别,即未提交读(read uncommitted)、提交读(read committed)、可重复读(repeatable read)、可串行化(serializable)。

未提交读(read uncommitted):一个事务还未提交,它所做的变更能被别的事务看到。事务可以读取未提交的数据,被称为脏读(dirty read),这种隔离级别在实际应用中一般很少使用;

提交读(read committed):一个事务提交之后,它所做的变更才能被别的事务看到。大多数数据库的默认隔离级别是提交读(read committed),比如 Oracle;

可重复读(repeatable read):一个事务在执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。在可重复读隔离级别下,未提交变更对其他事务也是不可见的。该级别保证了在同一个事务中,多次读取同样记录的结果是一致的。MySQL 的默认事务隔离级别是可重复读(repeatable read);

可串行化(serializable):serializable 是最高的隔离级别。对同一行数据,读写都会进行加锁。当出现锁冲突时,后面访问的事务必须等前一个事务完成,才能继续执行。实际应用场景很少用到这种隔离级别,只有在非常需要确保数据一致性,而且可以接受没有并发的情况,才会使用这种隔离级别。

隔离级别脏读可能性不可重复度可能性幻读可能性加锁读
未提交读(read uncommitted)yesyesyesno
提交读(read committed)noyesyesno
可重复读(repeatable read)nonoyesno
可串行化(serializable)nononoyes

4、脏读、幻读、修改丢失、不可重复读:

脏读:当一个事务正在对一个数据进行操作,但是操作的结果还没有写入到数据库中时,另一个事务来读取这个数据,所进行的操作的结果很可能是不正确的。

幻读:假设有事务A,B 和数据X,当A顺序读取X,Y,Z后,B在数据库中插入新的数据N,M,而后A第二次读取,发现多了几条数据。

修改丢失:假设有事务A,B 和数据X,Y,Z,当A读取X时,B也读取X,然后A对X进行写入,随后B对X进行写入。如此A写入的数据就被覆盖(丢失)了。

不可重复读:假设有事务A,B 和数据X,A读取X后,B对X进行修改,此时A再次读取X,会出现前后X的值不同的情况。即同一个事务两次读取一个数据的结果不同。

5、Mysql事务的特点:

(1)自动提交:

如果不是显式地开始一个事务,每个查询都会被当做一个事务执行 commit。

(2)隔离级别调整:

默认情况下,MySQL 的隔离级别是可重复读(repeatable read)。MySQL 可以通过 set transaction_isolation 命令来调整隔离级别,新的隔离级别会在下一个事务开始时生效。

6、事务处理:

#多条语句时,批量执行,事务提交
#有了事务,多步操作就形成了原子性操作,高并发下也不会引起数据错乱
#mysql的事务默认就是开启的  -- 多条语句一起操作时,要么一起成功要么一起失败
BEGIN; #关闭事务的自动提交
INSERT INTO user (id) VALUES(25);#成功
INSERT INTO user (id) VALUES(5);#已经存在5了,会失败
COMMIT; #手动提交事务


回滚 rollback
#多条语句,批量执行,insert插入重复的主键导致失败时,事务回滚
BEGIN;
INSERT INTO user (id) VALUES(15);
INSERT INTO user (id) VALUES(35);#存在了
ROLLBACK;#事务回滚,就不会再提交了

十二、多表联查:

多表查询是指基于两个和两个以上的表的查询。

1、笛卡尔积:

#把两个表的数据都拼接起来
SELECT * FROM dept,emp

2、内连接:inner join,只有数据存在时才能发送连接。即连接结果不能出现空行。

select stu.sname,stu.sbirthday,s.degree from students stu inner join scores s on s.sno = stu.sno where s.degree > 70;

3、外连接:left join,如果数据不存在,左表记录会出现,而右表为null填充。right join,如果数据不存在,右表记录会出现,而左表为null填充.

十三、索引:

1、什么是索引:

MySQL 索引的工作原理,类似一本书的目录,如果要在一本书中找到特定的知识点,先通过目录找到对应的页码。

2、索引的优缺点:

总的来说,索引三个优点如下:

索引可以大大减少 MySQL 需要扫描的数据量;
索引可以帮助 MySQL 避免排序和临时表;
索引可以将随机 IO 变为顺序 IO。

缺点:
对于非常小的表,大多数情况,全表扫描会更高效;
对于中大型表,索引就非常有效;
对于特大型表,建索引和用索引的代价是日益增长,这时候可能需要和其他技术结合起来,如分区表。

3、索引的实现:

一般使用B树,B+树或哈希表来实现。

4、索引的分类:

1、主键索引:

数据表的主键列使用的就是主键索引。

一张数据表有只能有一个主键,并且主键不能为 null,不能重复。

2、辅助索引:

单值索引:一个索引只包括一个列,一个表可以有多个列
唯一索引:索引列的值必须唯一,但允许有空值;主键会自动创建唯一索引
复合索引:一个索引同时包括多列

5、索引的实现:

#查看索引
show index from students;
#新建单值索引
create index sname_index on students(sname);
alter table students add index (sname);
#删除索引
alter table students drop index sname;
#新建唯一索引:
alter table students add unique (sname);
#创建复合索引
alter table students add index idx_name_birth (sname,sbirthday);
#创建复合唯一索引:
alter table students add unique uni_idx (sname,sbirthday);

十四、Mysql存储引擎:

MySQL 的存储引擎是插件式的,用户可以根据实际的应用场景,选择最佳的存储引擎。MySQL默认支持多种存储引擎,以适应不同的应用需求。

使用 show engines; 来查看Mysql支持的存储引擎。

和存储引擎相关的命令:

mysql> show variables like '%storage_engine%'; #查看默认引擎。

show table status like "table_name" ;#查看表的存储引擎。

从上图可以看出,Mysql默认使用的存储引擎是InnoDB,是最重要、使用最广泛的存储引擎。InnoDB 具有提交、回滚、自动崩溃恢复的事务安全保障,拥有独立的缓存和日志,提供行级别的锁粒度和强大的并发能力。在大多数使用场景中,包括事务型和非事务型存储需求,InnoDB 都是更好的选择,除非有非常特别的原因需要使用其他存储引擎。

InnoDB具有以下特点:

(1)自动增长列:

InnoDB 表的自动增长列,插入的值可以为空,也可以人工插入,如果插入的值为空,则实际插入的值是自动增长后的值。

create table test_tb(
id int primary key auto_increment,
id_number varchar(20) not null unique,
name varchar(18) not null,
age int not null default 0,
CHECK(age >= 0 and age<=200));

create table test_forgrein(
user_id int primary key not null,
address varchar(50),
FOREIGN KEY(user_id) REFERENCES test_tb(id));

当id为自动增长时,如果插入为null,则实际插入的数据是自动增长后得到的值。InnoDB中,自增长列必须是索引,同时必须是索引的第一个列 。如果不是第一个列,数据库会报出异常!

(2)主键和索引

InnoDB 表是基于聚簇索引建立的,聚簇索引也叫主索引,也是表的主键,InnoDB 表的每行数据都保存在主索引的叶子节点上。InnoDB 表必须包含主键,如果创建表时,没有显式指定主键,InnoDB 会自动创建一个长度为 6 个字节的 long 类型隐藏字段作为主键。所有的 InnoDB 表都应该显式指定主键。

InnoDB 表中,除主键之外的索引,叫做二级索引。二级索引必须包含主键列,如果主键列很大的话,其他的所有索引都会很大。因此,主键是否设计合理,对所有的索引都会产生影响。

一般来说,主键的设计原则大致如下:

满足唯一和非空约束;
主键字段应尽可能地小;
主键字段值基本不会被修改;
优先考虑自增字段,或查询最频繁的字段。

十五、SQL优化:

原则:

1、减少数据访问: 设置合理的字段类型,启用压缩,通过索引访问等减少磁盘IO
2、返回更少的数据: 只返回需要的字段和数据分页处理 减少磁盘io及网络io
3、减少交互次数: 批量DML操作,函数存储等减少数据连接次数
4、减少服务器CPU开销: 尽量减少数据库排序操作以及全表查询,减少cpu 内存占用
5、利用更多资源: 使用表分区,可以增加并行操作,更大限度利用cpu资源

总结到SQL优化中,就三点:

  • 最大化利用索引;
  • 尽可能避免全表扫描;
  • 减少无效数据的查询;

优化手段:

1. 尽量避免在字段开头模糊查询,会导致数据库引擎放弃索引进行全表扫描。

即避免:

select id,user_name from user_tb where user_name like "%陈%" 

而应当:

select id,user_name from user_tb where user_name like "陈%" 

2、不要在where子句中使用or来连接条件,or可能会导致索引失效,应当用UNION或UNION ALL:

即避免:

SELECT * FROM student WHERE id=1 OR salary=30000

而应当:

SELECT * FROM student WHERE id=1 
UNION ALL
SELECT * FROM student WHERE salary=30000

3、避免使用in或not in,同样会导致索引失效,数值可以使用between and,子查询可以用exist代替:

即避免:

SELECT * FROM student WHERE ID IN (1,2,3);

而应当:

SELECT * FROM student where id BETWEEN 1 AND 3;

避免:

SELECT * FROM student WHERE id IN (SELECT id FROM Sid);

而应当:

SELECT * FROM student EXIST (SELECT id FROM Score WHERE Score.id=student.id);

4、避免null值判断,应当给属性赋初值,如:0;

5、查询尽量避免返回大量数据,应当使用分页;

6、字符串怪现象:不加单引号时,是字符串跟数字的比较,它们类型不匹配,MySQL会做隐式的类型转换,把它们转换为数值类型再做比较

反例:

#未使用索引

EXPLAIN

SELECT * FROM student WHERE NAME=123

正例:

#使用索引

EXPLAIN

SELECT * FROM student WHERE NAME='123'

7、查询条件不能用 <> 或者 !=;

8、order by 条件要与where中条件一致,否则order by不会利用索引进行排序;

9、避免在where中对字段进行表达式操作;

即避免:

select * from student where id+1-1=1;

而应当:

select * from student where id = 1+1-1;

10、distinct过滤的字段要少:过滤字段会消耗大量的计算机资源;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值