• mysql


    # 编码:
    1. 查看创建数据库时设置的编码格式:
      shwo create database 数据库名;
    2. 查看创建表时所设置的 编码格式 和 字段详细
      show create table 表名;
    3. 修改数据编码格式/修改表的编码格式
        # gbk collatb gbk_chinese_ci;
    库:alter database 库名 character set utf8 collate utf8_general_ci; 表:alter table 表名 character set utf8 collate utf8_general_ci;



    注: 凡是带select 的不会修改表中的数据 只是将数据列出来 在数据中查询null 不能用等号 要用 xx
    is null 如果null 参与计算 那么返回的只会是 null
    查询一个字段:
    select name from class; 查询多个字段:(逗号隔开) select name,name,name from class; //name:查询的字段 class:查询的表名 计算: select name,age*10 from class; select name,age*10 size from class; 带有条件的查询: 等于:= ; 不等于:<>/!=; between ..and.. :两个值之间 is null :为null(is not null不为空) 并且: and; 或者: or; (and和or同时存在and优先级高 解决优先级问题可以加 ()括号) in: 包含,相当于多个 or (not in :不在这个范围中) not : not可以非取,主要用在 is 或者 in 中 模糊查找:like like '%p%' : 百分号是一个占位符 意思是从 0 到 n 个任意字符 //like 'p%' 以p 开始的 like'%p' 以p结尾的 like '_p%' : 下划线代表任意一个字符 //'__p%' 第二个字母为p 的字符 '%p_' 倒数第二个字母为p的字符 select name,age from class where age = 15; //找到age 为 15 的数据 select name,age from class where age between 15 and 20; //找到age 为 1520 的数据 //注: between 中 第一个数字 必须 小于 第二个数字 排序(默认升序): 排序采用 order by 子句 ,order by 后面跟上排序字段 多个用逗号隔开 如果where子句存在 那么 order by 必须排在 whrer 语句的后面 select users.sal from emp order by sal asc; //asc 升序 //users里面的sal select users.sal from emp order by sal desc;//desc 降序 select * from emp order by sal asc;(所有的) 如果前面相等 后面 的按照ename 的降序排序 select users.sal from emp order by sal asc, ename desc; //asc 降序 数据处理函数/单行处理函数 lower : 转换小写 select lower(ename) as ename from emp; //as xx 重命名 upper : 转换大写 select upper(要转换的列名称) as from 要转换的列名称 要转换的表名称; substr : 截取字符串 select substr(被截取的字符串.起始下标.截取长度) from emp; length : 取长度 select length(ename) from emp; trim : 去除前后空白 select ename from emp where enmae = trim(' zs '); round : 四舍五入 (两个参数 : 要四舍五入的数字 , 四舍五入的位数) select round(123.456,1); //结果: 123.5 rand : 生成随机数 select rand(); 生成100以内的数字 select round(rand()*100); ifnull : 可以将null转换成一个值 (空值处理函数) select ename.ifnull(comm,0) as comm from emp; //把comm为空的 设置为 0 并且 将 表名称 改为 comm //年薪 select ename.(sal + ifnull(comm,0)) * 12 as yearsal from emp; 月薪+补助 查看版本号:select version(); 查看表的创建语句: show create table users; str_to_date('日期字符串','日期格式') str_to_date 函数通常使用在插入操作中, 字段是date类型,不接受字符串varchar类型, 需要通过该函数将varchar变成date在出入数据,才能成功 %Y 年 %m 月 %d 日 %H 时 %i 分 %s 秒 MYSQL默认的日期格式 : %y-%m-%d; select ename,hiredate from emp where hiredate = '1981-12-17'; 调整格式: select ename,hiredate from emp where hiredate = str_to_date( '1981-12-17',%Y-%m-%d); //查询1981-12-17 入职的人 date_format(时期类型数据,'日期格式') data_format// 将日期类型data转成特定的日期字符串varchar select ename,date_format(hiredate,'%m-%d-%y') as hiredate from emp; 分组函数: 分组函数不能直接使用 where 语句中 sum(); //求和 (自动忽略 null(空值)) select sum(age) from class;z max(); //最大值 (自动忽略 null(空值)) select max(age) from class; min(); //最小值 (自动忽略 null(空值)) select min(age) from class; avg(); //平均值 (自动忽略 null(空值)) select avg(age) from class; count(); //统计数据 在这个字段(age)中 数据不为空的总和 (自动忽略 null(空值)) select count(age) from class; count(*);//满足这个条件的 记录总和 (个数) select count(*) from class where age is null; distinct //查询结果中 去除重复记录 ( 只能出现所有字段的最前方 ) select distinct age from class; having : havingwhere 功能都是为了完成数据的过滤 havingwhere 后面都是添加条件 wheregroup by 之前完成过滤 havinggroup by 之后完成过滤 分组查询: order by : 表示通过哪个或者哪些字段进行 排序 group by : 表示通过哪个或者哪些字段进行 分组 //分组的第一列会进行排序 (从小到大,从a-b) //如果有where 在 group by 之前 就会无法执行 select job,avg(m) job列,age(m) m的平均值 from class group by 写在后面 job having avg(m) > 1500; 一个完整的 DQL 语句总结: 以下关键词顺序不能换: select ... from ... where ... group by ... having ... order by ... 执行顺序: 1.from 从某张表中检索数据 2.where 经过某条件进行过滤 3.group by 然后分组 4.having 分组后如果不够继续过滤 5.select 查询出来 6.order by 排序输出 连接查询: 查询数据的时候都只是从一张表中检索数据,被称为单表查询 在实际开发中,数据并不是储存在一张表中的,实在多张表中 这些表 和 表 之间存在关系, 我们要检索数据的时候需要将 多张表联合起来取得有效数据,这种夺标查询被称为 连接查询 或 跨表查询 SQL92语法: 内连接中的等值连接 select e.ename,d.dname from emp e, dept d where e.deptno = d.deptno;//后面可以继续加 and.. (要查询表内数据的名字) (要查询的表) (过滤条件) //过滤条件是 :两个表中都有对应的 相同 序号 而且 一一相对 //在跨表查询的时候 给 表内的数据名起个特殊的名字 : e.enmae , d.dname , c.cxxx; SQL99语法: 内连接中的 等值连接 (用的多) 优点: 表连接独立出来了 , 结构更清晰 如果还需条件的话还可以继续 where 进行过滤 两种写法都一样: 完整写法 : select e.ename,d.dname from emp e inner join dept d on e.deptno = d.deptno; 分解: select a.表一中某一列名字,b.表二某一列名字 from 表一名字 a inner join 表二名字 b on 过滤项 inner可省略 : select e.ename,d.dname from emp e join dept d on e.deptno = d.deptno;//可以继续 where... //on是表连接的条件 select name,age from class1 name having age <20; select name,age from class1 name having age <20; 查询一个班级的总人数: 可以通过 sex(性别) 来查询 1 = 男 , 2 = 女; mysql> select sex,count(*) as people from class1; +------+--------+ | sex | people | +------+--------+ | 1 | 6 | +------+--------+ 多张表进行连接的语法格式: select xxx from a join b on 条件 join c on 条件; 原理: a 先和 join b 进行连接 结束后 a 在和 c 进行连接 select a.xx,b.xx,c.xx from class a join class b on a.d = b.d join class c on xx between xxx and xxx update: 如果我们需要修改或更新 MySQL 中的数据,我们可以使用 SQL UPDATE 命令来操作: 语法: UPDATE table_name SET field1=new-value1, field2=new-value2 [WHERE Clause] update table(表格名字) set field1(列名) = new value1(当前列的新内容) where(后面判断) peo = 1; update 语句可用来修改表中的数据, 简单来说基本的使用形式为: update 表名称 set 列名称=新值 where 更新条件; union: 操作符用于连接两个以上的 SELECT 语句的结果组合到一个结果集合中。多个 SELECT 语句会删除重复的数据。 SELECT expression1, expression2, ... expression_n FROM tables [WHERE conditions] UNION [ALL | DISTINCT] SELECT expression1, expression2, ... expression_n FROM tables [WHERE conditions]; 参数: expression1, expression2, ... expression_n: 要检索的列。 tables: 要检索的数据表。 WHERE conditions: 可选, 检索条件。 DISTINCT: 可选,删除结果集中重复的数据。默认情况下 UNION 操作符已经删除了重复数据,所以 DISTINCT 修饰符对结果没啥影响。 ALL: 可选,返回所有结果集,包含重复数据。 with rollup : WITH ROLLUP 可以实现在分组统计数据基础上再进行相同的统计(SUM,AVG,COUNT…)。 mysql> SELECT name, SUM(singin) as singin_count FROM employee_tbl GROUP BY name WITH ROLLUP; +--------+--------------+ | name | singin_count | +--------+--------------+ | 小丽 | 2 | | 小明 | 7 | | 小王 | 7 | | NULL | 16 | 其中记录 NULL 表示所有人的登录次数。 我们可以使用 coalesce 来设置一个可以取代 NUll 的名称,coalesce 语法: select coalesce(a,b,c); 参数说明:如果a==null,则选择b;如果b==null,则选择c;如果a!=null,则选择a;如果a b c 都为null ,则返回为null(没意义) mysql> SELECT coalesce(name, '总数'), SUM(singin) as singin_count FROM employee_tbl GROUP BY name WITH ROLLUP; +--------------------------+--------------+ | coalesce(name, '总数') | singin_count | +--------------------------+--------------+ | 小丽 | 2 | | 小明 | 7 | | 小王 | 7 | | 总数 | 16 | left join: 会将查询列中 左边的 所有项显示 即使 没有对应的 值(如果没有对应的值的话会显示 nullright join : 会将查询列中 右边的 所有项显示 即使 没有对应的 值(如果没有对应的值的话会显示 null) mysql> SELECT a.runoob_id, a.runoob_author, b.runoob_count FROM runoob_tbl a RIGHT JOIN tcount_tbl b ON a.runoob_author = b.runoob_author; +-------------+-----------------+----------------+ | a.runoob_id | a.runoob_author | b.runoob_count | +-------------+-----------------+----------------+ | 1 | 菜鸟教程 | 10 | | 2 | 菜鸟教程 | 10 | | 3 | RUNOOB.COM | 20 | | 4 | RUNOOB.COM | 20 | | NULL | NULL | 22 | +-------------+-----------------+----------------+ 事务: begin 开始一个事务 rollback 事务回滚 commit 事务确认 alter : 修改默认值: ALTER TABLE testalter_tbl(表名) ALTER i(表列名) SET DEFAULT(设置默认值) 1000; 删除字段默认值: ALTER TABLE testalter_tbl(表名) ALTER i(表列名) DROP(删除) DEFAULT(删除表中 i 的 deffault 这一项 (设置完后会 null) 修改表名: ALTER TABLE testalter_tbl RENAME TO alter_tbl; alter其他用途: 修改存储引擎:修改为myisam alter table tableName engine=myisam; 删除外键约束:keyName是外键别名 alter table tableName drop foreign key keyName; 修改字段的相对位置:这里name1为想要修改的字段,type1为该字段原来类型,first和after二选一,这应该显而易见,first放在第一位,after放在name2字段后面 alter table tableName modify name1 type1 first|after name2; 子查询: 子查询就是 select嵌套select 子查询:(where 后面 使用子查询) select ename,sal from emp where sal > (select avg(sal) from emp) 子查询:(from 后面 使用子查询) 技巧: 将查询结果当做临时表 select t.deptno,t.avgsal,s.grade from (select deptno,avg(sal) as avgsal from enp group by deptno) t //当做临时表t join salgrade s on t.avgsal between s.losal and s.hisal; limit: 1.limit 用来获取一张表中的部分数据 2.limit 只能在mysql数据库中存在 语法: limit 起始下标,要获取的长度 默认从零开始 , 零表示 表中的 第一条记录 示: 找出员工表中的前五条数据: select ename from emp limit 5; 等同 select ename from emp limit 0,5; 5表示从表中记录下标0开始,取五条 找出年龄最大的3个人: select name,age from class1 order by age desc limit 5; +------+------+ | name | age | +------+------+ | dy | 30 | | vc | 25 | | bb | 20 | | aa | 17 | | ls | 14 | +------+------+ mysql 中通用的分页(只适合于Mysql数据库管理系统) select t.* // t 表中的全部 from t // t 表 order by t.x sal/desc //t 表中的某一个字段 升序/降序 limit (pageNo - 1) * pageSize,pageSize; 解析: 每一页显示三条数据 起始下标,获取的长度 第一页: 0,3 第二页: 3,3 第三页: 6,3 第四页: 9,3 ... 约束(constraint): 约束是对表中的数据的限制条件 约束语句: 非空约束 not null 唯一性约束 unique 主键约束 primary key 简称:pk 外键约束 foreign key 简称:fk 检查约束 目前Mysql不支持,oracle数据库支持 一.非空约束: not null 约束字段,不能为Null值,必须给定具体的数据 示: 创建表,给字段添加非空约束(创建用户表,用户名不能为空) drop table if exists t_user; //如果没有 t_user 这个表就删除 如果有就 不删除 create table t_user( id int(10), name varchar(32) not null,//限制不能为空 email varchar(128) ); insert into t_user(id,name,email) values (1,'jack','111@qq.com'); 如果这里 name为空的话 会报错 (not null的限制) 二.唯一性约束 unique 约束的字段具有唯一性,不可重复 示: 创建用户,保证邮箱唯一 列级约束: drop table if exists t_user; create table t_user( id int(10), name varchar(32) not null, email varchar(128) unique //email 这个字段中的内容 不能有重复的 ); insert into t_user(id,name,email) values (1,'jack','jack@qq.com'); 当email重复时就会无法执行(会报错) insert into t_user(id,name,email) values (2,'zs','jack@qq.com'); 示: 表级约束: drop table if exists t_user; create table t_user( id int(10), name varchar(32) not null, email varchar(128), unique(email) //单独分离出来 ); //使用表级约束给多个字段联合添加约束 drop table if exists t_user; create table t_user( id int(10), name varchar(32) not null, email varchar(128), unique(name,email) //这段意思是 name和email 两个字段 联合起来不能重复 ); insert into t_user(id,name,email) values(1,'abc','abc@qq.com'); //输出结果:ok insert into t_user(id,name,email) values(2,'abcd','abc@qq.com');//输出结果:ok name和email 可以单独 的 可以重复 但是一旦联合起来 就不能重复 insert into t_user(id,name,email) values(3,'abc','abc@qq.com'); //输出结果:no 给约束起名字: 如果需要需要删除某个约束 , 那么就需要通过 一个名字找到对应的约束进行删除 步骤: 1.创建名字 create table t_user( id int(10), name varchar(32) not null, email varchar(128), 起名字: constraint t_user_email_upique unique(name,email) //约束的英文词 //给约束起的名字 //约束(要约束的字段) ); 2.使用下面这个库 use information_schema; 3.找到 TABLE_CONSTRAINTS 注: 这张表中专门存储约束信息 4.查询 desc TABLE_CONSTRAINTS 的表结构 5.找到 constraint_name(所有约束的名字) 6.执行这个语句 : select constraint_name from table_constraints where table_name='t_user'; 当 表名字等于 't_user' 的时候 查询 其中的 constraint_name 表约束 not nullunique 的联合使用 //既不能为空,也不能重复 示: drop table exists t_user; create table t_user( id int(10), name varchar(32) not null unique ); 三.主键约束 primary key 简称pk 1.主键涉及到的术语: 主键约束 主键字段 主键值 2.三者关系: 表中的 某个字段 添加 主键约束 后,该字段 被称为主 键字段, 主键字段中出现的 每一个数据 都被称为 主键值 用法: 给一个字段添加主键约束,被称为单一主键 //列级定义方式 drop table if exists t_usre; create table t_user( in int(10) primary key; //添加主键 name varchar(32) ); //表级约束 drop table if exists t_usre; create table t_user( in int(10), name varchar(32), primary key(id); //添加主键 ); //单一主键 标记主键 起名: drop table if exists t_usre; create table t_user( in int(10), name varchar(32), constraint t_user_id_pk(这是表名) primary key(id); //添加主键 ); 注: 给多个字段联合添加一个主键约束,被称为符合主键 但: 无论是 单一主键 还是 复合主键 ,一张表中主键约束只能有一个 复合主键(表级约束): drop table if exists t_usre; create table t_user( in int(10), name varchar(32), primary key(id,name); //添加主键 ); 复合主键(表级约束 起名字): drop table if exists t_usre; create table t_user( in int(10), name varchar(32), constraint t_user_id_pk(这是表名) primary key(id,name); //添加主键 ); 3.给某个字段添加 primary key 后,该字段不能重复,并且也不能为空, 效果和 not null upique 约束相同,但是本质不一样,主键字段还会默认添加"索引-index" 4.一张表应该有主键字段,"主键值"是当前行数据的唯一标识,"主键值"是当前行数据的身份证号 即使表中两行记录相关的数据是一样的,但是由于主键值不同,我们可以认为这是两条不同完全的数据 5.主键根据性质分类: 自然主键:(用的多) 主键值若是一个自然数,这个自然数和当前表的业务没有任何关系,这种主键叫做自然主键 业务主键: 主键值和当前表中业务紧密相关的,这种主键叫做业务主键,当业务主键发生改变的时候, 主键值通常会受到影响 6.在mysql数据库管理系统中提供了一个自增的数字,专门用来自动生成主键值, 主键值不需要维护,也不需要用户提供,自动生成,这个自增的数字默认从1开始,以此递增1,2,3,4... drop table if exists t_usre; create table t_user( in int(10) primary key auto_increment, //添加主键的自增值(auto_increment) name varchar(32), ); insert into t_user(name) values('jack'); insert into t_user(name) values('jack'); insert into t_user(name) values('jack'); select * from t_user; 三: 外键约束 foreign key 简称fk 1.外键涉及到的术语: 外键约束 外键字段 外键值 2.三者关系: 某个字段添加外键约束后,该字段称为外键字段 外键字段中的每一个数据都是外键值 3.外键也分为 : 单一外键(给一个字段添加外键约束) 和 符合外键(给多个字段添加一个外键约束) 4.一张表中可以有多个外键字段 理解: 为了保证a表中的className数据都来自 b表中的 class 字段中的数据, 有必要给a表中className 字段添加外键约束,className字段被称为 外键字段, 该字段 中 的值 被称为外键值 注: 外键值可以是null 外键字段去引用一张表中的某个字段的时候,被引用的字段必须有unique约束 有了外键引用之后,表分为父表和子表,被引用的是父表,引用的表示子表, 创建表时先创建父表,再创建子表,删除数据的时候,先删子表中的数据,在删父表中的数据 插入数据的时候 先插入父表中的数据,在插入子表中的数据 示: drop table if exists t_student; drop table if exists t_class; create table t_class( cno int(3) primary key, cname varchar(128) not null unique ); create table t_student( sno int(3) primary key, sname varchar(128) not null unique, classno int(3), constraint t_student_classno_fk foreign key(classno) references t_class(cno) //起的名字 这是一个外键 引用的是 t_class 表中的 cno ); insert into t_class(cno,cname) values(100,'one'); insert into t_class(cno,cname) values(200,'two'); insert into t_class(cno,cname) values(300,'three'); insert into t_student(sno,sname,classno) values (1,'jack',100); insert into t_student(sno,sname,classno) values (2,'ls',100); insert into t_student(sno,sname,classno) values (3,'whh',200); insert into t_student(sno,sname,classno) values (4,'xm',200); insert into t_student(sno,sname,classno) values (5,'cq',300); insert into t_student(sno,sname,classno) values (6,'ff',300); insert into t_student(sno,sname,classno) values (7,'cc',300); 内连接 与 外链接 的区别: 内连接: a表 和 b表 只能 将 够匹配的 数据匹配出来 不匹配的数据 就不会显示 外链接: a表 和 b表 会将 能够匹配的 和 不能够匹配 的数据全部查询出来 # mysql 数据类型 1. varchar(长度) : varchar(3)表示存储的数据不能超过三个字符长度 两者区别: varchar 会根据数据的实际长度进行分配 节省空间 但是分配的时候 需要执行判断程序 ,效率低 char 不需要动态分配空间 给多少就 使用多少 效率高 但是对导致空间浪费0 2. char(长度): char(3) 表示存储的数据不能超过三个字符长度 3. int: 整数型 int(3) 表示最大可以储存999 4. bigint: 长整型 对应java的 long类型 5. float : 浮点型单精度 6. double : 浮点型双精度 7. data : 日期类型 在实际开发中为了通用,一般不使用日期类型,采用字符春代替日期的比较多 8. blob : binary large object 二级制大对象 专门存储图片声音视频等数据 存储图片很常见,但是存储大的视频 一般都是提供一个视频的连接地址 9. clob : character large object 字符大对象 可以存储比较大的文本, 4G+ 的字符串可以存储 not in : 不会自动忽略空值 in : 会自动忽略空值 如果在 not in 的查询结果中有空值 那么,会影响查询结果, 需要手动 排空值 加个判断: where 名字 is not null # 数据库导出 window 的 dos 命令下: //导出整个数据库 mysqldump 库名>D:库名.sql-u root -p123; //路径 //导出指定库下的指定表 mysqldump 库名 表名>D:库名.sql -u root -p123 //导入 登陆Mysq数据库管理系统之后执行: source D:库名.sql 级联更新和级联删除:(谨慎使用) 在删除父表中数据的时候,级联删除子表中的数据 on delete cascade 删除外链约束: alter table t_student drop foreign key t_student_classno_fk; 添加外链约束: alter table t_student add constraint t_student_classent_fk foreign key(classno) references t_class(cno) on delete cascade; 在更新父表中数据的时候,级联更新子表中的数据 on update cascade 数据库设计三范式: 注: 设计数据库表的时候所依据的规范: 1.要求有主键,并且要求每一个字段原子性不可再分 2.要求所有非主键字段完全依赖主键,不能产生部分依赖 3.所有非转字段和主键字段之间不能产生传递依赖 # 事务 1.事务只和 数据操作有关系 要么全部执行 要么全部不执行 注: 在事务进行过程中,未结束之前,DML语句是不会更改底层数据库文件中的数据, 只是将历史操作记录一下,在内存中完成记录,只有在事务结束的时候,而且是 成功结束的时候才会修改底层硬盘中文件的数据; 2.事务四个特征(ACID): 原子性: 事务是最小的工作单元 一致性: 事务要求所有的DML(数据操作)语句操作的时候,必须是同时成功,或者同时失败 隔离性: 事务A和事务B之间具有隔离 持久性: 是事务的保证,事务终结的标志 (内存中的数据持久到硬盘文件中) 3.术语(不是SQL语句): 开始事务: start transaction 事务结束: end transaction 提交事务: commit transaction 回滚事务: rollback transaction 4.和事务有关的SQL语句: begin; 开始 commit; 提交 rollback; 回滚 5.事务开始的标志,事务结束的标志: 开始: 任何一条DML语句(insert update delete)执行,标志事务的开始。 结束: 注:提交 或者 回滚 任何一条语句 都会结束 事务 提交:成功的结束,将所有的MDL语句操作历史纪录和底层硬盘文件中的数据来一次同步。 回滚:失败的结束,将所有的DML语句操作历史记录全部清空; 可以隐藏表的字段 create view deptview as select deptno as a.dname as b.loc as c from dept; ------------------------| a b c | | xxx xxx xxx | | ------------------------| create view myview as DQL //只能跟查询语句 索引需要维护! 什么情况下需要添加索引: 1.该字段数据量庞大 2.该字段很少进行DML操作[DML操作多的话,索引需要不断的维护,效率低下] 3.该字段经常出现在where条件中 创建索引: //添加unique 表示dept表中的dname字段添加一个唯一性约束 1.create unique index 索引名 on 表名(列名); create unique index dept_dname_index on dept(ename); 2.alter talble 表名 add unique index 索引名 (列名); create index test_index on emp(sal); 删除索引: 1.drop index index_name on table_name; //删掉table_name 中的索引index_name 2.alter table table_name drop index index_name; //删掉table_name 中的索引index_name 3.alter table table_name drop primary key; //删除primary key 索引时使用, 因为一个表只可能只有一个primary key 索引 # 引擎 myisam : 适合大量的数据 读而少量数据更新的混合操作 , myisam 表的另一种适用情形是适用压缩的读表 不支持事务 innodb : 如果查询中包含较多的数据更新操作,应使用 innodb; 支持事务,并且mysql崩溃后 会有数据保存(备份); memory : 可以使用 memory 来存储给非永久的需要的数据,或者是能够从基于磁盘的表中重新生成的数据;
  • 相关阅读:
    实验四 决策树算法及应用
    实验三 朴素贝叶斯算法及应用
    实验二 K-近邻算法及应用
    实验一 感知器及其应用
    实验三 面向对象分析与设计
    实验二 结构化分析与设计
    实验一 软件开发文档与工具的安装与使用
    ATM管理系统
    活动图与流程图的区别与联系
    四则运算题目生成程序
  • 原文地址:https://www.cnblogs.com/chaoqi/p/10558121.html
Copyright © 2020-2023  润新知