软件:mysql、Navicat for MySQL
一开始不想写mysql的安装步骤,但是第二次安装还是出现了问题....无奈
版本:mysql-8.0.16-winx64
解压后发现没有my.ini 文件和data文件夹。
第一步:生成data文件夹
//cd到mysql的bin文件下
C:\WINDOWS\system32>d:
D:\>cd D:\Program Files\mysql_winx64\bin
//输入如下代码
D:\Program Files\mysql_winx64\bin>mysqld --initialize-insecure --user=mysql
第二步:编写my.ini
[client]
port = 3308
default-character-set = UTF8MB4
[mysqld]
port = 3308
character-set-server = UTF8MB4
basedir=D:\Program Files\mysql_winx64 //改成自己的安装路径
datadir=D:\Program Files\mysql_winx64\data 改成自己的安装路径
group_concat_max_len=20000
[WinMySQLAdmin]
D:\Program Files\mysql_winx64\bin\mysqld.exe //改成自己的安装路径
第三步:
添加系统变量, 在path 添加
D:\Program Files\mysql_winx64\bin
利用文本文档打开 D:\Program Files\mysql_winx64\data路径下的后缀为.err的文件,查看root@localhost 用户后面的password.
cmd中输入
--服务开启
net start mysql;
--进入root账号
mysql -u root -p
--更改密码
set password = '123456';
--设置新用户
create user 'lv'@'localhost' identified by '123456';
就可以开心的玩耍了...
1. mysql服务端架构
a)最外层:数据库管理系统(DBMS);最大单元
b)第二层:数据库(DB);
c)第三层:二维数据表table;
d)第四层:字段field,具体存储某种类型的数据;
关键字:
row 行
column 列 field
2. 操作:从外到内---> 最外层-->第二层-->第三层-->第四层;
3. 数据库操作(第二层)
1)创建数据库
基本语法: create database 数据库名字 [库选项];
create database mydatabase;
库选项:数据库的相关属性
字符集:charset 字符集,代表着当前数据库下的所有表存储的数据默认指定的字符集(如果当前不指定,那么采用DBMS默认的)
校对集:collate 校对集
Create database 数据库名字 charset 字符集名称;
create database mydatabase2 charset gbk;
2)显示数据库
基本语法:show databases like ‘匹配模式’;
_:匹配当前位置单个字符
%:匹配指定位置多个字符
获取以my开头的全部数据库: ‘my%’;
show databases like 'my%';
获取m开头,后面第一个字母不确定,最后为database的数据库;’m_database’;
show databases like 'm_database1';
获取以database结尾的数据库:’%database’;
show databases like '%database';
显示创建数据库:
show create database mydatabase1;
3)选择数据库
为什么要选择数据库?因为数据是存储到数据表,表存在数据库下。如果要操作数据,那么必须进入到对应的数据库才行。
use 数据库名字;
use mydatabase1;
4)修改数据库
修改数据库字符集(库选项):字符集和校对集
基本语法:alter database 数据库名字 charset 字符集;
alter database mydatabase1 charset gbk;
5)删除数据库
drop database 数据库名字;
4.数据表操作(第三层)
1)创建数据表
基本语法:create table 表名(字段名 字段类型 [字段属性], 字段名 字段类型 [字段属性],…) [表选项]
有两种方式可以将表挂入到指定的数据库下:
a)在数据表名字前面加上数据库名字,用“.”连接即可:数据库.数据表;
create table mydatabase1.class(
name varchar(10)
)charset utf8;
b)use 数据库名
use mydatabase1;
2)显示表
show tables;
3)显示表结构
显示表包含的字段信息(名字,类型,属性)
describe 表名;
Desc 表名;
show columns from 表名;
describe class;
desc class;
show column from class;以上三个语句 显示内容相同
4)显示表的创建语句
show create table 表名;
5)设置表属性
表属性指的就是表选项:engine,charset和collate
基本语法:alter table 表名 表选项 [=] 值;
alter table class charset utf8;
6)修改表的结构
修改表名:rename table 旧表名 to 新表名
修改表选项:alter table 表名 表选项 [=] 新值
7)删除表结构
基础语法:drop table 表名[,表名2…],可以同时删除多个数据表
drop table class;
5.字段操作(第四层)
1)新增字段
alter table 表名 add [column] 新字段名 列类型 [列属性] [位置first/after 字段名]
字段位置:字段想要存放的位置
First:在某某之前(最前面),第一个字段
After 字段名:放在某个具体的字段之后(默认的)
alter table student add column age int;
alter table student add id int first; --放在第一个位置
2)修改字段
alter table 表名 change 旧字段名 新字段名 字段类型 [列属性] [新位置]
修改字段类型(属性):alter table 表名 modify 字段名 新类型 [新属性] [新位置]
alter table my_student change age nj int;
3)删除字段
删除字段:alter table 表名 drop 字段名
alter tables my_student drop nj;
6.数据操作基础
1)插入操作
基本语法:向表中指定字段插入数据
Insert into 表名[(字段列表)] values(对应字段列表)
insert into my_student (id,name) values (1,'jack');
insert into my_student (name) values ('Tom');
insert into my_student values (3,'San');
2)查询操作
查询表中全部数据:select * from 表名; //*表示匹配所有的字段
select *from my_student;
查询表中部分字段:select 字段列表 from 表名; //字段列表使用逗号“,”隔开
select name from my_student;
简单条件查询数据:select 字段列表/* from 表名 where 字段名 = 值; //mysql中没有==符号
select name from my_student where name = 'jack';
3)删除操作
基本语法:delete from 表名 [where 条件]; //如果没有where条件:意味着系统会自动删除该表所有数据(慎用)
delete from my_student where name = 'Tom';
4)更新操作
基本语法:update 表名 set 字段名 = 新值 [where 条件];//如果没有where条件,那么所有的表中对应的那个字段都会被修改成统一值。
update my_student set id = 2 where name ='San';
7.主键:用途???
1)创建主键
方案1:直接在需要当做主键的字段之后,增加primary key属性来确定主键
方案2:在所有字段之后增加primary key选项:primary key(字段信息)
create table my_pri1(
usename varchar(10)
primary key(username)
)charset utf8;
alter table my_student add primary key(name);
2)删除主键
基本语法:alter table 表名 drop primary key;
alter table my_student drop primary key;
3)主键约束
当前字段对应的数据不能为空;
当前字段对应的数据不能有任何重复;
4)自动增长
auto_increment
5)唯一键
创建唯一键:
直接在表字段之后增加唯一键标识符:unique[ key]
create table my_unique(id int primary key auto_increment,
username varchar(10) unique)charset utf8;
所有字段使用unique key 字段
create table my_unique(id int primary key auto_increment,
username varchar(10),
unique key(username))charset utf8;
唯一键效果:仅在不为空的情况下,不允许重复
删除唯一键:
删除的基本语法:alter table 表名 drop index 唯一键名字;
alter table my_unique drop index username;
8.表关系(表与表之间的关系)
1)一对一
一对一:一张表中的一条记录与另外一张表中最多有一条明确的关系;
2)一对多
一个母亲有几个孩子,一个孩子对应一个母亲;
通常也叫作多对一的关系。通常一对多的关系设计的方案,在“多”关系的表中去维护一个字段,
这个字段是“一”关系的主键。
3)多对多
一张表中的一条记录在另外一张表中可以匹配到多条记录,反过来也一样。通过第三张表维护。
一对多+中间表+多对一 -->多对多
9.高级操作
1)插入操作
create table student(
id varchar(10) primary key comment '主键,学生ID',
name varchar(10) not null comment '学生姓名'
)charset utf8;
insert into student values('0001','张三'),('0002','李四'),('0003','王五'),('0004','张六');
insert into student values('0004','王婷');--冲突
主键冲突解决:
a)类似插入数据语法,如果插入的过程中主键冲突,那么采用更新方法。(修改)
Insert into 表名 [(字段列表)] values(值列表) on duplicate key update 字段 = 新值;
insert into student values('0004','王婷') on duplicate key update name ='王婷';
b)当主键冲突之后,干掉原来的数据,重新插入进去。
Replace into [(字段列表)] values(值列表);
2)蠕虫复制
蠕虫复制:一分为二,成倍的增加。从已有的数据中获取数据,并且将获取到的数据插入到数据表中。
基本语法:
Insert into 表名 [(字段列表)] select */字段列表 from 表;
3)更新数据
a)在更新数据的时候,特别要注意:通常一定是跟随条件更新
update 表名 set 字段名 = 新值 where 判断条件;
b)如果没有条件,是全表更新数据。但是可以使用limit 来限制更新的数量;
update 表名 set 字段名 = 新值 [where 判断条件] limit 数量;
update my_simple set name = 'e' where name='a' limit 4;
4)删除数据
truncate 表名; --> drop + create
5)查询操作
完整的查询指令:
Select select选项 字段列表 from 数据源 where条件 group by分组 having条件 order by排序 limit限制;
select distinct * from student;--去重复
select all * from student;-- 全部记录
别名:
字段名 as 别名;
select distinct name as name1,name name2 from student;
6)from数据源
From是为前面的查询提供数据:数据源只要是一个符合二维表结构的数据即可。
单表:
select *from student;
多表:
select *from student,my_student;
多张表的结果:两张表的记录数相乘,字段数拼接;(笛卡尔积,需要避免)
7)动态数据
8)where子句
用来从数据表获取数据的时候,然后进行条件筛选。
9)group by 子句
根据指定的字段,将数据进行分组:分组的目标是为了统计
group by 字段名;
表增加一个字段:
alter table student add classid int;-- classid 字段
更新:
update student set classid = 1 where id in('0001','0002');
update student set classid = 2 where id = '0003';
--分组
select * from student group by classid;
Group by是为了分组后进行数据统计的,只保留每组的第一条记录;
利用一些统计函数:(聚合函数)
count():统计每组中的数量,如果统计目标是字段,那么不统计为空NULL字段,如果为*那么代表统计记录
avg():求平均值
sum():求和
max():求最大值
min():求最小值
更新数据:
update student set age=18,height =185 where id = '0001';
update student set age=20,height =165 where id = '0002';
update student set age=15,height =181 where id = '0003';
select classid ,count(*),max(age),min(height),avg(age) from student ;
select classid ,count(*),max(age),min(height),avg(age) from student group by classid;--按班级查询
Group_concat():为了将分组中指定的字段进行合并(字符串拼接)
--显示每一组的人名(拼接)
select classid ,group_concat(name),count(*),max(age),min(height),avg(age) from student group by classid;
多分组:
10)having子句:
强调:having是在group by之后,group by是在where之后:where的时候表示将数据从磁盘拿到内存,where之后的所有操作都是内存操作。
11)order by子句:
根据校对规则对数据进行排序
基本语法:order by 字段 [asc|desc]; //asc升序,默认的;desc降序
select *from student order by height asc;
对多字段排序:
order by 字段1 规则,字段2 规则;
12)limit子句
纯粹的限制获取的数量:从第一条到指定的数量
基本语法: limit 数量;
select *from student limit 2;
主要用于分页;(每页2条数据)
select *from student limit 0,2;
select *from student limit 2,2;
注意:limit后面的length表示最多获取对应数量,但是如果数量不够,系统不会强求
10.运算符
算数运算符: + - * / %
比较运算符:>, >=, <, <=, =, <>
逻辑运算 and or not
select '1' <=>1,0.02<=>0,0.02<>0;
is :Is是专门用来判断字段是否为NULL的运算符
is null /is not null;
select *from student where calssid is not null;
like:Like运算符:是用来进行模糊匹配(匹配字符串)
like'匹配模式';
11.联合查询
基本语法:
Select 语句
Union [union 选项]
Select 语句;
union 选项:与select选项基本一样;
--默认去重
select *from student
union
select *from student;
select *from student
union all
select *from student;
注意细节:union理论上只要保证字段数一样,不需要每次拿到的数据对应的字段类型一致。
永远只保留第一个select语句对应的字段名字。
order by
a)在联合查询中,如果要使用order by,那么对应的select语句必须使用括号括起来
b)orderby在联合查询中若要生效,必须配合使用limit:而limit后面必须跟对应的限制数量(通常
可以使用一个较大的值:大于对应表的记录数)
(select *from student where gender ='男' order by height asc limit 10)
union
(select *from student where gender ='女' order by height desc limit 10);
12.连接查询
将多张表连到一起进行查询(会导致记录数行和字段数列发生改变)
意思:
在关系型数据库设计过程中,实体(表)与实体之间是存在很多联系的。在关系型数据库表的设计过程中,
遵循着关系来设计:一对一,一对多和多对多,通常在实际操作的过程中,需要利用这层关系来保证数据的完整性。
操作:
交叉连接;
内连接;
外连接:左外连接(左连接)和右外连接(右连接);
自然连接;
a)交叉连接
将两张表的数据与另外一张表彼此交叉;
原理:
aa)从第一张表依次取出每一条记录
bb)取出每一条记录之后,与另外一张表的全部记录挨个匹配
cc)没有任何匹配条件,所有的结果都会进行保留
dd)记录数 = 第一张表记录数 * 第二张表记录数;字段数 = 第一张表字段数 + 第二张表字段数(笛卡尔积)
基本语法:表1 cross join 表2;
select *from student corss join my_student;
本质:form 表1,表2;
b)内连接
基本语法:表1 [inner] join 表2 on 匹配条件;
--select *from student inner join my_student on classid=id;
select *from student inner join my_student on student.id=my_student.id;
如果条件中使用到对应的表名,而表名通常比较长,所以可以通过表别名来简化;
select *from student as a inner join my_student b on a.id=b.id;
c)外连接
外链接:outer join,按照某一张表作为主表(表中所有记录在最后都会保留),根据条件去连接另外一张表,从而得到目标数据。
外连接分为两种:左外连接(left join),右外连接(right join)
左连接:左表是主表
右连接:右表是主表
aa)确定连接主表:左连接就是left join左边的表为主表;right join就是右边为主表
bb)拿主表的每一条记录,去匹配另外一张表(从表)的每一条记录
cc)如果满足匹配条件:保留;不满足即不保留
dd)如果主表记录在从表中一条都没有匹配成功,那么也要保留该记录:从表对应的字段值都未NULL
基本语法:
左连接:主表 left join 从表 on 连接条件;
右连接:从表 right join 主表 on连接条件;
select *from student as a left join my_student b on a.id=b.id;
select *from student as a right join my_student b on a.id=b.id;
特点:
1、 外连接中主表数据记录一定会保存:连接之后不会出现记录数少于主表(内连接可能)
2、 左连接和右连接其实可以互相转换,但是数据对应的位置(表顺序)会改变
d)自然连接
using 关键字:是在连接查询中用来代替对应的on关键字的,进行条件匹配。
原理:
aa)在连接查询时,使用on的地方用using代替
bb)使用using的前提是对应的两张表连接的字段是同名(类似自然连接自动匹配)
cc)如果使用using关键字,那么对应的同名字段,最终在结果中只会保留一个。
基本语法:表1 [inner,left,right] join 表2 using(同名字段列表); //连接字段
select *from student left join my_student using(id);
13.子查询 sub query
指在一条select语句中,嵌入了另外一条select语句,那么被嵌入的select语句称之为子查询语句。
主查询:第一条select语句;
子查询和子查询的关系:
a)子查询是嵌入到主查询中的;
b)子查询的辅助主查询的:要么作为条件,要么作为数据源;
c)子查询其实可以独立存在:是一条完整的select语句;
功能分类:
a)标量子查询:子查询返回的结果是一个数据(一行一列);
b)列子查询:返回的结果是一列(一列多行);
c)行子查询:返回的结果是一行(一行多列);
d)表子查询:返回的结果是多行多列(多行多列);
e)Exists子查询:返回的结果1或者0(类似布尔操作);
位置分类:
a)Where子查询:子查询出现的位置在where条件中
b)From子查询:子查询出现的位置在from数据源中(做数据源)
1)标量子查询
子查询得到结果是一个数据(一行一列);
基本语法:select * from 数据源 where 条件判断 =/<> (select 字段名 from 数据源 where 条件判断); //子查询得到的结果只有一个值
select *from student where classid= (select classid from student where name='张三');
select classid from student where name='张三'; //一行一列 班级id
2)列子查询
子查询得到的结果是一列数据(一列多行);
基本语法:
主查询 where 条件 in (列子查询);
select classid from student;
select name from student where classid in(select classid from student);
3)行子查询
返回的结果是一行(一行多列);
行元素:字段元素是指一个字段对应的值,行元素对应的就是多个字段:多个字段合起来作为一个元素参与运算,把这种情况称之为行元素。
基本语法:
主查询 where 条件[(构造一个行元素)] = (行子查询);
--取年龄最大,身高最大;
select *from student where (age,height)=(select max(age),max(height) from student);
--取年龄最小,身高最大;
select *from student where (age,height)=(select min(age),max(height) from student);
4)表子查询
返回的结果是多行多列(多行多列);
行子查询是用于where条件判断:where子查询;
表子查询是用于from数据源:from子查询;
基本语法:
Select 字段表 from (表子查询) as 别名 [where] [group by] [having] [order by] [limit];
5)Exists子查询
Exists子查询:查询返回的结果只有0或者1,1代表成立,0代表不成立;
基本语法:
where exists(查询语句); //exists就是根据查询得到的结果进行判断:
如果结果存在,那么返回1,否则返回0
子查询的关键字:
1)in
主查询where 条件in (列子查询);
2)any
任意一个 = any(列子查询):条件在查询结果中有任意一个匹配即可,等价于in
3)some
4)all
14.密码丢失
如果忘记了root用户密码,就需要去找回或者重置root用户密码;
1)停止服务
stop net mysql;
2)重新启动服务:mysqld.exe –skip-grant-tables //启动服务器但是跳过权限
3)当前启动的服务器没有权限概念:非常危险,任何客户端,不需要任何用户信息都可以直接登录,而且是root权限;
新开客户端,使用mysql.exe登录即可;
4)修改root用户的密码:指定 用户名@host
update mysql.user set password = password('root') where user ='root' and host='localhost';
5)关闭服务器,进程中关闭mysqld;
15.外键
16.视图
1)创建视图
视图的本质是SQL指令(select语句)
基本语法:create view 视图名字 as select指令; //可以是单表数据,也可以是连接查询,联合查询或者子查询
create view student_class_v as
select *from student as s left join
my_student as c
on
s.classid = c.id;
2)使用视图
基本语法:select 字段列表 from 视图名字 [子句];
3)修改视图
修改视图:本质是修改视图对应的查询语句
基本语法:alter view 视图名字 as 新select指令;
4)删除视图
基本语法:drop view 视图名字;
17.系统变量
show variables;--显示全部的系统变量;
查看系统变量的值;
select @@autocommit;
修改系统变量:
局部修改:set 变量名 =值;
全局修改:set global 变量名=值;|| set @@global.变量名 = 值;
全局修改之后:所有连接的客户端并没发现改变?全局修改只针对新客户端生效(正在连着的无效);
会话变量:
定义用户变量:set @变量名 = 值;
在mysql中因为没有比较符号==,所以是用=代替比较符号:有时候在赋值的时候,会报错:mysql为了避免系统分不清是赋值还是比较;
特定增加一个变量的赋值符号: :=
set @变量名:=值;
局部变量:
18.流程控制
1)if语句
用在select查询当中,当做一种条件来进行判断;
基本语法:if(条件,为真结果,为假结果);
用在复杂的语句块中(函数/存储过程/触发器)
基本语法
If 条件表达式 then
满足条件要执行的语句;
End if;
select *, if(age>18,'符合','不符合') as judge from student;
复合语句:
If 条件表达式 then
满足条件要执行的语句;
Else
不满足条件要执行的语句;
//如果还有其他分支(细分),可以在里面再使用if
If 条件表达式 then
//满足要执行的语句
End if;
End if;
2)while循环
While 条件 do
要循环执行的代码;
End while;
19.函数
20.存储
存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,存储在数据库中,经过第一次编译后再次调用不需要再次编译(效率比较高),
用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对象(针对SQL编程而言)。
与函数比较:
相同点:
1)存储过程和函数目的都是为了可重复地执行操作数据库的sql语句的集合。
2)存储过程函数都是一次编译,后续执行.
不同点:
1)标识符不同。函数的标识符为FUNCTION,过程为:PROCEDURE。
2)函数中有返回值,且必须返回,而过程没有返回值。
3)过程无返回值类型,不能将结果直接赋值给变量;函数有返回值类型,调用时,除在select中,必须将返回值赋给变量。
4)函数可以在select语句中直接使用,而过程不能:函数是使用select调用,过程不是。
操作:
基本语法
Create procedure 过程名字([参数列表])
Begin
过程体
End
Create procedure my_pro1()
Begin
select *from student;
End
Create procedure my_pro1()
select *from student;
查看过程:
创建语句:show create procedure 过程名字;
show create procedure my_pro1;
调用过程
调用过程有专门的语法:call 过程名([实参列表]);
call my_pro1;
删除过程
基本语法:drop procedure 过程名字;
存储过程也允许提供参数(形参和实参);
in
表示参数从外部传入到里面使用(过程内部使用):可以是直接数据也可以是保存数据的变量;
out
表示参数是从过程里面把数据保存到变量中,交给外部使用:传入的必须是变量;
如果说传入的out变量本身在外部有数据,那么在进入过程之后,第一件事就是被清空,设为NULL
inout
参数使用级别语法(形参)
过程类型 变量名 数据类型; //in int_1 int
外部创建3个变量:
set@n1 =1;
set@n2 =2;
set@n3 =3;
delimiter $$
create procedure my_pro3(in int_1 int, out int_2 int, inout int_3 int)
begin
select int_1, int_2, int_3;
set int_1 = 10;
set int_2 = 100;
set int_3 = 1000;
select int_1, int_2, int_3;
select @n1,@n2,@n3;
set@n1 ='a';
set@n2 ='b';
set@n3 ='c';
select @n1,@n2,@n3;
end
$$
21.触发器 trigger
触发器是一种特殊类型的存储过程,它不同于我们前面介绍过的存储过程。
触发器主要是通过事件进行触发而被执行的,而存储过程可以通过存储过程名字而被直接调用。
作用:
1)可在写入数据表前,强制检验或转换数据。(保证数据安全)
2)触发器发生错误时,异动的结果会被撤销。(如果触发器执行错误,那么前面用户已经执行成功的操作也会被撤销:事务安全)
语法:
Create trigger 触发器名字 触发时机 触发事件 on 表 for each row
Begin
End
触发对象:on 表 for each row,触发器绑定实质是表中的所有行,因此当每一行发生指定的改变的时候,就会触发触发器。
触发时机:每张表中对应的行都会有不同的状态,当SQL指令发生的时候,都会令行中数据发生改变,
每一行总会有两种状态:数据操作前和操作后 before after
触发事件:
mysql中触发器针对的目标是数据发生改变,对应的操作只有写操作(增删改);
insert update delete
a)创建表
create table my_goods(
id int primary key auto_increment,
name varchar(20) not null,
inv int
)charset utf8;
create table my_orders(
id int primary key auto_increment,
goods_id int not null,
goods_num int not null
)charset utf8;
b)插入
insert into my_goods values(null,'手机',1000),(null,'电脑',500),(null,'平板',100);
查看:
select *from my_goods;
select *from my_orders;
c)创建触发器
Create trigger 名字 after insert on my_orders for each row;
delimiter $$
create trigger after_insert_order_t after insert on my_orders for each row
begin
update my_goods set inv = inv -1 where id = 1;
end
$$
delimiter;
d)查看触发器
show triggers\G
Show create trigger 触发器名字;
show create trigger after_insert_order_t;
e)触发触发器
想办法让触发器执行:让触发器指定的表中,对应的时机发生对应的操作即可。
11)表为my_orders
22)在插入之后
33)插入操作
select *from my_goods;
select *from my_orders;
insert into my_orders values(null,1,1);
select *from my_orders;
insert into my_orders values(null,2,10);
select *from my_orders;
select *from my_goods;
f)删除触发
基本语法:drop trigger 触发器名字;
drop trigger after_insert_order_t;
show triggers;
g)关键字
触发器针对的是数据表中的每条记录(每行),每行在数据操作前后都有一个对应的状态,
触发器在执行之前就将对应的状态获取到了,将没有操作之前的状态(数据)都保存到old关键字中,
而操作后的状态都放到new中。
基本语法:关键字.字段名
Old和new并不是所有触发器都有:
Insert:插入前全为空,没有old
Delete:清空数据,没有new
delimiter $$
create trigger after_insert_order_t after insert on my_orders for each row
begin
update my_goods set inv = inv - new.goods_num where id = new.goods_id;
end
$$
delimiter;
insert into my_orders values(null,2,10);
select *from my_goods;
select *from my_orders;
音频相关文章的搬运工,如有侵权 请联系我们删除。
微博:砖瓦工-日记本
联系方式qq:1657250854